[AVAILABLE] for the core primitives below. [ROADMAP] for KMS/HSM key
custody, clearly separated.
Signature algorithms
Evidence:
packages/crypto/test/SignatureProvider.test.ts,
Dilithium3SignatureProvider.test.ts, dilithium3-cross-instance.test.ts.
Hash algorithms
HashAlgorithms: sha256, sha3-512, blake3 (packages/shared/src/config/CryptoAlgorithms.ts).
Configured via HASH_PROVIDER. Used for trustRecordHash, businessTransactionHash
(via ExecutableContentHasher → TrustRecordHasher, the same computation on signing and
verifying sides), and receipt hashing.
Key/algorithm binding guard
Signing or verifying with the wrong key type for the configured provider (e.g. an Ed25519 key against an ML-DSA-65 provider) fails closed with an error naming both the expected and actual key type, it does not silently dispatch based on the key’s own type (assertKeyType, used by both signature providers).
Key custody today: local PEM files
FileKeyProvider reads <PARMANA_KEY_DIR>/<keyId>.private.pem /
<PARMANA_KEY_DIR>/<keyId>.public.pem from disk, one directory, keys distinguished by ID
(default, pq, gateway), not by separate per-file path variables. This is the only
implemented key provider. See Deploy patterns for the full set of
keys a running server needs.
Per-tenant signing keys (opt-in)
A transaction whosemetadata.tenantId is set signs its Execution Authorization under a
dedicated tenant.<tenantId> key when one has been provisioned (same FileKeyProvider
layout: scripts/generate-keypair.ts --algorithm ed25519 --key-id tenant.<tenantId>),
instead of the single shared default key every deployment uses otherwise
(TenantKeyResolver, packages/runtime/src/TenantKeyResolver.ts). Verification already
resolves the right public key per-authorization via its own keyId field (the key/algorithm
binding guard above, and 2.28’s keyProvider/keyExpiryStore options), so a tenant key just
needs to exist — no verifier-side configuration change.
This is naming-convention key selection, not KMS/HSM custody: the tenant’s
private key still lives as a local PEM file, provisioned by hand, one
generate-keypair run per tenant. An unprovisioned or malformed tenantId
falls back to the shared default key rather than failing closed, deliberate,
so adoption is incremental, but worth knowing before relying on it for
isolation.There is a live incident on record: the default signing key committed to this
repository before 2026-07-05 was publicly exposed and is permanently
compromised. It was rotated on 2026-07-05. This is exactly the kind of
exposure KMS/HSM custody is designed to prevent, see Roadmap, Move
1.
Key rotation, same algorithm
Distinct from the algorithm-migration gap below: rotating to a new key pair under the same algorithm, because a key may be compromised, or on a routine schedule, is built and tested for every durable evidence signer (Trust Records, Refusal Records, Audit Events), mirroring the pattern the Authorization/Gateway envelope already had viakeyProvider/keyExpiryStore. PARMANA_VERIFICATION_KEY_ID /
PARMANA_VERIFICATION_SECONDARY_KEY_ID point new signing at a freshly generated keyId
(scripts/rotate-verification-key.ts); every already-issued record keeps verifying
unaffected, since verification always resolves the public key by the record’s own stored
keyId, never a hardcoded “current” one. FileKeyProvider.listKeys() enumerates every
key a deployment currently holds, and GET /keys/:keyId / GET /.well-known/jwks.json
make them fetchable by a third party.
No algorithm migration path yet
AuthorizationVerifier does not dispatch verification based on the envelope’s algorithm
field, a verifying process supports exactly one configured PRIMARY_SIGNATURE_PROVIDER at a
time. Re-keying from Ed25519 to ML-DSA-65 while retaining the ability to verify
previously-signed records is an explicit Future Claim, not yet built. The
key rotation above is same-algorithm only (a new Ed25519 key replacing an old Ed25519 key,
for example) — it does not close this gap, which is specifically about changing which
algorithm a verifying process trusts while old records under the previous algorithm
remain verifiable.