# Railiance staged promotion — tenant-engine TEN-WP-0008 onboards this repo to `railiance.app.v1` without changing the contract. Production is described, not redeployed. ## T02 decision: kustomize, not Helm, not a dummy chart The schema accepts any stage `commands` and check `type`s including `command` and `kubernetes`. This workload ships a multi-document manifest, now rendered by `deploy/kustomization.yaml` (`kubectl apply -k deploy/`). That is option 2 in TEN-WP-0008-T02: converting to kustomize is cheap and matches the small-headless-service precedent (`qonto-assistant`). What the schema does **not** require, and what `bin/railiance deploy|promote --apply` still requires, is a Helm chart plus `values/stage3-production.yaml`. Plan mode of those commands fails closed on "no Stage 2 helm check declared" / missing chart. That is a CLI gap, not a missing field in `app.toml`. Per the workplan we do not paper over it with a chart we would never apply. Requested of `railiance-bootstrap` as `RAIL-BS-IN-0001`. Stage commands in `app.toml` are therefore the kubectl invocations that actually work against this shape. Stage 1 (`bin/railiance run`) validates them by rendering both overlays locally. ## Canary TEN-WP-0009 removed the ReadWriteOnce PVC and switched the Deployment to `RollingUpdate`, so a second pod is storage-feasible. `canary_mode = "isolated"` is a distinct Deployment/Service (`tenant-engine-canary`) whose selector does not match the production Service. It does not take `user-engine` traffic. Overlay: `deploy/canary/`. ## Recorded stable (T03) `[stages.stage3].previous_stable` is the contract's copy of "what should be running": ``` tenant-engine@sha256:a8e8086ffc5b772c1391b166f5e1884b90f7d327b152c205eceae129df555c24 ``` That is the TEN-WP-0009 PostgreSQL runtime pin, the same digest `deploy/base/tenant-engine.yaml` and `make verify-pin` use. Onboarding does not ship a newer image. ## Rollback ladder | Digest | Role | | --- | --- | | `a8e8086ffc…` | current stable (PostgreSQL) | | `023ac49f5c…` | previous PostgreSQL image (leased-login ownership defect) | | `7dc9d7bf1f…` | last SQLite/PVC image — **not** a rollback target after any PostgreSQL write | Older TEN-WP-0007 pins (`44ca65f3…` / `08be0b1d…` / `2249e8c6…`) remain the lifecycle/guardrail feature ladder: rolling past a pre-lifecycle digest removes routes `user-engine` depends on. ## Secrets `secrets.references = []` is deliberate. Postgres URL and flex-auth caller token are projected by those platforms from OpenBao. This repo does not catalogue them. ## Criticality `high`. Argument is in `[app].description`. Not `critical`: not internet-facing, holds no application secret, fail-closed on outage. Not `medium`: flex-auth and key-cape are live consumers.