#125 peering recipient discovery: live ListRecipients + send picker (v0.6.22) #233

Merged
Cordy merged 3 commits from feat/125-recipient-discovery into main 2026-08-14 02:49:56 +00:00
Owner

Implements the greenlit design from the recipient-discovery decision memo: a live picker on the send dialog, degrading to a leak-free local-history fallback.

Backend

  • New ListRecipients RPC on the authenticated cairn.peer.v1.Peering control plane. The receiver returns its Receivers user allow-list narrowed to residents — reusing the exact delivery gate (Recipients.Exists, #123) — as one audited peer-recipient-list event. This formalizes the §4.3 enumeration a size-0 PrepareTransfer probe already permits; it moves no data and leaks nothing new. Fail-closed on a disabled peer.
  • Group receivers are deliberately not expanded (no IdP enumeration), so a group-only receivers list yields no suggestions and the field stays free-text — it still succeeds at send time via the live group check.
  • Client.Recipients (Hello→Authenticate→ListRecipients) + RecipientsFor default; Registry.ReceiverUsers/Peer helpers.

API + UI

  • GET /api/v1/peering/peers/{peer}/recipients, gated exactly like the peers list (only a permitted sender may enumerate; a peer the caller may not use is indistinguishable from one that doesn't exist). On success {recipients, live:true}; on peer-unreachable/can't-enumerate it falls back to the caller's OWN prior recipients for that peer ({live:false}) — local send history from peer-transfers.json, never the peer's roster.
  • Send dialog gains a <datalist> picker populated on open and on peer change, with a hint distinguishing live vs. history. Recipient field stays free-text.

Tests: endpoint (live / history-fallback / fail-closed-for-non-senders), ListRecipients (resident allow-listed / disabled-peer), ReceiverUsers. Full go build/vet/test green on the runner after protobuf regen.

Closes #125.

Implements the greenlit design from the recipient-discovery decision memo: a live picker on the send dialog, degrading to a leak-free local-history fallback. **Backend** - New `ListRecipients` RPC on the authenticated `cairn.peer.v1.Peering` control plane. The receiver returns its `Receivers` user allow-list narrowed to residents — reusing the exact delivery gate (`Recipients.Exists`, #123) — as one audited `peer-recipient-list` event. This formalizes the §4.3 enumeration a size-0 `PrepareTransfer` probe already permits; it moves no data and leaks nothing new. Fail-closed on a disabled peer. - Group receivers are deliberately not expanded (no IdP enumeration), so a group-only receivers list yields no suggestions and the field stays free-text — it still succeeds at send time via the live group check. - `Client.Recipients` (Hello→Authenticate→ListRecipients) + `RecipientsFor` default; `Registry.ReceiverUsers`/`Peer` helpers. **API + UI** - `GET /api/v1/peering/peers/{peer}/recipients`, gated exactly like the peers list (only a permitted sender may enumerate; a peer the caller may not use is indistinguishable from one that doesn't exist). On success `{recipients, live:true}`; on peer-unreachable/can't-enumerate it falls back to the caller's OWN prior recipients for that peer (`{live:false}`) — local send history from `peer-transfers.json`, never the peer's roster. - Send dialog gains a `<datalist>` picker populated on open and on peer change, with a hint distinguishing live vs. history. Recipient field stays free-text. Tests: endpoint (live / history-fallback / fail-closed-for-non-senders), `ListRecipients` (resident allow-listed / disabled-peer), `ReceiverUsers`. Full `go build`/`vet`/`test` green on the runner after protobuf regen. Closes #125.
Cordy merged commit 04e8ebd0be into main 2026-08-14 02:49:56 +00:00
Cordy deleted branch feat/125-recipient-discovery 2026-08-14 02:49:58 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#233
No description provided.