Skip to content

Add Ed25519 out-of-domain approval signature mode (#24)#31

Merged
SSBrouhard merged 1 commit into
mainfrom
feat/24-approval-signatures
Jun 11, 2026
Merged

Add Ed25519 out-of-domain approval signature mode (#24)#31
SSBrouhard merged 1 commit into
mainfrom
feat/24-approval-signatures

Conversation

@SSBrouhard

Copy link
Copy Markdown
Owner

Implements issue #24 per the design of record in docs/approval_signing_design.md. Closes #24.

What

Opt-in --approval-auth signature mode: 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)

  • Broker recomputes proposal_hash from stored state; only approval_nonce, key_id, signature_version are caller-supplied, each covered by the signature ✅
  • Operator-signed payload is exactly 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_at excluded from signed payload; broker sets it per policy after verification ✅
  • Missing pubkey in signature mode → readiness cannot_verify + approval DENY; no silent HMAC fallback ✅
  • Algorithm mismatch vs keyring key_id → deny ✅ (test: test_algorithm_mismatch_is_denied)
  • Replayed nonce → deny; nonce state persisted (JSON + SQLite stores) and pruned to approval TTL + window grace ✅
  • Full detached signature persisted in ApprovalRecord and in the vmga_proposal_approved evidence event (non-repudiable, independently re-verifiable) ✅
  • Execution-time cryptographic re-verification of the stored signature — signature-mode equivalent of strict-mode HMAC re-verify against state-file-write attacks ✅
  • Key rotation: historical records verify under retained keys; removed key denies ✅
  • vmga-approval-sign operator-side signer; private key never enters broker paths ✅
  • Domain separation via signature_version for 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.pyVMGA release check: PASS
  • python -m pytest -q116 passed
  • python -m compileall src tests scripts integrations → pass
  • integrations/openclaw: npm test → 3 passed; npm run plugin:validatePlugin plugin.vmga is valid.
  • git diff --check → clean

Implemented with Codex (gpt-5.5, low effort); maintainer review added the evidence-event signature persistence (gate gap) and its test.

🤖 Generated with Claude Code

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>
@SSBrouhard SSBrouhard merged commit dbbfa9c into main Jun 11, 2026
5 checks passed
@SSBrouhard SSBrouhard deleted the feat/24-approval-signatures branch June 11, 2026 01:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Asymmetric out-of-domain approval signatures

1 participant