sandbox-core
The foundational TypeScript library. Edge-runtime-compatible: uses only Web APIs (TextEncoder, btoa/atob, crypto.subtle via
@noble/hashes, crypto.randomUUID, crypto.getRandomValues). No
node:fs, no node:crypto, no Buffer.
Conformance is enforced by
__tests__/conformance.test.ts — every
sandbox-issued pack is fed through @enfinitos/sdk-auditor’s
verifyAll. A drift in any encoder, signature, chain, metering, or
settlement primitive will fail the suite. CI gates the sandbox
release on it.
HTTP API
Each route underapps/web/app/api/sandbox/ is a tiny adapter
between the HTTP boundary and the sandbox-core state machines.
Common scaffolding lives in _lib/wrapHandler.ts:
- Parses cookies + HMAC validation
- Per-IP rate limiting
- JSON body parsing
- Persists the mutated tenant state back to the store
- Wraps errors into the standard envelope
Storage
The tenant store is aMap<tenantId, TenantState> keyed under a
global Symbol so all routes share one view per Worker isolate. The
interface (apps/web/app/sandbox/_lib/store.ts) is intentionally
small — get, set, delete — so a future swap to Cloudflare
KV / D1 / Durable Objects requires no route-handler changes.
Why module-level memory works for sandbox
Sandbox traffic is single-visitor, short-session, low-stakes. A typical visitor finishes the six-step flow in 5–20 minutes. Cloudflare Workers keep their isolates warm for tens of minutes under continuous traffic; the eviction case is detectable and recoverable (the API returns 410 TENANT_EVICTED; the UI prompts the user to hit Reset).Upgrading to persistent storage
When sandbox traffic is high enough that eviction is common, the upgrade is:- Create a Cloudflare KV namespace bound to the Pages project.
- Replace
memoryStorein_lib/store.tswith a KV-backed implementation matching the same interface. - KV reads are eventually consistent (~60s globally) — sandbox tenants are per-visitor so consistency isn’t a concern.
- Set an explicit TTL (24h matches the cookie max-age).
In-browser verifier
apps/web/app/sandbox/_components/SandboxConsole.tsx runs the
seven-check audit roundtrip client-side using sandbox-core
primitives:
- Envelope version is
envelope.v1. canonicaliseProofPayloadre-encodes each record byte-identically.sha256HexOfString(payloadCanonical)reproducesafterHash.- The hash chain is intact end-to-end.
- Every Ed25519 signature verifies against the published key.
- Metering records re-project from receipts.
- Settlement lines reconcile per-meter to gross.
Cross-environment story
A sandbox-issued pack verifies under any auditor pointed at the sandbox key directory. A production-issued pack verifies under any auditor pointed at the production key directory. Cross-pointing fails asUNKNOWN_KEY_ID — there is no environment-conditional
code path on the auditor side. The same library handles both.
This is the property that makes the sandbox useful for compliance
review: anything that verifies under sandbox will verify under
production once a real tenant exists.