tenant-engine/railiance
tegwick 6644ad8402
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 50s
Onboard tenant-engine to the staged-promotion contract
TEN-WP-0008. railiance/app.toml declares criticality=high, empty secrets,
isolated canary, and the live PostgreSQL digest as previous_stable.
Manifests render through kustomize (deploy/ and deploy/canary/). Stage 1
passed. Stage 2/3 Helm-only CLI gap requested as RAIL-BS-IN-0001 rather
than a dummy chart.

Assistant: grok
Assistant-Session: 01a04cea-e5e8-7081-a0fc-808ebbc35fa9
2026-08-29 14:51:27 +02:00
..
app.toml Onboard tenant-engine to the staged-promotion contract 2026-08-29 14:51:27 +02:00
README.md Onboard tenant-engine to the staged-promotion contract 2026-08-29 14:51:27 +02:00

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 types 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.