design.html section 20a (Friend-of-Friend Visibility): - Section header badge: planned → v0.7.0 complete - FoFClosed PostVisibility table row: planned → v0.7.0 - All 5 layer rows in the implementation table: planned → v0.7.0 - Custom-subset row retained as v2 (genuinely deferred per spec) sessions.md: full session entry for the Layer 1-5 implementation arc. 34 commits, ~24 new fof:: integration tests, key design decisions preserved (slot_binder_nonce circularity fix, per-post pub_x/priv_x, multi-epoch receiver-chain V_me storage, retroactive cascade delete, key-burn semantics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
24 KiB
Contributor Sessions Log
Rolling log of active sessions on the ItsGoin repository. Every contributor — Lead or Jr — appends an entry on session start and updates it on session end. Newest entries at the top.
See CONTRIBUTING.md for the protocol. See AGENTS.md for the Claude-specific session-start checklist.
2026-05-13 to 2026-05-15 — primary Claude (Lead) — docs/fof-spec-layer1-bio-grants → master
Started: May 13 UTC. Released v0.7.0 stable on May 15 UTC.
Instance: Scott's primary Claude (Lead)
Issue: implement FoF spec Layers 1–5 end-to-end
Branch: docs/fof-spec-layer1-bio-grants (continued from prior spec-drafting session; merged to master at d46fcb4 on May 15)
Scope: Friend-of-Friend post gating: per-persona vouch keys, anonymous bio-post wrapper distribution, FoF-gated comments with CDN verification, FoF-closed encrypted bodies, V_me lifecycle (rotation/cascade/key-burn), unlock cache + retry sweep. Pre-deploy hardening pass. Version bump to 0.7.0 stable.
Commits landed on master (34 total, 1fdf9a9..d46fcb4):
Layer 1 (vouch primitive):
8a53d83schema + storage API + HPKE-sealed vouch-grant crypto + 3 testsbc008c5wire types (VouchGrantBatch) + V_me auto-gen on persona create3ee5c30publish path: bucketed-padding VouchGrantBatch in bio postsd1afcecreceive-path scan + follow-gating + scan cache (2 e2e tests)34c5b60Tauri commands + Settings UI for vouching
Layer 2 (Mode 2 + CDN verify + revocation + access-grant):
74fec3bwrap-slot dual-derivation seal/open primitives + 4 tests0f5147awire types: WrapSlot, FoFCommentGating, CommentPermission::FriendsOfFriends, RevocationEntrybdcd214fof.rs: build_fof_comment_gating with bucketed padding673f9e2wired FoF gating into post-create path00522f4reader unlock + commenter authoring + sig verify (1 roundtrip test)63ff5adCDN four-check verification on AddComment receive583033epersist FoF fields + fof_revocations table6a76adeFoFRevocation diff + sign/verify/apply + retroactive cascade-delete (2 tests)96118d7FoFAccessGrant diff + retroactive read widening (1 test)10de3f6Tauri commands + frontend compose-picker for Mode 2
Layer 3 (Mode 1 FoFClosed):
856f386PostVisibility::FoFClosed variant + body encrypt/decrypt + body-size bucket padding (3 tests)66b7804create_post_fof_closed + read_fof_closed_body + frontend hooks for locked/unlocked posts (1 e2e test)
Layer 4 (V_me lifecycle + cascade + key-burn):
c0de21down_post_slot_provenance + Node::rotate_v_me + cascade_revoke_v_me_epoch (1 test)c2f2203FoFKeyBurn primitive (1 test)fdbf97fsupersedes_post_id field for re-issue pathce710a6Tauri commands + Settings "Rotate my vouch key" UI
Layer 5 (perf):
12a3058unlock cache + unreadable-posts queue + author-direct fast path + sweep on V_x arrival (2 tests)
Pre-deploy hardening (audit pass):
aa190dbwire-shape validation on incoming FoF posts; unreadable-queue per-persona cap of 4096 (7 tests)4ec3a80key-burn replay rejection (monotonic timestamps); MAX_SWEEP_PER_CALL=256 (1 test)
Release prep:
d46fcb4version bump 0.6.2 → 0.7.0; download page updated with FoF release notes
Test count: 158 passing on master (added ~24 new fof:: integration tests across Layers 1–5 + hardening).
Build state: full-pipeline deploy initiated on May 15 (./deploy.sh from this Linux host: CLI + AppImage + APK in parallel, sign APK, sequential SCP uploads, anchor swap with signed release announcement). Windows installer separate (uploaded by Windows host team).
Key design decisions worth knowing:
slot_binder_nonce(32B random per post) replaces the spec's "post_id in HKDF info" — PostId = BLAKE3(post) was circular here. Same anti-replay property.- Per-V_x signing keypair (
pub_x/priv_x) generated per-post (not per-V_x-genesis). Comment signing is asymmetric Ed25519; PQ-migration deferred. Body + comment-payload encryption is symmetric ChaCha20-Poly1305 (PQ-safe). vouch_keys_receivedkeyed by(holder, owner, epoch)— multi-epoch retention is the receiver-chain mechanism. New V_me from a voucher appends; old key isn't deleted.- Revocation is per-post per-pub_x with retroactive cascade-delete. V_me rotation is grandfather-by-default; cascade is opt-in via
cascade_revoke_v_me_epoch. Key-burn swaps slots in-place for leaked-key scenarios.
Pending after deploy succeeds:
- Live shakedown on real devices (Scott has been looking forward to this).
- Per-post Revoke / Grant Access UI surfaces (Tauri commands exist; only Rotate has a Settings button so far).
- Update
MEMORY.md"Current Status" to v0.7.0 once anchor swap confirms healthy.
Stopping point: deploy script running in background; master at d46fcb4. Awaiting deploy completion notification.
2026-04-24 — primary Claude (Lead) — docs/fof-spec-layer1-bio-grants
Started: April 24 UTC
Instance: Scott's primary Claude (Lead)
Issue: none (spec refinement)
Branch: docs/fof-spec-layer1-bio-grants
Scope: Fold Scott + Opus's Layer 1 design answer into the spec. Vouch distribution moves from DM-wrapped VouchGrant to HPKE-sealed per-recipient wrappers carried in the voucher's bio post, leveraging existing bio-post CDN propagation and HPKE (RFC 9180) key privacy for recipient anonymity.
Key design commitments added to Layer 1:
- HPKE RFC 9180 (DHKEM X25519 + HKDF-SHA256 + ChaCha20Poly1305) for per-recipient wrappers; one ephemeral pubkey per batch; 48B per wrapper.
- HKDF
info = "itsgoin/vouch-grant/v1/" || bio_post_id— recipient-free (non-negotiable for key privacy). - No prefilter tag on grants (no prior shared secret); full X25519 trial at ~60µs per wrapper per persona is tolerable (≤90ms even at 512×3 worst case).
- Scan policy: auto-scan bio posts of followed personas; manual "check bio" gesture for non-followed; scan cache keyed by
(scanner_persona, bio_author, bio_epoch). - Bucket-padding (64/128/256/512) and per-publish wrapper shuffle for size/position opacity.
- No separate
vouches_issuedtable on the wire; bio post IS the authoritative record. Local-onlyown_vouch_targetstracks what the persona has granted. - Incremental grant-as-comment path (Scott's suggestion for avoiding full republish) deferred; v1 ships with full republish per change.
Completed:
- Rewrote
docs/fof-spec/layer-1-vouch-primitive.mdend-to-end. - README updated: Layer 1 scope line + added bio-post integration bullet.
- Self-merged to master.
Pending:
- Opus confirmation passes still open on other layers (WrapSlot byte layout, AEAD choice for body, padding schemes).
- Layer 2–6 untouched in this pass.
Stopping point: Scott asked to hold merges until Layers 2–6 iterations complete. Branch stays open locally and on Forgejo; continuing to stack commits on it.
Update 2026-04-24 — Layer 2 rewrite (CDN-level verification)
Scope: Scott shared Opus's Layer 2 design answer. Folded in.
Design commitments added:
- Per-
V_xsigning keypair(pub_x, priv_x)— replaces single per-postpub_post/priv_post. CDN can now verify comment signatures against a publishedpub_post_setbefore forwarding, killing the bandwidth-amplification DoS an admitted FoF member could otherwise mount. - Dual-derivation wrap slot:
read_slot → CEK,sign_slot → priv_x. One unwrap yields both capabilities. Slot structure is shared with Layer 3 (canonical form lives here). - Comment body encrypted under
CEK_comments = HKDF(CEK, "comments")— Mode 2 comments are genuinely FoF-read-gated now, not just FoF-sign-filtered at render (strengthening vs skeleton). - Propagation-node four-check accept rule: valid
pub_x_index, not inrevocation_list,group_sigverifies,identity_sigverifies. Any fail → drop without forwarding. - Author-signed revocation diff appended to post header; CDN honors on next sync. Per-chain revocation at propagation layer.
pub_x_indexis a per-post pseudonym — leaks "these N comments came through the same chain" within a single post; re-randomizes across posts. Accepted tradeoff for CDN-level DoS resistance.- v1 ships Ed25519 inline (~77KB header at 500 vouchees). PQ future requires Merkle-commit over
pub_post_setwith per-comment inclusion proofs; deferred but spec shape doesn't preclude.
Files touched:
docs/fof-spec/layer-2-mode2-fof-comments.md— rewritten end-to-end.docs/fof-spec/layer-3-mode1-fof-closed.md— prominent "partially superseded" banner added; body retained pending reconciliation when Scott + Opus review Layer 3.docs/fof-spec/README.md— glossary updated (pub_x/priv_x,pub_post_set,revocation_list); integration bullet updated for newInlineCommentfields + CDN accept rule.
Open questions I raised back to Scott (awaiting his answer before finalizing):
(pub_x, priv_x)lifecycle: generated atV_xgenesis (Layer 1) and stable across posts, vs regenerated per-post by author. Lead leaning per-post. Needs confirmation.pub_post_setpadding vswrap_slotspadding — real/dummy alignment when dummies shouldn't be indexable bypub_x_index.- Non-FoF rendering of comment count (reveal engagement? suppress?).
- Who holds
priv_me(author) — generated alongsideV_meat Layer 1, vs per-post regeneration. Same as #1 but for author's own entry.
Pending:
- Scott reviews / answers open questions.
- Layer 3 reconciliation when Scott + Opus get to Mode 1.
- Layers 4–6 iterations.
Stopping point: commit b8b38a6 (Layer 1) + new commit for Layer 2 both on branch; not merged. Awaiting Scott.
Update 2026-05-13 — design.html FoF section (20a) added
Added a new section 20a. Friend-of-Friend Visibility to website/design.html, sitting between Encryption (20) and Delete Propagation (21). Marked all subsections badge-planned. Layer table at the bottom shows ship status per layer.
Key writing decisions:
- Up-front disambiguation note: this section's "vouch" is the cryptographic V_me primitive, distinct from the directory-vouch system in section 27. Symmetric disambiguation note added to section 27 pointing the other direction.
- User-facing 4-level model (Public / Friends-only / FoF / Custom-v2) leads. Crypto primitives follow.
- Mode 1 vs Mode 2 split called out via
carddivs. - CDN-level verification highlighted as the propagation-DoS resistance story.
- Revocation lifecycle: three
cardblocks — per-post default, V_me rotation, opt-in cascade + key-burn. - PQ-readiness explicitly addressed (symmetric primitives PQ-safe; Ed25519 → ML-DSA-65 swap path noted).
- Cross-ref to
docs/fof-spec/for implementation detail.
Tables updated:
- Visibility variants table (in section 20) now has a
FoFClosedrow with overhead + bucketed-audience note. - New layer-status table at the bottom of section 20a shows the five ship-able layers.
Other touched:
- TOC entry added (
20a. Friend-of-Friend Visibility). reference_design_index.mdauto-updated by the design-index hook on save.- Section 27 (Directory) got a reciprocal disambiguation note pointing at section 20a.
Files in this commit:
website/design.htmlsessions.md(this entry)
Branch state: still docs/fof-spec-layer1-bio-grants, still unmerged. Implementation can now begin from a coherent public design + internal spec.
Update 2026-05-13 — Layer 4 written (rotation + revocation + key lifecycle)
Iterative session with Scott. Recap of where the model landed:
Rotation/revocation model (now in spec):
- Default narrowing of comment authority on a post = Layer 2 revocation (existing mechanism). No new wire primitive.
- Advanced narrowing of read access = full re-issue with
supersedes_post_idlink. Discouraged due to network overhead. V_merotation = the persona-wide revocation primitive. Generate new V_me, distribute via next bio-post batch to non-revoked vouchees only. Revoked person retains old V_me.- Receiver-chain model: receiver appends new V_me to
vouch_keys_received(does NOT overwrite). Trial-unwrap iterates the chain. UX-wise the "current" key is the newest; older epochs are archived but kept for historical decrypts. - Grandfather-by-default: CDN is V_me-blind, so rotation does NOT auto-cascade comment deletion. Revoked vouchee keeps comment authority on old posts unless the author opts to cascade per-pub_x revocations.
- Per-post cascade is opt-in: author can query a local
own_post_slot_provenancetable to find pub_x's sealed under V_me_old in any of their posts, then publish per-pub_x RevocationEntries to cascade. - Key-burn primitive (new, optional): signed
KeyBurnDiffswaps an old wrap_slot for a new one in-place on a specific post. Used when V_me leaked and the author wants to scrub it from the CDN copy of old posts. Body CEK unchanged; affects future fresh-decrypts only.
Cryptographic stack confirmed (Scott reconfirmed):
- Body encryption: symmetric ChaCha20-Poly1305 under CEK. PQ-safe.
- Wrap_slots: AEAD under V_x. PQ-safe.
- Comment signing: asymmetric Ed25519 (per-V_x per-post
(pub_x, priv_x)). NOT PQ-safe; ML-DSA-65 migration deferred. Scott confirmed the asymmetric-for-signing tradeoff is intentional — it's what makes CDN-level bandwidth-DoS filtering work.
Files touched in this round:
docs/fof-spec/layer-4-keypair-rotation.md: full rewrite from skeleton.docs/fof-spec/layer-1-vouch-primitive.md: rotation language updated to point at Layer 4's append-only model; multi-epoch UI hook added.
Branch state: docs/fof-spec-layer1-bio-grants (despite the name, holds all Layer 1–4 spec work). Commit pending. Not merged per Scott's standing instruction.
Pending:
- Layer 5 (unlock cache + prefilter): existing skeleton text still reflects single per-post keypair model. Needs reconciliation with per-V_x model from Layer 2.
- Layer 3 (Mode 1): partially-superseded banner still present. Needs Scott/Opus reconciliation pass.
- Layer 6 (revocation): stub still. Largely obviated by Layer 4 work.
Update 2026-04-24 — Layer 3 round 2 (last two open questions)
Two follow-up questions resolved:
- Access-grant slot ordering: append at tail (not re-shuffle). I'd initially overcorrected to a "switch comments from index to pub_x bytes so shuffles are free" change; Scott reverted that and clarified the choice. Append-at-tail preserves
pub_x_indexstability across the post's lifetime — already-stored comments stay verifiable, no write amplification on grant. Accepted positional-recency leak (tail = newest grants). - Minimum slot bucket: 8. Singleton/tiny-set posts pad up to 8 slots. Brand-new personas don't publish "I have no vouchees" headers.
Files touched:
docs/fof-spec/layer-2-mode2-fof-comments.md: access-grant lead decision made explicit about append-at-tail and index stability.docs/fof-spec/layer-3-mode1-fof-closed.md: minimum-8 floor added to padding lead decision; both open questions moved to Resolved.sessions.md: this entry.
Update 2026-04-24 — Layer 3 round 1 + cross-cutting padding rule (corrected)
Scott talked to Opus and resolved Layer 3 open questions + introduced a unified padding rule that supersedes Layer 2 round 2's rand(32..=128).
First-pass misread (corrected by Scott): I initially wrote the rule as "power-of-2 up to 256, then real + rand(0..=256) above." That's wrong — the rule is bucketed throughout, not random above the threshold.
Bucketed padding rule (applies to both slot count and body size):
- ≤256 real units → next power-of-2 bucket (8, 16, 32, 64, 128, 256).
-
256 real units → next linear-step bucket: +128 step for slots (384, 512, 640, …), +256KB step for body bytes (512KB, 768KB, 1024KB, …).
- Deterministic. Author publishes
next_bucket(real); dummies fill the gap.
Why this is stronger than random: observers learn the bucket but never the position within it. Across multiple posts from the same author, the bucket is stable until the author crosses a boundary — so no "min over many posts" attack converges tighter than the bucket bound. Random padding would have leaked min(observed) - max_noise as a floor.
Linear-step above 256 vs pure power-of-2: avoids the 2× waste of jumping 256→512 for an author with 257 vouchees. Above 256, step buckets are 128 (slots) or 256KB (body) so worst-case in-bucket overhead is bounded (~33% at the worst spot).
Applies uniformly to slot count and body size.
Other resolved Layer 3 questions:
- Custom mode UI deferred. v1 ships three presets only: Public / Friends-only / FoF.
- Slot dedup at
V_xbyte level. One slot per unique key. - Body-length padding adopted.
Files touched:
docs/fof-spec/layer-3-mode1-fof-closed.md: Lead decisions updated (hybrid padding, dedup, three-preset UI); open questions split into still-open + Resolved; ship criteria updated.docs/fof-spec/layer-2-mode2-fof-comments.md: padding rule promoted to hybrid scheme; size budget rewritten with three regime examples; privacy section rewritten for two-regime analysis; Resolved bullet superseded with pointer.sessions.md: this entry.
Still-open Layer 3 questions worth flagging to Scott:
- Access-grant ordering — does appending a new slot re-shuffle the full
wrap_slots/pub_post_set(preserves the random-order privacy property but invalidatespub_x_indexvalues in already-stored comments), or is it append-only (pub_x_indexis stable but tail-positional leak says "these are recent grants")? Lead leaning: append-only; index stability matters for revocation and stored-comment verification. - Minimum slot-count floor for tiny authors. Power-of-2-of-1 = 1, which leaks "this persona has one vouch (probably just themselves)." Lead leaning: minimum bucket of 8.
Pending: Layers 4–6 iterations. Scott to confirm two flagged questions.
Update 2026-04-24 — Layer 2 round 2 (Scott answers all 5 questions)
Scott resolved all five open questions:
- Per-post
(pub_x, priv_x)— confirmed. - Random-count dummy padding (
rand(32..=128)) replaces power-of-2 buckets, with dummy pubkeys inpub_post_setso.len() == wrap_slots.len(). Across multiple posts from the same author, an observer cannot even establish a reliable floor for the real vouch-set size. - Non-FoF comment UX: "Comments are private" affordance with optional "Request access via DM" button. No count leak.
- Author's own entry in
pub_post_set— confirmed. - Revocation is retroactive delete + forward. File-holders delete locally-stored comments signed by the revoked
pub_x, then propagate the diff. Stronger than stop-forwarding — prior garbage is cleaned up as the diff sweeps the mesh.
New primitive: access-grant author comment. Author can retroactively widen a post's read-set by publishing an author-signed special comment appending a new WrapSlot + pub_post_set entry. Lets a newly-vouched persona gain read + comment access without republishing the whole post. Answers the "non-FoF requests access via DM, author approves" UX loop.
Files touched:
docs/fof-spec/layer-2-mode2-fof-comments.md— updated Lead decisions, post-header, revocation flow (retroactive), added Access-grant author comment section, updated Privacy tradeoff (size-leak analysis with random padding), Open questions split into unresolved + Resolved, size budget, ship criteria.sessions.md— this entry.
Commit pending.
2026-04-23 — primary Claude (Lead) — docs/fof-spec-skeleton
Started: late April 23 UTC
Instance: Scott's primary Claude (Lead role)
Issue: none (spec-drafting work; hand-off to Opus for crypto fill-in)
Branch: docs/fof-spec-skeleton
Scope: Skeleton spec for Friend-of-Friend (FoF) post gating. Lays out the per-person vouch-key (V_me) primitive, four visibility levels (Public / Friends-only / FoF / Custom), Mode 1 (FOF_CLOSED) and Mode 2 (public post + FoF comments), and a six-layer implementation plan. Crypto byte layouts and algorithm specifics are marked TBD — OPUS for Opus to fill in.
Completed in this session:
docs/fof-spec/README.md— top-level overview, user-facing model, design properties, layering plan, out-of-scope, glossary, integration with existing primitives.docs/fof-spec/layer-1-vouch-primitive.md—V_xkeys, per-persona keyring,VouchGrantwire format (DM-wrapped).docs/fof-spec/layer-2-mode2-fof-comments.md—CommentPolicy::FriendsOfFriends,pub_post/priv_post/ wrap-slot primitives,group_sig+vouch_macon comments.docs/fof-spec/layer-3-mode1-fof-closed.md—PostVisibility::FoFClosed, wrap-slot byte layout, anonymous 2B prefilter, power-of-2 slot padding.docs/fof-spec/layer-4-keypair-rotation.md—PostKeyRotationrecord, explicitpub_post_indexon comments, per-post re-gating.docs/fof-spec/layer-5-prefilter-and-cache.md—vouch_unlock_cache,vouch_unreadable_posts, author-direct fast path, keyring-change retry sweep.docs/fof-spec/layer-6-revocation.md— stub; candidate designs A–D; Lead leaning is coarse-rotation with UX polish (Candidate D); revisit after 30 days of production data.
Pending after this PR merges:
- Opus review pass: fill in
TBD — OPUSmarkers (AEAD specifier, key sizes, WrapSlot byte layout, prefilter tag algorithm confirmation, epoch granularity, etc.). - Lead re-review after Opus fills in crypto.
- Per-layer branch schedule for implementation (Layer 1 ships first, independently exercised).
Stopping point: session ending after Lead self-merges docs/fof-spec-skeleton to master. Branch to be deleted locally + remote.
2026-04-23 — primary Claude (Lead) — chore/workflow-adoption
Started: late April 23 UTC
Instance: Scott's primary Claude (Lead role per feedback_senior_role.md)
Issue: none yet (inaugural PR; this is the chicken-and-egg case noted in CONTRIBUTING.md)
Branch: chore/workflow-adoption
Scope: Introduce the multi-contributor workflow to the repo. Creates CONTRIBUTING.md, AGENTS.md, and this file (sessions.md) with a seed entry.
Pre-existing state at session start:
- v0.6.2 shipped end-to-end earlier today: APK, AppImage, CLI, anchor (PID 3475521, up since ~17:39 UTC).
- Last merged-to-master commit before this branch:
2ce668a— People-tab rewrite (recency sort, profile-post Discover, bio modal, ignore primitive, per-author feed filter). - Active artifacts on
itsgoin.com/public_html/:itsgoin-0.6.2.apk(183.7 MB),itsgoin_0.6.2_amd64.AppImage(177.7 MB),itsgoin-cli-0.6.2-linux-amd64(40.8 MB). - No other contributors active.
Completed in this session (before this commit):
- Designed the Lead role + amendments to the base workflow (hotfix carve-out, partnered build/deploy go-no-go, Lead-pulls-queue review pattern, re-evaluation triggers, Scott's contributor-alignment role, Lead self-merge authority).
- Saved
feedback_senior_role.mdto instance memory. - Wrote
CONTRIBUTING.md,AGENTS.md,sessions.md(this file). Originally drafted the agent guide asCLAUDE.mdbut that filename is.gitignored at the repo root because it has historically been a credential-leak vector; switched toAGENTS.mdwith an explicit security banner. - Iterated on Scott's role: initial draft put him in the PR-routing / build-authorizer position; revised to watch contributor alignment + partner on ship, Lead self-merges.
Pending after this PR merges:
- Phase 0 prereqs from
CONTRIBUTING.md: Forgejo CI (cargo check --workspace+cargo test -p itsgoin-coreon push + PR), branch protection on master (require PR + 1 review + green CI), second Forgejo account + SSH key for Jr Claude(s). Scott coordinates.
Stopping point: session ending — Lead self-merged this PR to master (inaugural exercise of the self-merge authority the PR itself establishes, per Amendment 6). Branch chore/workflow-adoption deleted locally + remote.