This page is a direct mirror of
docs/CLAIMS.md sections 3 and 5, read that
file for the authoritative version.Claims that hold, with their scope
Non-bypassable envelope verification (Conditional Claim 3.1). For any system running@parmana/envelope-verifier, execution requests not authorized by Parmana are
cryptographically impossible to accept, only for a receiving system that (a) runs the
verifier and (b) gates every execution-triggering code path behind its result. Parmana
enforces nothing at the network level. The default local server does both (a) and (b) for
each connector it registers, see The gateway for the mechanism and
its one real remaining caveat: a new connector isn’t reachable without a bootstrap code
change.
Fleet-wide single-use requires a shared NonceStore (3.2). Single-use enforcement is
scoped to whichever NonceStore instance performs the check. Independent instances each
using their own store can each accept the same authorization once. MemoryNonceStore
loses all state on restart. Every envelope’s bounded TTL limits, but does not eliminate,
the exposure window from either gap.
Durable, third-party-verifiable refusal and audit records (RFC-0021, 3.11). Every
policy rejection produces a signed Refusal Record, independently verifiable at POST /refusal/verify with no API key or database lookup required, just the artifact and
Parmana’s public key. Production caller-authentication audit events
are signed the same way, verifiable at POST /audit/verify. Two scope caveats: Refusal
Record writing is evidentiary and fails open by design (a rejection is never blocked or
delayed by it; only the durable record can go silently missing, never the correctness of
the rejection itself), and only production (Supabase) audit sinks sign — the in-memory
test sinks don’t.
Hybrid (Ed25519 + ML-DSA-65) signing capability, not yet deployed (3.13). Trust
Records and Receipts can be dual-signed with both a classical and a post-quantum
algorithm at once, with verification requiring both signatures independently, fail-closed.
This is a built, tested capability — CRYPTO_MODE=hybrid is real, validated
configuration — but it is opt-in and not running anywhere today: every deployed
environment signs Ed25519 alone.
Caveat: @parmana/sign, the public verification SDK, does not yet recognize the
hybrid envelope shape; a third party verifying a hybrid-signed record through it today
checks the legacy Ed25519 signature only — a genuine but partial verification, not the
full hybrid guarantee. This repository’s own packages/crypto/src/OfflineVerifier.ts
(TypeScript) and python/parmana/crypto/offline_verifier.py (Python, Ed25519 only)
do recognize the hybrid envelope and check both signatures independently, offline,
with zero network access — use these for a full hybrid check today, not @parmana/sign,
until that separate, external package is updated.
Hybrid-signature downgrade resistance, opt-in. A genuinely hybrid-signed record’s
signatures array (the ML-DSA-65 half) can be stripped entirely with no cryptographic
trace: schemaVersion and signatures are outside the hashed content by design (so the
legacy Ed25519 signature keeps verifying pre-hybrid-era records unchanged), and
verification silently falls back to the classical signature alone whenever the array is
absent. An opt-in HYBRID_SIGNATURE_REQUIRED flag closes this: when set, a record missing
its signatures array is rejected outright, no fallback. Off by default, so this protects
only a deployment that turns it on once every record it issues going forward is genuinely
hybrid-signed.
Claims Parmana intentionally does not make
Not “not yet” items, no implementation could honestly back these, unscoped:- Execution is impossible to bypass under all circumstances.
- Mathematical proof of execution correctness.
- Cryptographic proof of every aspect of runtime behavior.
- Guaranteed regulatory compliance.
- Absolute prevention of all unauthorized execution.
- Tamper-proof operation in every deployment environment.
- “Non-bypassable” or “the single execution authority” as an unscoped, system-wide claim, envelope verification is opt-in per receiving endpoint (see 3.1 above).
- Deterministic signature output for ML-DSA-65, those signatures are randomized by design; only verification is deterministic.
Known incidents
Policy-evaluation signals were not bound to the executed Intent (2026-07-28, RESOLVED). The most severe gap found in this project’s history: a live, reproducible bypass of the core “no unauthorized execution” invariant.PolicyEngine evaluated whatever signals a caller
declared in the request body; ExecutionGateway signed and executed intent.target/
intent.parameters, a completely disjoint set of fields nothing cross-checked. A caller
could declare signals describing a small, fully-verified action while intent executed
something else entirely, and still receive a signed, APPROVED Execution Trust Record for
it. Live proof-of-concept: signals declared a fully verified, policy-approved 999,999,999. Before the fix: 200, policy decision
APPROVED, execution COMPLETED, a real signed trust record and receipt issued for it, the
exact artifacts this project’s independently-verifiable-execution claim rests on, attesting
to something that never happened as described. A related, compounding finding:
authority.principalId (who the trust record says approved the action) was likewise
caller-declared with no binding to the identity callerId actually proves, any caller
holding any valid API key could claim to be any human or role, including a successful
“impersonate the CEO” proof-of-concept. Found via an external adversarial security exercise,
not this project’s own internal audit process.
Fixed by Policy.boundSignals + SignalIntentBinder (binds specific signal keys to intent
dot-paths, checked before PolicyEngine.evaluate; see Policies and the
decision for the mechanism), isPrincipalAllowed
(binds authority.principalId to the authenticated callerId), and a compounding IDOR fix,
isOwnedByCaller (any caller could previously read any other caller’s complete
transaction/trust-record/receipt history). 28 regression tests reproduce the exact live
exploit shapes and assert they’re now rejected, plus positive controls proving legitimate
requests are unaffected. One thing this fix deliberately does not cover, stated plainly
rather than left implicit: boundSignals only binds the specific fields a policy author
declares, it does not independently verify that an unbound signal (vendorVerified,
riskScore, and similar) is actually true; those remain caller-declared attestations.
The default signing key committed to this repository before 2026-07-05 was publicly
exposed in the public GitHub repository and must be treated as permanently compromised,
all signatures produced by that key are void for authenticity purposes regardless of when
signed. The key pair was rotated on 2026-07-05.
Four ML-DSA-65 (Dilithium3) private signing keys committed to a feature branch during the
post-quantum signature provider work were confirmed, by raw key-byte comparison, to be
distinct from any key ever trusted by production or local configuration. Unlike the incident
above, no signature produced by this key pair was ever accepted as authentic by this
codebase. A fresh keypair was generated regardless, the feature branch’s history purged, and
the exposure independently verified across every remote hosting this repository’s history.
Caller authentication, principal binding, and ownership scoping: three separate layers
packages/api gates every route except GET /health behind a caller bearer key, see
Authentication. Three distinct claims, not one, and it
matters which one you’re relying on:
- Route access is not scoped. Any authenticated caller can call any route, there is no per-key allowlist of which endpoints a given credential may reach.
- Principal assertion is scoped, the fix described in “Known incidents” above. A caller
may only submit a transaction whose
authority.principalIdis itself, or an identity explicitly granted viaApiKeyEntry.allowedPrincipalIds, never “anything,” the default with no grant configured is “only itself.”isPrincipalAllowed,packages/api/src/auth/isPrincipalAllowed.ts. - Data ownership is scoped, the same fix. A caller can no longer read another caller’s
transactions, trust records, or receipts,
metadata.submittedByis stamped server-side from the authenticated caller (never trusted from the client), andisOwnedByCallergates every read route by it; cross-caller access reads as a clean404, not a403that would confirm the target id exists.packages/api/src/auth/isOwnedByCaller.ts.