itsgoin/IMPLEMENTATION_PLAN_0.6.md
Scott Reimers 9f2603f981 0.5.3 → stable; document 0.6.x Identity Architecture plan
- Promote 0.5.3 to stable on download page
- "Coming in Beta" section describes 0.6.x privacy features
- Add design.html §28: Identity Architecture (Planned) — network/posting
  ID split, multi-persona, ephemeral DM IDs, file-holder CDN, CDN-only
  DM privacy
- IMPLEMENTATION_PLAN_0.6.md: phased rollout across 0.6.0 through 0.6.5,
  each backward compatible, each a standalone release

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 18:06:26 -04:00

199 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Implementation Plan: Identity Architecture Rollout (0.6.x beta cycle)
## Context
0.5.3-beta is graduating to stable. The 0.6.x beta line introduces the Network-ID / Posting-ID split, multi-persona support, ephemeral rotating DM identities, file-holder CDN restructure, and CDN-only DM privacy.
Full architectural plan: `/home/sologretto/.claude/plans/woolly-nibbling-glade.md`
Canonical reference: `website/design.html` §28
Memory summary: `reference_identity_architecture.md`
Each phase below is a standalone release. Each phase is backward compatible with peers on earlier versions (they degrade gracefully or stay on the old path). After all phases ship, 0.7.0-beta consolidates and 0.7.x becomes the candidate for the next stable promotion.
---
## Phase 1 (v0.6.0-beta): Remove direct `PostPush` for encrypted posts
**Goal:** Eliminate the sender→recipient traffic signal. Encrypted DMs propagate via the existing ManifestPush / CDN tree, indistinguishable on the wire from any other encrypted post.
**Scope:**
- Remove or gate `push_post_to_recipients` in `crates/core/src/node.rs`
- Ensure new encrypted posts still trigger a normal header update on neighbor posts (already done by existing CDN logic) so they propagate
- Verify the existing ManifestPush fan-out path reaches recipients who follow the author's posting ID (today they do since follows pull posts)
- Add a "CDN delivery SLA" doc note: expect ~seconds to tens-of-seconds latency for DMs to followers, minutes worst case for offline-then-online recipients
**Verification:**
- Send an encrypted DM with two test devices. Confirm the recipient receives it without any direct-push message firing (network log inspection)
- Measure p50/p95 delivery latency on a small mesh
- Backward compat: verify a v0.6 client can DM a v0.5 client and vice versa
**Risks:**
- Latency regression for non-follower recipients (they won't get it until Phase 3 or comment-intro shipping). For Phase 1, keep the push path behind a compile flag for non-follower recipients if safety is a concern — or explicitly document that "DMs to non-followers don't reach yet; follow or comment on their post"
---
## Phase 2 (v0.6.1-beta): File-holder CDN + header-diff propagation
**Goal:** Replace the upstream/downstream tree with per-file flat holder sets. Prerequisite for multi-device (because upstream-toward-author doesn't work with multiple authoring network IDs).
**Scope:**
- New `file_holders` table: `(file_id, peer_id, last_interaction_ms, direction)` — direction records whether we sent or received the file with this peer, for potential reuse
- Populate on ManifestPush receive, blob fetch, blob serve, engagement diff exchange
- Cap per file_id at 5 holders (LRU on `last_interaction_ms`)
- Refactor engagement diff delivery: instead of "send to upstream," send to the file's up-to-5 known holders
- Keep `post_upstream` / `post_downstream` tables for compat reads during the transition
- ManifestPush propagation logic: when header of file A changes, look up A's holders, send diff to them
- Receiver behavior: apply header diff, pull any referenced new files
**Wire protocol:**
- `BlobHeaderDiff` and `ManifestPush` messages stay the same on the wire
- What changes is the sender's list of destinations (was: upstreams; now: holders)
**Verification:**
- Mesh test: create a post, track its propagation; confirm holders accumulate up to 5 diverse peers
- Engagement propagation: a reaction on a deeply-nested post still reaches the author (now: via the post's holders)
- Backward compat: a v0.6.1 sending to a v0.6.0 holder should still work (v0.6.0 applies header diff normally)
**Risks:**
- Churn in holder sets during network instability (holders going offline trigger LRU replacement). Need soak testing.
- Potential duplicate diff delivery if holder sets overlap. Idempotent application is already required by existing code.
---
## Phase 3 (v0.6.2-beta): Merged pull + recipient-match
**Goal:** Nodes can find DMs addressed to them without a distinguishable "searching for DMs" traffic pattern. Handles the case where a DM exists on a peer you're connected to but you don't follow the author.
**Scope:**
- Add index on `wrapped_key.recipient` in storage (migration)
- Extend `PullSyncRequestPayload` handling: peer returns posts matching `author ∈ query_ids` OR `wrapped_key.recipient ∈ query_ids`
- Client: always include own NodeId in the pull query's NodeId list
- No new message type; existing PullSync handler gets smarter
- UX: no user-visible change (pull is internal)
**Wire protocol:**
- No wire format change. Same fields, broader server-side matching logic.
**Verification:**
- Send a DM from A to B where A is not followed by B. Verify B receives it on next pull cycle (via the recipient-match).
- Benchmark pull query cost with the new OR-clause. Should be near-zero with the index.
- Backward compat: a v0.6.2 pulling from a v0.6.1 peer still works (peer ignores the "recipient match" intent since it only indexes author)
**Risks:**
- Query cost grows with posts held × recipient list length. Index is mandatory.
- Peer can keep a log of "query included NodeId X" — tied to your connection anyway, not new info.
---
## Phase 4 (v0.6.3-beta): Posting-key / network-key split
**Goal:** Decouple signing identity from network identity. Foundation for multi-device and multi-persona. This phase ships WITHOUT UI for creating multiple personas — it's the plumbing.
**Scope:**
- `PostingIdentity` struct in `crates/core/src/types.rs`: `{ node_id, secret_seed, display_name, created_at }`
- Storage: `posting_identities` table (list of all held posting keys), `active_default_posting_id` setting
- Storage: migrate existing identity → single posting identity with the same key as the network key (no behavior change for existing users)
- `crypto.rs`: separate signing primitives — `sign_with_posting_key` vs `sign_with_network_key`. Keep existing `sign_manifest` working by delegating to posting-key variant when available
- `Node`: load posting keys alongside network key at startup
- `BlobHeader.author`: populated from posting key (was: network key, but they were equal)
- Posts signed with posting key; connections still use network key
- Export/import bundle includes posting key (in addition to network key)
- Wire: no new message types; `InitialExchange` doesn't need to change because posting IDs are only relevant for signed content, not connection setup
**Wire protocol:**
- `BlobHeader` already has an `author` field. We just populate it from posting key instead of network key.
- For mixed-version networks: v0.6.3 posts signed by a posting_id that happens to equal the author's network_id are indistinguishable from v0.6.2 posts. Backward compat is automatic.
- First-run migration: existing users have network_id == posting_id. Nothing changes for them until they explicitly create a second persona.
**Verification:**
- Existing identity still works; no data loss
- Posts from upgraded clients still validate on older clients
- Posts from older clients still decrypt and render on upgraded clients
**Risks:**
- Signature verification regression if `author` field handling changes subtly. Need extensive cross-version testing.
- Storage migration needs transaction safety.
---
## Phase 5 (v0.6.4-beta): Multi-persona UX
**Goal:** Let users create and use multiple posting identities with clean UX.
**Scope:**
- IPC: `list_posting_identities`, `create_posting_identity(name, avatar)`, `set_default_posting_identity(id)`, `delete_posting_identity(id)`
- Frontend: Settings > Personas page with create/list/delete
- Compose box: persona picker (avatar + name + dropdown)
- Contextual defaults: posting to a circle uses that circle's last-used persona
- Feed: merged view, filter pills per persona
- Reply/comment: default persona = whichever decrypted the post
- Subtle per-post labels showing which persona's follow surfaced each item
**Wire protocol:**
- No changes (posting keys are already supported from Phase 4)
**Verification:**
- Create three personas, post from each, confirm peers see three distinct authors
- DM each persona from a peer; confirm messages route to separate inbox threads locally
- Social graph separation test: follow one peer from Persona A and a different peer from Persona B; confirm merged feed shows both but filter isolates each
**Risks:**
- UX complexity regression — the merged feed with filters is non-trivial. Start with two-persona users and expand.
- Existing users with single identity should see ZERO UI change until they opt in to creating a second persona.
---
## Phase 6 (v0.6.5-beta): Ephemeral rotating DM IDs + local archive
**Goal:** Maximum traffic-graph concealment for DMs. Each thread gets a rotating posting ID, messages include handshake for the next ID, local archive preserves history.
**Scope:**
- Per-thread ephemeral posting ID generation
- Handshake field in encrypted post payload: `next_posting_id: SecretSeed`
- Sliding window of last 10 accepted IDs per thread
- Local archive post: encrypted-to-self, replicates across user's linked devices via the multi-device shared-posting-key mechanism
- UX: DMs appear as continuous thread in the UI despite wire-level rotation
- Group thread rotation
**Wire protocol:**
- No new message types — ephemeral posting IDs are just short-lived posting keys. The handshake field lives inside the encrypted payload.
**Verification:**
- Observer test: capture a DM thread's wire traffic; confirm no cryptographic tie between successive messages
- Resilience: drop a message mid-thread; confirm the next message catches up via the sliding window
- Archive test: scroll back through a 100-message thread; confirm all messages visible via local archive even though wire-level IDs are long forgotten
**Risks:**
- Complexity of rotation + archive is high. Lots of state to get right.
- UX: users need to understand that "they can't recover messages from a new device without importing the archive" — this is true already for any encrypted history, but doubly so here.
---
## Version promotion plan
- **0.5.3-beta → stable** (this work). Last stable of the pre-split architecture.
- 0.6.0 through 0.6.5 are beta releases shipping Phases 1-6.
- **0.7.0-beta** consolidates and cleans up deprecated code paths (post_upstream/downstream tables dropped, old push code removed).
- **0.7.x-beta** gets real-world soak testing as the full new architecture.
- **0.7.N → stable** once the new architecture is proven.
## Order-of-operations recommendations
- Phases 1 and 2 can overlap (CDN restructure can happen while PostPush is being removed — they touch different code paths).
- Phase 3 depends on Phase 2 being in place (the file-holder refactor touches pull handling).
- Phase 4 is a prerequisite for 5 and 6 but doesn't need to wait for 1-3 (it's local/storage only, wire protocol unchanged).
- Phase 5 UX should wait for Phase 4 to ship and stabilize so persona-aware code is well tested.
- Phase 6 is the most complex; ship last.
## What must not regress
- Existing users upgrading from 0.5.3 should see no behavior change until they explicitly opt in to new features.
- Cross-version interoperability is required at every phase boundary.
- Data integrity: all migrations must be transaction-safe and reversible (keep old tables until N+1 phase).
## Not in scope for 0.6.x
- Search/discovery improvements (existing Worm still used)
- Anchor/directory redesign (separate planned track)
- Erasure-coded CDN replication (separate planned track)
- Reciprocity / Phase 2 economic features (still deferred)