Demo & dev environments — runbook
Two isolated, non-production surfaces from the design:demo.findmydata.io— a public, isolated demonstration of the real product running on synthetic data only, safe for anyone to poke at.dev.findmydata.io— a private engineering environment behind identity-aware access; never public, never customer data.
1. Demo mode (product) — built
The product has a fail-closed demo mode (FMD_DEMO_MODE=true,
kernel/config.ts). When set, the deployment refuses to boot unless it is
safe as a public demo:
FMD_CONNECTOR_MODEmust bemock— a demo uses synthetic data via the mock M365 tenant, never a live Graph tenant. (Boot fails ongraph.)- Live label writes (
FMD_FEATURE_PURVIEW_LABEL_WRITE) and directory sync (FMD_FEATURE_ENTRA_DIRECTORY_SYNC) are forbidden (boot fails if enabled). demoModeis surfaced atGET /api/ready; the web UI shows a persistent “Demo environment — synthetic data only” banner.
schedule) at whatever cadence you like (e.g. every 6 h).
Hosting the demo
The product is a long-running Bun + SQLite container, so it needs a container host (not Cloudflare Workers). Reuse the existing Azure Container Apps IaC (infra/main.bicep) with a demo profile — set FMD_DEMO_MODE=true,
FMD_CONNECTOR_MODE=mock, FMD_AUTH_MODE=dev (or a demo IdP), an ephemeral
volume (so a restart is a clean slate), and low CPU/memory + max-replicas=1 to
bound cost. Fly.io / Render work equally well. Then:
- Cloudflare DNS:
demo→ the container host (proxied is fine here — no GitHub Pages cert dependency). - Put Cloudflare Turnstile (or Bot Fight Mode) in front to bound abuse.
- Point the scheduled reset job at the demo instance’s volume/DB.
2. Protected dev — dev.findmydata.io via Cloudflare Access
Do not rely on an obscure hostname. Gate the dev instance with Cloudflare
Access (Zero Trust) — an identity-aware proxy with SSO/MFA and narrow
membership. Access is free up to 50 users.
Setup (Cloudflare dashboard → Zero Trust):
- Cloudflare Tunnel (
cloudflared) from the dev host so it needs no public inbound ports — the tunnel dials out to Cloudflare, which routesdev.findmydata.ioto it. Create the tunnel, runcloudflaredon the dev box, and add a public hostnamedev.findmydata.io→http://localhost:8710. - Access application for
dev.findmydata.io:- Policy: Allow only a named list of emails / an identity-provider group (e.g. your Google Workspace), require MFA.
- Session duration short (e.g. 24 h); everything else blocked by default.
- Cloudflare DNS: the Tunnel creates the
devCNAME automatically (proxied). - Validate: an unauthenticated request to
https://dev.findmydata.iois challenged by Access; only allowlisted, MFA’d identities get through.