Deployment Targets & Portability
Generalising the per-tenant stack from one GCP project to any suitable target, including split and customer-hosted topologies.
Generalising the per-tenant stack (
50,51) from "one GCP project" to "any suitable target, including split and customer-hosted topologies." Placement becomes a per-tenant manifest; the isolation, provenance, and grounding invariants never change. Extends the doctrine "placement is configuration; isolation is invariant" (50).
Why
One buyer set wants very different homes for the same product:
- a commercial / journalistic / academic tenant is happy on our managed GCP silo;
- a Swiss public body wants compute and data on a Swiss hoster, our keys or theirs;
- a bank wants the app on our cloud but the database in their AWS account under their KMS;
- a defence / sovereign buyer wants the whole stack inside their accredited (possibly air-gapped) enclave and brings their own feeds (the classified-capable tier).
So the tenant stack must be portable and splittable across providers, not GCP-only.
The model: capabilities → provider adapters
A tenant stack is a fixed set of capabilities. Each is satisfied by a pluggable provider adapter behind a stable contract, so where it runs is configuration, not a rewrite.
| Capability | Stable contract | Adapters (today → roadmap) |
|---|---|---|
Compute (api, ingestors, realtime) | container + env-injected secrets + private egress | GCP Cloud Run → AWS Fargate/ECS · Azure Container Apps · on-prem k8s · Swiss hoster (Exoscale / Infomaniak / Swisscom) |
| Canonical DB | PostgreSQL 16 + PostGIS, RLS, PITR | Cloud SQL → AWS RDS/Aurora-PG · Azure DB for PG · customer-managed PG (their cloud / on-prem) |
| Doc/RAG store (if used) | document store + vector search | pgvector-in-PG (single-store, default per D1) → Atlas · customer Mongo |
| Blobs | object store, versioned, CMEK | GCS → S3 · Azure Blob · MinIO / on-prem |
| Cache / queue | KV + async queue | Memorystore + Cloud Tasks → ElastiCache + SQS · Redis + RabbitMQ on-prem |
| Secrets / KMS | secret store + envelope key (customer-controllable) | Secret Manager + Cloud KMS → AWS Secrets Manager + KMS · Azure KV · HashiCorp Vault · customer KMS (BYOK / HYOK) |
| Network | private compute↔data, no public DB | per-provider VPC/VNet + private link / peering / VPN |
| Edge | TLS, WAF, LB | Cloud Armor + Cloud LB → CloudFront/WAF · customer edge |
The 51 Terraform "tenant module" becomes a composition of per-capability sub-modules selected by the tenant's topology manifest, instead of one hard-wired GCP module.
The topology manifest (per tenant)
Provisioning input gains a topology block declaring where each capability lives:
module "tenant" {
source = "../../modules/tenant"
slug = "caledonia-ports"
plan = "pro"
blueprint = "maritime"
topology = {
compute = { provider = "gcp", region = "europe-west6" } # Zürich
canonical = { provider = "aws", region = "eu-central-1",
managed_by = "customer", dsn_ref = "secret://caledonia-pg-dsn" }
blobs = { provider = "gcp", region = "europe-west6" }
secrets = { provider = "customer-vault", kms = "customer" } # HYOK
rag = { provider = "pgvector" } # single-store, no Mongo
edge = { provider = "swiss-hoster" }
}
}managed_by = "customer" means insigz operates against an endpoint the customer owns and supplies; the credential arrives out-of-band (42, 23), insigz holds only a scoped, rotatable connection secret — never the root credential.
Named deployment profiles (the menu we sell)
| Profile | Compute | Data | Keys | For |
|---|---|---|---|---|
| gcp-managed (default) | insigz GCP | insigz GCP | insigz KMS | commercial / OSINT / academic |
| swiss-sovereign | Swiss hoster / europe-west6 | same | insigz or customer | CH public sector, neutrality-sensitive |
| split-data | insigz cloud | customer cloud DB (AWS/Azure) | customer KMS | banks / regulated wanting data in their account |
| customer-data, our-compute | insigz / Swiss hoster | customer infra / on-prem PG | customer KMS | strict data-residency, app convenience |
| customer-hosted / sovereign-enclave | customer environment (on-prem, can be air-gapped) | customer | customer | defence / classified-capable (they bring the feeds) |
Invariants — true on every target (placement must never weaken these)
- Tenant isolation (silo + RLS + classification/cell) holds identically (
43,82). - Signed provenance on every observation; the per-tenant Ed25519 key lives in that tenant's secret/KMS provider — customer-held where the profile says so (
20,42). - Grounded, citation-validated AI unchanged; in enclave profiles the model is the air-gapped / accredited inference adapter behind the same grounding contract (
32,80). - Expand→migrate→contract migrations run per target via
insigzctl(52,83). - Audit append-only + two-sided break-glass works across providers (
83). - No public DB listeners — compute↔data is always private link / peering / VPN.
What gets harder (own it, price it)
- Cross-plane latency: compute and DB in different clouds/regions adds RTT to every query — co-locate by region where possible, and the "never hold a PG tx across a Claude stream" rule (
60) becomes mandatory, not advisory. - Connectivity & trust: mTLS + private interconnect between providers; split key custody (HYOK) needs careful boot-time resolution.
- Backups/DR, observability, break-glass all become per-provider; the control plane must speak each backend.
- Ops cost rises with topology diversity — support only the five named profiles, not arbitrary combinations.
Control-plane impact (62)
- The provisioning orchestrator (Cloud Workflows) selects per-capability sub-modules from the manifest; it still holds no tenant data credentials — it wires references, and the tenant's own service identity resolves them at boot.
- Fleet telemetry + break-glass must traverse provider boundaries (telemetry pulled per-provider; the break-glass token is validated by the tenant app wherever it runs —
83). - Decommission runs the snapshot-then-destroy flow against each provider in the manifest.
Decisions to ratify (proposed — extend the register in 00)
- Capability/adapter architecture: the tenant module is a composition of per-capability sub-modules behind stable contracts; GCP is the reference adapter, others built on demand.
- Supported-topology matrix: only the five named profiles are supported (no arbitrary mixes) to bound ops.
- HYOK: customer-held KMS is a first-class option, not just CMEK on our KMS.
- Single-store off-GCP: non-GCP / enclave targets default to pgvector single-store unless document volume requires Mongo.
Gaps to close
- Define the stable contract (interface + Terraform variable shape) per capability so adapters are interchangeable.
- Pick the first non-GCP adapter to build (AWS RDS for
split-datais the likely first paying ask). - Specify cross-provider networking (PrivateLink / peering / VPN) and the mTLS/cert story.
- Define the enclave / air-gapped install bundle — offline images, the accredited model adapter, data-diode ingest (the classified-capable tier).
- Set per-profile latency / DR / support SLAs (they differ from the all-GCP SLOs in
53).