Agent-owned database service with HTTP APIs and Nimbus contracts.
This repository is a public mirror. New development happens in the Cumulus Create monorepo.
Source of truth: https://github.com/Cumulus-s/cumulus-create Package: https://www.npmjs.com/package/%40cmls%2Fcumulus-db License: AGPL-3.0-only
npm install @cmls/cumulus-dbCumulus Database is a standalone agent-owned database service. Relay provisions
workspaces through POST /v1/relay/signup; agents then use the returned
endpoint, database id, data token, and admin token.
Cumulus DB v1 now has two storage roles:
- hosted provider runtime: PostgreSQL with
cumulus_systemandcumulus_dataschemas, - local reference engine: deterministic JSONL files under
CUMULUS_DB_DATA_DIR.
The product boundary is not raw SQL. The boundary is Nimbus canonical JSON IR, the HTTP API, the scope model, audit records, snapshots, and SDK/MCP contracts.
This directory is licensed under AGPL-3.0-only. See LICENSE.
The rest of the Cumulus repo is licensed separately. Keep database-provider code inside this directory, and keep app-side integration over HTTP/token APIs.
cp apps/cumulus-db/.env.example apps/cumulus-db/.env
npm run db:build
CUMULUS_DB_MASTER_KEY="$(node -e 'console.log(Buffer.alloc(32, 7).toString("base64"))')" npm run db:startRuntime data is written under CUMULUS_DB_DATA_DIR and is gitignored.
Select the runtime engine with CUMULUS_DB_ENGINE:
# Local reference engine.
CUMULUS_DB_ENGINE=jsonl npm run db:start
# Hosted-style runtime using PostgreSQL.
CUMULUS_DB_ENGINE=postgres \
CUMULUS_DB_POSTGRES_URL=postgres://postgres@127.0.0.1:5432/postgres \
CUMULUS_DB_AUTO_MIGRATE=true \
npm run db:startCUMULUS_DB_AUTO_MIGRATE=false is the default. With that default, apply
postgres/system-v1.sql and postgres/data-v1.sql before startup.
GET /healthPOST /v1/relay/signupGET /v1/databasesPOST /v1/databases/:dbId/recordsPOST /v1/databases/:dbId/searchPUT /v1/databases/:dbId/kv/:keyPOST /v1/databases/:dbId/secrets/revealPOST /v1/env/parseGET|POST /mcp
The provider exposes a local/dev Cumulus-native auth server surface:
GET /.well-known/openid-configurationPOST /oauth/authorizefor authorization code + PKCE with local email-code records,POST /oauth/device_authorizationandPOST /oauth/device_authorization/verifyfor CLI/device login,POST /oauth/tokenfor authorization code, device code, and restricted token exchange,GET|POST /oidc/userinfofor user claims.
This public implementation keeps email, passkey step-up, and rate-limit records in local provider memory. Real email delivery, production OIDC signing keys, durable auth-session storage, and external key custody belong in the private production overlay.
The /v1/system surface is the protected control plane. It uses hard scopes:
database:admin does not automatically satisfy new system scopes.
Tokens that grant hard system scopes require token:create, and the caller
must already hold each hard scope being granted.
GET /v1/system/scopeslists the v1 hard scopes and labels.POST /v1/system/agents/bootstrapcreates a pending agent workspace and returns a limitedcu_agt_v1_<publicId>_<secret>token. It requires the admin header unlessCUMULUS_DB_PUBLIC_AGENT_BOOTSTRAP_ENABLED=trueis set for a local development provider.GET /v1/system/state?dbId=...reads principals, grants, schema versions, snapshots, plans, and approvals. Requiressystem:read.GET /v1/system/audit?dbId=...reads audit events. Requiresaudit:read.POST /v1/system/schema/plancompiles Nimbus source or accepts Nimbus IR, computes the three-way schema plan, and classifies risk. Requiresschema:plan.POST /v1/system/schema/approvalsissues a short-lived plan-bound approval. Requiresmember:approve.POST /v1/system/schema/applyapplies a plan. Safe plans requireschema:apply_safe. Destructive plans requireschema:apply_destructiveand the approval token bound to the plan hash.POST /v1/system/schema/revertrestores a schema version or snapshot. Requiresschema:revert_localand a revert approval token.GET|POST /v1/system/snapshotslists or creates encrypted logical snapshots.
The MCP manifest returns both the compatibility tool-name list and structured
toolSchemas with required arguments, mode, and dry-run-first metadata for
system actions:
cumulus.plan_schema, cumulus.read_system_state,
cumulus.request_approval, cumulus.apply_schema,
cumulus.create_snapshot, cumulus.revert_version, and
cumulus.rotate_self_token.
Build first, then use the provider-owned CLI:
npm run db:build
npm run db:cli -- login --db-id db_example --scope "openid email system:read"
npm run db:cli -- login --device-code dev_code_from_previous_step
npm run db:cli -- agent init --admin-key replace-with-strong-secret
npm run db:cli -- db plan --db-id db_example --token cu_pat_v1_public_secret --file schema.nimbus
npm run db:cli -- db approve --db-id db_example --token cu_pat_v1_public_secret --plan-id plan_example
npm run db:cli -- db apply --db-id db_example --token cu_pat_v1_public_secret --plan-id plan_example
npm run db:cli -- db snapshot --db-id db_example --token cu_pat_v1_public_secret
npm run db:cli -- db approve --db-id db_example --token cu_pat_v1_public_secret --kind revert --version-id ver_example
npm run db:cli -- db revert --db-id db_example --token cu_pat_v1_public_secret --version-id ver_example --approval-token apv_secret
npm run db:cli -- system grants ls --db-id db_example --token cu_pat_v1_public_secret
npm run db:cli -- system grants set --db-id db_example --token cu_pat_v1_public_secret --principal-id agt_example --grant system:read
npm run db:cli -- audit tail --db-id db_example --token cu_pat_v1_public_secret
npm run db:cli -- nimbus check schema.nimbusThe CLI calls HTTP endpoints. It does not import the storage engines directly.
Nimbus is a small declarative language that compiles to canonical JSON. Secrets stay as references:
namespace acme {
collection agents {
fields: {
id: { type: "ulid", required: true },
status: { type: "string", enum: ["active", "disabled", "pending"] }
}
}
secret backup_kek {
from: env("CUMULUS_BACKUP_KEK")
}
}
The compiler:
- emits
nimbus.cumulus/v1alpha1canonical JSON, - sorts keys before hashing,
- promotes
///doc comments, - rejects reserved namespaces such as
systemunless the caller is provider-owned; public HTTP planning never accepts a caller-provided override, - compiles
env("NAME")to{ "kind": "envRef", "name": "NAME" }instead of reading the secret value.
New machine tokens are opaque and classed, for example
cu_agt_v1_<publicId>_<secret>, cu_pat_v1_<publicId>_<secret>, and
cdb_admin_v1_<publicId>_<secret>.
The provider stores the public id and an HMAC-SHA-256 of the random secret using
the provider master key. Old local SHA-256 token records still verify so
existing development workspaces do not break.
The schema lifecycle is:
- compile Nimbus source to canonical JSON IR,
- read live and last-applied state,
- compute a plan with risk labels,
- require approval for destructive plans,
- create an encrypted pre-apply snapshot for medium or higher risk,
- write live and last-applied state,
- append audit records,
- expose a schema version or snapshot as a revert target.
Snapshots are product-level logical snapshots. Each snapshot uses a random per-snapshot DEK with AES-256-GCM and AAD metadata. The DEK is wrapped by the configured provider key in local/dev. Production client-controlled KEK custody belongs in the private overlay, but the public storage format already stores only wrapped keys and ciphertext.
Run this service separately from the Next.js site on a host with persistent
disk mounted at CUMULUS_DB_DATA_DIR, for example /var/data/cumulus-db.
Use Cumulus logical snapshots for restores; disk snapshots are extra safety,
not the database restore format.
Hosted Cumulus should run the official provider on PostgreSQL. The public v1
schema contracts are postgres/system-v1.sql and postgres/data-v1.sql.
cumulus_system holds the control-plane contract for orgs, identities, human
accounts, agent accounts, memberships, tokens, audit logs, schema versions,
snapshots, approvals, and revert runs. cumulus_data is the runtime store used
by PostgresCumulusDbEngine for workspaces, tokens, records, WAL, audit,
system state, and encrypted snapshots. The JSONL engine stays useful for local
development, fixtures, and deterministic tests.