Fixture mode
Status: stable. Fixture mode is supported in the TypeScript SDK via
createFixtureFetch()and in the Rust SDK by construction (GestaltClient::fixture()).
What fixture mode is
Section titled “What fixture mode is”Fixture mode lets you exercise the Gestalt SDK without running the cloud. Calls return shape-correct, deterministic responses. No network. No durable state. No real consequence.
It is useful for:
- Unit tests that exercise your Koerper’s calls without standing up infrastructure.
- Offline development when the cloud is not reachable.
- CI environments where booting the cloud would slow the build.
- Reproducible demos where you need the same response every time.
- SDK shape verification — confirming your code consumes the membrane’s response shape correctly.
It is not useful for:
- Verifying that the cloud accepts your envelopes (use a real cloud in fixture mode for that).
- Proving anything about real consequence (everything is fixture, always).
- Performance testing (fixture mode is fast for the wrong reasons).
TypeScript: createFixtureFetch()
Section titled “TypeScript: createFixtureFetch()”Pass it as the fetchImpl option:
import { GestaltClient, createFixtureFetch } from "@gestalt/sdk";
const client = new GestaltClient({ baseUrl: "http://fixture", fetchImpl: createFixtureFetch(),});
const tenant = await client.tenantSelf();// {// operation: "tenant.self",// outcome: "verified",// body: { tenant: "tenant_node:rheinwerk_calibration", productionAdmission: false },// receipt: { ref: "receipt:fixture_tenant_self", outcome: "verified", fixture: true, ... }// }What createFixtureFetch() returns for each route
Section titled “What createFixtureFetch() returns for each route”Every fixture response carries fixture: true on the receipt and
productionAdmission: false (or equivalent) on the body. A few
illustrative shapes:
| Route | Outcome | Body shape |
|---|---|---|
GET /v1/tenant/self | verified | { tenant, productionAdmission: false } |
POST /v1/intents/precheck | refused | { failedGate: "required_evidence_missing", missingEvidence: ["invoice_payload"] } |
POST /v1/shop/prepare | admitted | { prepareToken: "fixture-prepare-token" } |
POST /v1/shop/commit | admitted | { signer: { kind: "hosted_operator_delegate" }, durableCommit: { status: "fixture" } } |
POST /v1/proofs/request | refused | { failedGate: "missing_entitlement" } |
POST /v1/proofs/bundle | verified | { bundle: { id: "proof_bundle:m6_...", productionAdmission: false } } |
POST /v1/authority/packages/* | admitted | { manifestHash: "sha256:fixture_manifest", sourceHash: "sha256:fixture_source", selfActivation: "refused", productionAdmission: false } |
POST /v1/reality/fork | projected | { productionAdmission: false } |
POST /v1/reality/{commit|diff|promote|discard} | admitted | { productionAdmission: false } |
POST /v1/zeitgestalt/query | verified | { receiptBacked: true } |
POST /v1/human-auth/challenge | verified | { challenge: "human_auth_challenge:...", biometricMaterialSeenByGestalt: false } |
POST /v1/human-auth/passkey/verify | admitted | { humanPresenceReceipt: "...", standingCreated: false, biometricMaterialSeenByGestalt: false } |
POST /v1/effects/intent | queued | { effectIntent, effectOutbox, effectExecutionClaimed: false, rawAdapterPayloadExposed: false } |
POST /v1/effects/dispatch | executed | { effectAttempt, effectReceipt, externalActDuplicated: false } |
POST /v1/economy/invoice | admitted | { invoice, receivableObligation, closureSurface, rawConnectorPayloadExposed: false } |
POST /v1/economy/period-close | admitted | { periodClose, productionAdmission: false } |
Routes not listed return 404 fixture route not found.
Rust: GestaltClient::fixture()
Section titled “Rust: GestaltClient::fixture()”The Rust SDK is fixture-only by construction:
use gestalt_sdk::GestaltClient;
let client = GestaltClient::fixture();It returns serde_json::Value shapes that mirror the cloud’s fixture
responses. See rust.md for examples.
Mixing fixture mode with the live cloud
Section titled “Mixing fixture mode with the live cloud”You can talk to the live cloud in fixture mode (the cloud itself is in fixture mode today):
const client = new GestaltClient({ baseUrl: "http://127.0.0.1:3011", token: "fixture-session-token",});Or you can use the SDK’s built-in fixture fetch with no cloud:
const client = new GestaltClient({ baseUrl: "http://fixture", fetchImpl: createFixtureFetch(),});Both will return responses that match the cloud’s contract shape. The first sees actual cloud-side fixture logic (Gravity gates, route handlers, authority resolution). The second is pure local stubs.
For end-to-end fixture tests, prefer the live cloud. For unit tests,
prefer createFixtureFetch().
Fixture bearer tokens
Section titled “Fixture bearer tokens”The fixture cloud accepts these bearer tokens (constants in
crates/gestalt-cloud/src/lib.rs):
fixture-session-token valid primaryfixture-session-token-secondary valid alternateexpired-fixture-session-token refuses with session_expiredwrong-scope-fixture-session-token refuses with scope_mismatchtampered-fixture-session-token refuses with token_tamperedThese let you write tests that exercise the auth refusal paths.
How fixture mode reflects production discipline
Section titled “How fixture mode reflects production discipline”Fixture mode is not a relaxation of the membrane. It is a shape-faithful rehearsal:
- Refusals are emitted with structured fields exactly like production refusals will be.
- Receipts carry the
fixture: truemarker so they cannot be confused with real receipts. productionAdmission: falseis asserted in every response body so no Koerper can accidentally rely on a fixture as if it were authentic.- Operations that close
runtime_owner: cloud_geistboundaries (key custody, package activation) refuse self-activation, refuse unscoped disclosure, refuse cross-tenant access — all in fixture shape.
A Koerper built against fixture mode that handles refusals, projections, pending actions, and closure surfaces correctly will work the day the cloud becomes authentic.
Fixture honesty rules
Section titled “Fixture honesty rules”If you build a Koerper that uses fixture mode:
- Don’t strip the
fixture: truemarker. Anywhere a receipt is surfaced, the marker should be visible. - Don’t display fixture data as real. Mark fixture-derived UI states clearly.
- Don’t fork production logic on fixture status. A Koerper should call the membrane the same way; the cloud’s posture is the cloud’s responsibility.
- Don’t extend the fixture vocabulary. If a refusal code or capability ref is missing, file an issue — don’t invent it client-side.