Skip to content

feat(id): compiler-version provenance + journal-recorded trust decisions (#1069) - #4263

Merged
dezren39 merged 2 commits into
mainfrom
queue/6097-1069-remainder
Nov 2, 2026
Merged

dezren39 merged 2 commits into
mainfrom
queue/6097-1069-remainder

Conversation

@dezren39

@dezren39 dezren39 commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Implements the #1069 remainder scoped by task 6097 (queue task 6097, lane C):

Changes

  • Compiler-version provenance: SourceBuildProvenance gains compiler_version (#[serde(default)] so pre-field journal records still deserialize), populated in world_compile::compile() by probing roc version; a failed probe records an empty string rather than failing a compile whose identity is already pinned by compiler_blake3.
  • Journal-recorded trust decisions: new journal-only JournalEntry::ModuleTrustDecision patterned on BuilderInstalled. install_wasm_reserved computes the decision at the trust gate — server_compiled (gate inapplicable), no_trust_list, or signature_verified with the publisher key — and threads it through the new install_program_with_trust handle method so the actor persists it alongside the ProgramInstalled event. Replay treats it as audit-only; it takes the default journal-version arm (no version bump, like BuilderInstalled).

Verification (honest)

  • All 7 touched files parse under rustfmt (edition 2024).
  • NOT yet compile-verified: the laptop is under heavy nix-build load (60-90) and this worktree has a cold target dir, so cargo check did not complete within the shift. CI on this PR is the compile/test gate; expect a fix-forward round if the compiler objects (most likely spots: the install_wasm_reserved callers under #[cfg(feature = "sandbox")] and any exhaustive JournalEntry handling in tests).
  • Rejected modules still leave no journal entry: the decision is computed only after the gate passes, and only admissions are installed.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

…ons (#1069)

- SourceBuildProvenance gains compiler_version (serde-defaulted for
  journal compat), populated in compile() from a roc version probe;
  a failed probe records an empty string instead of failing the
  compile.
- New journal-only JournalEntry::ModuleTrustDecision, patterned on
  BuilderInstalled: install_wasm_reserved computes the decision at
  the trust gate (server_compiled / no_trust_list /
  signature_verified + publisher key) and threads it through
  install_program_with_trust so the actor persists it alongside the
  ProgramInstalled event. Replay treats it as audit-only, and it
  requires no journal version bump (default arm).
@dezren39
dezren39 requested a review from a team as a code owner November 2, 2026 07:42
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 59 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b60bce89-b2c1-4bb8-826c-ce0b9b022f96
Commits

Reviewing files that changed from the base of the PR and between ddd0d42 and 32da50e.

Files selected for processing: 10
  • pkgs/id/src/world/actor.rs
  • pkgs/id/src/world/core.rs
  • pkgs/id/src/world/handle.rs
  • pkgs/id/src/world/mod.rs
  • pkgs/id/src/world/tests.rs
  • pkgs/id/src/world_compile.rs
  • pkgs/id/src/world_session/mod.rs
  • pkgs/id/src/world_store.rs
  • pkgs/id/tests/world_fork.rs
  • pkgs/id/tests/world_fork_cli.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-02T08:49:03.263467Z 32da50e Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b03f8216a

ℹ️ 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".

Comment thread pkgs/id/src/world_compile.rs Outdated
Comment on lines +252 to +254
let compiler_version = std::process::Command::new(&roc_bin)
.arg("version")
.output()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bound the version probe and run it off the async executor

If the configured compiler or its wrapper hangs while reporting its version, this synchronous output() blocks a Tokio worker indefinitely. The compilation deadline is only created later inside spawn_blocking, so neither the supplied timeout nor the empty-string fallback protects this new subprocess. This can leave a compile request permanently stuck and stall unrelated tasks sharing the worker. Run the probe off the executor with a bounded deadline and bounded captured output, treating a timeout as an unavailable version.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the follow-up commit on this PR. The version probe no longer runs as a synchronous output() on the async path: it now runs inside the compile job's existing spawn_blocking closure via probe_compiler_version, which spawns roc version as a child, drains its stdout through the same tail-bounded reader used for compiler stderr (64 KiB cap), polls try_wait against a 5 s deadline (VERSION_PROBE_TIMEOUT), and kills the child past the deadline. A timeout, spawn failure, or non-zero exit records the empty version, exactly as a failed probe did before — the artifact identity stays pinned by compiler_blake3. New unit tests: a fake compiler that reports a version (recorded), one that hangs (killed at a 200 ms test bound, records empty, returns promptly), and one that exits non-zero (records empty).

Comment thread pkgs/id/src/world/actor.rs Outdated
Comment on lines +1330 to +1335
if let Some(decision) = trust {
return self.persist(JournalEntry::ModuleTrustDecision {
module_hash: module_hash.clone(),
basis: decision.basis,
publisher: decision.publisher,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Persist the trust decision atomically with the install event

If this audit append fails after the preceding Committed append succeeds, an ordinary admin install now returns InstallError::Unavailable without replacing the running program, even though its ProgramInstalled event is already durable. On restart, journal replay activates that replacement despite the failed install response, and no complete trust decision accompanies it. Previously ordinary admin installs had no second fallible append between persisting the event and activation. Persist the install and its trust decision as one durable record or atomic batch so an audit-write failure cannot split live and restored state.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the follow-up commit on this PR. The trust decision is no longer a second journal append: it is now carried inside the ProgramInstalled event itself (WorldEventKind::ProgramInstalled.trust, #[serde(default, skip_serializing_if = "Option::is_none")], mirroring the existing provenance field), so the install and its trust decision are the single Committed record — one durable append, nothing to split. An audit-write failure is now impossible between persisting the event and activation because there is no second append. The separate JournalEntry::ModuleTrustDecision variant and its replay arm are removed; replay reads the decision from the install event. The decision is still journal-recorded with the module hash (on the event) and the verifying publisher key (in the decision), per code#1069's acceptance criteria.

Codex P2s on PR #4263:
- world_compile: the roc version probe ran as a synchronous output()
  on the async path, unbounded. It now runs inside the compile jobs
  spawn_blocking closure via probe_compiler_version: child polled
  against a 5s deadline and killed past it, stdout drained
  nonblocking into a tail-bounded buffer (no reader thread to join,
  so a grandchild holding the pipe cannot block it either). Timeout
  or failure records an empty version, as a failed probe did before.
- world install: the trust decision was a second journal append
  after the Committed install event, so an audit-write failure could
  split live and restored state. The decision is now carried inside
  ProgramInstalled itself (serde-default trust field, mirroring
  provenance), making install + decision one durable record; the
  separate ModuleTrustDecision journal entry is removed.

Tests: 3 new version-probe unit tests (reported version recorded,
hung compiler killed at bound, failing probe records empty);
world_compile+world_session 83 pass, world::tests+world_store 152
pass, world_fork 4 + world_fork_cli 6 pass, cargo check --all-targets
pass.
@dezren39

dezren39 commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

@codex review — follow-up commit 32da50e fixes both P2 findings from the 0b03f82 review (bounded off-executor version probe; trust decision carried inside the ProgramInstalled event as one durable record). Please re-review the new head.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 32da50e308

ℹ️ 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".

@dezren39
dezren39 merged commit bd0465e into main Nov 2, 2026
1 check passed
@dezren39
dezren39 deleted the queue/6097-1069-remainder branch November 2, 2026 10:57
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.

1 participant