target-revenue/workplans/TREV-WP-0011-railiance-reef-deployment.md
tegwick ee87fa28ea Add TREV-WP-0011: Railiance reef deployment workplan
Deploys the Trust Service and Control Plane UI to Railiance
infrastructure-as-code behind revenue.coulomb.social. T01 is a human
decision gate on deployment pattern (own-repo k8s/railiance vs.
railiance-apps chart, one process vs. two, CNPG database, OpenBao
secrets, subdomain/TLS, credential bootstrap) before any manifest work
starts. Deployment is explicitly scoped as infrastructure delivery,
not a Phase go-live decision (that remains WP-0008-T05).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 16:37:59 +02:00

7.5 KiB
Raw Blame History

id type title domain repo status owner topic_slug created updated
TREV-WP-0011 workplan Deploy Trust Service and Control Plane to the Railiance reef infotech target-revenue active claude infotech 2026-07-30 2026-07-30

Deploy Trust Service and Control Plane to the Railiance reef

Deploy the hosted Trust Service (service/app.py, WP-0006) and the Control Plane interactive UI (service/control_plane_app.py, WP-0009-T04) to Railiance infrastructure-as-code, on a rail hosted in reef-railiance's grouped home substrate, fronted by the subdomain revenue.coulomb.social.

This is an infrastructure delivery workplan, not a governance one: it does not authorize a real Phase to go live for any repo. That gate remains workplans/TREV-WP-0008-governance-and-pilot-rollout.md T05, independent of whether the software is reachable at a public URL. The Control Plane UI itself already carries this disclaimer in its footer (service/control_plane_templates/base.html) and will continue to once deployed.

Reference deployment: railiance-vergabe-teilnahme / railiance-apps/charts/vergabe-teilnahme is the closest existing precedent — a Django app, its own Postgres, a Helm chart living in railiance-apps, an Ingress with cert-manager.io/cluster-issuer: letsencrypt-prod, and runtime secrets via an ExternalSecret reading an OpenBao ClusterSecretStore. issue-core is a second precedent using a different pattern — its own repo carries k8s/railiance and an ArgoCD Application points repoURL directly at that repo rather than at railiance-apps. T01 below has to pick between these two patterns (or a third) rather than assume one.

id: TREV-WP-0011-T01
status: todo
priority: high
human_accept_required: true

Decide the deployment pattern (human gate). Concretely:

  • Manifest home: does target-revenue carry its own k8s/railiance path (like issue-core) with an ArgoCD Application pointing straight at this repo, or does the Helm chart/Ingress/manifests live in railiance-apps/charts/target-revenue alongside vergabe-teilnahme (this repo's TRSL licensing and its being a monetization-framework repo, not an application repo, may argue for keeping deploy manifests out-of-tree)?
  • Process topology: service/app.py (Trust Service) and service/control_plane_app.py (Control Plane UI) are two separate FastAPI app objects today, sharing the same Postgres and the same Ed25519 signing key. Deploy as two Deployments/Services behind one Ingress with path-based routing, or mount one inside the other (app.mount("/control-plane", control_plane_app)) into a single process/image? The latter needs a small code change (WP-0009-T04's Optional-Next-Step note flagged this as undecided); the former needs no code change but two sets of secrets/probes.
  • Database: a dedicated CNPG (CloudNativePG) Cluster for this workload's Postgres (matching the cnpg-option-a-* manifests already in railiance-apps), sized appropriately for a pilot-scale Trust Service instance — not the shared state-hub Postgres, per this project's own standing rule about never reusing that instance for hosted-service data.
  • Secrets: which values go through OpenBao + ExternalSecret (TRF_SIGNING_KEY_HEX, TRF_CONTROL_PLANE_SECRET_KEY, TRF_DATABASE_URL/the trf_app role password) versus which, if any, are fine as plain Helm values.yaml — following the reuse-surface-runtime-externalsecret.yaml pattern, one ClusterSecretStore per workload namespace.
  • Subdomain and TLS: confirm revenue.coulomb.social DNS is (or will be) pointed at the Railiance ingress, and that letsencrypt-prod issuing for a coulomb.social subdomain has no unresolved prerequisite (SAN limits, existing wildcard, etc.) — check railiance-infra/ railiance-platform docs rather than assuming parity with whywhynot.de.
  • Founding credential bootstrap: how the first binky admin credential is seeded into the deployed database — an idempotent migration-adjacent script, or a documented one-time manual kubectl exec/psql step, consistent with how railiance-apps/railiance-platform already handle comparable one-time bootstrap actions.

Record the decision here (Result) before any manifest is written — this gate exists because every later task in this workplan assumes a specific answer to each bullet above.

id: TREV-WP-0011-T02
status: todo
priority: high

Containerize. Add a Dockerfile (and, if T01 decided on two processes, two images or one image with two entrypoints/commands) building the service extras (fastapi, uvicorn, jinja2, itsdangerous, python-multipart, psycopg[binary], psycopg-pool) plus static/whynot-design and control_plane_templates/ as part of the image — nothing in T04's implementation currently assumes local filesystem paths outside the package, but this should be verified for a container context (non-root user, read-only root filesystem where the app's own static/ template files don't need write access). Push to forgejo.coulomb.social/coulomb/target-revenue per the existing image registry convention (vergabe-teilnahme's values.yaml image.repository pattern).

id: TREV-WP-0011-T03
status: todo
priority: high

Provision the database and secrets per T01's decision: a CNPG Cluster, the 00010006 migrations applied against it (as a Job, an init step, or a documented manual run — decide which, consistent with however railiance-apps's other CNPG-backed workloads handle first-boot migration), the trf_app role and its grants (already defined in the migration files themselves), an OpenBao ClusterSecretStore + ExternalSecret surfacing TRF_SIGNING_KEY_HEX, TRF_CONTROL_PLANE_SECRET_KEY, and the trf_app password/DSN into the workload's namespace.

id: TREV-WP-0011-T04
status: todo
priority: high

Helm chart, Ingress, and ArgoCD wiring. Following T01's chosen home (own-repo k8s/railiance vs. railiance-apps/charts/target-revenue): Deployment(s)/Service(s)/Ingress for revenue.coulomb.social with cert-manager.io/cluster-issuer: letsencrypt-prod and TLS, readiness/ liveness probes against a real health path (neither service/app.py nor control_plane_app.py currently exposes one — add a trivial /healthz to each rather than probing an authenticated or Postgres-dependent route), and an ArgoCD Application (railiance-tenants project, matching issue-core.application.yaml's shape) with automated sync.

id: TREV-WP-0011-T05
status: todo
priority: medium

Bootstrap and smoke-test the live deployment. Seed the founding binky admin credential per T01's decision, confirm https://revenue.coulomb.social/login is reachable and TLS-valid, sign in, register a throwaway test Phase (id clearly marked as a smoke test, not a real candidate), append a Development Credit entry, confirm the audit log and metrics reflect it, then decide whether to leave that smoke-test Phase in place (clearly labeled) or remove it — Phase Manifests are append-only by design (no delete path), so if a smoke test is unacceptable to leave behind, use a disposable local/staging instance for this step, not the production deployment, and only do a read-only login check against the real one. Update README.md's WP-0011 summary row and this workplan's Result sections; add a short deployment note (URL, how to sign in, that no Phase go-live is authorized by deployment alone) to docs/ or SCOPE.md as appropriate.