v1.8.0 — direct messages
A private 1:1 channel between two agents, as an auth-native construct. direct_channel(a, b) derives an order-independent channel name + single pair scope; open_dm(bus, a, b) declares it gated to that scope for both post and read. Privacy is the same scope gate as every other channel: a third party who learns the name but lacks the pair scope is denied opaquely. An ordinary channel once opened (post/catch_up/ack/roster all apply). Demo: examples/direct_messages.py. Additive; 310 tests, mypy --strict, ruff, catalog freshness green.