Add Ed25519 out-of-domain approval signature mode (#24)#31
Merged
Conversation
Implements docs/approval_signing_design.md: - Opt-in signature mode (--approval-auth signature --approval-public-keys); broker holds public keys only, never signs - Broker recomputes proposal_hash from stored state; only nonce, key_id, signature_version accepted from caller, all covered by the signature - expires_at excluded from operator-signed payload, broker-set per policy post-verification - Missing keyring in signature mode: cannot_verify readiness, DENY at approval; no silent HMAC fallback - Algorithm mismatch vs keyring, replayed nonce, inactive/unknown key, unknown approver, expired window all DENY; nonce store persisted and pruned to approval validity horizon - Execution-time cryptographic re-verification of the stored signature (state-file-write defense, signature-mode equivalent of strict HMAC) - Full detached signature persisted in ApprovalRecord AND the vmga_proposal_approved evidence event for non-repudiation - vmga-approval-sign operator-side CLI signer (PEM Ed25519) - HMAC mode unchanged, documented as broker-forgeable advisory/dev - Domain separation via signature_version=vmga-approval-ed25519-v1 Implemented with Codex (gpt-5.5); evidence-event persistence gap fixed and full validation run in review. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Implements issue #24 per the design of record in
docs/approval_signing_design.md. Closes #24.What
Opt-in
--approval-auth signaturemode: the broker verifies detached Ed25519 operator approvals against a public-key-only keyring and never holds signing material. HMAC mode is unchanged and remains documented as broker-forgeable advisory/dev.Acceptance gates exercised (design doc §Acceptance Gates)
proposal_hashfrom stored state; onlyapproval_nonce,key_id,signature_versionare caller-supplied, each covered by the signature ✅proposal_id, proposal_hash, approver_id, time_window, approval_nonce, key_id, signature_version; canonical UTF-8 JSON, sorted keys, compact separators; payload with unexpected fields rejected ✅expires_atexcluded from signed payload; broker sets it per policy after verification ✅cannot_verify+ approvalDENY; no silent HMAC fallback ✅key_id→ deny ✅ (test:test_algorithm_mismatch_is_denied)ApprovalRecordand in thevmga_proposal_approvedevidence event (non-repudiable, independently re-verifiable) ✅vmga-approval-signoperator-side signer; private key never enters broker paths ✅signature_versionfor future Add tamper-evident evidence ledger and verification command #2 checkpoint reuse ✅Residuals (named)
Cannot detect: attacker controlling the approver private key, compromised operator signing device, operator intentionally signing a bad approval. Hard approval-enforcement claims require the private key outside both broker and agent authority domains; otherwise advisory.
Verification (local)
python scripts/vmga_release_check.py→VMGA release check: PASSpython -m pytest -q→116 passedpython -m compileall src tests scripts integrations→ passintegrations/openclaw:npm test→ 3 passed;npm run plugin:validate→Plugin plugin.vmga is valid.git diff --check→ cleanImplemented with Codex (gpt-5.5, low effort); maintainer review added the evidence-event signature persistence (gate gap) and its test.
🤖 Generated with Claude Code