Skip to content

feat: dig-node chat subsystem — chat message types + chat.* RPC over dig-message/dig-gossip - #133

Merged
MichaelTaylor3d merged 4 commits into
mainfrom
feat/chat-subsystem
Aug 2, 2026
Merged

feat: dig-node chat subsystem — chat message types + chat.* RPC over dig-message/dig-gossip#133
MichaelTaylor3d merged 4 commits into
mainfrom
feat/chat-subsystem

Conversation

@MichaelTaylor3d

@MichaelTaylor3d MichaelTaylor3d commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

What & why

Lane B of the dig-chat epic (dig_ecosystem#768 / #793) — the dig-node chat subsystem, the transport half of dig-chat. A node seals an app-supplied opaque DIGCHAT1 envelope into a dig-message envelope to the recipient's 0x0010 BLS key and dig-gossip directed-sends it (opcode 220); inbound frames are opened, registry-dispatched, and surfaced via a poll RPC. Double-seal upholds NC-1 — the node never parses chat content.

Delivered

  • crates/dig-chat-protocol (new workspace member) — the 5 chat MessageKinds on dig-message band 0x0200 (ChatMessage carrying opaque bytes + receipts/typing/presence), KATs. Sealing-key-agnostic, content-blind.
  • crates/dig-node-core/src/chat.rsseal_outbound / open_into_inbox / process_inbound_frame, bounded ChatInbox, monotonic anti-replay ChatState, MessageRegistry wiring, and the chat.send / chat.poll RPC handlers.
  • RPC dispatch + OpenRPC catalogue (served: "local"); workspace version 0.61.0 → 0.62.0 (minor); dig-node-core SPEC.md §5.5.2.

Verified (scoped — see disk note)

cargo fmt --check clean · cargo clippy -p dig-chat-protocol -p dig-node-core -p dig-node-service --lib -- -D warnings clean · dig-chat-protocol 13 KATs + doctest pass · dig-node-core --lib chat 6 pass incl. the NC-1 on-wire-ciphertext test (neither the DIGCHAT1 body nor the plaintext message id appears on the wire), send→receive opaque-byte round-trip, fail-closed on unresolvable sender / malformed envelope, bounded-inbox eviction, monotonic counter. TDD caught a real leak (message_id in the cleartext correlation_id) — fixed in 448d24e.

Scoped/deferred (tracked follow-ups — not blocking this foundation)

  • Live inbound loop to the peer bring-up (run_peer_network draining GossipHandle::inbound_receiver() into the inbox) — the handler is built + unit-tested; wiring is gated on the key directory.
  • resolveSealingKey / DID→(sealing key, peer_id) directory — for now chat.send takes app-supplied {recipient_did, recipient_pub, peer_id, envelope}.
  • Promote chat.send/chat.poll into the shared dig-rpc-protocol Method enum; receipts/typing/presence delivery; group/onion.

Disk note

The full cargo build/clippy --all-targets + the openrpc_drift_guard test overflow the ~38G dev-container quota from clean — those gates run here on PR CI. Local verification was scoped to --lib + the touched crates.

Tracks dig_ecosystem#793. 🤖 Generated with Claude Code

@MichaelTaylor3d
MichaelTaylor3d marked this pull request as ready for review August 2, 2026 05:43
MichaelTaylor3d and others added 4 commits August 2, 2026 06:21
Salvage anchor for Lane B of the dig-chat epic (#768): the dig-node chat
subsystem — chat message-type crate (band 0x0200 on dig-message) + chat.*
RPC + dig-gossip transport wiring. Implementation follows on this branch.

Refs #793, #768, #781
Co-Authored-By: Claude <noreply@anthropic.com>
Add the transport half of dig-chat (epic #793, Lane B): the node seals an
app-supplied opaque DIGCHAT1 envelope into a dig-message envelope to the
recipient's 0x0010 BLS identity key and dig-gossip directed-sends it (opcode
220), and surfaces inbound decoded ChatMessages via a poll RPC.

- Add `dig-chat-protocol` as a workspace member crate: the five chat message
  types on dig-message's dig-chat band (0x0200), content-blind, with KATs.
- Register the chat types into a MessageRegistry and add the `chat` subsystem
  module: seal_outbound / open_into_inbox / process_inbound_frame + a bounded
  per-node inbox and a monotonic anti-replay counter.
- Wire `chat.send` (seal + directed send, returns message_id) and `chat.poll`
  (drain inbox) into the RPC dispatch and the OpenRPC method catalogue.
- Double seal upholds NC-1: neither the DIGCHAT1 body nor the plaintext message
  id appears in the on-wire bytes; the node never parses chat content.
- Bump the workspace version to 0.62.0 (minor) and document the subsystem in
  SPEC.md §5.5.2.

The sealing-key directory (resolveSealingKey) is deferred: the app supplies the
recipient sealing key + gossip peer_id, and the inbound sender-key resolver is
caller-supplied.

Co-Authored-By: Claude <noreply@anthropic.com>
correlation_id is a CLEARTEXT dig-message envelope header; carrying the
message_id there would expose it on the wire. Zero it for one-shot chat
messages — the id travels sealed inside the ChatMessage payload.

Refs #793
Co-Authored-By: Claude <noreply@anthropic.com>
The inbound handler (process_inbound_frame) is implemented + unit-tested,
but the run_peer_network loop that feeds it is not yet wired, so chat.poll
returns empty in the shipped build until that lands. State this explicitly
so an integrator does not build against chat.poll expecting delivery.

Addresses the review gate's SPEC-accuracy finding. Refs #793
Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3d
MichaelTaylor3d merged commit 9860579 into main Aug 2, 2026
15 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the feat/chat-subsystem branch August 2, 2026 06:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant