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 16384These 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.