Changelog
User-visible changes to the Brain protocol, HTTP API, MCP surface, and SDK. Internal refactors, performance work, and bug fixes that don't change behaviour are omitted unless they affect integrators.
v0.5.9 (surface onboarding admin auth)
Surface onboarding endpoints for Slack OAuth install, Teams install and revoke, and email recipients, routes, and domains now require a Brain bearer JWT with
surfaces:admin. The gateway derives the tenant from the principal instead of trusting tenant ids in request bodies.Email custom sender domains are verified by Brain-side DNS checks for SPF, DKIM, and DMARC before activation. A reverify endpoint can refresh the result.
Slack OAuth install state is signed with
SLACK_INSTALL_STATE_SECRETinstead of reusing the OAuth client secret.
v0.5.8 (surface approval audit ordering + OpenAPI cleanup)
Safety and contract-polish release. No endpoint behavior is loosened.
Fixed. Surface approval ordering
Surface approval signatures now happen after the decision audit record. Slack, Teams, and email approval flows re-check policy first, write the audit record, then record the approval signature that contributes to quorum. This keeps quorum-changing approval writes from preceding the audit evidence for the same human decision.
Dual approval still records the first approver. The post-audit approval hook runs for both awaiting-second-approval and terminal approvals, so quorum can build without moving signing into the execution handoff.
Approver role checks are stricter. A roleless actor no longer satisfies a
signersentinel, and disabled users no longer count as active approvers.
Changed. OpenAPI contract quality
OpenAPI lint now runs clean with zero warnings. The contract now includes proprietary license metadata, explicit documented error responses for operations that only listed success responses, and regenerated SDK types.
Intentional route-shape exceptions are documented in Redocly config. The implemented Fastify routes retain their existing paths, and the disabled legacy
POST /v1/execution/executeroute remains documented as returning422rather than a fake success response.
v0.5.7 (money-path reservation lifecycle)
Safety hardening for the PaymentIntent execution path. No API, MCP, or SDK surface changed.
Fixed. Reservation-backed execution handoff
Balance reservations now have a live lifecycle. For ledger-account-backed payments,
execute()locks the source account, locks the latest balance snapshot, rechecks available balance net of active reservations, then creates a reservation in the same transaction that moves the PaymentIntent fromapprovedtodispatchingand enqueues the durable outbox row. The outbox row storesreservation_id; settlement consumes the reservation, and deterministic rail failure releases it. Check #8 already subtracted active reservations, and the locked recheck makes the handoff race-free.Outbox and PaymentIntent state races fail closed. Settlement now verifies that
dispatching -> executedactually updated the PaymentIntent before appending the execution receipt, consuming the reservation, or recording spend. Deterministic failure similarly verifiesdispatching -> failedbefore releasing a reservation. A lost race routes the worker to retry/reconcile instead of producing a mismatched outbox/PaymentIntent state.Outbox idempotency fallback is tenant-scoped. The conflict lookup now selects by both
tenant_idandidempotency_key, matching the unique index and preserving correctness outside strict RLS test environments.Readiness evidence is profile-gated.
production-readiness --profilenow treats evidence strength as a release gate, not only a display field. Staging requires exercised core safety rows such as Base Sepolia on-chain E2E; mainnet requires exercised money-path, rail, audit, and contract evidence. A newpnpm run readiness:evidence -- --profile stagingcommand emits a diligence-ready report with row status, evidence state, blockers, and known limitations.
Changed. Boot composition
Production DB role expectations moved out of
services/api/src/main.tsinto a focused composition module. Runtime behavior is unchanged; the boot binary is smaller and the role matrix is easier to review.
v0.5.6 (docs-accuracy remediation + error docs_url)
docs_url)Documentation-accuracy pass across the published docs, reconciling them to the code as the source of truth: the §6 gate-check count (13 numbered + 10 hardening = 23), the MCP scope error code (-32002, not -32004), the route migration table (/execution/* propose/register stay live; /agents/{id}/propose and /agents/register 404), the MCP surface size (12 tools / 7 resources / 5 prompts), the self-serve signup path (POST /v1/signup), the credential model (brain_sk_ is the bearer service token), the decision/status vocabularies (allow|confirm|reject and their SDK aliases), the webhook event catalog (payment_intent.*), and the deployed Base Sepolia contract addresses. No API / MCP / SDK behavior changed except the item below.
Changed. Error envelope docs_url
docs_urlerror.docs_urlnow points at the published error reference. It previously emittedhttps://docs.brain.fi/errors/{code}, a path with no page (every self-help link 404'd). It now emitshttps://docs.brain.fi/resources/errors#{code}, which lands on the canonical error registry.
v0.5.5 (GDPR erasure hardening)
Second-pass review remediation of the tenant blob-purge workflow (RFC 0003). Compliance- and diligence-facing; the internal worker/test detail is omitted.
Changed. Tenant erasure is now crash-safe and audit-atomic
A crashed purge worker can no longer silently strand a GDPR Article 17 erasure. A job claimed by a worker that then dies (left in
purging) is now reclaimed by another worker once its lease expires, and every status write is fenced on a unique lock token so a resurrected stale worker cannot overwrite the new owner's result.A transient cloud error no longer masquerades as a permanent legal hold. Per-object delete failures are classified: throttling / 5xx / network / authorization errors are retried, and only a confirmed WORM / object-lock response makes the job terminal (
blocked_legal_hold). Previously any failed delete was treated as a legal hold, so a 503 could permanently stop an erasure.Purge-lifecycle audit events are now written transactionally. Each state transition records its audit intent in the same database transaction as the status change (via an outbox), and a publisher delivers it to the audit service idempotently. This removes the prior ordering where an audit event could be emitted before the state write (orphaning a "completed" record) and the
audit-emit-failedsentinel that let a job complete with no real audit event. A tenant deletion now returns a truthful committed result even if the audit service is momentarily unavailable.
v0.5.4 (audit-build binding, GDPR erasure, money-path CI)
Review-remediation batch. The internal CI/test work is omitted; the items below are API-, compliance-, or diligence-facing.
Fixed. Proof API
GET /v1/proof/{action_id}no longer 500s for an in-flight payment. A PaymentIntent that is executed but stilldispatching(settlement async, not yet anchored) now returns a 200 partial proof (gate checks present,merkle_rootempty until anchored) instead of an internal error. Root cause was a never-run-on-Postgres evidence query referencing non-existent columns.policy_hashis now hex-encoded (was a raw byte buffer).
Added. GDPR Article 17 erasure (RFC 0003)
Tenant deletion now durably and permanently erases Raw blob bytes.
DELETE /v1/tenants/{id}enqueues atenant_blob_purge_jobsrow in the deletion transaction; a privileged worker drains it viaBlobAdapter.purgeTenantwith bounded retries, a dead-letter state, legal-hold surfacing, and per-lifecycle audit events (tenant_blob.purge_requested/_completed/_blocked_legal_hold/_retried/_exhausted).purgeTenantdoes version-aware deletion (S3 every object version + delete marker; Azure versions + snapshots), so erasure is permanent in a versioned bucket, closing the gap where a "deleted" response left the user's PII recoverable.
Changed. Mainnet escrow audit binding (diligence)
Audit approval binds to the audited build, not just a commit.
contracts/audit-status.jsonapproval now additionally requires the compiler settings, contract-source-tree hash, and creation/runtime bytecode hashes, plus an explicitapproved_chain_ids. A CI step recomputes them from the working tree + Foundry artifact and fails the build on drift; the mainnet escrow boot fence also requires the booting chain to be inapproved_chain_ids. A single shared validator now backs the runtime fence, the CI guard, and the readiness command (previously the runtime path was a barestatus === "approved"check).The mainnet escrow boot fence now also verifies the DEPLOYED on-chain bytecode. With an escrow address configured on Base mainnet, the api reads the live contract code via
eth_getCodeand refuses to boot unless it matches the audited runtime bytecode. Because Solidity writesimmutablevalues (the escrow arbiter) into the deployed code at construction, the audited hash and the on-chain code are compared with those immutable byte ranges masked; an approvedcontracts/audit-status.jsonnow carries the maskedruntime_bytecode_sha256plus theimmutable_referencesranges. A wrong, unaudited, or tampered deployment becomes a refused boot rather than a silent funds-custody risk.
v0.5.3 (CI + demo integrity)
Internal hardening. No API, protocol, MCP, or SDK surface change. Recorded here because it restores an end-to-end proof artifact integrators rely on, and one item affects anyone bootstrapping the schema.
Fixed. CI + golden-path
The golden-path smoke runs end-to-end as a post-merge CI gate again. Its job depends on the unit+integration job, which had been red on an unrelated, masked test-schema failure, so the smoke was silently skipped and the full
seed → ingest → normalize → propose → policy → execute → proofchain was not actually exercised in CI. The prerequisite suite is green again and the smoke passes front to back (propose →approved→ execute →dispatching).The demo seed no longer trips the §6 duplicate-payment gate (check 11.5). A freshly-seeded counterparty's payment instructions were stamped
now(), which thedestination_recently_changedrule correctly reads as a vendor-account-swap signal. The seed's backdate mitigation had been scoped to the on-chain recipient only; it now backdates every seeded counterparty for the tenant, so the default ACH demo settles cleanly. The §6 gate itself is unchanged and still fail-closed.The migration set is self-contained for
pgcrypto. A migrations-only bootstrap (for example a test schema that does not run thepostgres-initextension script) now createspgcryptovia migration0031, so the migration0027payment-instruction trigger'sdigest()call resolves instead of failing at first insert. This affects anyone building a schema from the migration set alone.
v0.5.2 (control-plane hardening)
Follow-up review fixes. All stricter / fail-closed.
Changed. Safer defaults + provenance
The default tenant policy never auto-executes money. A freshly provisioned tenant's default now requires human confirmation for
outbound_payment/onchain_txabove the confidence floor (with a single-signer approval); non-money actions still auto-allow. The prior blanketautorule (which the repo's own policy linter flags as unsafe-for-money) is gone. A tenant signs a constrained autonomy policy to earn unattended money movement.High-trust provider source types are reserved to authenticated ingestion.
source_type: "plaid"/"stripe"are refused on the generic/raw/ingestroute withraw_source_reserved(403); they may only arrive via the HMAC-verified/raw/webhooks/{provider}path, so araw:writecaller can't mint high-trust evidence by choosing the label.
Fixed. Audit-control plumbing
The committed
contracts/audit-status.jsonnow ships in the production image, so the mainnet escrow boot fence can actually pass once the audit is approved (previously it was excluded and failed closed forever).pnpm run production-readinessnow models the same two-part mainnet-escrow condition as the runtime boot fence (committed approved record and env attestation), so the report can no longer show green for a deployment the runtime would reject.
v0.5.1 (autonomy + provenance hardening)
A safety-hardening batch. All changes are stricter (fail-closed), never more permissive.
Changed. Tighter defaults + authorization
Default confidence floor raised to
0.6. A freshly provisioned tenant's default policy now rejects auto-execution of an intent backed only by an uncorroborated, document-extracted obligation (capped at0.5); a corroborated obligation (reconciliation lifts it to ~0.7+) still passes. Tenants with their own signed policy are unaffected.Signed per-agent action allowlist (
PolicyDocument.agent_actions) is now enforced on every action-resolution path (explicit request, event map, intent-classifier match, and default action), not just explicit requests. A denied action can no longer be smuggled in via an event mapping or a default.Evidence trust derives from the raw artifact's
source_type, not the caller-chosen parser label, so araw:writeprincipal can no longer mint high-trust evidence by labelling its parserplaid/stripe.
Added. Obligation-direction safety
obligation_direction_invalid(422). A new obligation-linked PaymentIntent must target a knownpayableobligation; anull/unknown orreceivable(wrong-way) direction is refused at creation. The §6 gate's check 6.7 continues to rejectreceivableat execute for already-created intents.
Added. Operational / diligence
contracts/audit-status.jsonis the committed source of truth for the external smart-contract audit; mainnet escrow now boots only when that record saysapproved(a bare env flag no longer bypasses a pending audit).BlobAdapter.purgeTenantprimitive for GDPR Art. 17 tenant erasure (deletes Raw bytes under a tenant prefix; WORM/legal-hold-protected blobs are surfaced, not force-deleted).
v0.5 (M2M Commerce + Self-Serve Onboarding)
Two additive tracks: machine-to-machine (M2M) agent commerce (RFC 0001) and self-serve onboarding (RFC 0002). Everything money-moving here is shadow-first / fail-closed. The new settlement rails are unregistered at boot and the new contracts are unaudited testnet/reference code. Self-serve signup is gated behind BRAIN_SELF_SERVE_SIGNUP (default off, sandbox-first).
Added. Self-serve onboarding (RFC 0002)
POST /v1/signup. Open, sandbox-first tenant + owner creation (email + password). Returns a verification token directly only outside production (no email provider wired yet). Registered only whenBRAIN_SELF_SERVE_SIGNUPis enabled; returns 404 when the flag is off.POST /v1/auth/verify-email. Verify the owner's email with the issued token.POST /v1/auth/login. Email + password login for the human owner; mints an owner JWT.POST /v1/tenants/{tenant_id}/wallets. Link a wallet to a tenant; a linked wallet can then sign in over SIWX as the owner.Agent on-chain registration is async: a newly registered agent starts
pending_onchainand a relayer submits theBrainMCPAgentRegistryregistration (the relayer is fail-closed until configured).
Added. M2M / x402 settlement (RFC 0001)
x402_settleaction type. USDC-on-Base settlement via thex402_baserail.escrow_releaseaction type. Milestone / dispute-split release via theescrow_baserail (BrainEscrow).Both settlement rails are unregistered at boot and fail closed until promoted; they throw rather than fake-settle.
Five dormant-until-wired §6 gate checks (3.5 on-chain-settlement-permitted, 5.5 agent-counterparty-attested, 6.5 x402-payment-context, 6.6 escrow-state-bound, 8.5 micropayment-cap-in-window). Each adds a row only when the intent carries settlement/escrow context and its on-chain loader is configured; the canonical path is unchanged for non-settlement payments.
On-chain-settlement reconciliation matcher; agent counterparties;
chain_tx_hashonledger_transactions.
Added. Smart contracts (Base; unaudited)
BrainEscrow. Custodial escrow with partial release, refund, and dispute splits (UNAUDITED reference implementation, testnet only).BrainReputationRegistry. An ERC-8004-style per-agent reputation pointer / score root (RFC 0001, UNAUDITED testnet). Policy reads it as a tighten-only threshold input. Never a money gate or a §6 precondition.
Errors
signup_email_taken(409),signup_token_invalid(400),wallet_already_linked(409),auth_invalid_credentials(401),auth_email_unverified(403).
v0.4 (Agent Autonomy v3)
Hardens the 19-agent internal library for production autonomous execution. Money-movers stay shadowed by default. Going live is a deliberate, per-agent promotion (strict caps + allowlisted rails); no agent moves money until promoted.
Added. HTTP API
POST /v1/agents/route. Routing decision only (no run).POST /v1/agents/run. Route → resolve action → dry-run gate → persist run → propose (shadow-aware; a shadowed agent's financial proposal terminates asshadow_completed).POST /v1/agents/events. Enqueue an event-driven route/run job.GET /v1/agents/runs,GET /v1/agents/runs/{run_id},GET /v1/agents/runs/{run_id}/why. Run history + the structured-reason / trace / gate / receipt bundle.GET /v1/agents/routing-decisions/{id}. Routing decision detail.POST /v1/agents/{agent_id}/halt,POST /v1/agents/halt-category. Kill-switch: pause an agent's in-flight intents + quarantine it, or emergency-stop a whole category.POST /v1/payment-intents/{id}/pause,POST /v1/payment-intents/{id}/resume. Pause/resume an approved intent (resume re-runs the live §6 gate).GET /v1/payment-intents/{id}/replay-investigation. Typed forensic record (intent + executions + rail receipts + linking ids).
Added. Policy DSL (signed)
agent.id,tenant.category,action.in/action.not_in,agent.behaviorHash,agent.spend_in_window,agent.tx_count_in_window, and rule-levelapproval_required_above. All covered by the policy content hash, so they're signed.
Added. Smart contracts
BrainSmartAccount.pauseSessionKey(holder)/unpauseSessionKey(holder). Disable execution while preserving the key record, window spend, limits, and metadata (distinct fromrevokeSessionKey, which is permanent removal).BrainMCPAgentRegistry.registerAgentnow takes abehaviorHash;updateBehaviorHash(...)re-attests on a model/prompt/tool change. The §6 gate adds check 1.5 (runtimebehaviorHashmust match the registered value).
Changed
Agent.stateaddsquarantined(additive enum widening).Typed rail receipts (
ach/wire/erp/onchain): the audit-after step refuses to commit unless the receipt validates against the rail's schema.
Errors
agent_proposal_duplicate(409). Proposal-layer idempotency collision.
SDK (@brain/sdk)
@brain/sdk)New
agents.route/run/enqueueEvent/listRuns/getRun/why/getRoutingDecision/halt/haltCategoryandpayments.pause/resume/replayInvestigation. Generated types regenerated from the OpenAPI spec.
v0.3.1 (poc-investor-demo)
Breaking changes
BRAIN_DEMO_MODEenv var now requires literal"true"or"false". Previouslyz.coerce.boolean()silently coerced"false","0","no"totrue. Update any.envor CI config using those forms.Brain.getMaskedApiKey()renamed togetMaskedToken(). Follows theapiKey → tokenrename in this release.
Added
Dockerfile. Multi-stage build for thebrain-serversingle-process boot binary.GET /v1/demo/token. Mints a 15-minute read-heavy JWT for the golden demo tenant (requiresBRAIN_DEMO_MODE=true, refused inNODE_ENV=production).POST /v1/audit/anchor/publish. On-demand anchor trigger (requiresaudit:admin, 60s per-tenant cooldown).Live viem anchor broadcaster.
AUDIT_PUBLISHER_KEY+AUDIT_ANCHOR_ADDRESSwires on-chain anchoring to Base Sepolia.CORS_ALLOWED_ORIGINSconfig variable. Replaces the previous reflect-any-origin behaviour.tools/demo-reset. Wipes and re-seeds golden-path demo-tenant business entities; audit log preserved.
Current: Six-Layer Protocol with MCP
The current release introduces a Normalized Ledger between Raw and Wiki, splits Execution into a dedicated Agent layer, and adds the MCP server.
Added
Normalized Ledger layer. Eleven entities: accounts, balances, transactions, counterparties, obligations, documents, categories, transfers, invoices, payment intents, reconciliation matches.
Payment Intents. Agent-proposed financial actions live as Ledger rows, queryable like any other entity.
Pre-execution gate. Deterministic check against live Ledger state before any payment executes: 13 numbered checks plus 10 hardening additions (23 entries total; several record
not_applicableuntil their loaders are wired). See the pre-execution gate.MCP server.
POST /v1/agents/mcp, JSON-RPC 2.0 over single-shot HTTP. 12 tools, 7 resource templates, 5 canned prompts.Agent contributions. External agents with
raw:writescope can push artifacts into the Raw layer with cryptographic attribution./v1/audit/entity/{type}/{id}endpoint. Pull every audit event that touched a specific Ledger row.
Changed
Ledger is now the source of truth. Wiki is downstream of Ledger and regenerable from Ledger plus Raw at any time.
Wiki no longer authoritative for financial state. Wiki holds human-readable memory only; balances, transactions, and obligations come from Ledger.
Execution renamed to Agent. The Agent layer covers proposal, scope enforcement, and the propose-only MCP surface.
Routes added.
/payment-intents/*,/agents/run, and/agents/mcpare the v0.3 paths that are mounted today. The legacy/execution/*routes remain live and fully supported: the generic propose/approve flow (/execution/propose,/execution/approve) and external-agent registration (/execution/agents/register) still run through them and have no v0.3 replacement. The reserved/agents/{id}/proposeand/agents/registerpaths appear in the OpenAPI spec but are not yet implemented and return 404; do not migrate to them.
Six Layers (Was Five)
The previous protocol had five layers: Raw, Wiki, Policy, Execution, Audit.
The current protocol has six: Raw, Ledger, Wiki, Policy, Agent (renamed from Execution), Audit.
Migration from the Previous Version
/execution/propose
Still live (no replacement); or /agents/run for routed agent proposals
/execution/execute
/payment-intents/{id}/execute
/execution/agents/register
Still live (no replacement); /agents/register is not yet implemented
/execution/mcp
/agents/mcp
Wiki for current balances
brain.accounts.list (Ledger)
Wiki for transaction filtering
brain.transactions.list (Ledger)
Only /execution/execute and /execution/mcp have v0.3 replacements; both carry Deprecation/Sunset headers. The propose/approve and agent-registration routes under /execution/* are not deprecated and remain the supported path.
Earlier: Five-Layer Protocol
Five layers: Raw, Wiki, Policy, Execution, Audit.
Wiki was the source of truth for financial state.
MCP surface lived under
/execution/mcp.
Last updated
