Building blocksDatabase

Astrogate Database usage

Documentation version: 858adedd187db2e94614b1dfd389e4bf98e6e202:ac5d527caaa1f97eee9d71262e7c843ae7b24000e01ba5b44931108b2b489c0d

Status: working-tree integration, 28 October 2026. The package is private and unpublished. Use the pinned maintained engine and clients from this repository. The acceptance ledger owns profile evidence and open gates. This guide does not authorize a production deployment.

Resolve an environment first

A trusted operator registers a database group, exact public HTTP/WSS endpoints, private engine origin, configured login authority and allocation owner. Every technical tenant, project and environment needs explicit admission budgets. Missing policy denies admission. Shared environments use native logical apps on one shared engine; this is not one engine process per app. Dedicated and Private placements have ownership models but are not accepted by the Shared rehearsal.

The management API creates a database through a durable operation:

const accepted = await management.databases.create(projectId, environmentId, {
  expectedRevision: 1,
  expectedEnvironmentKind: 'preview',
  initializationRef,
}, { idempotencyKey, signal });
const operation = await management.operations.get(accepted.operationId, signal);
const binding = await management.databases.get(projectId, environmentId, signal);

management is the configured server-only management client. Its credential is independently scoped by the API. The caller retains the logical idempotency key across a lost acknowledgement; reading a pending operation is not cancellation. Wait for successful completion and a ready binding. The registered data gateway also accepts a server-only POST /v1/database/probe with {appId} and a scoped resource.read observer credential. It verifies native app-credential/schema access and returns only {ready: true}; it cannot grant a database session or return customer records.

Native pg-boss owns retries, and one coordinator owns creation and credential maintenance. No Git provider, application framework or application server receives its own provisioner.

The public binding contains the native app UUID, exact environment and role, revision, initialization/schema/dataset references, cell/location and HTTP/WSS endpoints. It contains no administrator, PostgreSQL or secret-manager credential. A branch name, NODE_ENV or a manifest cannot grant access or implicitly choose Production.

Browser and React

Use the actual native schema and methods. These names are inferred from the pinned native packages, not copied into a second query API:

import { createClient, i, id } from '@astrogate/sdk/browser';

export const schema = i.schema({
  entities: {
    items: i.entity({ name: i.string(), ownerId: i.string() }),
  },
});

const astrogate = createClient({ binding, schema });
await astrogate.db.auth.signInWithToken(databaseSessionToken);
const result = await astrogate.db.queryOnce({ items: {} });
await astrogate.db.transact(
  astrogate.db.tx.items[id()]!.update({ name: 'Example', ownerId: nativeSubject }),
);

The application's authenticated server obtains databaseSessionToken using the session exchange below. nativeSubject is the app-specific native identity returned by the verified native session, never a role or permission supplied by the browser. Production policies must constrain record ownership through native CEL. A public app UUID is not authority to read data.

@astrogate/sdk/react composes the actual native React factory and inferred hooks with the same binding/schema. Follow the native lifecycle: unsubscribe when disposing a subscription and shut down an owned standalone client when it is no longer used. Browser state is not an SSR request-user container.

Application server and configured authentication

Better Auth verifies the application's signed cookie, live session and logout. Its private introspection adapter returns authority, subject, session ID and expiry. Infrastructure checks the configured authority and an explicit app grant, and maps the subject to a stable app-specific native UUID. Email is never the linking key. Operator GitHub login is a separate authority.

import {
  exchangeDatabaseSession, createClient,
} from '@astrogate/sdk/server';

const token = await exchangeDatabaseSession({
  binding,
  cookie: request.headers.get('cookie') ?? '',
  issuerCredential,
  signal: request.signal,
});
const astrogateServer = createClient({ binding, schema, sessionToken: token });
const result = await astrogateServer.db.query({ items: {} });

The issuer credential stays in the application server. Infrastructure validates its database.session.issue capability and exact registered app/actor binding; a forged app ID or native user token cannot become an issuer. Cookies need not cover the infrastructure domain. Do not accept an arbitrary caller-provided binding or forward a credential through redirects. Resolve it through the trusted environment owner.

The server client is the actual native admin package restricted with asUser({token}); it is not a platform administrator. Privileged schema, platform, storage and token-creation routes are denied at the data gateway. Passing a different asUser option cannot elevate an application token.

The installed data gateway bounds metadata/authority admission as well as native work. Realtime initialization has a separate bounded handshake; persistent sockets are not subject to a short HTTP response lifetime.

Existing HTTP and realtime access is revalidated against the live authority and app grant. The initial target deadline is at most 60 seconds, including the configured revalidation cadence and request deadline; see measured results in the ledger. Authority unavailability fails closed. Native sign-out invalidates the exact database session, and another sign-in reserves a different token. Queue-owned collection revokes expired/disabled native sessions and removes their encrypted authority cookies. It retains retry state until retirement succeeds. Scoped cookie/token values never belong in logs or browser builds.

Native behavior and supported boundary

The executed subset includes inferred entity schemas, native query/transaction syntax, record ownership CEL, scoped server queries, real browser read/write/ delete, reactive subscriptions and reconnect after controlled database recovery. Use the native source inventory for reviewed upstream provenance. The compatibility tests are in sdk/test/ and api/internal/database/.

The current gateway permits native query, transaction, session verification, exact sign-out and the reviewed realtime query/presence events. Unused native login, guest, administration, schema, file, stream, SSE and secret-sync routes are denied. A method existing on an upstream client is not permission to use a blocked lane. Native storage and managed jobs remain their own later blocks.

Native admin-only aggregates do not become available through an app-scoped server client. Grouping and additional aggregates are not implemented. This building block does not expose unrestricted PostgreSQL SQL or a complete customer login service. The minimum Better Auth/session boundary is implemented before protected data access, rather than postponed to the later identity step.

Explicit Preview dependency startup

The portable astrogate.json declares requirements only:

{
  "version": 1,
  "framework": "next",
  "database": { "initializationRef": "sha256:<reviewed-plan-digest>" }
}

The supported startup subset resolves an explicitly authorized hosted Preview. The installation already supplies PostgreSQL, the maintained engine, OpenBao, the authority adapter, queue and coordinator. A local application can use that binding with the same SDK. A complete local laptop engine bundle and the application watcher/start command remain step 4 and later installation gates. SDK import never starts services.

Build api/cmd/astrogate-dependencies and invoke it explicitly, for example:

astrogate-dependencies -project /absolute/app -target /private/preview-target.json \
  -output /absolute/app/.astrogate-binding.json -deadline 30s -poll 250ms \
  -response-bytes 16384

These polling/deadline/envelope values are an installation test example, not commercial app limits. Choose the profile's justified values. The protected 0600 target file supplies Origin, CAFile, TokenFile, Tenant, Project, Environment and ExpectedRevision. No token value appears in the manifest or command line. The server enforces the Preview role precondition before native creation, and the launcher also verifies the returned role. Concurrent starts reuse one app; output is replaced atomically only after readiness. A readiness failure preserves operation state and data and returns an actionable error.

Reviewed schema and safe test data

Installation configuration registers immutable native initialization files by product, tenant, project and SHA-256 reference. A file contains schemaRevision, datasetRevision, native transaction steps and native CEL rules. The trusted operator reviews those effects; an arbitrary request cannot select another project's initialization or administrator credential.

Schema/data steps and a protected initialization marker commit in one native transaction. Failed steps roll back. Retrying after an acknowledgement loss reuses the marker and does not overwrite edited data. The controller reapplies only the matching initial policy before atomic readiness and records actual schema/dataset revisions. A ready operation is not initialized again. A delayed bootstrap uses atomic insert-if-absent for its initial deny policy and cannot replace already initialized permissions. Changed templates require an explicit migration/reset decision. A test dataset is rejected for Production.

astrogateInitialization is an internal marker namespace denied by native CEL; application callers cannot read, create, change or delete its records. A public schema import is not an administrator endpoint, and an application session cannot change this policy. Supported code/database migration ordering for customer deployments is the next application-hosting step, not an automatic extension of this startup command.

The Preview launcher probes native connectivity again on reuse. Metadata readiness alone is insufficient. A changed initialization reference reports an explicit migration requirement and preserves existing data. Live probes use the registered endpoint and installation trust roots, never a manifest-supplied hostname.

On this page