Provisioning data resources

Databases, object storage, and Redis all follow the same three-beat pattern: provision → attach → reveal. Provisioning creates the resource inside your project; attaching wires its connection details into a service as env vars; revealing hands you the raw credentials when a tool or a human needs them directly.

The env-var key names are a stable contract — a value can change if a resource is migrated to a different backend, but the key never does. Injected vars take effect on the service’s next deploy or restart.

Databases (Postgres / MySQL)

{ "name": "provision_database",
  "arguments": { "projectId": "…", "kind": "postgres", "attachServiceId": "…" } }
  • kind selects the engine (Postgres or MySQL). provision_database creates the database + user on the platform’s host engine, encrypts the password, and — because attachServiceId is set — auto-creates a DATABASE_URL runtime env var on that service. Omit attachServiceId to provision unattached and wire it up later.
  • reveal_database_credentials returns the full bundle (host, port, db name, user, password, connection URL) using the internal docker-bridge host that services inside the platform use. Every reveal is audit-logged.

Reaching a database from outside the platform

For local development or an external tool, use the public host and an IP allowlist:

  1. add_database_allowlist with a cidr (typically a /32) and optional ttlHours. This adds a rate-limited firewall rule plus an engine-level grant scoped to this DB’s role from this source — cross-tenant probes are refused at the protocol level.
  2. reveal_database_public_credentials returns credentials with the public hostname. The URL only connects from an allowlisted IP.
  3. list_database_allowlist / remove_database_allowlist manage the entries.

Object storage (S3-compatible buckets)

{ "name": "create_bucket",
  "arguments": { "projectId": "…", "label": "uploads", "attachServiceId": "…" } }

create_bucket mints scoped credentials and, when attachServiceId is set, injects six runtime env vars: S3_ENDPOINT, S3_REGION, S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_FORCE_PATH_STYLE.

  • attach_bucket_to_service / detach_bucket_from_service inject or remove those six vars on any service (idempotent). Detaching keeps the bucket and its objects; only the service’s access goes away.
  • reveal_bucket_credentials returns the full credential bundle for an unattached service, a local dev env, or a tool that doesn’t read env vars. Audit-logged; the secret grants full read/write.
  • list_buckets shows buckets in a project and which services each is attached to.

Browser uploads (CORS)

If a browser app makes direct pre-signed GET/PUT requests to a bucket, set a CORS policy:

{ "name": "set_bucket_cors",
  "arguments": { "bucketId": "…", "rules": [
    { "allowedOrigins": ["https://app.example.com"],
      "allowedMethods": ["GET", "PUT", "HEAD"] } ] } }

set_bucket_cors replaces the whole policy (it is not a merge). get_bucket_cors reads the current rules. CORS is enforced by the browser only — it is not access control. A private bucket stays private; every request still needs a signed URL. Avoid "*" origins in production.

Redis / Valkey

Provisioning is asynchronous:

{ "name": "provision_redis",
  "arguments": { "projectId": "…", "tier": "default", "attachServiceId": "…" } }

provision_redis returns immediately with status='provisioning'. tier sets memory: small = 128MB, default = 256MB, large = 1024MB. It is subject to the deploy gate and a host RAM budget (returns quota_exceeded when full).

  1. Poll list_redis until the instance reports status='ready'.
  2. reveal_redis_credentials returns host/port/password and the full REDIS_URL (redis://:<password>@…:<port>/0) — only once ready.
  3. attach_redis_to_service / detach_redis_from_service inject or remove REDIS_URL (idempotent; instance must be ready).

Instances are durable by default (AOF persistence) and reachable from the project’s services over the internal network.

Deleting

Deletes are destructive and mostly irreversible — see Deleting resources for delete_database, delete_bucket, and delete_redis and exactly what each removes vs preserves.