@clgplatform/verify
v1.5.0
Published
Standalone verifier for CLG signed decision receipts. Validates signatures and hash chains without contacting the CLG platform.
Downloads
119
Maintainers
Readme
@clgplatform/verify
Independent verifier for CLG signed receipts and receipt chains.
What it is
@clgplatform/verify is a verification layer for receipts emitted by CLG-integrated runtimes.
It validates receipt integrity and authenticity cryptographically.
What it verifies
- canonical hash matches content
- signature is valid
- required fields are present
- previous receipt hashes link correctly in chains
What it does not do
- does not intercept MCP tool calls
- does not enforce mandates
- does not create receipts
- does not replace runtime controls or governance processes
It can verify offline when you provide a local key or resolver.
The CLI defaults to HTTP key resolution unless you pass --public-key, --jwks, or --offline.
Library usage resolves keys according to the PEM string or resolver you pass to verifyReceipt or verifyChain.
Installation
npm install @clgplatform/verifyQuick start
import { verifyReceipt, fileResolver } from '@clgplatform/verify';
const result = await verifyReceipt(receipt, fileResolver('./signing-key.pem'));
console.log(result.valid);CLI usage
# single receipt
clg-verify receipt receipt.json
# chain
clg-verify chain receipts.json
# local key file
clg-verify --public-key signing-key.pem receipt receipt.json
# JWKS-style endpoint
clg-verify --jwks https://api.clgplatform.com/.well-known/clg-keys receipt receipt.json
# force no default HTTP key lookup (requires --public-key or --jwks)
clg-verify --offline --public-key signing-key.pem receipt receipt.json
# pretty JSON output
clg-verify --pretty --public-key signing-key.pem chain receipts.json
# stdin
cat receipt.json | clg-verify --public-key signing-key.pem receipt -Exit codes
| Code | Meaning | |---:|---| | 0 | Valid | | 1 | Invalid | | 2 | Error (network, file, parse) |
Library usage
Single receipt:
import { verifyReceipt, httpResolver } from '@clgplatform/verify';
const result = await verifyReceipt(receipt, httpResolver('https://api.clgplatform.com'));Receipt chain:
import { verifyChain, jwksResolver } from '@clgplatform/verify';
const result = await verifyChain(receipts, jwksResolver('https://api.clgplatform.com/.well-known/clg-keys'));JWKS Verification (v1.4.0+)
Verify receipts using the platform's RFC 7517 JWKS endpoint — no manual key exchange needed:
import { verifyReceiptWithJwks } from '@clgplatform/verify';
const result = await verifyReceiptWithJwks(receipt, {
baseUrl: 'https://clgplatform.com',
});
console.log(result.valid); // true if hash + signature check outThis fetches /.well-known/jwks.json, finds the key matching the receipt's
signing_key_id, converts JWK→PEM, and verifies. Existing verifyReceipt() is unchanged.
You can also use the lower-level functions directly:
import { fetchJwks, findKeyByKid, jwkToPem } from '@clgplatform/verify';
const jwks = await fetchJwks('https://clgplatform.com');
const jwk = findKeyByKid(jwks, receipt.signing_key_id);
const pem = jwkToPem(jwk);
// use pem with verifyReceipt or your own cryptoResolvers
httpResolver(baseUrl?)→ fetches{baseUrl}/v1/keys/{kid}jwksResolver(url?)→ fetches key set once and caches bykidstaticResolver(pem)→ always returns the same PEMfileResolver(path)→ reads PEM from local file
You can also pass a PEM string directly to verifyReceipt / verifyChain.
How verification works
- Select canonical content fields.
- Canonicalize the content.
- Hash canonical content.
- Compare computed hash with
receipt_hash. - Verify signature with signer public key.
- Verify
previous_receipt_hasheslinks for chains.
Use with @clgplatform/mcp
@clgplatform/mcpguards MCP tool execution and creates signed receipts.@clgplatform/verifyverifies those receipts afterward.
Status
Beta.
License
BUSL-1.1. See LICENSE.
