insigz docs
Product Spec

The Control Plane — insigz Control (platform-owner console)

The backstage console platform owners use to run the fleet of single-tenant instances, handling provisioning, billing, support, and maintenance.

Entry: insigz Control.html (a standalone console with its own login — separate from the tenant app insigz app.html) Files: control/control-data.jsx (seed) · control/control-shell.jsx (theme/router/auth + RBAC + shared UI) · control/control-fleet.jsx · control/control-tenants.jsx · control/control-provision.jsx · control/control-infra.jsx · control/control-surfaces.jsx (Billing · Support · Observability · Audit · Team) · control/control-app.jsx (root + break-glass gate) Doctrine: the same human-commit + full-audit rigor (Q8/Q10) that governs the product governs the control plane — destructive infra actions need a typed confirm, and any tenant-data access is a logged, consented break-glass.

Files 00–16 describe the application/data plane — the product a customer uses. This file describes the control plane: the backstage console the platform owners use to run the fleet of tenant instances. In multi-tenant SaaS terms, the data plane is where tenants do their work; the control plane spans all tenants and handles onboarding, provisioning, billing, support and maintenance for the operators.

Why insigz needs a heavy control plane

insigz is single-tenant by deployment (the full-stack silo model): every customer gets a dedicated, isolated stack — its own Cloud Run service, its own Postgres with row-level security, its own sealed secrets (see §2, §08, the security page). That isolation is a selling point, but it means onboarding a tenant is infrastructure provisioning, not a row insert. The control plane therefore has real responsibilities: it stands up and reconfigures cloud infrastructure when a customer is created, tracks the lifecycle of every instance, and rolls out releases per-tenant. A pooled (shared-DB) SaaS could get away with a thin control plane; insigz cannot.

The two planes (and the two logins)

Data planeControl plane
WhoCustomer analysts, facultyinsigz operators (Ops, Support, Finance, Owner)
Entryinsigz app.htmlinsigz Control.html
ScopeOne tenant's worldEvery tenant
DoesInvestigate, report, war-gameProvision, monitor, bill, support, audit

They are deliberately separate apps with separate auth. The control plane never ships to a customer. A discreet ↗ APP link in the header lets an operator jump to the tenant app (used by break-glass).

Surfaces (the 10-item left rail)

  1. Fleet (/fleet) — the owner's-eye pulse: tenant count by status, contracted ACV (CHF), cloud cost/yr, gross margin %, open incidents, active seats; a fleet-status distribution bar; a Needs attention queue (degraded / suspended / open-ticket tenants); recent control-plane activity; a provision CTA.
  2. Tenants (/tenants) — the master table of every customer (status · region · plan · seats · health · ACV), searchable and status-filtered. Rows open the tenant detail.
  3. Tenant detail (/tenants/:id) — the deep view, tabbed:
    • Instance — the dedicated Cloud Run service (revision, resources, autoscaling, region, custom domain), the isolated Postgres (instance, tier, storage, connections, HA), and Secrets & isolation (Secret Manager keys, last rotated, residency, RLS, audit log). Rotate-secrets is a gated action.
    • Usage & health — API calls/day, ingest/day, DAU, storage (sparklines); uptime / p99 / error-rate; per-tenant incidents.
    • Users — operator-read roster of the tenant's seats (user management itself lives inside the tenant).
    • Contract — the fixed CHF engagement, term, billing split, invoices, and margin (ACV − cloud cost).
    • Support — this tenant's tickets, CSAT, SLA.
    • Danger zoneSuspend / Reinstate, Rotate all secrets, Decommission — each gated; decommission requires typing the tenant's short code.
    • Break-glass (header) — opens the consent gate (below).
  4. Provision (/provision) — the headline. See "The provisioning flow" below.
  5. Infrastructure (/infrastructure) — the whole fleet of Cloud Run services + Postgres instances + secrets across regions; and Releases: channels (stable/legacy), fleet-wide rollout, and per-tenant version pinning (release management — a tenant can stay on a pinned version).
  6. Billing & Finance (/billing) — fixed-price CHF engagements, 12-month terms (not metered SaaS): ACV, one-time setup, cloud cost/yr, blended gross margin; contracts-and-margin-by-tenant table; usage signals (seats, API calls, storage, ingest) shown for FinOps/capacity planning, explicitly not billed; upcoming renewals.
  7. Support (/support) — the cross-tenant ticket queue with SLA timers tied to each plan; filterable by open/pending/closed.
  8. Observability (/observability) — per-tenant health (because a healthy fleet average hides one customer in trouble): avg uptime, open incidents, worst p99, degraded count; active-incident cards; a per-tenant health table with latency sparklines.
  9. Audit log (/audit) — an append-only record of every control-plane action, filterable by kind; break-glass entries are flagged and tinted.
  10. Team & access (/team) — the operator roster and a role/capability matrix.

A ⌘K palette jumps to any surface or tenant.

The provisioning flow (control-provision.jsx)

Provisioning a tenant is a four-stage wizard — Configure → Infra preview → Provisioning → Ready:

  1. Configure — customer name (auto-slugs the subdomain), owner name/email (for the invite), blueprint, region/residency, plan tier (sizes the Cloud Run + Postgres), storage, and the contract value. A note reminds the operator this stands up a fully isolated single-tenant stack; term defaults to 12 months.
  2. Infra preview — a terraform plan-style read-out of exactly what will be created (Cloud Run service, isolated Postgres, secrets, tenant config) with an estimated monthly cost. Nothing is created until confirmed.
  3. Provisioning — a live run of 8 ordered steps, shown two ways at once: friendly steps (Reserving the cloud project → Laying down the private network → Provisioning the dedicated database → Sealing the secrets → Deploying the application → Building the canonical model → Wiring DNS & TLS → Final checks & owner invite) and an expandable raw log streaming the actual gcloud / psql / insigzctl commands. The runner is an idempotent state machine: exactly one step is ever "running"; it is guarded so it can never double-fire.
  4. Failure handling — the run deliberately demonstrates a recoverable failure at the Postgres step (an Error 409 cooldown), halts, and offers Retry from this step — provisioning is idempotent and resumes without leaving dangling resources. On completion it shows the instance is live, that an owner invite was sent, and that the run was written to the audit log.

The steps mirror a real automated single-tenant provisioning pipeline (project + APIs → VPC/connector → Cloud SQL Postgres with RLS → Secret Manager → Cloud Run deploy with secrets bound → schema migrate + blueprint seed → domain-mapping + TLS + tenant register → health-check + owner invite).

RBAC + break-glass (the access doctrine)

Not every operator needs billing or customer-data access — the console enforces least privilege. Five control-plane roles (control-data.jsx):

RoleCan
Ownereverything: provision, decommission, billing, team, break-glass, release, suspend
Opsprovision, release, suspend, break-glass
Financecontracts, invoices, margin — no infra actions
Supporttickets, tenant health, break-glass — no infra/billing writes
Read-onlyview everything; no writes, no break-glass

can(capability) gates every action button; surfaces a role can't act on show the control disabled with a reason (e.g. Provision tells a Finance/Read-only operator it's restricted).

Break-glass is the controlled way an operator enters a customer's live instance. It is a modal consent gate that requires a reason (attached to the audit entry), a time-box (15/30/60 min), and an explicit consent checkbox, then opens the tenant app and writes a flagged audit record. This is the control-plane expression of the product's grounding/oversight doctrine: tenant-data access is never silent — it is scoped, justified, and logged.

Gated actions

Destructive or sensitive actions route through a shared human-commit gate (useGate): a modal that states the action, optionally requires typing a confirmation word (e.g. the tenant short-code to decommission), and notes that it's logged. This is the same Accept/commit discipline as the product's Proposal Inbox (§13), applied to infrastructure.

Data model (mock, but shaped like the real thing)

control-data.jsx seeds ~12 tenants across the maritime/energy/sanctions/research/academic blueprints, with varied lifecycle states (live, degraded, provisioning, trial, suspended). Each tenant carries: identity + blueprint + region + plan; the instance (Cloud Run service/revision, Postgres tier/storage/HA, secret count, custom domain); health (uptime/p99/error/last-deploy); usage (API/ingest/DAU/storage/sources); contract (ACV, setup, term, billing, signed); cloudCostMo; and support (open tickets, CSAT). Alongside: incidents, support tickets, the operator team, the audit log, releases, regions, and plan tiers. Derived helpers compute fleet stats, money formatting, and compact numbers.

Doctrine fit

PrincipleIn the control plane
Q8 — AI supports, never decidesThe control plane is operator-driven; no autonomous infra changes. Destructive actions are explicit human commits.
Q10 — bounded, reversible, loggedSuspend is reversible; decommission is gated + typed-confirm + 30-day retention; break-glass is time-boxed and audited.
Grounding / provenanceEvery action writes to the append-only audit log with actor, target, and note — the same "show your work" stance the product takes with [OBS-####].
IsolationThe whole reason the control plane is heavy: single-tenant silos with per-tenant Postgres + RLS + secrets.

Prototype boundary

Real now: all 10 surfaces; the tenant model + fleet stats; the full provisioning wizard (configure → preview → live state-machine run → failure/retry → ready) with friendly steps and raw command log; RBAC capability-gating across every action; the break-glass consent gate; the typed-confirm destructive gates; per-tenant version pinning UI; ⌘K; the audit log. Deferred / simulated: the actual GCP calls (the prototype renders the exact gcloud/Terraform sequence but does not execute it); live metrics (health/usage are seeded, not streamed); a real auth/IdP + IP-allowlist behind the operator login; and writing a newly-provisioned tenant back into the live Tenants list (today the run is a faithful simulation). When a real provisioning backend lands, the wizard's steps already map 1:1 to it.