Skip to content

fix(audit): resolve checkpoint and MCP stores consistently - #636

Merged
vladimirrott merged 9 commits into
lacs-project:mainfrom
dannyward630:fix/audit-store-resolver
Oct 27, 2026
Merged

vladimirrott merged 9 commits into
lacs-project:mainfrom
dannyward630:fix/audit-store-resolver

Conversation

@dannyward630

@dannyward630 dannyward630 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Routes audit verification, export, checkpointing, MCP doctor, and MCP verification through the shared audit-store resolver. On packaged installs, readers select the system daemon store when no explicit or per-user store exists. MCP verification includes audit_store_note with the reason and selected path when this fallback is used. Checkpoint errors explain when EACCES hides the root-owned system store and tell the operator to run under sudo.

Related Issues

Fixes #557, fixes #479.

Validation

  • cargo fmt --all --check and git diff --check passed.
  • cargo test -p sysknife-cli --bin sysknife --locked: 317 passed, including the source guard that rejects audit callsites bypassing the shared resolver.
  • cargo test -p sysknife-core --locked: 102 passed plus 1 doctest.
  • Focused CLI checkpoint integration test passed (1 test).
  • Focused MCP audit-verification integration test passed (1 test).
  • bash scripts/check_repo_completeness.sh passed.
  • The current evidence baseline is 2,014 Rust tests (2,011 on current main plus three tests added here). The published rounded figures remain 2,000+.
  • scripts/check_test_reachability.sh could not run because PyYAML/yamllint is not installed in this environment. scripts/render_figures.py --write is blocked locally because macOS /bin/bash 3.2 cannot run the metadata script's associative arrays; no rounded figure changed.
  • A prior full CLI-suite run on this Mac failed the upstream remote-distro fallback test when local distro detection returned None. The focused tests and CLI unit suite pass; CI on this updated head is pending.

No live audit store was accessed. No privilege or trust boundary changed; the daemon remains the only privileged executor.

AI assistance: Codex assisted with implementation and tests.

@dannyward630
dannyward630 marked this pull request as ready for review October 26, 2026 15:07

@vladimirrott vladimirrott left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, Danny. The fix is right: checkpoint, sysknife_audit_verify and the doctor chain check now resolve the store through resolve_audit_store(), the same resolver audit verify uses, and I found no default_database_path() caller left in apps/ outside the resolver. The choose_audit_store_with_paths seam is a good shape.

Two things before I merge.

1. The new tests pass with the call sites reverted. Every new test sets SYSKNIFE_DATABASE_PATH, and default_database_path() returns that variable first (crates/sysknife-core/src/lib.rs:44). Old and new code therefore read the same file in those tests. Put default_database_path() back at runner.rs:1383 or mcp_server.rs:1395 and nothing goes red. the_report_carries_the_which_machine_caveat pins audit_store_details, but it injects the store, so it never passes through the wrapper either. The bug in #557 lives in those call sites, so they need a test that fails when one goes back to the per-user path. The cheapest version that holds: a test that reads runner.rs and mcp_server.rs and fails if default_database_path( appears in an audit path outside the resolver. A seam on the system path (a resolve_audit_store_from(...) the wrappers call, driven by a test) is stronger if you'd rather.

2. checkpoint loses the sudo hint on a packaged install. As a non-root operator against the 0700 /var/lib/sysknife, path_is_present counts the EACCES as present, so checkpoint now picks the system store, then require_exists (runner.rs:2611, a plain Path::exists()) reports audit key not found at /var/lib/sysknife/.... audit verify gives the same person "the system daemon's store is root-owned, so run this under sudo" (runner.rs:1187). Reusing that hint in checkpoint would close it.

Small one: "Fixes #557 and #479" only links #557, since GitHub needs the keyword in front of each number. Fixes #557, fixes #479 closes both.

I'll write the CHANGELOG line at merge.

@dannyward630

Copy link
Copy Markdown
Contributor Author

The parity test and docs are pushed, and the workspace baseline now matches the suite. All required checks passed on 9b17eac; the manual container-smoke job was skipped by its workflow conditions. The PR is ready for maintainer review.

@vladimirrott vladimirrott left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Both items are done, and done the way I'd have asked for them. Approving at 00841e5b.

The wiring is pinned now. cli_and_mcp_audit_readers_do_not_bypass_the_shared_store_resolver reads runner.rs and mcp_server.rs and fails if either calls the per-user resolver. I proved it in a no-network container: the test passes as written, and with let resolved_store = sysknife_core::resolve_audit_store(); swapped back to AuditStoreChoice::PerUser(sysknife_core::default_database_path()), the same test FAILED. Checkpoint also gives the same sudo guidance as audit verify now, so a non-root operator on a packaged install gets told what to do instead of "audit key not found".

One small note for later, not for this PR: the scan matches the qualified sysknife_core::default_database_path(, so a future use sysknife_core::default_database_path; followed by a bare call would slip past it. Matching the bare name, or listing the import too, would close that.

The board is green, the baseline of 2,014 matches the suite, and the PR body now closes both #557 and #479. Merging through the gate.

@vladimirrott
vladimirrott merged commit c098c15 into lacs-project:main Oct 27, 2026
13 checks passed
vladimirrott added a commit to anyingiit/sysknife that referenced this pull request Oct 27, 2026
Main reached 2,014 with lacs-project#636; this branch adds six, so the baseline is 2,020.
vladimirrott added a commit that referenced this pull request Oct 27, 2026
Minor release. #627 keys request_hash with an HMAC under the audit key
(chain_version 4; previews stored by an older release fail closed after
upgrading) and #639 changes the history request a newer CLI sends, so a
caller relying on the old behaviour notices: the middle digit moves.

Also: the planner sees only its host's distribution (#626, #656, #658,
#684), checkpoint and the MCP audit tools share the audit-store resolver
(#636), every workflow job has a time limit (#662), a weekly cargo audit
(#640), release hardening (#635, #637, #660), and every published figure
is rendered from its source (#685).


Claude-Session: https://claude.ai/code/session_01UpyrhbDTW1gBwzGAC44GYU

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants