Commit graph

10 commits

Author SHA1 Message Date
Scott Reimers
d7ce2f734c docs(design.html): add section 20a Friend-of-Friend Visibility
Public-facing architecture description of the FoF post-gating system
specified in docs/fof-spec/. Sits between section 20 (Encryption) and
section 21 (Delete Propagation). All subsections marked badge-planned.

Covers the user-facing 4-level visibility model, V_me primitive,
bio-post HPKE distribution, dual-mode operation (public-body+FoF-
comments vs FoFClosed), CDN-level comment verification, bucketed
padding scheme, revocation/rotation/key-burn lifecycle, PQ-readiness,
and the five ship-able layers.

Visibility variants table updated with the new FoFClosed row.

Disambiguation note added at top of section 20a noting this "vouch"
is the cryptographic V_me primitive, distinct from the directory
vouches in section 27. Reciprocal disambiguation note added at top
of section 27 pointing the other direction.

TOC entry added.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 01:20:43 -04:00
Scott Reimers
971766cb3c docs: Layer 4 — rotation, revocation, key lifecycle
Captures the decisions from the Layer 4 conversation with Scott:

Default narrowing on a single post = Layer 2 revocation (existing).
Advanced narrowing of read access = full re-issue with optional
supersedes_post_id link (network-heavy, opt-in).

V_me rotation = the persona-wide revocation primitive. Generate new
V_me, distribute to non-revoked vouchees via next bio-post batch.
Receiver-chain model: receivers append new V_me alongside old (not
overwrite). Trial-unwrap iterates the chain.

Grandfather by default: CDN is V_me-blind, so rotation does NOT
auto-cascade comment deletions. Revoked vouchee retains comment
authority on old posts unless author opts to cascade per-pub_x
revocations.

Per-post cascade is opt-in. Local-only own_post_slot_provenance
table lets author query "which pub_x's in my posts were sealed
under V_me_old?" and publish per-pub_x RevocationEntries.

New optional KeyBurnDiff primitive (signed header-diff) swaps a
V_me_old wrap_slot for a V_me_new one in-place on a specific post.
For the leaked-V_me scenario. Body CEK unchanged.

Skeleton's PostKeyRotation record removed entirely.

Layer 1 updated: rotation is append-only at receivers; pointer to
Layer 4. Multi-epoch bio-post-batch toggle hook added.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 01:07:04 -04:00
Scott Reimers
4123e032cb docs: Layer 3 round 2 — append-at-tail grants, min bucket 8
Resolve the two remaining Layer 3 open questions:
- Access-grant ordering: append at tail. pub_x_index values in
  already-stored comments stay valid; no write amplification. Tail-
  is-recent positional leak is the accepted cost (vs re-shuffle which
  would force comments to reference signers by 32B pub_x bytes).
- Minimum slot bucket: 8. Singleton posts pad up to 8 so brand-new
  personas don't publish "no vouchees" headers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:58:06 -04:00
Scott Reimers
9040d70bf6 docs: correct padding rule — bucketed throughout, not random above 256
Prior round misread Opus's recommendation: I wrote "rand(0..=256) above
256" for slots and "round up to nearest 256KB above 256KB" for body.
Body was right; slots were wrong. Correct rule: bucketed throughout.

Slot buckets: 8, 16, 32, 64, 128, 256 (power-of-2 sub-256), then
384, 512, 640, 768, ... (+128 steps above).

Body buckets: 1KB, 2KB, ..., 256KB (power-of-2 sub-256KB), then 512KB,
768KB, 1024KB, ... (+256KB steps above; aligns with future chunk size).

Stronger privacy than random: observer learns bucket, never position
within it. Stable across posts; no min-over-many-posts floor attack.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:47:44 -04:00
Scott Reimers
3ee20736aa docs: Layer 3 round 1 + unified hybrid padding rule
Hybrid padding rule (slots + body, same shape):
- <=256 real units: pad to next power of 2 (8, 16, ..., 256)
- >256 real units: pad to real + rand(0..=256) / nearest 256KB

Replaces Layer 2 round 2's rand(32..=128). Small authors/posts get
strong bucket-grouping; large authors/posts get probabilistic noise
without 2x bandwidth waste of pure power-of-2 at scale.

Layer 3 resolutions:
- Custom mode deferred; v1 ships Public / Friends-only / FoF only
- Slot dedup at V_x byte level (one slot per unique key)
- Body-length padding adopted

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:43:11 -04:00
Scott Reimers
a79cab049f docs: Layer 2 round 2 — resolve 5 questions + access-grant primitive
Fold in Scott's answers:
- Per-post (pub_x, priv_x); confirmed.
- Random rand(32..=128) dummy padding replaces power-of-2 buckets;
  dummy pubkeys in pub_post_set so .len() == wrap_slots.len(). Floor
  count is unrecoverable across multiple posts.
- Non-FoF UX: "Comments are private" + optional "Request access via
  DM" button. No count leak.
- Author's own (pub_me, priv_me) in pub_post_set; confirmed.
- Revocation is retroactive delete + forward: file-holders delete
  locally-stored comments signed by revoked pub_x on diff arrival,
  then propagate. Stronger than stop-forwarding.

New primitive: access-grant author comment. Author appends a
WrapSlot + pub_post_set entry for a newly-vouched persona via a
signed special comment — retroactive read widening without republish.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:37:24 -04:00
Scott Reimers
553fbd3a20 docs: Layer 2 — CDN-verified FoF comments (per-V_x keypair)
Replace single per-post priv_post with per-V_x (pub_x, priv_x). Post
header publishes pub_post_set; comments declare pub_x_index; CDN
propagation nodes verify group_sig + identity_sig against named pubkey
before forwarding. Kills bandwidth-amplification DoS from admitted-but-
malicious FoF members.

Dual-derivation wrap slot (read → CEK, sign → priv_x) with shared
structure Layer 3 inherits. Comments encrypted under CEK_comments so
Mode 2 comments are genuinely FoF-read-gated, not just FoF-sign-filtered.

Author-signed revocation diff appended to post; CDN honors per-chain
revocation. Tradeoff: pub_x_index is a per-post voucher-chain pseudonym,
re-randomized across posts. Accepted.

Layer 3 banner added noting wrap-slot structure is now superseded by
Layer 2's canonical form; full reconciliation deferred.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 08:25:40 -04:00
Scott Reimers
b8b38a6f03 docs: Layer 1 — HPKE-sealed vouch grants via bio post
Replace DM-wrapped VouchGrant with HPKE (RFC 9180) per-recipient
wrappers in the voucher's bio post. Recipient anonymity via HPKE key
privacy; readers trial-decrypt per persona. 48B per wrapper, one
ephemeral pubkey per batch. Scan gated to follows + manual gesture.
Bucket padding + per-publish shuffle for size/position opacity.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 07:38:12 -04:00
Scott Reimers
1fdf9a94cc docs: FoF-gating spec skeleton (hand-off to Opus)
Drafts the Friend-of-Friend post-gating spec with crypto specifics
marked TBD — OPUS for Opus to fill in. Six-layer implementation plan;
each layer independently shippable.

Includes README overview + six layer files:
- Layer 1: V_me vouch primitive (keys, keyring, VouchGrant wire format)
- Layer 2: Mode 2 — public post + FoF-gated comments
- Layer 3: Mode 1 — FoFClosed (encrypted body via wrap_slots + prefilter)
- Layer 4: per-post keypair rotation
- Layer 5: unlock cache + prefilter optimization (perf-critical)
- Layer 6: revocation (stub; likely deferred post-v1)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 23:20:56 -04:00
Scott Reimers
518fa43f4f Adopt multi-contributor git workflow (CONTRIBUTING.md + AGENTS.md + sessions.md)
First-pass adoption of the branch-and-PR workflow so Scott can onboard
Jr Claude contributors without blocking on the Lead. This PR is also
the inaugural test case of the workflow — branch + PR + review rather
than direct-to-master.

Three new files at the repo root:

- **CONTRIBUTING.md** — authoritative workflow policy. Based on the
  doc Opus outlined, with ItsGoin-specific amendments:
    1. Hotfix carve-out: Lead retains direct-to-master authority for
       true production-down scenarios, with mandatory retrospective PR
       within 24h.
    2. Build trigger is explicit — Scott says "ship it," no rolling
       auto-deploy.
    3. Review SLA is "natural stopping point," no hard time budget.
       Exception: Jr blocked + Scott flags urgent → Lead preempts.
    4. Re-evaluation triggers for the Lead role (5+ agents, >1d review
       latency, rewriting PRs in review, Scott's routing load).
    5. Secrets policy explicit (`.deploy-creds` is .gitignored; never
       commit credentials).
  A Phase 0 checklist at the bottom tracks which prereqs (CI, branch
  protection, Jr Forgejo account) are still pending.

- **AGENTS.md** — cross-agent session-start guide. Originally drafted
  as CLAUDE.md, but that filename is `.gitignore`d at the repo root
  because it has historically been a credential-leak vector. Switched
  to AGENTS.md (emerging cross-tool convention) with an explicit
  security banner at the top forbidding credential writes. Covers
  session start, role-specific starts (Lead vs Jr), session end,
  critical rules.

- **sessions.md** — rolling contributor coordination log. Seeded with
  an entry for this PR and the current post-v0.6.2-ship state (anchor
  PID 3475521, shipped artifacts, last merged commit 2ce668a).

No code touched. Workflow-only.

Phase 0 prereqs still open after this PR:
- Forgejo CI (`cargo check` + `cargo test` on push + PR)
- Branch protection on master (require PR + 1 review + green CI)
- Second Forgejo account + SSH key for Jr Claude(s)
2026-04-23 20:07:54 -04:00