brain / spec.md
Leon4gr45's picture
Deploy complete BrainAPI source ea2acb63d782
89e57b7 verified
|
Raw History Blame Contribute Delete
28.4 kB
BrainAPI Unified Authentication, Credential Registry, Console Login & Runtime Hardening
Status: Implementation specification
Repository: `JsonLord/brainapi2`
Implementation branch: `feat/unified-auth-runtime`
Source PR: #8, branch `jules-4649944271521841670-0d5c9ccf`
Verified implementation base: `eb08a1549754fab8ec2459bb4472644630d4cb99`
Original handoff PR head: `784fecf82694cf5646d247836eb3f173b4a05941`
Base registry fix: `fix/authoritative-brain-registry` at `42cde77950db2e24a1b7acbc3477274bd9cad06a`
Date: 2026-10-21
---
0. Executive decision
BrainAPI must stop treating a Brain, an access credential, a browser login session, and an administrator credential as the same concept.
Target model:
```text
SYSTEM_PAT
└── one stable deployment-level administrator credential
├── administer brains/workspaces
├── create/revoke scoped access tokens
├── access any workspace
└── qualify the service
Brain / Workspace
└── durable resource identity
├── no automatically generated credential
└── no credential stored as part of resource identity
AccessToken
└── explicit named credential
├── scoped to one brain/workspace
├── explicit permissions
├── hash at rest
├── plaintext shown once on creation
└── revocable independently of the brain
ConsoleSession
└── short-lived browser session
├── created after an access token is verified
├── opaque HttpOnly Secure cookie
├── never persists SYSTEM_PAT or scoped token in browser storage
└── may have no selected workspace until the human chooses one
```
This pass must also fix the runtime defects observed in live Hugging Face testing:
split `SYSTEM_PAT` / `BRAINPAT_TOKEN` semantics;
console rejects a valid system credential because login validation hits `/meta/entity-labels` against a fake `default` brain;
every Brain automatically generates a fresh PAT;
generated PATs can leak through SQL/error logs;
invalid structured-ingest requests become HTTP 500 because validation errors contain a non-JSON-serializable `ValueError`;
failed ingestion causes repeated `/tasks/None` polling;
trace queues fill while probing unused Mongo/Neo4j/Milvus/RabbitMQ services;
HF memory runs on ephemeral filesystem when `/data` is absent without a strong release gate;
secondary hardening warnings: Celery as root, PostgreSQL `SQL_ASCII`/trust defaults, unresolved Pydantic warning.
The registry-authority fixes from `42cde779...` and the qualified EmbeddingGemma 2 / 512d vector contract are invariants and must not regress.
---
1. Non-negotiable invariants
1.1 Registry authority
The persisted Brain registry is authoritative.
An unknown brain read must return:
```text
404 BRAIN_NOT_FOUND
```
and must not create:
Brain rows;
Workspace rows;
PostgreSQL databases/schemas;
vector indexes;
graph state;
Redis application state.
This includes semantically read-only POSTs such as `/retrieve/search` and `/retrieve/context`, plus Agent API and MCP equivalents.
1.2 Credentials are not resource identity
Creating a Brain or Workspace MUST NOT implicitly create a credential.
Deleting/archiving a resource MUST NOT rotate unrelated credentials.
Rotating/revoking a credential MUST NOT change Brain or Workspace identity.
1.3 One canonical administrator secret
`SYSTEM_PAT` is the canonical deployment-level administrator secret.
HTTP, MCP, console, qualification scripts and optional OAuth must all resolve system identity through the same auth service.
1.4 No default administrator token
Remove every usable fallback such as:
```python
os.getenv("SYSTEM_PAT", "brainpat_default_token")
```
Missing administrator credentials must fail closed in production.
1.5 Plaintext-token rule
Plaintext credentials may exist only:
while being verified;
while a newly created scoped token is returned once;
as the injected `SYSTEM_PAT` secret.
They must never be:
stored in Brain rows;
returned by Brain/workspace listing APIs;
written to logs, traces, SQL errors or exceptions;
stored in browser `localStorage`/`sessionStorage`;
committed to repository files.
---
2. Current defects to replace
At PR #8 head, system auth is split approximately as follows:
```text
BrainPATMiddleware -> SYSTEM_PAT
/meta/login-info -> SYSTEM_PAT
console copy -> SYSTEM_PAT
Config.brainpat_token -> BRAINPAT_TOKEN
entrypoint bootstrap -> BRAINPAT_TOKEN
HF env example -> BRAINPAT_TOKEN
MCP legacy/system path -> BRAINPAT_TOKEN
```
This is invalid because it can create two administrator credentials.
The console also currently treats system auth as:
```json
{"is_system_pat": true, "brain_id": "default"}
```
then calls `/meta/entity-labels` to validate login. With `DEFAULT_BRAIN_FALLBACK=false`, a valid system token may authenticate and still be rejected by the UI because no `default` Brain exists.
The current `Brain` model also auto-generates `pat` with Python `random.choice`; this must be removed from new resource creation.
---
3. Central AuthService
Create one authoritative auth service. Exact module layout may follow repo conventions, but all surfaces must delegate to it.
Suggested conceptual API:
```python
class AuthService:
def authenticate_token(self, token: str) -> Principal: ...
def authorize_workspace(self, principal: Principal, brain_id: str, permission: str) -> None: ...
def create_access_token(self, ...) -> IssuedToken: ...
def revoke_access_token(self, token_id: str) -> None: ...
def list_access_tokens(self, ...) -> list[AccessTokenMetadata]: ...
def create_console_session(self, principal: Principal) -> ConsoleSession: ...
def resolve_console_session(self, cookie: str) -> Principal: ...
def revoke_console_session(self, cookie: str) -> None: ...
```
These must use it:
`BrainPATMiddleware`;
`/auth/*`;
`/meta/login-info` compatibility route;
workspace Agent API;
workspace MCP;
root/legacy MCP while retained;
system/workspace admin routes;
console;
qualification scripts.
After this refactor, route/middleware code must not perform independent system-token environment comparisons.
---
4. Canonical SYSTEM_PAT and compatibility migration
Resolve secrets at startup as follows:
```text
SYSTEM_PAT set, BRAINPAT_TOKEN unset
-> use SYSTEM_PAT
SYSTEM_PAT unset, BRAINPAT_TOKEN set
-> temporarily use BRAINPAT_TOKEN as legacy alias
-> emit one deprecation warning, never the value
both set and identical
-> use SYSTEM_PAT
both set and different
-> FAIL STARTUP with SYSTEM_PAT_CONFLICT
neither set
-> production: FAIL STARTUP
```
There must never be two simultaneously valid system administrator tokens.
Expose one resolved config field:
```python
config.system_pat
```
Any temporary `config.brainpat_token` compatibility property must resolve to the same canonical value and be marked deprecated.
Update:
`entrypoint.sh`;
`deploy/env.hf.cpu.example`;
`Agent.md`;
console help copy;
MCP code;
qualification scripts.
---
5. Principal model
Introduce an explicit principal.
Example:
```python
@dataclass(frozen=True)
class Principal:
kind: Literal["system", "access_token", "console_session"]
subject_id: str
brain_id: str | None
permissions: frozenset[str]
token_id: str | None = None
```
System principal:
```text
brain_id = None
permissions includes system:admin
```
Scoped principal:
```text
brain_id = lifeos-projects
permissions = explicit scoped permissions
```
A system principal MUST NOT be represented as `brain_id="default"`.
---
6. Explicit scoped access-token registry
6.1 Data model
Persist explicit access tokens in the system PostgreSQL database.
Minimum fields:
```text
id
label
brain_id
token_prefix
token_hash
permissions
created_at
last_used_at
expires_at
revoked_at
legacy
created_by
```
Do not store plaintext.
6.2 Token generation
Generate with `secrets`, e.g.:
```python
plaintext = "bpat_" + secrets.token_urlsafe(32)
```
Persist a cryptographic hash and a safe display prefix.
6.3 Permission vocabulary
Minimum target vocabulary:
```text
memory:read
memory:write
brain:read
system:admin
```
If granular route mapping is too large for the first pass, `brain:read` / `brain:write` may be used initially, but permission storage and centralized authorization must exist now.
6.4 Resource creation no longer creates credentials
These create resources only:
```text
POST /system/brains
POST /system/workspaces
```
They MUST NOT generate or return a PAT.
6.5 Token-management endpoints
System administrator only:
```text
GET /system/access-tokens
POST /system/access-tokens
DELETE /system/access-tokens/{token_id}
```
Example create request:
```json
{
"brain_id": "lifeos-projects",
"label": "hermes-prod",
"permissions": ["memory:read", "memory:write"]
}
```
Creation response may return the new plaintext token exactly once:
```json
{
"id": "...",
"label": "hermes-prod",
"brain_id": "lifeos-projects",
"permissions": ["memory:read", "memory:write"],
"token_prefix": "bpat_ab12...",
"token": "bpat_<plaintext-shown-once>"
}
```
List endpoints NEVER return plaintext or token hash.
---
7. Legacy per-brain PAT migration
Existing stored Brain PATs must remain temporarily usable so current agents are not locked out.
During the compatibility window, `AuthService.authenticate_token()` may check:
canonical system PAT;
new access-token registry;
legacy persisted Brain PAT.
Legacy PAT rules:
own Brain only;
never system privileges;
rate-limited deprecation warning without token value;
internally identifiable as legacy;
no new Brain receives an automatic legacy PAT.
Provide a migration/rotation helper that reports Brain name and migration status without printing plaintext.
Any token previously emitted in SQL/application logs must be considered exposed and rotated after the new registry is available.
---
8. Browser console authentication
The console must stop keeping plaintext PATs in browser storage.
8.1 Endpoints
Add:
```text
POST /auth/session
GET /auth/me
POST /auth/logout
```
`POST /auth/session` accepts a token over TLS, verifies it through `AuthService`, creates a random opaque server-side Redis session, and returns an HttpOnly cookie.
Cookie requirements:
```text
HttpOnly
Secure
SameSite=Strict
Path=/
configurable TTL, default ~8h
```
Do not echo the submitted token.
8.2 CSRF
Cookie-authenticated unsafe browser requests must use a CSRF token associated with the server session and sent in `X-CSRF-Token`.
Direct Bearer/BrainPAT agent requests do not use browser CSRF.
8.3 `/auth/me`
System response:
```json
{
"authenticated": true,
"kind": "system",
"is_system": true,
"brain_id": null,
"permissions": ["system:admin"]
}
```
Scoped response:
```json
{
"authenticated": true,
"kind": "access_token",
"is_system": false,
"brain_id": "lifeos-projects",
"permissions": ["memory:read", "memory:write"]
}
```
8.4 Console storage
Remove token plaintext from `AuthSession` / `sessionStorage`.
The console may store non-secret UI state such as API base URL and last workspace slug.
8.5 Login UI
Rename human-facing `BrainPAT` field to `Access token`.
Explain two token classes:
```text
Administrator token
SYSTEM_PAT configured by deployment operator
Workspace token
explicit named scoped token created for an integration/agent
```
Do not tell users that Brain creation returns a token.
8.6 System login flow
Correct flow:
```text
POST /auth/session
GET /auth/me -> system, brain_id=null
GET /system/workspaces
select valid workspace
```
Use last valid workspace if present; otherwise first active workspace; if none exist, show admin empty state.
DO NOT call `/meta/entity-labels` to decide whether login succeeded.
DO NOT invent a `default` Brain.
8.7 Scoped login
A scoped token login:
resolves the token's Brain;
discovers only authorized workspace(s);
selects its workspace;
hides system/workspace-admin controls.
---
9. Agent and MCP authentication
New integrations should prefer:
```http
Authorization: Bearer <token>
```
Keep:
```http
BrainPAT: <token>
```
as compatibility transport.
All validation delegates to `AuthService`.
For `/brains/{workspace_slug}/...`:
```text
system principal -> allowed
matching scoped token -> allowed according to permission
valid different-brain token -> 403 FORBIDDEN
unknown/revoked token -> 401 AUTH_INVALID
```
Workspace MCP must accept the SAME canonical system PAT as HTTP and console. It must not use independent `BRAINPAT_TOKEN` administrator semantics.
Legacy root MCP may remain but must use the same service.
---
10. Compatibility `/meta/login-info`
Keep temporarily for old clients as a thin view over `/auth/me`.
System:
```json
{"is_system_pat": true, "brain_id": null}
```
Scoped:
```json
{"is_system_pat": false, "brain_id": "lifeos-projects"}
```
Mark deprecated. Never return `"default"` for system auth.
---
11. Structured-validation error serialization
Current failure:
```text
RequestValidationError
-> exc.errors()
-> ctx.error contains ValueError
-> JSONResponse serialization fails
-> HTTP 500
```
Required behavior:
```text
invalid request
-> HTTP 422
-> JSON-safe VALIDATION_ERROR envelope
```
Sanitize error details using an appropriate FastAPI/Pydantic JSON encoder or a safe recursive encoder.
Expected shape:
```json
{
"detail": [
{
"type": "value_error",
"loc": ["body", "data", 0],
"msg": "Value error, direct triples require subject, subj_event, and object",
"ctx": {"error": "direct triples require subject, subj_event, and object"}
}
],
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed.",
"resolution": "Correct the fields listed in detail and retry.",
"request_id": "..."
}
}
```
Regression-test both root and workspace structured-ingest routes.
---
12. Stop `/tasks/None` polling
Repository clients/console may poll task status only when:
```text
HTTP == 202
AND task_id is a non-empty string
```
For 4xx/5xx:
render the structured error;
do not start polling.
For malformed 2xx without task ID:
fail client-side with a deterministic contract error;
do not request `/tasks/None`, `/tasks/null`, etc.
Add a regression test proving failed ingestion generates zero task-status requests.
---
13. Route discovery
Do not add arbitrary aliases solely to hide caller mistakes.
Document canonical routes and mark observed wrong patterns as invalid.
Canonical examples:
```text
POST /system/brains
POST /system/workspaces
GET /brains/{slug}/agent/capabilities
GET /brains/{slug}/api/openapi.json
GET /brains/{slug}/agent/openapi.json
```
Invalid/obsolete examples seen during probes:
```text
POST /brains
POST /system/brains/{id}
GET /system/brains/{id}
GET /agent/capabilities
GET /brains/{slug}/api/meta/login-info
```
Clients should discover routes from workspace discovery/OpenAPI instead of guessing paths.
---
14. Runtime tracing hardening
14.1 Probe only active dependencies
HF profile should monitor:
```text
PostgreSQL yes
Redis yes
Ollama yes
```
Probe MongoDB/Neo4j/Milvus/RabbitMQ only when configured as active backends.
14.2 Queue consumer invariant
No trace consumer/sink must mean no indefinitely accumulating queue.
Acceptable designs:
do not enqueue when no subscriber exists;
install a bounded logging subscriber;
explicit `TRACE_MODE=disabled|log|queue`.
HF default must not fill the 10k queue and spam one warning per dropped event.
14.3 Saturation behavior
If drops occur:
rate-limit warning logs;
expose dropped-event count;
do not emit an endless warning storm.
---
15. Persistence state and release gate
BrainAPI is a memory service. Ephemeral state must be first-class and visible.
Expose:
```text
PERSISTENCE_MODE=durable|ephemeral
```
auto-detected from configured durable root.
Health/readiness should include non-secret persistence state.
Example:
```json
{
"status": "degraded",
"service": "brainapi",
"persistence": {
"mode": "ephemeral",
"root": "/app/.data/brainapi"
}
}
```
Production without durable storage may start only with an explicit staging/recovery override such as:
```text
ALLOW_EPHEMERAL_STORAGE=true
```
but then:
health remains degraded;
console shows a persistent warning;
production release qualification is NO-GO.
Do not break local development defaults unnecessarily.
---
16. Secondary hardening
Implement where safe in this pass; otherwise report explicitly as follow-up blockers.
PostgreSQL
new clusters should use UTF-8 rather than `SQL_ASCII`;
prefer safe local password/SCRAM auth over broad trust if practical;
do not destructively reinitialize existing clusters.
Celery
Run worker as a dedicated unprivileged user rather than root.
Pydantic warning
Resolve the unresolved `lifespan` forward-reference warning or identify its upstream owner. Do not globally suppress warnings.
---
17. Console access-token UX
System administrators get an `Access tokens` section in workspace settings.
Show only metadata:
```text
Label
Token prefix
Permissions
Created
Last used
Expiry
Status
```
Actions:
```text
Create token
Revoke token
```
Creation must warn:
```text
This token is shown once. Copy it now.
```
No reveal-existing-token function.
Never show `SYSTEM_PAT` in the UI.
Scoped users must not see token administration unless explicitly authorized.
---
18. Brain/workspace response audit
These must never return credential plaintext:
```text
/system/brains-list
/system/workspaces
/system/workspaces/{slug}
workspace discovery
console bootstrap
```
Remove/deprecate `pat` from client-visible Brain models.
A legacy DB `pat` column may remain temporarily during migration but must not leak through serialization.
---
19. Logging/redaction
Create a reusable secret-redaction policy for:
```text
SYSTEM_PAT
Authorization
BrainPAT
new access-token plaintext
legacy Brain PAT
Postgres password
Redis password
Celery URL credentials
```
Do not debug auth by logging token values.
Database errors must no longer contain plaintext token INSERTs because new token storage contains only hashes.
---
20. Required tests
20.1 Config resolution
```text
SYSTEM_PAT only -> success
legacy BRAINPAT_TOKEN only -> success + deprecation
both identical -> success
both different -> SYSTEM_PAT_CONFLICT / startup failure
neither in production -> failure
no default admin token -> proven
```
20.2 Auth parity
Across root HTTP, workspace API, Agent API, workspace MCP and retained legacy MCP:
```text
SYSTEM_PAT -> system access
scoped new token -> own brain allowed
scoped new token -> other brain 403
unknown token -> 401
missing token -> 401
revoked token -> 401
legacy Brain PAT -> own brain allowed during migration
```
20.3 Console login
System:
```text
POST /auth/session -> success
GET /auth/me -> brain_id null
GET /system/workspaces -> success
no /meta/entity-labels validation required
```
Scoped:
```text
/auth/session -> success
/auth/me -> correct brain
workspace discovery -> only authorized workspace
```
Invalid credential yields 401 and no session cookie.
Logout invalidates the server session.
20.4 Browser secret handling
Prove plaintext tokens are absent from:
```text
localStorage
sessionStorage
URL
persisted React state after login
```
20.5 Token lifecycle
```text
create Brain -> no token generated
create Workspace -> no token generated
create access token -> plaintext once
list tokens -> no plaintext/hash
use token -> success
revoke -> subsequent auth fails
```
20.6 Validation serializer
Malformed structured ingestion on root and workspace API:
```text
422 VALIDATION_ERROR
JSON serializable
no exception object
```
20.7 Task polling
Failed ingestion generates zero `/tasks/None`/`null` requests.
20.8 Trace monitoring
HF profile:
```text
probes Postgres, Redis, Ollama
not Mongo/Neo4j/Milvus/RabbitMQ
queue remains bounded/drained over simulated time
```
20.9 Persistence
Test durable and ephemeral modes; ephemeral production is visibly degraded and cannot receive production GO.
20.10 Preserve existing gates
Rerun:
authoritative registry B1-B4 tests;
real PostgreSQL/Redis integration;
EmbeddingGemma qualification.
Embedding requirements remain:
```text
embeddinggemma-2:270m
native 768
stored 512
all five pgvector schemas vector(512)
no runtime model pull
```
---
21. Implementation order
Phase A — central auth resolution
Add central `AuthService` / Principal model.
Resolve `SYSTEM_PAT` plus legacy alias.
Switch middleware, meta and MCP to it.
Add config/auth tests.
Keep legacy Brain PAT validation.
Phase B — console sessions
Add `/auth/session`, `/auth/me`, `/auth/logout`.
Redis-backed opaque sessions + CSRF.
Remove plaintext PAT browser persistence.
Remove fake default Brain.
Remove `/meta/entity-labels` login validation.
Phase C — explicit access-token registry
Add token persistence.
Add create/list/revoke APIs.
Cryptographic generation + hash at rest.
Stop automatic `Brain.pat` creation.
Add admin token-management UI.
Phase D — legacy migration
Preserve legacy validation.
Add migration/rotation tooling.
Document exposed-token rotation.
Phase E — runtime correctness
Fix 422 serialization.
Fix null task polling.
Fix trace monitoring/queue behavior.
Add persistence degraded state.
Apply safe secondary hardening.
Phase F — qualification
focused deterministic tests;
real PostgreSQL/Redis integration;
full non-integration suite;
full production Docker build;
offline EmbeddingGemma qualification;
exact-SHA HF deployment;
live acceptance.
---
22. Live HF acceptance gate
Do not claim completion from local tests alone.
Deploy one exact candidate SHA and record both GitHub candidate and HF source revision.
Authentication
```text
SYSTEM_PAT:
/auth/session -> success
/auth/me -> system, brain_id=null
/system/workspaces -> 200
console login -> success
workspace MCP -> success
```
There must be no second administrator secret.
Scoped token
Create a temporary named token for a disposable workspace:
```text
own Agent API -> success
own Native API -> success
own MCP -> success
other workspace -> 403
revoke token -> subsequent request 401
```
Registry regression
```text
unknown entities -> 404 BRAIN_NOT_FOUND
unknown search -> 404 BRAIN_NOT_FOUND
unknown context -> 404 BRAIN_NOT_FOUND
```
Registry/storage/cache unchanged.
Validation
Malformed structured ingest:
```text
422 VALIDATION_ERROR
```
not 500.
UI/client must not poll a task after that failure.
Tracing
Observe multiple monitor intervals:
no queue-full storm;
no DOWN spam for unused dependencies.
Persistence
If runtime remains ephemeral:
```text
release = DEGRADED / NOT PRODUCTION DURABLE
```
---
23. Out of scope
Do not redesign:
EmbeddingGemma model choice;
768 -> 512 Matryoshka/L2 pipeline;
retrieval/reranking architecture;
workspace URL authority;
B1-B4 registry architecture;
general agent orchestration;
external LifeOS behavior beyond documented client contracts.
Do not introduce a second identity provider merely to avoid fixing token semantics.
Optional MCP OAuth may remain, but it must resolve principals through the same central auth service.
---
24. Documentation terminology
Update `Agent.md`, HF env example, hosted-use docs, OpenAPI descriptions and console copy.
Canonical terms:
```text
SYSTEM_PAT
deployment administrator secret
Access token
named scoped credential for one Brain/Workspace
Console session
temporary browser session derived from verified credentials
Brain
memory namespace
Workspace
hosted routing/display facade for a Brain
```
The `BrainPAT` header may remain as compatibility transport, but do not call every credential a BrainPAT in human-facing UX.
---
25. Required final report
Return:
```text
branch
base SHA
final SHA
files changed
auth architecture implemented
SYSTEM_PAT migration behavior
legacy BRAINPAT_TOKEN behavior
legacy per-brain PAT behavior
new access-token schema
console session behavior
test counts/results:
config/auth
console
token lifecycle
migration
validation 422
task polling
tracing
persistence
registry regression
embedding qualification
integration
full suite
production Docker build result
HF deployed source revision
live auth results
live scoped-token results
live registry results
live 422 result
trace result
persistence mode
known exposed-token rotation status
remaining blockers
production GO/NO-GO
```
Do not report production GO while persistence is ephemeral.
Do not report auth GO unless HTTP API, console and MCP all accept the same canonical system administrator credential.
---
26. Definition of done
```text
[ ] exactly one canonical system administrator credential exists
[ ] SYSTEM_PAT works consistently in HTTP, console and MCP
[ ] legacy BRAINPAT_TOKEN cannot become a second independent admin secret
[ ] missing system secret fails closed
[ ] no usable default admin token exists
[ ] system console session has brain_id=null until workspace selection
[ ] console does not validate login through /meta/entity-labels
[ ] console does not persist plaintext PAT/token in browser storage
[ ] Brain creation does not generate a credential
[ ] Workspace creation does not generate a credential
[ ] scoped tokens are explicit, named, revocable and hashed at rest
[ ] plaintext scoped token is returned only once
[ ] Brain/workspace listings expose no token plaintext
[ ] old per-brain PATs temporarily work only for their own Brain
[ ] exposed legacy tokens have a rotation path
[ ] malformed requests return JSON-safe HTTP 422
[ ] failed ingestion never causes /tasks/None polling
[ ] trace monitor checks only active dependencies
[ ] trace queue cannot silently fill forever without a consumer
[ ] persistence mode is explicit
[ ] ephemeral persistence prevents production GO
[ ] authoritative registry regression tests pass
[ ] EmbeddingGemma 768->512 qualification passes
[ ] full production image builds
[ ] exact candidate SHA is deployed and verified live
```
## GitHub content checkpoints
Content backup runs before WorkspaceService.bootstrap and before serving. It
preserves canonical Brain IDs/workspaces and logical PostgreSQL data/graph/vector
contents with the full EmbeddingGemma index identity. Authentication registries,
legacy PATs, SYSTEM_PAT/GITHUB_PAT, token hashes, console/CSRF/Redis state and
internal passwords are excluded. Empty local data may restore a fully validated
snapshot; populated databases with unknown/divergent lineage fail closed rather
than being overwritten. Only registered Brains are exported. Periodic debounced
checkpoints and a bounded graceful-shutdown attempt use non-force Git pushes,
checksums and an operation lock. Existing authoritative registry, unified-auth,
side-effect-free missing-Brain reads and 768→512 embedding contracts continue to
apply. See docs/content-backup.md for format, recovery, variables and RPO limits.
## Verified checkpoint maintenance and explicit RPO policy
Preserve all unified-auth, authoritative-registry, side-effect-free 404 and
EmbeddingGemma native-768 → normalized-512 contracts above. Administrator-only
`/system/backup/{quiesce,checkpoint,status,resume}` controls content admission and
tracks accepted HTTP/MCP/Celery work through terminal settlement. A checkpoint
barrier must push, re-fetch HEAD and validate manifest/checksums before returning
its durable SHA; failures retain a closed write gate. Its non-secret manifest
handoff hold survives restore and requires explicit resume. No auth/session
registry joins content backup.
Startup verifies remote HEAD after restore and after workspace bootstrap. An
advance fails closed before serving stale writable content. Health distinguishes
local storage from checkpoint recoverability and exposes SHA/lag/dirty/age fields.
`BRAIN_BACKUP_MAX_RPO_SECONDS` defaults to interval=300; explicit operator opt-in
`ALLOW_CHECKPOINTED_PRODUCTION=true` permits ephemeral production readiness only
with qualified restore, current remote lineage, successful verification within
RPO, and healthy auth/database/embedding/access logging. Default false retains
NO-GO. Checkpoint recovery is always `zero_loss_durable=false`; abrupt termination
may lose writes since the last successful checkpoint.