Start versioned quorum bundle dispatch #15
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/issue-11-versioned-bundle-dispatch"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements proofed V1 quorum generation and verified loading, plus WebAuthn-authorized recryption of Caution-held shares to an attested destination. Supports external-PGP, WebAuthn and mixed holders while preserving the existing holder-signed OpenPGP transport.
Implementation head: Locksmith
2da3be5; integrated by Platforme38a05b, whose shared models/client dependencies and default enclave daemon all select this Locksmith revision. Historical proof verification uses Bootproof821b5c6.threshold/max. It rejects duplicate holder identities and shared signing/encryption material between holders; equivalent encryption subkeys within one holder remain valid.Validation
Recorded local/synthetic evidence, not deployed-Nitro acceptance:
Remaining work and boundaries
Fresh review and merge remain required; the old change-request review is stale and is not treated as resolved by this description update. The broader roadmap still requires hosted Keymaker access control/network restrictions, production custody procedures, shared hash/profile contract finalization and dashboard creation. Rebuild the affected services and independently verify their PCR policies when deploying; a client upgrade alone does not update them. Existing bundles with shared encryption material are not repaired by stricter new-generation validation.
Legacy deployments must retain their original recovery artifacts and compatible tooling. A new quorum is a different key, not an automatic migration. Use the migration and acceptance runbook and record exact revisions/PCRs and issuance, threshold, negative and restart outcomes.
Related issues
Refs https://codeberg.org/caution/locksmith/issues/10, https://codeberg.org/caution/locksmith/issues/11 and https://codeberg.org/caution/locksmith/issues/12.
Service contract: https://codeberg.org/caution/platform/issues/383. Platform integration: https://codeberg.org/caution/platform/issues/384. Design: https://codeberg.org/caution/locksmith/issues/7.
Follow-up cleanup pushed in
91a33e7fa3ed457b867a3087407b93d915caa5df:Rechecked:
cargo test -p keymaker-models— passedcargo test -p locksmith bundle::tests::— passed, with existing warningscargo check --workspace --all-targets— passed, with existing warningsgit diff --check origin/main...HEAD— passedReview: Request changes
This patch introduces four P1 regressions:
Canonicalize labels before hashing bundles
crates/keymaker-models/src/lib.rs:77labelis aHashMap, so CBOR serialization order is nondeterministic. Keymaker and Locksmith may therefore hash the same logical bundle differently after a JSON round trip, causing nonce mismatches and failed necroproof verification.Please use a canonical map/CBOR representation and add a round-trip hashing test with multiple labels.
Validate durable proofs at their signing time
crates/locksmith/src/bundle.rs:170Verifying the Nitro certificate chain against the current wall clock makes persisted bundles unloadable once the attestation certificate expires.
Please validate certificate validity at the signed attestation timestamp while continuing to evaluate PCR-policy expiry against the current time.
Ship or provision the required PCR policy
crates/locksmith/src/bin/locksmithd.rs:5Startup now requires
/etc/caution/keymaker-pcr-policy.json, but the repository image neither includes nor mounts it.locksmithdtherefore panics before opening the shard listener.Please add the policy artifact to the image or explicitly provision/mount it in the deployment.
Replace or migrate the legacy bundled fixture
crates/locksmith/src/bin/locksmithd.rs:9Docker still packages
bundle-single.json, a flat V0 response with an empty necroproof. The new loader only accepts proofed, versioned bundles, so startup still fails even after supplying the PCR policy.Please package a valid proofed V1 bundle or provide a migration path for the legacy format.
Proposed plan
Summary
Implementation Changes
Canonical bundle hashing
GenerateQuorumBundletoserde_cbor::Valuebefore CBOR serialization;Valuemaps use canonical ordering.HashMapfields unchanged.Durable Nitro proof verification
Nitro::verify_at_attestation_time(nonce).timestampas milliseconds since Unix epoch from the COSE payload.verify(time, nonce)API.NecroproofVerifier::verify; retainnowon bundle-loading APIs exclusively for PCR-policy expiry.Docker artifacts
caution verify.threshold = max = 1.bundle-single.jsonwith that proofed V1 response.keymaker-pcr-policy.jsoncontaining the matching PCR0/1/2 set with no expiry.0644in-container, and remove the final-stage legacyADD.Public Interfaces and Compatibility
Nitro::verify_at_attestation_time.NecroproofVerifier::verifyno longer accepts a current-time argument.Test Plan
verify_at_attestation_time.HashMapinsertion orders produce identical hashes.nowset far beyond certificate expiry.cargo test --workspaceandcargo check --workspace --all-targets.locksmithdremains running/listening instead of panicking during startup.git diff --check.Assumptions
Follow-up pushed in
c0dae43:keymaker-modelsGenerateQuorumBundletype directly, with only a local extension trait for existing OpenPGP accessors.KeymakerPcrPolicymethods, renamed policy JSON fromallowedtosets, and validates PCR-set expiry at the signed necroproof timestamp.keyring.ascinto individual armored OpenPGP keys.Verification:
cargo test -p keymaker-models— passedcargo test -p locksmith bundle::tests::— passed, with existing warningscargo check -p keymaker --all-targets— passed, with existing warningcargo check -p keymaker-client --examples— passedcargo check -p locksmith --all-targets— passed, with existing warningsgit diff --check— passedNote: I left the
GenerateNecroprooferror conversion in explicitmap_errform because this dependency currently returnsBox<dyn Error + Send + Sync>anddterror::ResultExt::with_contextsis not available for that concrete error type in this workspace.Addressed the latest review comments in
0339414.Summary:
QuorumBundleExt/accessor trait and the legacyopenpgp_keyring()helper path..to_latest()and match directly on the V1Vec<Key>entries; OpenPGP certs are handled at the use site and WebAuthn remains an explicitunimplemented!()path for now.cosetdependency. PCR policy expiry is now checked against the timestamp read from the Nitro payload returned by a successfulattestation.verify(...).AGENTS.mdguidance so future agent runs avoid the same mistakes around Codeberg inline comments, local bundle wrapper/accessor traits, direct COSE decoding, and formatter pitfalls.Verification:
rustfmt --edition 2024 crates/locksmith/src/bundle.rs crates/locksmith/src/client.rs crates/locksmith/src/server.rscargo test -p keymaker-modelscargo test -p locksmith bundle::tests:: --no-fail-fastcargo check -p keymaker --all-targetscargo check -p keymaker-client --examplescargo check -p locksmith --all-targetsgit diff --checkThe existing warnings are unchanged/pre-existing (
minipgp6cfg, unusednow, keymaker reboot unreachable-code warning, andget_shards_test_util). Whole-workspacecargo fmtis still not used because the existingminipgp6.rsmodule-resolution issue blocks it; targeted rustfmt was used on touched Rust files.Latest follow-up is already on the PR branch at
e1a3aa8.Summary:
AGENTS.md; the PR file list now contains noAGENTS.md.AGENTS.mdignored so local agent guidance is not committed again.Rechecked now:
cargo test -p keymaker-models— passedcargo test -p locksmith bundle::tests:: --no-fail-fast— passed, with existing warningscargo check -p locksmith --all-targets— passed, with existing warningsgit diff --check origin/main...HEAD— passedPR state verified: mergeable; remote file list has no
AGENTS.md.Pushed follow-up
707bcdcto the existing PR branch.Summary:
LOCKSMITHD_UNSAFE_TEST_SECRET_HEXfor deterministic local keyforkd startup.CAUTION_UNSAFE_KEY_SERVICE_E2Efake necroproof/deterministic entropy behavior for local service e2e only.Verification run locally:
cargo test -p public-cert-service -p keymaker -- --nocapture— passed; public-cert-service 12 passed, keymaker test binary passed.Note: production still needs real deployment/supervision and Nitro/bootproof proofing; these hooks are deliberately named unsafe and are not default-enabled.
Summary:
Verification:
Remaining:
Outstanding review and production-release gates
Reviewed current head:
dc7409d2d853221185cd5a085f4d1880fcf53348, against7b411721068944fcae89acb3ed2b8c692689383f. Platform #391 currently consumesaccc9d36c3c47fc1ea2802f46266f508a19f02d0; the scan distinguished that integration pin from this newer head.No new High/Critical vulnerability or new code-level security merge blocker was confirmed by the Kimi source review and independent validation. That is not production approval. The remaining gates need to be kept distinct:
Review clearance
Codeberg still records an undismissed
REQUEST_CHANGESreview fromryansquaredagainst the much older91a33e7fa3ed457b867a3087407b93d915caa5df(review ID1605224). Please obtain a fresh maintainer disposition for the current head. This is not a claim that the original requested changes remain unfixed, nor a claim that Codeberg mechanically prevents merging; the PR body already correctly identifies the old review as stale.Production-release gates, not newly introduced regressions
keyfork-frame 0.1.1asynchronous decoder (src/asyncext.rs:20–24) allocates a peer-specified frame length before reading its contents. Locksmith reaches that decoder before holder authentication at server.rs:178–181; the reviewed receive path lacks a frame-size cap and read deadline. This is an inherited, deployment-dependent availability risk, not a demonstrated production incident. Cap size before allocation, bound concurrent receivers and add read deadlines; validate under constrained memory. Do not interpret allocation size as guaranteed immediate physical-memory consumption.Existing bundles also retain their embedded holder credential snapshots: deleting a platform credential is not revocation of its authority in previously issued bundles. Keep that documented lifecycle limitation explicit rather than presenting deletion/reset as a completed revocation mechanism.
Evidence boundary: source-only review; no tests, builds, service probes or deployments were run. The unauthenticated X25519-crash candidate was rejected because holder-signature verification precedes the assertion; it is not a blocker. These comments do not resolve prior review state or claim that production-release gates have been satisfied.
Deployment inputs remain on deploy/key-service and deploy/keymaker.