packages/tenancy-rls's buildTenantPolicySql emits ENABLE ROW LEVEL SECURITY plus FORCE ROW LEVEL SECURITY on every tenant table, so the policy binds the table owner too, not just other roles. The sole entry point, withTenant, opens a transaction, drops to the unprivileged app role, and binds the account id into a Postgres GUC (app.current_account) that every policy reads; a code path that forgets withTenant has no GUC bound and the table returns nothing. A one-time role pre-flight (assertRoleNotPrivileged) refuses to run if that role is ever a superuser or BYPASSRLS, since either would silently no-op FORCE ROW LEVEL SECURITY. Cross-tenant isolation is a CI test, not a convention.
Fail-closed by construction.
The same posture Caisson generates for your app governs this site: deny by default, prove it with code, claim nothing we do not ship. Caisson generates audit evidence, it is not the auditor.
$ curl -sI https://caisson.sh strict-transport-security: max-age=63072000; includeSubDomains; preload x-content-type-options: nosniff x-frame-options: DENY referrer-policy: strict-origin-when-cross- origin permissions-policy: geolocation=(), microphone=(), camera=() content-security-policy: default-src 'self'; …
The security your app inherits on day one.
These are product features, wired and tested into the codebase Caisson generates, not services we run on your behalf. You own the source and the evidence.
packages/kernel's ssrf.ts stops DNS rebinding on every user- or config-supplied URL (the alerting webhook transports and the AI-Production provider baseUrl both route through it. assertSafePublicUrl rejects non-https, credentials-in-URL, and a literal private/loopback/link-local/metadata host at the config boundary; assertResolvedHostPublic then resolves the hostname and re-checks every returned A/AAAA record against the same denylist immediately before the outbound fetch, so a public name that DNS-rebinds to 127.0.0.1 or 169.254.169.254 is caught where a literal-only check can't see it. ssrfGuardedFetch forces redirect: "error") only the original host is re-checked, so a followed redirect could otherwise carry the request past the guard.
Evidence buckets enable S3 Object Lock. The default is GOVERNANCE mode, inside the retention window an object cannot be overwritten or deleted by an app bug or an ordinary operator, though a caller holding s3:BypassGovernanceRetention can still override it. COMPLIANCE mode is available as an explicit, irreversible opt-in (production-only, gated behind irreversibleComplianceOptIn) for retention even the AWS account root cannot shorten.
Each audit row commits SHA-256 over the previous hash plus its own payload. Tampering with any historical row breaks every link after it, and the break is detectable, provable, and exportable.
packages/kernel's crypto.ts is the one home for secret comparison: safeEqualFixed converts both sides to equal-length buffers and runs node:crypto's timingSafeEqual for session tokens and HMAC outputs of known length; safeEqualVariable SHA-256-hashes both sides first for variable-length values like an admin-email allowlist entry, because a raw variable-length timingSafeEqual throws on a length mismatch and leaks a boolean through the catch. verifyAllowlisted scans every allowlist entry with no early return, so the timing never reveals which entry matched.
Sensitive columns are sealed with a data key derived per tenant via HKDF-SHA256. A leaked tenant key exposes one tenant, never the table; rotating the root re-derives every key without a re-encrypt scan.
How caisson.sh itself is secured.
A static site keeps the attack surface small, and we document exactly what ships.
caisson.sh is a static export served from Cloudflare's edge. Every page and the search index are prebuilt files: no origin server, no database, no sign-in, and no secrets anywhere in the build.
There are no forms and no API routes that accept input. Search runs entirely in your browser over a prebuilt index, so a query never leaves the page.
Every response carries HSTS with preload, X-Content-Type-Options: nosniff, a strict Referrer-Policy, a closed Permissions-Policy, and a tightened Content-Security-Policy. Framing is denied outright on every page, with one exception: the /demos/* embed surface, which a module page frames on this same origin and which no other site can frame.
Analytics run through Plausible, no cookies, no cross-site identifiers, no consent banner because there is nothing to consent to. Fonts ship from our own origin via next/font, so font-src stays locked to 'self' with no third-party font CDN in the trust surface.
A machine-readable policy lives at /.well-known/security.txt (RFC 9116). Report anything you find to security@caisson.sh, we read it.
The policy that ships, including what is not yet locked down.
We state CSP residuals plainly rather than imply a tighter policy than we run. Trust is the product; over-claiming it would defeat the point.
$ curl -sI https://caisson.sh | grep -i '^content-security-policy' content-security-policy: default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; img-src 'self' data:; font-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://static.cloudflareinsights.com; frame-src 'self'; connect-src 'self' https://cloudflareinsights.com
script-src and style-src still allow 'unsafe-inline'. Next inlines its own hydration bootstrap with no per-request nonce under the App Router, so those inline tags cannot be hash- or nonce-gated without breaking hydration. Beyond 'self' the policy allows exactly one third party: Plausible, for cookieless analytics. Nothing wider. Tightening the inline residual to per-script hashes is a tracked follow-up, not a shipped claim.
Caisson generates evidence. It is not an auditor.
Caisson ships the technical controls a framework asks for and generates the evidence pack. The audit, and your organizational controls, stay yours.
We never imply Caisson is SOC 2 or HIPAA certified. A codebase cannot be. It maps the live RLS policies, the SSRF guard, WORM retention, and the audit-chain proof to named controls so you can hand an auditor the evidence, not a screenshot. The technical-versus-administrative line is drawn on purpose, and we keep it visible.
The questions a security review asks first.
Is Caisson SOC 2 or HIPAA certified?
Does this site set tracking cookies?
What stops a DNS-rebinding attack against a webhook or provider URL I configure?
What runs behind caisson.sh?
How do I report a vulnerability?
Found something? Tell us.
We publish a machine-readable policy and read every report. No bounty program yet, the report still matters.