From b789ab5a19e6db1dd63efcf28e636c1550ef8b3a Mon Sep 17 00:00:00 2001 From: Scott Reimers Date: Wed, 22 Apr 2026 13:59:29 -0400 Subject: [PATCH] =?UTF-8?q?Design=20doc=20=C2=A728:=20update=20to=20reflec?= =?UTF-8?q?t=20v0.6.0=20shipped=20state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mostly a framing refresh — the underlying architecture description matches what v0.6.0 actually does. Per-subsection status badges so a reader can see at a glance what's shipped, what's partial, and what's deferred: - §28.1 two-layer identity: Shipped - §28.2 persona types: Shipped (minus ephemeral — folded into §28.4) - §28.3 multi-device: Partial (export/import works; no QR linking UX) - §28.4 ephemeral rotating DM IDs: Deferred + connection-model rationale written out - §28.5 CDN holder sets: Shipped, with drop-migration note - §28.6 DM privacy: Shipped (2 of 3 mechanisms; comment-as-intro machinery exists but no dedicated UX yet) - §28.7 user-facing: split into Shipped and Not-yet items - §28.8 key safety: Shipped (unchanged content) - §28.9 phase-by-phase rollout: each phase tagged Shipped v0.6.0 except Phase 6 (Deferred) Final paragraph replaces the old "beta and stable are separate networks" language with the hard-fork framing and a link to the upgrade path on the download page. Co-Authored-By: Claude Opus 4.7 (1M context) --- website/design.html | 71 +++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/website/design.html b/website/design.html index f52c7c4..4dccad2 100644 --- a/website/design.html +++ b/website/design.html @@ -1704,63 +1704,66 @@ END
-

28. Identity Architecture Planned

-

The 0.6.x beta line introduces a separation between network identity (per-device routing/connection key) and posting identity (the face/persona authoring content). This is the architectural foundation for multi-device, multi-persona, and DM-level traffic-graph privacy.

+

28. Identity Architecture Mostly Shipped (v0.6.0)

+

v0.6.0 separates network identity (per-device routing/connection key) from posting identity (the face/persona authoring content). This is the architectural foundation for multi-device, multi-persona, and DM-level traffic-graph privacy. Five of the original six phases shipped as v0.6.0; ephemeral rotating DM IDs (§28.4) are deferred pending connection-model design work.

-

28.1 Two layers of identity

+

28.1 Two layers of identity Shipped

Each device has ONE network key — used for QUIC connections, endpoint ID, mesh routing. It's never linked on the wire to any posting key.

-

Each user can hold MANY posting keys simultaneously — no "active" persona, no switching. Each posting key is a persona (Public, Private, Work, Family, per-conversation ephemeral, etc). Posts are signed with the posting key chosen at compose time.

+

Each user can hold MANY posting keys simultaneously — no "active" persona, no switching. Each posting key is a persona (Public, Private, Work, Family, etc). Posts are signed with the posting key chosen at compose time. On first launch after upgrading, the existing identity becomes the default posting key (same bytes as the network key for upgraders, so all prior signed content keeps verifying).

Privacy invariant: peers cannot determine which network IDs belong to a given posting ID, which posting IDs belong to the same network ID, or which posting IDs belong to the same user. These associations are private to the device owner.

-

28.2 Persona types

+

28.2 Persona types Shipped

  • Public posting IDs — main persona(s), openly associated with "you"
  • Private posting IDs — smaller-context personas for close contacts or specific groups
  • -
  • Contextual / ephemeral posting IDs — per-relationship, per-thread, or one-off; auto-generated and isolated
  • +
  • Contextual posting IDs — per-relationship or per-group; user creates one per context and sticks with it
-

28.3 Multi-device is a special case

-

"Two devices holding the same posting key" is a trivial case of the multi-key model. Link happens out-of-band between the user's own devices (QR / file / copy-paste bundle). The network sees no cross-device message announcing the relationship. Each device pulls content for its posting IDs via the normal CDN — the fact that two network nodes hold the same posting key is only discoverable if an observer has private knowledge (which they shouldn't).

+

28.3 Multi-device is a special case Partial

+

"Two devices holding the same posting key" is a trivial case of the multi-key model. Link happens out-of-band between the user's own devices via the existing identity export/import bundle — the export includes all posting identities so they restore on the second device. The network sees no cross-device message announcing the relationship; each device pulls content for its posting IDs via the normal CDN. The fact that two network nodes hold the same posting key is only discoverable if an observer has private knowledge (which they shouldn't).

+

In-app QR / file-share flows for easy linking between an existing device and a new one are not wired yet — today it's manual export-then-import.

-

28.4 Ephemeral rotating IDs for DM threads

-

DM threads and group messages use per-thread unique posting IDs that rotate per message. Each encrypted message includes a handshake field — the next posting ID to use. Observer sees a stream of distinct posting IDs with no cryptographic tie between them, defeating thread-level traffic correlation.

-

Desync recovery: receivers accept messages signed by any of the last N ephemeral IDs (sliding window). Message history (which can't be searched by rotating ID) is kept in a local encrypted-to-self archive — the archive is implemented as normal encrypted posts with recipient = user's own archive persona, replicating across the user's linked devices via self-follow.

+

28.4 Ephemeral rotating IDs for DM threads Deferred

+

The intent: DM threads and group messages use per-thread unique posting IDs that rotate per message. Each encrypted message would include a handshake field — the next posting ID to use. Observer sees a stream of distinct posting IDs with no cryptographic tie between them, defeating thread-level traffic correlation. Desync recovery via a sliding window of the last N accepted IDs. Message history kept in a local encrypted-to-self archive that replicates across linked devices via self-follow.

+

Why deferred: the current connection model is per-network-ID (peers establish QUIC sessions keyed by stable NodeId; holder-set learning assumes durable addressable authors). Ephemeral authors that come into existence per-thread need a crisper design for how a freshly generated posting ID becomes reachable fast enough to receive replies before the next rotation. The pieces needed to implement rotation (per-file holder sets, merged pull with recipient-match, per-posting-ID signing) are all in place — what's missing is the cold-contact discovery semantics for ephemeral recipients.

-

28.5 CDN restructure: per-file holder sets

-

The current upstream/downstream tree (which assumed a single author network endpoint) is replaced by a flat per-file holder set with header-diff propagation.

-

Each file (post, blob, manifest) has its own holder set. Each holder tracks up to 5 peers it recently interacted with about that specific file. When a new post is created, the creator updates the headers of recent prior posts (their manifests now reference the new post), then pushes the header diff to the up-to-5 known holders of each updated prior post. Recipients apply the header diff, see the reference to the new post, and pull it through normal sync.

-

Notifications thus route via network-ID peers who happen to hold related files — not via any tree rooted at the author. Content always arrives via pull, never pushed directly.

+

28.5 CDN: per-file holder sets Shipped

+

The earlier upstream/downstream tree (which assumed a single author network endpoint) is replaced by a flat per-file holder set with header-diff propagation.

+

Each file (post, blob, manifest) has its own holder set (up to 5 most-recent peers, LRU-capped). When a new post is created, the creator updates the headers of recent prior posts (their manifests now reference the new post), then pushes the header diff to each updated prior post's holder set. Recipients apply the header diff, see the reference to the new post, and pull it through normal sync.

+

Notifications thus route via network-ID peers who happen to hold related files — not via any tree rooted at the author. Content always arrives via pull, never pushed directly. Four legacy tables (post_upstream, post_downstream, blob_upstream, blob_downstream) were dropped in v0.6; a one-way migration seeds file_holders from them on first launch.

-

28.6 DM privacy model

-

Three complementary mechanisms eliminate the "A messaged B" traffic signal:

+

28.6 DM privacy model Shipped

+

Two of the three originally-planned mechanisms shipped in v0.6.0 and eliminate the "A messaged B" traffic signal for follower-to-follower and cold-contact-via-pull scenarios:

    -
  1. CDN-only propagation. Direct PostPush for encrypted posts is removed. All encrypted posts propagate via the file-holder CDN, indistinguishable from any other encrypted content.
  2. -
  3. Merged pull + recipient-match. Pull sync's query is extended so peers return posts matching author ∈ query_list OR recipient ∈ wrapped_keys. Client always includes its own NodeId alongside follows. The search pattern is indistinguishable from routine pull — no "searching for DMs" traffic fingerprint.
  4. -
  5. Comment-as-introduction for cold contact. Any public post with open comments serves as a message-request surface. Comments flow via engagement diffs through the post's holder network, reaching the author's linked devices via normal pull.
  6. +
  7. CDN-only propagation. Direct PostPush for encrypted posts is removed. All encrypted posts propagate via the file-holder CDN, indistinguishable on the wire from any other encrypted content.
  8. +
  9. Merged pull + recipient-match. Pull sync's query is a uniform list of NodeIds; server returns posts matching author ∈ query_list OR wrapped_key.recipient ∈ query_list. Client always includes its own NodeId alongside follows. No distinguishable "searching for DMs" traffic fingerprint — the query looks identical to a routine follow-pull.
  10. +
  11. Comment-as-introduction for cold contact. Any public post with open comments serves as a message-request surface. The machinery exists (engagement diffs flow through the post's holder network); a dedicated UX affordance for "start a conversation by commenting" is still on the todo list.

28.7 What the user sees

    -
  • One merged incoming feed (all content to all personas), with filter-by-persona pills
  • -
  • Reply/comment defaults to the persona whose key decrypted the post (override available)
  • -
  • Persona picker only appears at post-creation time, with contextual defaults
  • -
  • DMs to different personas appear as distinct conversation threads in the inbox
  • -
  • "New conversation with Alice" can offer a fresh per-thread ephemeral ID
  • +
  • One merged incoming feed (all content to all personas), with filter-by-persona pills Shipped
  • +
  • Per-post "(you) as <persona>" label on own posts authored by a non-default persona Shipped
  • +
  • Persona picker at post-creation time, auto-hidden with a single persona Shipped
  • +
  • Settings → Personas to create, delete, and set default Shipped
  • +
  • Reply/comment default persona = whichever key decrypted the post Not yet
  • +
  • Contextual compose defaults (e.g., posting to a circle auto-picks that circle's last-used persona) Not yet
  • +
  • DMs to different personas as distinct inbox threads Not yet
-

28.8 Key/collision safety

+

28.8 Key/collision safety Shipped

Posting keys and network keys are ed25519 seeds (256 bits of entropy). Birthday paradox reaches 50% collision at ~2128 keys generated — not a concern even at aggressive rotation rates across a global userbase. The operational risk is weak RNG during key generation; we rely on the platform CSPRNG everywhere.

-

28.9 Phased rollout

+

28.9 Rollout status

    -
  1. Phase 1 — Remove direct PostPush for encrypted posts (keeps existing CDN tree). Encrypted DMs propagate via ManifestPush like any other content.
  2. -
  3. Phase 2 — File-holder model + header-diff propagation replaces upstream/downstream. Diverse lateral holder networks per file.
  4. -
  5. Phase 3 — Merged pull + recipient-match search. DM search becomes indistinguishable from follow-pull.
  6. -
  7. Phase 4 — Posting-key / network-key split. Local-only linked-devices hints. Multi-persona plumbing.
  8. -
  9. Phase 5 — Multi-persona UX.
  10. -
  11. Phase 6 — Ephemeral rotating IDs for DM threads + local self-archive.
  12. +
  13. Phase 1 Shipped v0.6.0 — Direct PostPush for encrypted posts removed. Encrypted DMs propagate via ManifestPush like any other content.
  14. +
  15. Phase 2 Shipped v0.6.0 — File-holder model + header-diff propagation replaces upstream/downstream. Legacy tables dropped with a one-way seed migration.
  16. +
  17. Phase 3 Shipped v0.6.0 — Merged pull + recipient-match search. DM search indistinguishable from follow-pull. post_recipients index added.
  18. +
  19. Phase 4 Shipped v0.6.0 — Posting-key / network-key split plumbing. posting_identities table; seed migration copies network key in as default persona for upgraders.
  20. +
  21. Phase 5 Shipped v0.6.0 — Multi-persona UX (Settings page, compose picker, feed filter pills, per-post persona labels).
  22. +
  23. Phase 6 Deferred — Ephemeral rotating IDs for DM threads + local self-archive. See §28.4 for the open design question.
-

Beta and stable are separate networks. The 0.6.x beta line does not interoperate with 0.5.3 stable. This is an explicit simplification — no dual-writing legacy tables, no mixed-version wire handlers, no cross-network testing matrices. Users can cross tracks via the existing export/import identity bundle.

+

v0.6 is a hard network fork from v0.5. The two versions do not interoperate. This was an explicit simplification once the user base was small enough to migrate everyone directly — no dual-write tables, no legacy message handlers, no mixed-network testing. Users cross via the existing export/import identity bundle; see the download page for the upgrade path.