acpmux vault: refuse clearly on an older daemon, bound output reads by the deadline, status reports the daemon's store

Merged
TE
3d ago
+167-51

Fixes #34178, the follow-ups from the review of #33638 (receipt).

  1. Older daemon, no usable OS store. machine vault pull|forget used to reconnect to the same old daemon and fail again with method-not-found. A running daemon that answers method-not-found is no longer asked a second time. When this machine has no usable OS store, the command now refuses with vault.daemon_outdated: "the running acpmux daemon is older than this CLI ...; run acpmux daemon restart, then pull again". It does not restart the daemon on its own, since a vault pull should not take down the person's sessions. With a usable OS store, the pull still runs in the CLI as before.
  2. Output reads are bounded by the deadline. capture_until used to join the reader with no time limit after the command exited. The reader now hands its output back through a channel, and the CLI waits for it only until the deadline. A descendant that keeps stdout open (sh -c 'sleep 20 & exit 0') now ends as vault.secret_store_timeout at the deadline. Tests cover that case and a normal exit that returns its whole output.
  3. status reports the daemon's store. A new local-only _acpmux/vault_status returns {store} from the daemon's own selection. machine vault status reads it from the daemon, and falls back to the CLI's own probe only when no daemon is running or the daemon is too old to answer. The protocol IR and the generated web methods are updated, and the method is listed under machine.vault.pull.v1.

Panic ratchet. The ratchet job on #33638 (run 41682517900) was already red on base: acpmux indexing_slicing was 714 > 686 on #34058's run, plus non-deny counts across many crates this code doesn't touch. #33638 added 1 indexing hit and 9 arithmetic hits on top of that. This PR removes every ratchet hit in the vault code: it replaces Value indexing in cli/host_vault.rs with .get(), and uses saturating or checked arithmetic in vault/wire.rs, vault/store.rs and vault.rs. The base's other hits are not ours and are left alone.

Checks (fleet cmux-ci, job 5fbfeade7bc49191ce418e35):

  • cargo test -p acpmux --lib vault, protocol_ir, capability and host_vault tests: 55 passed.
  • cargo clippy -p acpmux --lib --bins --tests: clean in the touched files.
  • The ratchet's lint set over vault* and cli/host_vault.rs: no hits.
  • tests/test_send_path_caps.py: OK.

No value is printed, logged or put in argv.

Agent session: agent session

🤖 Generated with Claude Code


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


Summary by cubic

Fixes the follow-ups from the vault pull review (#33638): pulling and forgetting against an older daemon no longer retries and fails twice, output reads from store commands are bounded by the command deadline, and machine vault status reports the store the running daemon uses.

Changes

  • A running daemon answering method-not-found is not asked again; without a usable OS store the command refuses with vault.daemon_outdated and tells you to run acpmux daemon restart.
  • capture_until hands output back through a channel and waits only until the deadline, so a descendant keeping stdout open ends as vault.secret_store_timeout.
  • New local-only _acpmux/vault_status returns {store} from the daemon's own selection, with fallback to the CLI's own probe when no daemon runs or it is too old; protocol IR and generated web methods are updated.
  • Replaces Value indexing with .get() and uses saturating or checked arithmetic in vault code, clearing this PR's panic-ratchet hits.