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>
This commit is contained in:
parent
a2cc98cb25
commit
9f2603f981
3 changed files with 417 additions and 54 deletions
199
IMPLEMENTATION_PLAN_0.6.md
Normal file
199
IMPLEMENTATION_PLAN_0.6.md
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
# 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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue