Skip to content

fix(id): redact install seed from join projections - #250

Merged
dezren39 merged 1 commit into
mainfrom
sweep/240-redact-install-seed
Oct 17, 2026
Merged

dezren39 merged 1 commit into
mainfrom
sweep/240-redact-install-seed

Conversation

@dezren39

@dezren39 dezren39 commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Fixes #240.

Problem

ProgramInstalled { seed } was serialized to every joiner: WorldCore::events_after and the join snapshot (snapshot_unchecked) returned the retained event verbatim (verified: seed 424242 in fixture work on PR #239, and reproduced here with a new regression test that failed on main). A program whose hidden state is derived from init(seed) therefore leaked that state to every participant.

Solution (the issue's recommended option: treat the seed as secret)

  • New redact_install_seed projection in world.rs: a ProgramInstalled event keeps its module_hash (joiners need it to fetch the module via DownloadModule) but its seed is zeroed.
  • Applied in exactly the two join projections: WorldCore::events_after and WorldCore::snapshot_unchecked (which also covers the session snapshot/resnapshot paths and the lagged-subscriber resync, all of which go through snapshot/events_after with a JOIN capability).
  • Untouched, by design: the journal (JournalEntry::Committed/Checkpoint), the core's retained events, RestoredProgram, active_seed, and the install_program return to the admin — replay through the journal/admin path still uses the real seed the admin installed with. The live broadcast path already never forwards ProgramInstalled itself (it sends a fresh snapshot + ProgramChanged { module_hash }).

Tests

  • New regression test join_projections_redact_the_install_seed_but_the_journal_keeps_it: failed before the fix (seed 424242 in events_after), passes after; also asserts the journal restore path and core keep the real seed.
  • Targeted suite: cargo test --lib -- world:: world_session:: world_store:: world_hub:: — 122 passed, 0 failed.
  • cargo check --lib --no-default-features — passes (one pre-existing dead-code warning in event_store/ingest.rs, unrelated).
  • rustfmt/clippy binaries are unavailable in the sweep sandbox (same as id: lib does not build with --no-default-features #193/fix(id): build lib with --no-default-features #245); CI will verify.

ProgramInstalled { seed } was serialized to every joiner through
WorldCore::events_after and the join snapshot, so a program whose
hidden state derives from init(seed) leaked that state to every
participant.

Per the recommendation on #240, treat the seed as secret: add
redact_install_seed and apply it in the two join projections
(snapshot_unchecked and events_after). Joiners keep the module hash
(they need it to fetch the module) but see seed 0. The journal, the
core's retained events, RestoredProgram and the install/admin return
path keep the real seed, so replay through the journal/admin path is
unchanged.

Regression test: restore a journal whose install used seed 424242,
assert the restore/core keep it and that neither events_after nor the
snapshot exposes it.
@dezren39
dezren39 requested a review from a team as a code owner October 17, 2026 22:31
@coderabbitai

coderabbitai Bot commented Oct 17, 2026

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3437d121-c098-4f84-8c2b-d35c16bb44fd
📥 Commits

Reviewing files that changed from the base of the PR and between 7a3dc31 and 7226fd4.

📒 Files selected for processing: 1
  • pkgs/id/src/world.rs
+------------------------------+
| Here's looking at you, code. |
+------------------------------+
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Install seed is readable by every joiner

1 participant