fix(sn39): bind public status publications fail closed - #431
Conversation
Keep the complete validator journal private and project only a fixed operational allowlist into the group-readable status file. Bind the config, release launcher, systemd units, publisher, CLI, and regression tests to the same split so arbitrary event fields cannot reach the public stream.
Keep raw validator journals private during upgrade and publish only typed, event-specific operational fields. Fence raw/status transitions durably so interrupted or malformed publication cannot preserve a stale PASS, and document the stopped-writer migration and rollback boundary.
Publish a fail-closed PENDING marker before both event views and a digest-bound COMMITTED marker after them so interrupted refreshes cannot retain a stale PASS. Close fence metadata to reviewed categories, validate private-event commits, and keep the status regressions in required launch CI.
Bind each durable PENDING fence to the exact sanitized committed event, restrict public stage values to the reviewed enum, and leave a public generation pending when the source changes during publication. Add adversarial regressions for category substitution, reordered commits, stage leakage, and concurrent source updates.
ff46a29 to
9cfb137
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ff46a2959f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ("\n".join(human_lines) + ("\n" if human_lines else "")).encode("utf-8"), | ||
| human_log, | ||
| ) | ||
| if current_source_snapshot() != source_snapshot: |
There was a problem hiding this comment.
Close the source-change race before committing
If the validator appends a PENDING fence after this snapshot comparison but before the COMMITTED status.json replacement, the publisher commits the older generation and can expose the preceding PASS until the 60-second timer runs again. This is exactly the concurrent-write window the new protocol is intended to fail closed; the final commit needs synchronization with the writer or a post-commit check that restores PENDING when the source changed.
Useful? React with 👍 / 👎.
| # Remove a PENDING fence only when its exact COMMITTED partner is present. | ||
| # An unmatched fence is itself public evidence that the raw/status | ||
| # transition was interrupted and must remain visible as NOT_PROVEN. | ||
| events: deque[dict[str, Any]] = deque(maxlen=MAX_EVENTS) |
There was a problem hiding this comment.
Preserve unmatched fences beyond the display limit
When an interrupted transition is followed by more than MAX_EVENTS allowlisted rows without a restart, this bounded deque evicts the unmatched PENDING fence. build_status() then no longer sees publication_pending, so a later successful weight or provenance event can restore PASS even though the interrupted transition was never resolved; preserve unresolved fences separately from the bounded event display.
Useful? React with 👍 / 👎.
| "status": authority_status | ||
| if authority_fresh and publication_pending is None | ||
| else "NOT_PROVEN", |
There was a problem hiding this comment.
Clear burn_share while a source fence is pending
When the source contains an unmatched STATUS_PUBLICATION_PENDING after a fresh 90/10 submission, this guard correctly changes authority status to NOT_PROVEN, but the adjacent burn_share calculation still emits the stale value "0.10". Unlike an interrupted outer file publication, this source state is subsequently published with publication.phase=COMMITTED, so _status_publication_view() does not clear the value; apply the pending-fence condition to burn_share as well.
Useful? React with 👍 / 👎.
What this changes
Publishes a sanitized SN39 status stream without letting interrupted, mismatched, or concurrent writes preserve a stale public PASS.
Review and test evidence
Rebased onto current Cathedral main
76f59db, after PR #430 merged.Boundary
This is implemented, locally tested, independently reviewed, and pushed. It is not deployed or live-host proven. Issue #3 should remain open until the deployed publisher and public endpoint are independently verified.