Enterprise Readiness
Single diligence-facing index for fintech, bank, and platform buyers. For each enterprise concern, this page names the runtime guarantee, the code/test that enforces it, and the doc that explains it. So buyers don't have to read the source to answer "is this safe?".
Status as of main. Anything marked deferred is on the engineering roadmap. Anything marked external depends on a third party. The blocker for unrestricted mainnet production is at the bottom of this page.
At a glance
Tenant isolation (DB)
shipped
Postgres RLS + infra/db-roles.sql + composition/db-isolation.ts
Tenant isolation (blob)
shipped
Per-tenant path prefix <tenantId>/yyyy/mm/dd/sha256 (blobPath)
Wiki / Policy boundary
shipped
check-policy-no-wiki-read + check-wiki-no-ledger-write
Credential encryption at rest
shipped
AES-256-GCM + KMS provider (shared/src/crypto/aes-gcm.ts)
§6 deterministic payment gate
shipped
shared/src/gate/gate.ts (23 entries) + check-gate-bypass
External-agent HMAC handshake
shipped
services/api/src/agents/sign-agent-request.ts (signs and verifies)
MCP scope grants + per-tenant limits
shipped
BrainMCPAgentRegistry + services/mcp/src/server.ts
Audit log immutability
shipped
Append-only DB + Merkle anchoring on Base
Audit log retention
shipped
Preserved through tenant deletion (GDPR Art 17(3)(b))
Tenant deletion
shipped
DELETE /v1/tenants/{id} + 11 unit tests
Tenant blob purge
deferred
URIs surfaced; durable purge worker in RFC
Production boot fences (7+)
shipped
DB isolation, escrow audit, rails, AES key, inbound secret, loader, and outbox fences
Webhook delivery DLQ + retries
shipped
services/audit/src/webhook-dispatch-worker.ts
On-chain PII guard
shipped
check-no-onchain-pii + RFC 0001 §3
Per-tenant MCP rate limits
shipped
services/mcp/src/server.ts (Redis-backed)
External smart-contract audit
external
contracts/AUDIT-SCOPE.md ready, engagement pending
Docker VM production deploy
shipped
.github/workflows/main.yml builds GHCR images, migrates, recreates, and smokes health
Detail
Tenant isolation at the storage layer
Database. Postgres Row-Level Security is ENABLEd on every tenant table by migration. Enforcement requires infra/db-roles.sql to be applied in production. The request path runs as the non-owner brain_app role (FORCE ROW LEVEL SECURITY), and every cross-tenant background job/resolver runs under one of eight least-privilege BYPASSRLS roles, each granted only its layer's tables (raw worker, canonical projector, ledger projector, execution-outbox worker, audit verifier, audit publisher, resolver, tenant deletion) so a confused-deputy bug in one path cannot reach another layer. A boot fence (composition/db-isolation.ts) refuses to start the api in NODE_ENV=production when BRAIN_WIKI_DB_URL or any of the eight role URLs is missing, and a boot-time role check asserts each pool connects as its expected role with a forbidden-privilege list.
Blob storage. Every object lives under <tenantId>/yyyy/mm/dd/sha256. Paths are built by blobPath() in shared/src/blob/types.ts and never concatenated by hand. An RLS test against the non-owner brain_app role pins the boundary.
Process isolation (api vs workers)
The same image runs as an HTTP-only api and as separate background-worker processes (BRAIN_HTTP_ENABLED + BRAIN_WORKERS select the role; composition/process-roles.ts). Workers (ingestion, projection, execution-outbox drain, audit verification/anchoring, blob purge) restart and scale independently of api deploys, and the worker-only least-privilege DB credentials are never handed to the public api runtime. docker-compose.prod.yml ships this split (an api service with BRAIN_WORKERS=none and a worker service with BRAIN_HTTP_ENABLED=false). Every worker holds a per-worker Postgres advisory lease (leasedCycle), so running multiple worker replicas is safe: one is active at a time and a crashed holder's lock auto-releases for failover.
Wiki / Policy boundary
Brain's safety story rests on Policy reading Ledger only, never Wiki.
check-policy-no-wiki-read(CI) scans Policy code for any Wiki import.check-wiki-no-ledger-write(CI) scans Wiki code for any Ledger write.15 cross-layer invariants in
tests/invariants/enforce this end-to-end.
Credential encryption at rest
Plaid bank credentials are encrypted with AES-256-GCM before insert into raw_plaid_items.credentials. The key comes from Azure Key Vault in production (shared/src/crypto/kms-provider.ts) or BRAIN_SOURCE_CREDENTIAL_KEY in dev. A boot fence refuses to start in production with no provider configured.
The §6 deterministic pre-execution gate
Every money-moving action runs 23 deterministic checks (13 numbered + 10 hardening additions). Identity, behavior pinning, policy DSL, ledger state binding, balance, evidence, approvals, duplicate detection, obligation direction (payable vs receivable), audit before and after.
No LLM. No Wiki text. No skip path. The gate is pure code; the same inputs always produce the same outputs.
check-gate-bypass(CI) enforces that no rail dispatch orexecutedtransition can occur outsidePaymentIntentService.execute().Metrics:
brain.gate.check.count,brain.gate.outcome.count,brain.gate.duration_ms(Grafana scaffold atinfra/grafana/gate.json).tests/e2e/signed-agent-gated-payment.e2e.test.tsasserts checks 8 / 9.5 / 11.5 arepassand NOTnot_applicablefrom staging history.
External-agent HMAC handshake
External MCP agents call /v1/agents/mcp with a JWT validated against BrainMCPAgentRegistry (60s cache). Internal Python agents (reconciliation, payment, anomaly) verify X-Brain-Auth: sha256=<hex> over the request body via shared BRAIN_AGENTS_INBOUND_SECRET. Both sides fail closed in production:
The api refuses to start when
RECONCILIATION_AGENT_URLis set in prod withoutBRAIN_AGENTS_INBOUND_SECRET.The Python service raises
RuntimeErrorbeforeFastAPIis constructed whenBRAIN_ENV=productionand the secret is unset.
Audit log + Merkle anchoring
Append-only audit_events table. Periodic Merkle anchor publication to Base via BrainAuditAnchor. The /v1/audit/verify endpoint is unauthenticated (verify-without-trusting-Brain). Tenant deletion preserves audit_events and audit_anchors under GDPR Article 17(3)(b) legitimate-interest carveout (financial integrity), and the deletion itself is recorded as a tenant.deleted audit event so it's verifiable on the chain.
Tenant deletion (GDPR Article 17)
DELETE /v1/tenants/{id} walks every tenant-scoped table across the six layers in one transaction (brain_tenant_deletion role, BYPASSRLS, scoped to erasure). Returns per-table row counts + the list of raw_artifacts.blob_uri that require out-of-band purging (the database deletion is in-band; blob byte deletion is deferred to the privileged purge worker).
Blob purge (deferred)
This item is on the roadmap, not shipped. A misconfigured operator runbook could leave blob bytes in Azure Blob Storage after a tenant deletion.
Layer-1 immutability ("Raw is the source of truth, never mutated", per Brain_MVP_Architecture.md Layer 1) blocks an in-band BlobAdapter.purge() today. The architectural carveout that reconciles Layer-1 immutability with GDPR Article 17 is in RFC 0003 (in the repo at docs/rfcs/0003-blob-purge-article-17.md). Once signed off, phase B implements:
tenant_blob_purge_jobsdurable queue tablebackground worker that calls
BlobAdapter.purge(uri)per rowaudit events
tenant_blob.purge_requested / completed / failed / retried
Until phase B lands, operators run a separate cleanup pass against the URI list returned by the deletion endpoint.
Production boot fences (7+)
At least seven fail-closed boot fences protect production. A misconfigured production deploy fails to start rather than running degraded:
DB isolation (
composition/db-isolation.ts). Wiki + eight least-privilege role DB URLs required.Escrow audit (
composition/escrow-audit-gate.ts). Mainnet escrow requiresBRAIN_ESCROW_AUDIT_RECEIPT(preferred. URL/filepath/hash pointing at the audit report) or the legacyBRAIN_ESCROW_AUDIT_APPROVED="true"boolean.Live rails (
composition/rails-prod-fence.ts). At least one production rail must register.AES-256-GCM. Source-credential KMS provider must be configured.
Inbound agent secret.
BRAIN_AGENTS_INBOUND_SECRETrequired whenRECONCILIATION_AGENT_URLis set.Money-path loaders (
composition/payment-loaders-prod-fence.ts). Production requires always-applicable gate loaders.Outbox dispatch guard (
composition/outbox-dispatch-guard-fence.ts). The execution worker must re-check dispatch safety before rail dispatch.
Feature fences also protect demo provision-run and sandbox service-token routes when those routes are enabled.
Each fence emits the failure on stdout/stderr so log aggregators surface the exact missing env var or wiring error.
Per-tenant MCP rate limits
Redis-backed limiter in services/mcp/src/server.ts. Per-tenant + per-tool buckets. Configurable via env. No customer can starve another via the MCP surface.
Per-rail support matrix
A release-manager-facing per-rail support table lives in the repo at docs/rails-matrix.md (production_allowed, required env, chain, audit status, failure mode). The runtime capability log emits the same fields per rail at boot:
Diligence machinery (peer-review batch 7)
Beyond the runtime guarantees above, Brain ships repeatable operator and reviewer tooling that turns "is this safe to promote?" into a runnable check:
pnpm run production-readinessevaluates the current env against every boot fence, every rail'srequired_env_present, every CI guard's wiring, and every open risk in the register. Each row includesevidence_state, separate from status, so a configured-but-unexercised control cannot masquerade as proven. Exit 1 (red) when any P0 risk is open, any fence would fail, or the selected profile's evidence minimum is not met. Add--jsonfor machine output.pnpm run readiness:evidence -- --profile stagingemits a diligence-ready markdown report with status, evidence state, testnet E2E posture, audit status, rail posture, connector certification guards, and known limitations. Use it as the release-candidate attachment for staging and mainnet reviews.Machine-readable risk register at
docs/risk-register.json(mirrorsdocs/risk-register.md). The aggregator reads it directly; an openP0risk in the register automatically pins promotion to red.CI artifact uploaded per commit on the PR workflow (
production-readiness-${sha}, 90-day retention). Diligence reviewers can pull any commit's readiness JSON without rebuilding.Git-native trend tracking at
docs/readiness-history/<tag>.json. Per-release snapshots committed to the repo;pnpm run readiness-trendprints the trajectory (open P0 count, red/yellow/green counts, ΔP0 vs prior). No external dashboard required.
This is how the readiness story stays falsifiable: every claim has a code anchor, every claim has a runtime check, and every release has a snapshot you can compare against.
Blockers for unrestricted mainnet production
External contract audit must close before "unrestricted mainnet production-ready" is an honest claim. Until then, Brain is staging / controlled-pilot ready.
External smart-contract audit.
contracts/AUDIT-SCOPE.mdis ready. Engagement is pending. Until the audit clears and the deployed bytecode is verified, the boot fence (#2 above) refuses mainnet escrow.
The deploy chain itself is no longer an unstarted blocker: .github/workflows/main.yml builds the Node and Python agent images, pushes them to GHCR, applies production migrations before compose recreate, starts api, worker, and agents, and smokes https://api.brain.fi/health.
The on-chain executor has a testnet E2E that drives the real rail against a deployed BrainSmartAccount on Base Sepolia (tests/e2e/onchain-executor.testnet.e2e.test.ts, CI job testnet_onchain_executor_e2e); it is gated behind a repo variable + RPC/key secrets and runs once those testnet fixtures are provisioned. production-readiness --profile staging treats this as required exercised evidence, so the scaffolded job no longer passes a release-candidate gate by itself. This overlaps blocker #2 (the same deploy/provisioning substrate).
How to verify any one of these claims
Each row in the at-a-glance table names the code anchor. Reading that file is the verification. For runtime guarantees, the brain.runtime.capabilities log line is the single ops surface that proves which fences are armed and which rails are live in the running process.
Last updated
