Security posture
What we hold, and what we refuse to.
Ratchet sits in front of your most consequential actions. The smaller its blast radius, the better it does that job — so it is designed to know as little as possible.
Data boundaries
What Ratchet stores
- A SHA-256 fingerprint of your payload — never the payload
- Effect type, idempotency key, state, attempt count, timestamps
- The result you explicitly choose to record for replay
- Optional
agent_id,run_id, and a smallrequest_summaryyou control - Declared costs, in micro-USD
- An HMAC of each API key secret, keyed by a server-side secret
What Ratchet never has
- Your vendor credentials, API keys, or tokens
- The content of the actions it gates
- Network access to your systems — the gate is inbound only
- The ability to perform, retry, proxy, or modify any side effect
- Custody of any funds, yours or your customers'
Because only a fingerprint is stored, Ratchet can tell that a key was reused with different arguments — a real class of bug — without ever being able to reconstruct those arguments.
Implemented controls
Each of these has a test in the suite. Nothing here is aspirational.
Identity and access
- Keys stored as HMAC-SHA256, peppered with a server secret — a database leak alone yields no usable key
- Constant-time comparison, run even for unknown prefixes so timing reveals nothing
- Least-privilege scopes; a gating agent needs only
effects:beginandeffects:report - Immediate revocation, and per-key daily spend ceilings
Tenant isolation
- Every query is scoped by workspace; there is no unscoped read path
- A cross-tenant lookup returns
404, never a hint that the record exists - A valid lease token from another workspace is still rejected
- The same idempotency key in two workspaces is two independent effects
Outbound requests (SSRF)
- Webhook destinations must be https, DNS hostnames, on port 80 or 443
- Private, loopback, link-local, CGNAT, and cloud-metadata ranges are blocked — IPv4, IPv6, and IPv4-mapped forms
- DNS is re-resolved on every attempt and the socket is pinned to the checked address, closing the rebinding window
- A host resolving to any private address is refused outright, not filtered
- Redirects are never followed; response bodies are capped and discarded
Integrity of state
- A database-level unique constraint is what enforces at-most-once — not application logic
- Fencing tokens: a stalled worker cannot overwrite a newer attempt
- Budget reservations lock every scope before validating any, so parallel workers cannot collectively exceed a ceiling
- Credit movements are an append-only ledger, deduplicated by event id
Prompt injection
- Agent-supplied text is treated strictly as data. Nothing in a payload, summary, or result is ever interpreted as an instruction by Ratchet
- Effect types are pattern-constrained; results are size-capped
- Decisions come from stored policy and database state — never from request content
- An injected payload cannot widen a key's scopes, raise a budget, or change a policy
Payments
- Card details are entered on the provider's own page and never reach Ratchet
- Credit is applied only on a signed webhook — never because a browser reached a success URL, which is not proof that payment settled
- Payment webhooks are verified by HMAC over the raw body, with a replay window and event-id deduplication
- Refunds and disputes reverse credit through a compensating ledger entry, capped at what was actually credited
- Crypto is non-custodial. No private key is held and no funds are taken into custody; payments go directly to an address the operator controls
- Crypto quotes are struck in USD, so a price move between quote and settlement cannot mint credit. Underpayment is never rounded up
Rollback safety
- A compensation is itself a gated effect, so a retried rollback cannot double-refund
- A group being unwound refuses new forward steps
- A step with no compensation is reported irreversible; the group settles
unwind_failedrather than claiming a clean rollback - An effect with an unknown outcome blocks planning around it
Transport and abuse
- Per-key rate limiting, so tenants cannot exhaust each other
- Same-origin CORS by default; credentials are never granted to a wildcard origin
- Unknown request fields are rejected rather than silently dropped
- Secrets redacted from logs; internal detail never crosses the error boundary
- Payment webhooks verified by HMAC over the raw body, with a replay window
Retention and deletion
Effect records expire on a per-effect-type schedule you configure, bounded by your plan. Expired records are deleted by the worker — a leased effect is never collected, so live work cannot disappear. Deleting a workspace cascades to its keys, effects, policies, ledger, webhooks, and audit trail.
Reporting a vulnerability
Security reports are welcome and will not be met with legal threats. Include reproduction steps and give a reasonable window before disclosure. Contact details belong in the deployed instance's configuration — this build ships no contact address rather than a fake one.
What we do not claim
No third-party audit has been performed. There is no SOC 2 report, no penetration test, and no compliance certification. The controls above are implemented and covered by automated tests; that is a different and lesser thing than independent verification, and we will not blur the two.