Skip to content

feat(share): contacts — petnames, per-contact scope, per-pair inboxes, pause - #23

Merged
AbsoluteMode merged 1 commit into
mainfrom
feat/contacts
Jul 31, 2026
Merged

feat(share): contacts — petnames, per-contact scope, per-pair inboxes, pause#23
AbsoluteMode merged 1 commit into
mainfrom
feat/contacts

Conversation

@AbsoluteMode

Copy link
Copy Markdown
Owner

Closes the three "who exactly sees what" holes in the v1 gate, per the contacts design discussion:

  • Petnames: share trust <petname> — enrollment requires a name the owner chooses; the peer's self-claimed name is displayed as a quoted claim, never used for lookups or previews. A second contact can no longer pose as the first by naming.
  • Per-contact scope: share allow <project> --to <petname>; the everyone-bucket is --to all and must be typed out. Empty scope still means empty answers (default deny).
  • Per-pair inboxes: every pairing mints a fresh 128-bit inbox per side inside the invite's 10-minute window. The relay sees unrelated islands instead of a social graph, revoke physically stops us listening on that peer's inbox, and envelopes must arrive on the inbox minted for that exact peer (cross-inbox delivery drops). Identity address remains as legacy fallback — existing pairings keep working.
  • share pause / resume: kill switch that does not unpair anyone; paused means mail is not even fetched, so questions wait at the relay for its TTL.

Decision doc included: docs/decisions/2026-07-31-contacts-and-pair-addresses.md (also records what we rejected: KMS-next-to-the-search-server, direct p2p tunnels, approved-answer cache, solo/team as a config flag).

Tests: 270 passed — impersonation, petname uniqueness, scope isolation between two contacts, pause leaving mail unconsumed, distinct minted addresses both sides, cross-inbox rejection, revoke closing the channel, legacy-peer fallback.

🤖 Generated with Claude Code

…, pause

Three holes the v1 gate left open, all rooted in "who exactly is allowed
to see what":

- The name a peer introduces themselves with is their own text, so a second
  contact could enroll under the first one's name. Enrollment now requires a
  petname the owner chooses (share trust <petname>); every preview, candidate
  and lookup refers to it, never to the claimed name.

- Scope was one list for all trusted peers, but what one colleague should
  know is not what another should. share allow <project> --to <petname>
  grants per contact; the --to all bucket must be typed out, so opening a
  project to everyone is never the accident of a forgotten flag.

- One inbox address for every peer handed the relay a social graph and made
  revoke a flag rather than a closed door. Each pairing now mints a fresh
  128-bit inbox per side inside the invite's ten-minute window; envelopes
  must land on the inbox minted for that exact peer, revoke stops us
  listening on it, and the identity address stays only as a legacy fallback.

Plus share pause/resume: a brake, not a mode — paused means mail is not
even fetched (fetching is destructive), so questions wait at the relay
instead of being consumed and dropped.

Decision doc: docs/decisions/2026-07-31-contacts-and-pair-addresses.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@AbsoluteMode
AbsoluteMode merged commit 476b590 into main Jul 31, 2026
7 checks passed
@AbsoluteMode
AbsoluteMode deleted the feat/contacts branch July 31, 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.

2 participants