Operations: local fixture
Status: stable for fixture work. Production admission is gated; see reference/fixture-vs-production.md.
This page covers running the fixture cloud locally beyond a one-shot demo: storage profiles, restart persistence, smoke trials, and common patterns.
Quick start
Section titled “Quick start”See getting-started.md for the minute-by-minute walk. The TL;DR:
cargo run -p gestalt-cli -- cloud serve-fixture --addr 127.0.0.1:3011In another terminal:
curl -s http://127.0.0.1:3011/healthcurl -s http://127.0.0.1:3011/v1/tenant/self \ -H "Authorization: Bearer fixture-session-token"Run the cloud directly
Section titled “Run the cloud directly”The gestalt-cloud crate has its own binary you can run without the
CLI wrapper:
cargo run -p gestalt-cloud -- --fixture --addr 127.0.0.1:3011Flags:
--fixture fixture mode (no production admission)--no-root-key disable root signing; require hosted operator delegate--storage-profile <profile> surreal-memory | surreal-remote--addr <ip:port> bind addressStorage profiles
Section titled “Storage profiles”surreal-memory
Section titled “surreal-memory”The default. State lives in process memory and is lost on restart. Useful for quick demos and unit tests.
surreal-remote
Section titled “surreal-remote”Connects to a SurrealDB instance and persists state across restarts.
Required for commit.recent, m7.state, and other staging-durable
operations to retain data.
Set the environment variables (you can also write them to
/etc/gestalt-fixture.env for systemd; locally export them in your
shell):
export GESTALT_STORAGE_PROFILE=surreal-remoteexport GESTALT_SURREAL_REMOTE_ENDPOINT=ws://127.0.0.1:8000export GESTALT_SURREAL_REMOTE_NAMESPACE=gestalt_aion_cloudexport GESTALT_SURREAL_REMOTE_DATABASE=stagingexport GESTALT_SURREAL_REMOTE_TLS_REQUIRED=falseexport GESTALT_SURREAL_REMOTE_USERNAME=rootexport GESTALT_SURREAL_REMOTE_PASSWORD=rootRun a disposable local SurrealDB:
surreal start --user root --pass root --bind 127.0.0.1:8000 memoryThen start the cloud:
cargo run -p gestalt-cloud -- \ --fixture \ --no-root-key \ --storage-profile surreal-remote \ --addr 127.0.0.1:3011--no-root-key requires a durable hosted-operator grant to be
present; the local trial scripts seed one.
M-trial scripts
Section titled “M-trial scripts”The deploy/hetzner-cloudflare/ folder contains end-to-end trial
scripts that you can run locally. They exercise the membrane against
a real (local) cloud + SurrealDB and produce proof bundles under
target/.
deploy/hetzner-cloudflare/cloud-authority-trial.shdeploy/hetzner-cloudflare/gestalt-worldline-trial.shdeploy/hetzner-cloudflare/m7-durable-human-auth-trial.shdeploy/hetzner-cloudflare/m9-connector-evidence-trial.shdeploy/hetzner-cloudflare/m10-m11-effects-economic-trial.shdeploy/hetzner-cloudflare/m12-worldline-runtime-trial.shdeploy/hetzner-cloudflare/m13-identity-delegation-key-trial.shdeploy/hetzner-cloudflare/m14-capability-policy-trial.shEach script:
- starts (or re-uses) a local cloud + SurrealDB,
- runs the milestone-specific scenario through the membrane,
- writes a proof bundle to
target/gestalt-m<N>-trial/.
Set GESTALT_BASE_URL to point at a different cloud (default
http://127.0.0.1:3011).
Restart persistence
Section titled “Restart persistence”To prove that a staging-durable operation actually persists across
restarts:
# 1. start cloud + surreal as above# 2. commit something durablecurl -X POST http://127.0.0.1:3011/v1/commits/recent ...
# 3. stop the cloud# 4. start it againcargo run -p gestalt-cloud -- --fixture --no-root-key --storage-profile surreal-remote --addr 127.0.0.1:3011
# 5. verify the prior commit is still therecurl -s http://127.0.0.1:3011/v1/commits/recent \ -H "Authorization: Bearer fixture-session-token"The M-trial scripts automate this as part of their proof bundles.
The fixture cloud logs to stdout in fixture-shaped JSON. Treat logs
as observability, not as receipts. The receipts (returned in
MembraneResponse.receipt) are the audit-bearing artifacts.
Bearer tokens (recap)
Section titled “Bearer tokens (recap)”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 exist so you can deliberately exercise auth refusal paths.
Common gotchas
Section titled “Common gotchas”- Port already in use. Try a different
--addr. --no-root-keyrefuses commits. The world needs a hosted operator grant first; run a trial script that seeds one.- Surreal connection refused. Make sure
surreal startis running on the configured endpoint. - Receipts have
fixture: true. This is correct. Always.