Demo Provisioning
Demo provisioning has three distinct surfaces. Use the deployed support flow for a durable demo organization, the simulator for local generated activity, and the GCE VM helper only for an isolated ephemeral environment. None of these paths provisions a normal customer organization.
Choose the correct flow
| Flow | Status and scope | Owner | Persistence |
|---|---|---|---|
| Support portal Demos | Current deployed admin flow. Available only to callers with demo IAM permissions. | management-api, with merchant-api, terminal-api, terminal-onboarding, Auth, and Gateway dependencies | Durable application and Gateway state until an authorized demo deletion completes |
| Local simulator | Current local/dev and test-data flow. It targets an already running local stack and can optionally provision through management-api. | tools/simulator | Whatever persistence the selected local stack provides |
| GCE demo VM helper | Manual demo-only helper for an isolated emulator-backed VM. It is not the deployed platform provisioning path. | tools/demo/demo.sh and tools/demo/vm-startup.sh | Ephemeral VM, Spanner emulator, and Firebase Auth emulator state |
The old issue-tracking description is not an operating contract. Current behavior is defined by the controller, durable provisioning worker, simulator, and scripts listed below.
Deployed support flow
The support portal pages are:
apps/websites/portals/support/src/pages/DemosPage.tsxapps/websites/portals/support/src/pages/DemoDetailPage.tsx
They call management-api at /api/v1/demo-orgs. The controller separates read, use, create, and delete permissions (MGMT_DEMOS_READ, MGMT_DEMOS_USE, MGMT_DEMOS_CREATE, and MGMT_DEMOS_DELETE) and scopes agent callers to their accessible demo organizations and agent subtree. Agents may create and delete demos only through these scoped routes; staff remain unscoped. Do not call the API with a broad service credential or bypass the portal permission check.
Creation lifecycle
DemoOrgService.create creates an inactive demo organization and enqueues durable provisioning. DemoOrgProvisioner then, under a task lock:
- creates or reuses the demo store;
- creates or reuses the terminal;
- verifies or relinks the store's Gateway authorization;
- writes a
PEAK_GATEWAYAndroid/native Tap-to-Pay payment configuration; - grants the demo product entitlements and feature-plan settings;
- seeds IAM, a demo administrator, and merchant demo data; and
- activates the organization only after provisioning succeeds.
Creation therefore requires an active root agent with Gateway credentials. Staff callers select an eligible root when more than one exists; agent callers are pinned to their own scoped agent when the request omits agentId, and any supplied agent must remain within their authoritative subtree. A response with status provisioning is not ready for card or catalog demonstrations; the list/detail status becomes ready only after the durable task is complete and a Gateway store binding is operationally authorized.
The implementation sources are:
apps/microservices/management-api/src/main/java/com/myriad/management_api/controller/orgs/DemoOrgController.ktapps/microservices/management-api/src/main/java/com/myriad/management_api/service/DemoOrgService.ktapps/microservices/management-api/src/main/java/com/myriad/management_api/service/DemoOrgProvisioner.ktapps/microservices/merchant-api/src/main/java/com/myriad/merchant_api/controller/internal/InternalDemoController.kt
Deletion boundary
Demo deletion is destructive and intentionally rejects non-demo organizations. It is blocked while provisioning is pending or running. For a demo organization it removes merchant seed data, terminal onboarding tokens, terminal payment configuration and terminal records, Gateway store bindings and organization state, entitlements, stores, and the organization row. External cleanup failures stop final deletion rather than hiding partial cleanup. Agent callers may delete only demo organizations in their authoritative accessible organization set; staff callers remain unscoped.
Use the support portal only after confirming the exact demo organization ID. Never use this delete path as customer offboarding. If cleanup fails, preserve the error and reconcile the named dependency before retrying; do not manually delete the final organization row.
Local simulator
//tools/simulator:simulator is a Bazel java_binary. Its configuration lives in tools/simulator/src/main/kotlin/com/myriad/simulator/config/SimulatorConfig.kt. By default it points at the local Terminal, Merchant, Auth, and Management APIs and signs in to the local Firebase Auth emulator when explicit tokens are absent.
Start the local stack with its canonical local-validation workflow, then launch the simulator with Bazel:
bazel run //tools/simulator:simulator
Use JVM system properties for non-default IDs, URLs, seed, speed, or sim.auto-provision; do not paste real Firebase tokens into shell history. Auto-provisioning invokes ProvisionRunner through management-api, updates the simulator's in-memory IDs, and then proceeds to seed/live scenarios. Without auto-provisioning the simulator uses the configured IDs, which default to the deterministic local seed context.
Focused simulator verification is:
bazel test //tools/simulator:simulator_test
The simulator is not a production load generator. Do not point its mutation scenarios at production.
Ephemeral GCE demo VM helper
tools/demo/demo.sh creates, inspects, connects to, and deletes demo-* Compute Engine instances. tools/demo/vm-startup.sh installs Docker, pulls service images, starts the Spanner and Firebase Auth emulators, and schedules host shutdown after the configured TTL.
Treat this helper as privileged and demo-only:
upcreates a VM and may create a public firewall rule; review the selected GCP project, image tag, zone, machine type, and TTL before running it.downdeletes the named VM and all emulator data; verify the generateddemo-<name>instance before authorizing deletion.- The script defaults are convenience defaults, not evidence of the current deployed environment.
- The generated environment uses emulator credentials and must not receive production secrets, customer data, or production access tokens.
- Automatic host shutdown is not resource deletion. Use the authorized teardown path after the demonstration and confirm the instance is gone.
Use status, list, and logs for non-destructive inspection. Read the script's built-in usage before any up or down operation rather than copying a stale command from a ticket.
Failure ownership
| Symptom | First owner/check |
|---|---|
Demo remains provisioning | Durable onboarding task status and management-api logs |
| Creation says no eligible agent | Active root-agent Gateway credential configuration |
| Gateway binding never becomes ready | GatewayStoreBindingService result; do not replace the demo with cash-only to hide the failure |
| Seed/dashboard/catalog operation fails | merchant-api internal demo endpoint and internal-service authentication |
| Simulator cannot authenticate | Local Firebase emulator and the two configured tenant IDs |
| GCE VM bootstrap fails | tools/demo/vm-startup.sh serial/startup logs and image availability |
| Demo deletion fails | The specific external cleanup failure reported by DemoOrgService; retry only after reconciliation |