Conversation
noahgift
added a commit
that referenced
this pull request
Apr 24, 2026
…nic (Refs #118) RUSTSEC-2026-0104 was published 2026-04-23 — reachable panic in rustls-webpki 0.103.12's CRL parsing. Transitive via rustls → rustls-native-certs; upstream fix in rustls-webpki 0.104 but rustls hasn't bumped yet. aprender's `.cargo/audit.toml` already ignores this (observed in aprender CI audit-cmd `--ignore` list 2026-04-24). Syncing forjar's deny.toml to match so forjar CI (`cargo deny check`) doesn't block on the same class across repos. This unblocks the audit gate for #119 (integrity atomic-write fix). Fleet follow-up: paiml/infra clean-room template needs the same exemption — filed separately. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two related defects in state integrity handling.
DEFECT 1 — src/core/state/mod.rs:57,108 — silent sidecar error
let _ = integrity::write_b3_sidecar(&path);
After atomic rename of state.lock.yaml, the sidecar's Result was discarded.
Any failure (disk full, permission, signal, reaper race) left lock.yaml
(new) + .b3 (stale); next apply hard-failed with "integrity check failed".
Toyota Way violation: no signal at moment of corruption.
Fix: propagate with `?`; message points user at `forjar reseal`.
DEFECT 2 — no recovery for pre-existing drift
Users with drift from OLD forjar versions or git checkout had no recovery
short of `forjar apply --yes`. Adds `reseal` subcommand that rewrites
sidecars from current lock contents without converging infrastructure:
forjar reseal --all # reseal every state/*/lock.yaml
forjar reseal --file <path>
forjar reseal --machine <name>
forjar reseal --all --dry-run
Safety: each target YAML-parsed before sidecar rewrite — corrupt lock
cannot be blessed with a fresh sidecar.
FILES
- src/core/state/mod.rs — `?` propagation in save_lock + save_global_lock.
- src/cli/reseal.rs (NEW, TDG 97.5 A-) — cmd_reseal + 3 small helpers.
- src/cli/{mod,dispatch_misc}.rs + src/cli/commands/{mod,state_args}.rs —
Commands::Reseal wiring.
TEST
Smoke-tested against paiml/infra with 13/24 lock files mismatched. Apply
correctly rejected; `reseal --all` resealed 23 files 0 failures; next
apply passed the integrity gate.
Closes #118.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…nic (Refs #118) RUSTSEC-2026-0104 was published 2026-04-23 — reachable panic in rustls-webpki 0.103.12's CRL parsing. Transitive via rustls → rustls-native-certs; upstream fix in rustls-webpki 0.104 but rustls hasn't bumped yet. aprender's `.cargo/audit.toml` already ignores this (observed in aprender CI audit-cmd `--ignore` list 2026-04-24). Syncing forjar's deny.toml to match so forjar CI (`cargo deny check`) doesn't block on the same class across repos. This unblocks the audit gate for #119 (integrity atomic-write fix). Fleet follow-up: paiml/infra clean-room template needs the same exemption — filed separately. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bf2da13 to
bbc014e
Compare
`cargo deny check` and `cargo audit` are distinct tools reading distinct config sources. `cargo deny` reads `deny.toml` [advisories.ignore]. `cargo audit` 0.22 does NOT read config files — only CLI --ignore flags. forjar's audit.yml ran `cargo audit` bare. After RUSTSEC-2026-0097 (rustls-webpki) and RUSTSEC-2026-0104 (rustls-webpki CRL panic) published against rustls-webpki 0.103.12 (both already exempted in deny.toml), `cargo audit` correctly exited non-zero — the exemptions never reached it. CI green on deny, red on audit, despite the same advisory IDs being on the ignore list. Fix mirrors the aprender sovereign-ci.yml pattern: - New `.cargo/audit.toml` with the cargo-audit-native schema `[advisories] ignore = [...]`. Single source of truth for cargo-audit, kept in sync with deny.toml by convention (documented in file header). - audit.yml parses `.cargo/audit.toml` for RUSTSEC IDs at run time and builds `--ignore <id>` CLI flags, matching how paiml/.github#32 solved the same class upstream. Covers both -0097 and -0104 (same rustls-webpki transitive class, no safe upgrade before upstream 0.104).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #118. Two related defects in state integrity handling.
Defect 1 — silent sidecar-write error
src/core/state/mod.rs:57,108:After
save_lockatomically renamedstate.lock.yaml.tmp → state.lock.yaml, the sidecar'sResultwas discarded. If the sidecar write failed (disk full, fs hiccup, permission, signal, race with reaper), the apply reported success, but on-disk state waslock.yaml(new) +.b3(stale or missing). Next apply hard-failed:Toyota Way violation: defect propagated silently across time — no signal at the moment of corruption.
Fix: propagate with
?; error message points users to the newforjar resealsubcommand.Defect 2 — no recovery path for pre-existing drift
Users with drift from OLD forjar versions (or from
git checkout/merge that restoredlock.yamlwithout.b3) had no recovery short offorjar apply --yes. Adds aresealsubcommand that rewrites sidecars from current lock contents WITHOUT converging infrastructure:Safety: each target is YAML-parsed before its sidecar is rewritten. A malformed lock file is rejected (
"<path> is not valid YAML") soresealcannot bless a corrupt file and have next-apply silently trust garbage.Files
src/core/state/mod.rs—?propagation insave_lock+save_global_locksrc/cli/reseal.rs(NEW, TDG 97.5/100 A-) — 4 small fnssrc/cli/mod.rs— registermod resealsrc/cli/commands/{mod,state_args}.rs—Commands::Reseal(ResealArgs)src/cli/dispatch_misc.rs— dispatch toreseal::cmd_resealTest
Smoke-tested against real drift on
paiml/infrastate dir: 13/24 lock files mismatched →applycorrectly rejected.reseal --allresealed 23 files with 0 failures; next apply proceeded past the integrity gate. End-to-end fix confirmed on live state.TDG:
src/cli/infra.rsunchanged (89.1/100 A- baseline). Newsrc/cli/reseal.rs97.5/100 A-.Related
forjar applythe companion fixpaiml/infra#78.🤖 Generated with Claude Code