Security architecture
How IsoKron stays safe
A summary of the controls IsoKron uses to isolate tenants, protect credentials, and keep the audit trail tamper-evident. Disclosure channel: security@isokron.ai.
Live compliance posture
Operator-run probes against the audit substrate, the per-tenant isolation layer, and the retention pipeline. Updated when the operator runs the verifier — typically nightly.
Hash chain integrity
not reportedOperator-side verifier hasn't published a result yet. See RB-FOUNDATION-003.
Tenant isolation
not reportedProbe results not yet published. CI runs 109 tenant-isolation tests on every PR; see /docs.
Audit log retention
not reportedRetention SLO target: 90 days hot, 24 months cold. Operator-published verifier shows live numbers when wired.
Four-layer tenant isolation
Cross-tenant leakage is the highest-impact failure mode for a multi-tenant compiler. We assume any single layer can regress; four layers run in series so a leak has to defeat all four.
- Postgres Row-Level Security. Every tenant table carries a
workspace_idcolumn and a USING clause that compares it to the JWT-supplied org id viacurrent_setting('app.current_workspace_id'). The pool sets this GUC per-connection from the authenticated session. - JWT preHandler at the API gateway. The Clerk middleware verifies the bearer token, extracts
org_id, and binds it to the request. Every workspace-scoped route asserts the URL:wsIdmatches the JWT — a mismatch is a 403 before the handler runs. - MCP host enforcement. The claim endpoint that hands tickets to your agent fleet pins the MCP tool-surface hash at Stage 7. A claim against a workspace the JWT doesn't own, or against a tool surface that drifted, fails closed with HTTP 412.
- Worker-side explicit workspace filter. The
serviceQuery()wrapper that workers use to bypass RLS is runtime-checked: every call MUST include aworkspace_idfilter in its SQL, and the wrapper emits aservice_role_queryaudit row each time it's invoked. A tenant- isolation regression test exercises this in CI.
Append-only audit substrate
Every security-relevant action lands in the platform's append-only audit log — a per-tenant chain where each row contains the SHA-256 of the previous row in that tenant's chain. Tampering with an event invalidates the chain from that point forward; chain replay verifies in 60 seconds against an hourly Merkle anchor we publish to immutable storage.
Payloads are normalized with RFC 8785 JSON Canonicalization Scheme (JCS) before hashing — the same JSON serializes to the same bytes on every node, so two readers compute the same chain hash independently. Roles have no UPDATE or DELETE on the audit log; the only state transition is INSERT.
BYOK credentials
Your upstream LLM keys live in Supabase Vault encrypted at rest (per-workspace, AES-256-GCM with a tenant-scoped KEK). Decryption only happens inside the compile worker for the duration of one upstream call. The plaintext lives in a sodium-native SecureBuffer and never becomes a JavaScript String — when the call completes, the buffer's bytes are zeroed before the GC reclaims it.
Operator-side credentials (Layer 4 critic, vendor SDKs) sit behind a separate secret-management surface (Doppler) and never touch the customer credential path. This separation is enforced physically: customer-stage code can read only the Supabase Vault BYOK client; operator-stage code can read only the Doppler client. The two clients live in separate workspace packages and ESLint + Semgrep block cross-imports at PR time.
Logs + observability
Logs use structured JSON and never contain plaintext credentials. The BYOK pipeline only logs the last-4 of a key for correlation; the auth pipeline logs the JWT's jti claim, not the token. The customer-facing payload surface goes through a serializeForCustomer hook that asserts no operator-internal field name (oracle markers, internal verdicts) leaks downstream.
Privileged Postgres functions
Schema migrations use SECURITY DEFINER sparingly; each definer-context function is reviewed at PR time and the migrations index documents the boundary. The validate_event_log_insert guard runs INSIDE the chain advance, not as an after-the-fact trigger, so an attacker who bypasses the application layer still hits the substrate's consistency check.
Recovery Kit
We ship a binary Recovery Kit (audit-log chain verifier + Merkle-anchor reader + DB snapshot replayer) so an organisation can independently verify their chain even if IsoKron the company disappears. Recovery procedures live in the docs.
Translation Layer: where frontier calls execute
IsoKron supports five BYOK provider modes. Four of them (Anthropic, OpenAI, Google AI, xAI) route compile-stage inference straight to the upstream vendor using the API key you stored in Supabase Vault — prompts cross IsoKron servers in transit, vendor sees declaration content under its own privacy policy.
The fifth mode, claude-max-fleet, runs differently. Inference happens on your BYO-fleet host (a machine you operate, typically a Mac with @anthropic-ai/claude-agent-sdk installed and claude login executed). IsoKron sends compile prompts to your fleet host over an authenticated MCP channel; your fleet host resolves your Claude OAuth locally and runs the inference against your Claude subscription's billing. IsoKron servers never hold your Claude OAuth credential.
The auth handshake is yours: you install the SDK on the fleet host, you run claude login, you provision the bearer token IsoKron uses to reach the fleet's MCP endpoint. Rotation is a single claude logout + claude login on your machine; nothing on IsoKron's side needs to re-issue.
Disclosure
Found a vulnerability? Email security@isokron.ai with a clear repro and the affected component. We acknowledge within two business days; coordinated disclosure runs on a 90-day window from acknowledgement. We don't run a bug bounty yet but credit researchers in release notes when they ask to be named.