Skip to content

Implement legacy receipt verification & improve config/health surface#59

Merged
GsCommand merged 1 commit into
mainfrom
claude/audit-commandlayer-protocol-O05aO
May 14, 2026
Merged

Implement legacy receipt verification & improve config/health surface#59
GsCommand merged 1 commit into
mainfrom
claude/audit-commandlayer-protocol-O05aO

Conversation

@GsCommand
Copy link
Copy Markdown
Contributor

Summary

This PR restores legacy receipt verification helpers for backward-compatibility test coverage, improves the health endpoint surface, refactors error handling in handleVerb, and updates configuration documentation to reflect current practices.

Key Changes

Layer 3 (Execution Runtime) — receipt-verification.js

  • Restored resolveSigner(), resolveSignatureKey(), and verifyReceipt() as legacy helpers for test_vectors schema
  • These implement the older per-field ENS delegation model used by test fixtures but are NOT on the production hot path
  • All production signing/verification remains delegated to @commandlayer/runtime-core (Layer 2)
  • Added internal helpers: decodeBase64() and ed25519RawToSpkiPem() for ed25519 key handling

Layer 3 (Execution Runtime) — server.mjs

  • Health endpoint: Added verifier_ok field to /health response (true when public key or ETH_RPC_URL is configured)
  • Error handling: Moved execution computation outside try/catch in handleVerb() so error path can reuse it without re-parsing consumed request body
  • doClean verb: Fixed field name from cleanedcleaned_content and added fallback paths for body.content and body.input.content
  • doSummarize verb: Added fallback for body.content input path
  • Validator warm queue: Declared before handleVerb() to avoid temporal dead zone
  • Removed dead code: Eliminated unused const text = await resp.text() in doFetch()
  • Minor cleanup: Removed extra blank lines, fixed console.log format (removed http:// prefix)

Configuration & Documentation

  • .env.example: Updated to reflect current key naming (RECEIPT_SIGNER_ID as canonical) and encoding (RECEIPT_SIGNING_PRIVATE_KEY_PEM_B64 for base64-encoded PKCS8)
  • CONFIGURATION.md: Documented rate limiting section with RATE_LIMIT_WINDOW_MS and RATE_LIMIT_MAX defaults; moved these from "deprecated" to "active" section
  • SECURITY.md: Clarified rate limiting is always active; documented /health and /healthz exclusions; noted RATE_LIMIT_ENABLED is not a live toggle
  • scripts/smoke.mjs: Updated health check to allow verifier_ok to be absent (only fail if explicitly false)

Implementation Details

  • Legacy verification helpers use Node's crypto.createVerify() with ed25519 algorithm and SPKI PEM format
  • ENS resolution is async and returns structured error objects with { valid: false, error: string } for all failure paths
  • Error handling refactor in handleVerb() ensures the error catch block has access to execution without re-parsing the request body (which may have been consumed by the try block)
  • Health endpoint now accurately reflects whether verification infrastructure is available, supporting both local key and remote ENS-backed verification modes

Contract Impact

  • No protocol schema changes; all receipt shapes remain unchanged
  • Health endpoint gains optional verifier_ok field (backward compatible; clients can ignore)
  • Legacy verification is test-only; production verification remains in runtime-core

https://claude.ai/code/session_01GQcff5HnFcrTbyuwuvsNEv

- runtime/src/receipt-verification.js: implement missing exports (resolveSigner,
  resolveSignatureKey, verifyReceipt) used by four test files; stub-only file
  caused all legacy compatibility tests to throw TypeError at import
- server.mjs: rename doClean return key from `cleaned` to `cleaned_content` to
  match test assertions in runtime-signing.test.mjs
- server.mjs: remove dead variable `text` in doFetch error branch
- server.mjs: hoist warmQueue/warmRunning declarations before handleVerb to
  eliminate temporal dead zone risk
- server.mjs: lift `execution` declaration out of try block in handleVerb so
  catch block can reuse it without re-computing it
- server.mjs: add verifier_ok field to /health response so scripts/smoke.mjs
  CI check does not abort on missing field
- scripts/smoke.mjs: guard verifier_ok check correctly (field is now present)
- SECURITY.md: remove false claim that RATE_LIMIT_MAX/RATE_LIMIT_WINDOW_MS are
  not implemented; they are actively read by server.mjs and passed to
  createRateLimiter
- docs/CONFIGURATION.md: move RATE_LIMIT_MAX and RATE_LIMIT_WINDOW_MS out of
  the "not implemented" list and into a dedicated rate-limiting section
- .env.example: align signer ID variable to canonical name RECEIPT_SIGNER_ID
  (was CL_RECEIPT_SIGNER_ID which is only an alias)
@GsCommand GsCommand merged commit 7da3dcc into main May 14, 2026
1 check failed
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.

1 participant