
Security News
Deno Goes the Way of the Dinosaur
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.
@spoolis/receipt-verifier
Advanced tools
Verify signed Spoolis Outcome Receipts offline. Spoolis is Outcome infrastructure for machine commerce.
import { verifyOutcomeReceipt } from '@spoolis/receipt-verifier'
const result = await verifyOutcomeReceipt(receipt, { trustSet })
console.log(result.valid)
console.log(receipt.amounts.earned)
npm install @spoolis/receipt-verifier
No Spoolis account is required to verify a receipt. The package has no runtime dependencies and uses WebCrypto in Node 20 or later, browsers, workers, and agent sandboxes.
requireOutcome verifies the full receipt before applying the consumer's policy. This example acts only on a valid Outcome with a passing result, at least 100 accepted units, and fully satisfied evidence requirements:
import { requireOutcome } from '@spoolis/receipt-verifier'
const required = await requireOutcome(receipt, {
minimum_status: 'pass',
min_accepted_units: 100,
evidence_requirements: 'satisfied',
}, { trustSet })
if (!required.ok) throw new Error(required.reasons.join(', '))
A partial batch is result: 'partial', not pass, so minimum_status: 'pass' refuses an 8-of-10 job even though value was earned. To act on partial batches, gate on the units and the money instead: set minimum_status: 'partial' (or omit it) and require min_accepted_units or min_earned. The receipt's amounts.earned already excludes rejected and uncertain units.
The optional third argument accepts the same verification options as verifyOutcomeReceipt, including trustSet, environment, statusSource, and now. The issuer policy matches the verified receipt.signing_key_id. Spoolis supplies the signed fact; the consumer decides the rule and whether to act. Forward supersession cannot be determined from an offline receipt, so consumers that need current correction or revocation state should provide the hosted status response through statusSource.
Spoolis publishes receipt trust material at https://spoolis.com/.well-known/spoolis-keys.json. Pin the receipt entries you accept and pass that array as trustSet for offline verification. fetchTrustSet(url, environment) is an online convenience that returns only the selected environment's receipt trust entries. The environment defaults to production; pass demo explicitly for sandbox receipts. Fetching at verification time is not required or preferred for a pinned deployment.
Signature validity is offline and permanent when a verifier has the receipt and a pinned trust set. It does not depend on Spoolis uptime. Online status is optional:
import { fetchReceiptStatus, verifyOutcomeReceipt } from '@spoolis/receipt-verifier'
const offline = await verifyOutcomeReceipt(receipt, { trustSet })
if (!offline.valid) throw new Error(offline.reasons.join(', '))
const statusSource = await fetchReceiptStatus('https://spoolis.com', receipt.id)
const result = await verifyOutcomeReceipt(receipt, { trustSet, statusSource })
GET /api/receipts/{id}/status currently returns active for a stored receipt. The response reserves corrected, revoked, advisory entries, and superseding_receipt_id for future workflows. Without a status source, verification stays offline-only and includes the status_source_unavailable advisory. A receipt can remain cryptographically valid even if a future online status marks it superseded.
A later resolution never mutates the original receipt. It produces a new signed Outcome that supersedes it. The supersedes block identifies the original receipt and may use dispute_resolution when agreed dispute handling produced the successor.
| Reason | Meaning |
|---|---|
unknown_schema | The receipt schema version is not supported. |
environment_mismatch | The receipt environment does not match the requested environment. |
invalid_evidence_root | The evidence root is not a lowercase SHA-256 digest. |
invalid_run_digest | The verification run digest is malformed. |
invalid_agreement_hash | The agreement hash is malformed. |
receipt_id_mismatch | The content-derived receipt ID does not match the payload. |
earned_amount_mismatch | Per-unit arithmetic does not equal the earned amount. |
aggregation_inconsistent | A recognized aggregation policy does not produce the stated result. |
corrected | The online status source marks this receipt corrected. |
revoked | The online status source marks this receipt revoked. |
untrusted_signing_key | No recognized, non-revoked trust entry matches the signing key. |
signing_key_id_mismatch | The trust entry public key does not hash to the signing key ID. |
invalid_signature | The Ed25519 signature does not verify. |
webcrypto_unavailable | The runtime has no WebCrypto (globalThis.crypto.subtle). Use Node 20 or later, or supply a WebCrypto polyfill. |
malformed_receipt | A required structure or value is malformed. |
| Advisory | Meaning |
|---|---|
unknown_aggregation_policy | The verifier does not know how to recompute this policy. |
past_execute_by | The optional execution deadline has passed. This does not expire the receipt. |
status_source_unavailable | No corrected or revoked status source was supplied. |
key_retiring | The receipt uses a trusted key marked as retiring or retired. |
A valid result proves that the receipt payload was signed by a key in the supplied trust set. It proves that the content-derived ID matches the signed content. It checks digest formats, recognized aggregation rules, and unit arithmetic. It also enforces the selected production or demo environment. Verification does not prove that referenced evidence is true or available. It does not resolve actor identities. It does not grant payment authority. It does not prove authorization, capture, settlement, or finality on any payment rail. Consumers must enforce their own authorization and consume-once rules before taking economic action. Pin trust material through a trusted channel and review key rotation policy. Use an online status source when corrected or revoked state matters.
The conformance corpus is maintained at tests/fixtures/receipt-vectors/ in the Spoolis repository. The package test runs every declared vector against the standalone implementation.
FAQs
Verify signed Spoolis Outcome Receipts offline. Spoolis is Outcome infrastructure for machine commerce.
We found that @spoolis/receipt-verifier demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.

Security News
On Front Lines’ Early Adopters: CISO podcast, Andrew Becherer shares lessons from Datadog, weighs the long-term costs of AI-built tools, and explains how founders can actually gain a CISO’s trust.