All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 50s
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
242 lines
7.5 KiB
TOML
242 lines
7.5 KiB
TOML
schema_version = "railiance.app.v1"
|
|
|
|
# TEN-WP-0008. Modelled on qonto-assistant (small headless service) for
|
|
# stage commands, and on flex-auth for an empty secrets list and isolated
|
|
# canary. Stage 2/3 *commands* are kubectl against this repo's kustomize
|
|
# overlays. `bin/railiance deploy|promote --apply` currently requires a Helm
|
|
# chart the schema does not; that gap is requested of railiance-bootstrap
|
|
# rather than papered over with a dummy chart. See railiance/README.md.
|
|
|
|
[app]
|
|
id = "tenant-engine"
|
|
name = "tenant-engine"
|
|
repo = "tenant-engine"
|
|
owner = "infotech"
|
|
criticality = "high"
|
|
description = """
|
|
Canonical PIP for tenant-as-an-entity facts. flex-auth consults it live on
|
|
high-stakes decisions and key-cape consults it at token issuance. It holds
|
|
no application secrets and is not internet-facing, but an outage makes the
|
|
PDP fail closed fleet-wide. high, not critical: the PDP itself is high,
|
|
this is a data source whose unavailability is deny rather than an
|
|
unauthorized allow, and it does not hold a credential of its own.
|
|
"""
|
|
|
|
[source]
|
|
revision = "git:main"
|
|
artifact = "image"
|
|
digest_policy = "required"
|
|
|
|
[rollback]
|
|
strategy = "image-digest"
|
|
command = "kubectl -n tenant-engine rollout undo deploy/tenant-engine"
|
|
verification = """
|
|
make verify-pin agrees repo, spec, and running pod; GET /health returns
|
|
200 with store_backend=postgresql; lifecycle routes still present.
|
|
Do not roll back to sha256:7dc9d7bf1fcbb3f3ad7035366f4cd44038322995a126b4423142e446ca5c9cd5
|
|
(SQLite/PVC) after any PostgreSQL write. The TEN-WP-0007 ladder still
|
|
holds for older images: rolling past a pre-lifecycle digest removes
|
|
GET/PATCH/retire/reactivate that user-engine depends on.
|
|
"""
|
|
|
|
[[platform.dependencies]]
|
|
name = "platform-pg"
|
|
kind = "postgres"
|
|
required = true
|
|
stage = "stage2"
|
|
evidence = "rapp-postgres consumer tenant-engine can reach platform-pg:5432; /health reports store_backend=postgresql."
|
|
|
|
[[platform.dependencies]]
|
|
name = "flex-auth-tenant-engine"
|
|
kind = "identity"
|
|
required = true
|
|
stage = "stage2"
|
|
evidence = "http://flex-auth-tenant-engine.flex-auth.svc.cluster.local:8080/healthz returns 200."
|
|
|
|
[[platform.dependencies]]
|
|
name = "forgejo-oci"
|
|
kind = "other"
|
|
required = true
|
|
stage = "stage2"
|
|
evidence = "Image forgejo.coulomb.social/coulomb/tenant-engine is pullable by digest."
|
|
|
|
[[platform.dependencies]]
|
|
name = "railiance01-k3s"
|
|
kind = "network"
|
|
required = true
|
|
stage = "stage2"
|
|
evidence = "kubectl -n tenant-engine get ns reports Active on railiance01."
|
|
|
|
[secrets]
|
|
# Runtime secret custody is OpenBao's. Postgres URL and flex-auth caller
|
|
# token are projected files owned by those platforms, not entries this
|
|
# repo catalogues. An empty list is the correct answer (TEN-WP-0008-T01).
|
|
references = []
|
|
|
|
[[observability.health_endpoints]]
|
|
name = "local-health"
|
|
url = "http://127.0.0.1:8090/health"
|
|
stage = "stage1"
|
|
expected_status = 200
|
|
|
|
[[observability.health_endpoints]]
|
|
name = "cluster-health"
|
|
url = "http://tenant-engine.tenant-engine.svc.cluster.local:8090/health"
|
|
stage = "stage2"
|
|
expected_status = 200
|
|
|
|
[[observability.health_endpoints]]
|
|
name = "canary-health"
|
|
url = "http://tenant-engine-canary.tenant-engine.svc.cluster.local:8090/health"
|
|
stage = "stage2"
|
|
expected_status = 200
|
|
|
|
[stages.stage1]
|
|
enabled = true
|
|
namespace = "local"
|
|
release = "tenant-engine-local"
|
|
commands = [
|
|
"make test",
|
|
"make validate-app-toml",
|
|
"kubectl kustomize deploy",
|
|
"kubectl kustomize deploy/canary",
|
|
]
|
|
checks = ["unit-tests", "contract-schema", "kustomize-production", "kustomize-canary"]
|
|
evidence = ["pytest output", "app.toml schema validation", "kustomize render of deploy/ and deploy/canary"]
|
|
requires_approval = false
|
|
|
|
[stages.stage2]
|
|
enabled = true
|
|
namespace = "tenant-engine"
|
|
release = "tenant-engine-canary"
|
|
commands = [
|
|
"kubectl apply -k deploy/canary --dry-run=server",
|
|
"kubectl apply -k deploy/canary",
|
|
]
|
|
checks = ["server-dry-run", "canary-ready", "canary-health", "operator-approval"]
|
|
evidence = ["server-side dry-run of isolated canary", "deploy/tenant-engine-canary Available", "canary /health 200", "State Hub approval id"]
|
|
requires_approval = true
|
|
canary_mode = "isolated"
|
|
observation_minutes = 15
|
|
|
|
[stages.stage3]
|
|
enabled = true
|
|
namespace = "tenant-engine"
|
|
release = "tenant-engine"
|
|
commands = [
|
|
"kubectl apply -k deploy --dry-run=server",
|
|
"kubectl apply -k deploy",
|
|
]
|
|
checks = ["stage2-accepted", "rollback-target", "cluster-health", "operator-approval"]
|
|
evidence = ["promotion commit", "new stable digest in previous_stable and deploy/base/tenant-engine.yaml", "post-promotion make verify-pin"]
|
|
requires_approval = true
|
|
promotion_mode = "release-replace"
|
|
# TEN-WP-0008-T03: the contract's recorded stable, not only the manifest pin.
|
|
# Current production (TEN-WP-0009 PostgreSQL runtime), CI-built from d2a7fe3.
|
|
previous_stable = "tenant-engine@sha256:a8e8086ffc5b772c1391b166f5e1884b90f7d327b152c205eceae129df555c24"
|
|
|
|
[[checks]]
|
|
id = "unit-tests"
|
|
type = "command"
|
|
stage = "stage1"
|
|
description = "Run repository unit tests."
|
|
required = true
|
|
run = "make test"
|
|
timeout_seconds = 600
|
|
|
|
[[checks]]
|
|
id = "contract-schema"
|
|
type = "command"
|
|
stage = "stage1"
|
|
description = "Validate railiance/app.toml against railiance.app.v1."
|
|
required = true
|
|
run = "make validate-app-toml"
|
|
timeout_seconds = 60
|
|
|
|
[[checks]]
|
|
id = "kustomize-production"
|
|
type = "command"
|
|
stage = "stage1"
|
|
description = "Render the production kustomization locally, no cluster contact."
|
|
required = true
|
|
run = "kubectl kustomize deploy"
|
|
|
|
[[checks]]
|
|
id = "kustomize-canary"
|
|
type = "command"
|
|
stage = "stage1"
|
|
description = "Render the isolated canary kustomization locally, no cluster contact."
|
|
required = true
|
|
run = "kubectl kustomize deploy/canary"
|
|
|
|
[[checks]]
|
|
id = "local-health"
|
|
type = "http"
|
|
stage = "stage1"
|
|
description = "Confirm a locally served /health when one is running."
|
|
required = false
|
|
url = "http://127.0.0.1:8090/health"
|
|
expected_status = 200
|
|
timeout_seconds = 10
|
|
|
|
[[checks]]
|
|
id = "server-dry-run"
|
|
type = "command"
|
|
stage = "stage2"
|
|
description = "Server-side dry run of the isolated canary overlay before apply."
|
|
required = true
|
|
run = "kubectl apply -k deploy/canary --dry-run=server"
|
|
|
|
[[checks]]
|
|
id = "canary-ready"
|
|
type = "kubernetes"
|
|
stage = "stage2"
|
|
description = "Isolated canary Deployment reaches Available."
|
|
required = true
|
|
namespace = "tenant-engine"
|
|
resource = "deploy/tenant-engine-canary"
|
|
condition = "Available"
|
|
|
|
[[checks]]
|
|
id = "canary-health"
|
|
type = "http"
|
|
stage = "stage2"
|
|
description = "Isolated canary Service /health returns 200."
|
|
required = true
|
|
url = "http://tenant-engine-canary.tenant-engine.svc.cluster.local:8090/health"
|
|
expected_status = 200
|
|
timeout_seconds = 10
|
|
|
|
[[checks]]
|
|
id = "cluster-health"
|
|
type = "http"
|
|
stage = "stage2"
|
|
description = "Production Service /health returns 200."
|
|
required = true
|
|
url = "http://tenant-engine.tenant-engine.svc.cluster.local:8090/health"
|
|
expected_status = 200
|
|
timeout_seconds = 10
|
|
|
|
[[checks]]
|
|
id = "operator-approval"
|
|
type = "manual"
|
|
stage = "stage2"
|
|
description = "Human approval recorded before the isolated canary is applied and before the production pin moves."
|
|
required = true
|
|
evidence_required = "State Hub approval note id, candidate digest, rollback target (previous_stable)."
|
|
|
|
[[checks]]
|
|
id = "stage2-accepted"
|
|
type = "manual"
|
|
stage = "stage3"
|
|
description = "Stage 2 gates passed for the same candidate artifact."
|
|
required = true
|
|
evidence_required = "State Hub Stage 2 acceptance progress id."
|
|
|
|
[[checks]]
|
|
id = "rollback-target"
|
|
type = "manual"
|
|
stage = "stage3"
|
|
description = "Previous stable digest is recorded in previous_stable before promotion."
|
|
required = true
|
|
evidence_required = "tenant-engine image digest currently in previous_stable and deploy/base/tenant-engine.yaml."
|