Security

Built to fail closed.

Seal is fail-closed by design: an unknown, missing, or malformed input always resolves to the safe verdict, and every decision is written to an append-only, hash-chained audit trail in the same transaction as the state change.

Fail closed, always

Default deny. Evaluation of untrusted input is total — it never throws. An unknown policy, a missing field, a malformed payload, or an expired request yields require_approval or deny, never the permissive path.

Atomic state + audit

A status change and its audit event co-commit in one database transaction. A verdict without its audit record — or an audit record without the verdict — cannot exist. Races are serialized with row and advisory locks, not read-modify-write in application code.

Append-only by construction

The audit log has no update or delete path, enforced in application code and by a database guard. Each event is hash-chained to the previous one, so any tampering breaks the chain and is detectable.

Tenant isolation

Every request, API key, and audit event is org-scoped. Queries filter by org id; an id alone never grants access. API keys are scoped to least privilege and reviewer roles are explicit.

Hostile-input handling

Agent payloads are treated as hostile: sizes are bounded, inputs are schema-parsed with zod at the border before reaching any logic, and there is no implicit string-to-number coercion or ReDoS surface.

Verifiable on demand

You can verify the integrity of the audit chain at any time. The chain proves the complete, ordered history of every decision — what was requested, by which agent, under which policy, and who approved it.
Chain of custody

Reconstruct any decision, end to end.

Every request carries its full history: created, escalated, and resolved — each event stamped, hash-linked, and attributable to an agent, a policy, and a human reviewer. Nothing is edited after the fact because nothing can be.

ImmutableOrderedAttributableVerifiable
Audit chain
created
sha256:3f9a…c2
escalated
sha256:a71b…4e
approved · ada@acme
sha256:d0c8…91

Security FAQ

What does fail-closed mean in practice?+

If Seal cannot confidently produce a permissive verdict — because input is unknown, missing, malformed, or the request expired — it returns the safe verdict and the gated action does not run. The permissive path is never the default.

How is the audit log tamper-evident?+

Each audit event is hash-chained to the previous one and committed in the same transaction as the state change it records. There is no update or delete path on the log. Altering any past event breaks the hash chain, which verification detects.

How is tenant data isolated?+

Every row — approvals, keys, audit events — carries an org id, and every query is org-scoped. Access is never granted on an id alone, and API keys are scoped to least privilege.