itsgoin/docs/fof-spec/layer-6-revocation.md
Scott Reimers 73b1e24f9a docs: spec cleanup — Layer 5 wording, Layer 3 banner, Layer 6 superseded
Layer 5: replace two priv_post references in author-direct fast path
with the correct per-V_x CEK + priv_x lookup. Cache/prefilter logic
unchanged.

Layer 3: replace the "partially superseded" warning banner with a
plain scope note explaining the Mode 1/Mode 2 distinction reduces to
"body encrypted vs body plaintext"; wrap-slot canonical form lives in
Layer 2.

Layer 6: mark as superseded by Layer 4. README updated to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 01:10:43 -04:00

5.2 KiB
Raw Blame History

Layer 6 — Revocation & Rotation Cascades

Status: Superseded by Layer 4 (2026-05-13). Layer 4 settled the revocation and cascade design: V_me rotation as the persona-wide revocation primitive, receiver-chain storage, grandfather-by-default with author-opt-in per-post cascades, and the optional KeyBurnDiff primitive for leaked-V_me scenarios. Nothing in Layer 6 below is load-bearing; this file is retained as a record of the alternatives that were considered before Layer 4 was written.

Original scope (now resolved by Layer 4): Mechanism for a persona to un-vouch a specific vouchee without rotating V_me (which affects everyone), and for cascading rotations when a down-chain vouchee is un-vouched.


The problem

In Layers 15, the only way to revoke a vouch is to rotate V_me and re-distribute to every remaining vouchee. This is:

  • Coarse: rotates everyone to remove one.
  • Expensive at scale: O(remaining_vouchees) DM sends.
  • Traceable: observers can't see who, but a flurry of DMs hints at a change.
  • Cascading: if Alice rotates her V_me, every FoFClosed post Alice authored that was open to "friends" was open under V_alice_old; new readers on the updated V_alice_new can't decrypt old posts. Post-level Layer 4 rotation fixes this only if the author re-wraps every post under the new set.

Layer 6 is where we explore whether any of these frictions is worth addressing, and at what cost.


Out of scope for v1

Without Layer 6, here's what breaks vs. what holds:

  • Holds: FoF gating works. Revocation works (via coarse V_me rotation). Privacy properties intact.
  • Breaks: surgical un-vouch. If Alice wants to remove Bob but keep Charlie, she must rotate V_alice, re-give to Charlie. If she has 50 vouchees, that's 49 re-grants. Probably tolerable for a social-graph change that's inherently rare. Sharp corner only at large vouchee fanout.

Lead leaning: v1 ships without Layer 6. Revocation is via coarse V_me rotation. Revisit after usage data shows whether surgical revocation is load-bearing.


Candidate designs (if we do Layer 6 later)

Candidate A: Revocation List signed by voucher

Voucher publishes (revoked_vouchee_id, since_epoch). Readers exclude posts whose vouch_mac identifies a chain through a revoked vouchee.

Drawbacks:

  • Requires vouch_mac to be public (not just for author strict mode).
  • Publishes the social graph — the thing we worked to keep private.
  • Non-starter without Zero-Knowledge proofs.

Candidate B: Per-vouchee key derivation

Instead of one V_me, derive a per-vouchee key V_me_bob = HKDF(V_me_master, bob_id). To revoke Bob, rotate V_me_master (affects everyone again — same problem).

Alternative: author re-wraps posts under V_me_current \ {V_me_bob}. This is per-post rotation (Layer 4) with deliberate exclusion. Feasible but requires the author to know which slot was Bob's — which breaks anonymous wrap slots.

Candidate C: Forward-secrecy ratchet

V_me ratchets forward on a cadence. Old vouchees retain access to content encrypted before revocation; lose access to new. Avoids explicit revocation. Close to Signal's group ratchet.

Complexity is significant. Would require a per-persona state machine, out-of-band sync of current epoch between persona's devices, etc.

Candidate D: Accept the coarse rotation

Acknowledge V_me rotation IS the revocation primitive. Smooth the UX:

  • UI: "Remove Bob from your Friends" → warns "This will re-distribute your Friends key to your other 49 Friends."
  • Background rotation task handles the N DMs.
  • Existing FoFClosed posts don't auto-re-wrap (remain under old V_alice). Author can opt to re-wrap specific posts via Layer 4.

Lead leaning: Candidate D. The "problem" is mostly UX friction, addressable with good affordances.


Open design questions (deferred)

  • Is there user demand for surgical revocation that doesn't rotate everyone?
  • What's the actual fanout distribution? If p95 vouchee count is <20, coarse rotation is a ~20-DM operation — tolerable.
  • Does Candidate D's UX feel heavy enough that users avoid revoking at all? (Anti-pattern: graph accumulates stale vouches.)
  • For Mode 2 (public posts with FoF comments), revocation has different urgency — author cares about who can still COMMENT, not about access to past content. Is surgical comment-only revocation simpler? (Hint: Layer 4 rotation on a specific post already does this coarsely — rotate priv_post, re-wrap under the narrowed set.)

What Layer 6 should deliver IF we build it

Not decided. Placeholder:

  • A defined revocation primitive (candidate selected).
  • Cascading / not-cascading behavior specified.
  • UI surface consistent with Layers 15.
  • Does NOT introduce per-vouchee public identifiers in any wire format.

Decision point

Revisit after Layers 15 ship and 30 days of production usage. Signals that would move Layer 6 into scope:

  • p95 vouchee count > 50 (coarse rotation cost meaningfully high).
  • User reports of "I want to remove X but not everyone."
  • Privacy audit finding that the DM-flurry of coarse rotation leaks social-graph change timing.

Absent those, Layer 6 stays deferred.