diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index ddb23f4..1db62c8 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -54,8 +54,8 @@ | task | CORE-WP-0010-T03 | todo | — | workplans/CORE-WP-0010-runtime-absorption-and-archive.md | | task | CORE-WP-0010-T04 | todo | — | workplans/CORE-WP-0010-runtime-absorption-and-archive.md | | task | CORE-WP-0010-T05 | todo | — | workplans/CORE-WP-0010-runtime-absorption-and-archive.md | -| task | CORE-WP-0011-T01 | progress | — | workplans/CORE-WP-0011-railiance01-production-relocation.md | +| task | CORE-WP-0011-T01 | done | — | workplans/CORE-WP-0011-railiance01-production-relocation.md | | task | CORE-WP-0011-T02 | done | — | workplans/CORE-WP-0011-railiance01-production-relocation.md | -| task | CORE-WP-0011-T03 | todo | — | workplans/CORE-WP-0011-railiance01-production-relocation.md | +| task | CORE-WP-0011-T03 | wait | — | workplans/CORE-WP-0011-railiance01-production-relocation.md | | task | CORE-WP-0011-T04 | todo | — | workplans/CORE-WP-0011-railiance01-production-relocation.md | | task | CORE-WP-0011-T05 | todo | — | workplans/CORE-WP-0011-railiance01-production-relocation.md | diff --git a/docs/evidence/core-hub-coulombcore-inventory-2026-08-20.md b/docs/evidence/core-hub-coulombcore-inventory-2026-08-20.md new file mode 100644 index 0000000..9748b22 --- /dev/null +++ b/docs/evidence/core-hub-coulombcore-inventory-2026-08-20.md @@ -0,0 +1,92 @@ +# Core Hub CoulombCore production inventory — 2026-08-20 + +This is a metadata-only, read-only inventory captured over the existing +`coulombcore` SSH route. No Secret value or database credential was read. +Secret inspection used `kubectl describe`, which exposed key names and byte +sizes only. + +## Source host and runtime + +| Item | Live CoulombCore state | +| --- | --- | +| Node | `254.130.205.92.host.secureserver.net` / `92.205.130.254` | +| Kubernetes | `v1.30.3+k3s1`, Ready | +| Namespace | `core-hub`, labeled `railiance.io/postgres-client=apps-pg` | +| Helm | release `core-hub`, revision 1, chart `core-hub-0.1.0` | +| Deployment | `core-hub-api`, Deployment revision 2, 1/1 Ready | +| Image reference | `gitea.coulomb.social/coulomb/core-hub:a33191a` | +| Pulled image ID | `sha256:5e1334eb25975b5f7792d2ae9289898586224133896c6aa55bd27cdc776fb10c` | +| Service | `core-hub-api`, ClusterIP, port `8010` | +| Ingress | Traefik, `hub.coulomb.social`, TLS Secret `core-hub-tls` | +| Runtime configuration | `CORE_HUB_ENV=production`, `CORE_HUB_AUTO_CREATE_TABLES=0` | +| Runtime Secret metadata | `core-hub-prod-env`; keys `CORE_HUB_API_TOKEN` (64 bytes) and `CORE_HUB_DATABASE_URL` (131 bytes) | +| Database boundary | Namespace declares the `apps-pg` consumer; the Secret value was not read | +| Migration | `core-hub-prod-migrate` completed once in 65 seconds using the same image tag | +| Health | Public `/healthz` and `/readyz` both returned `status: ok` | + +The source pod has zero restarts and has been running for 41 days. Resource +requests/limits already match the package baseline: 250m/512Mi requests and +1 CPU/1Gi limits. Readiness and liveness use `/readyz` and `/healthz`. + +## Source-to-package differences + +The `rapp-core-hub` chart `0.3.0` intentionally changes the following platform +posture on railiance01: + +- immutable Forgejo image digest + `sha256:0db6f7c646c6d4c1fbc844dc266fcf883584637e1c1f47802efe1c6a98558d3c` + instead of the source's mutable Gitea tag and pulled digest; +- a dedicated non-token-mounting ServiceAccount rather than `default`; +- non-root, read-only-root-filesystem, dropped-capability and seccomp settings + rather than empty pod/container security contexts; +- default-deny plus explicit DNS, PostgreSQL and ingress NetworkPolicies rather + than no NetworkPolicy objects; +- separate static API-token, runtime database and migration database Secrets + rather than one combined `envFrom` Secret; and +- mounted-file credential rotation supervision rather than process-lifetime + environment values. + +The target railiance01 preflight found a Ready `v1.35.1+k3s1` node and no +existing `core-hub` namespace or workload. Public Ingress remains disabled in +the package until the operator-approved traffic cutover. + +External Secrets Operator CRDs are installed on railiance01. Existing audit-core +KV and database stores demonstrate the required two-store pattern, but no +Core Hub store exists yet. The `rapp-postgres` repository also has no accepted +Core Hub consumer declaration. These are explicit platform gates; the package +must not be applied with placeholder Secrets or a standing database password. + +The exact target image was pulled successfully by digest. Inside that image, +`core_hub.app`, Uvicorn and Alembic import successfully under UID/GID 10001 with +a read-only root filesystem and only a temporary `/tmp`. The image declares no +default user, so the chart's explicit non-root security context remains +required. This proves entry-point and filesystem compatibility without starting +a database writer. + +The application image differs from the live source and therefore must pass the +private shadow restore, schema, public-catalog, protected-route and consumer +smokes before traffic moves. This is an explicit verification gate, not an +assumption of image equivalence. + +## Rollback anchors + +- Keep the CoulombCore Deployment, Service, Ingress, Secret and database writer + intact until stabilization closes. +- The authoritative live image rollback anchor is the pulled digest + `sha256:5e1334eb25975b5f7792d2ae9289898586224133896c6aa55bd27cdc776fb10c`, + with tag `a33191a` retained as historical context. +- Helm reports revision 1, while Kubernetes reports Deployment revisions 1 and + 2 with two retained ReplicaSets. Because the Deployment has post-Helm rollout + history, do not rely on `helm rollback` alone for the source fallback. +- Traffic rollback restores `hub.coulomb.social` and the active tunnel to + CoulombCore before disabling the railiance01 writer. + +## Read-only commands used + +- `kubectl get nodes -o wide` +- namespace-scoped `kubectl get`/`rollout history` for Deployment, ReplicaSet, + Pod, Service, Ingress, Job, NetworkPolicy, ServiceAccount and ConfigMap +- `kubectl describe secret core-hub-prod-env` +- `helm -n core-hub history/get values/get manifest core-hub` +- public HTTPS `/healthz` and `/readyz` requests +- digest-pinned local image pull and non-root/read-only import smoke diff --git a/workplans/CORE-WP-0011-railiance01-production-relocation.md b/workplans/CORE-WP-0011-railiance01-production-relocation.md index 3290577..20da43a 100644 --- a/workplans/CORE-WP-0011-railiance01-production-relocation.md +++ b/workplans/CORE-WP-0011-railiance01-production-relocation.md @@ -45,7 +45,7 @@ evidence. Do not make runtime absorption into hub-core a prerequisite. ```task id: CORE-WP-0011-T01 -status: progress +status: done priority: high ``` @@ -74,15 +74,18 @@ Forgejo on 2026-08-20. The only remaining Gitea image reference is historical evidence in finished `CORE-WP-0004`; confirm the live source Deployment image and digest before declaring the dependency closed. -An attended source-cluster inventory remains required. On 2026-08-20 the -CoulombCore kubeconfig pointed at the documented local API port `16443`, but -the tunnel was down; the current ops-bridge config no longer contains -`k3s-api-coulombcore`. The sanctioned warden signer route was followed, but its -credential broker requires an operator-held OpenBao issuer login unavailable -to this non-interactive session. No alternate credential path was attempted. -After operator login, collect metadata-only Deployment/Service/Ingress, image -digest, Secret names and keys (never values), database target, resource policy, -and Helm revision evidence before closing this task. +Completed after the documented local API tunnel proved stale: existing direct +SSH access provided a metadata-only `kubectl`/Helm path without retrieving a +new credential. Production is Ready on CoulombCore Kubernetes `v1.30.3+k3s1`, +Helm chart `0.1.0`, using mutable tag `a33191a` whose pulled image ID is +`sha256:5e1334eb25975b5f7792d2ae9289898586224133896c6aa55bd27cdc776fb10c`. +It has one combined environment Secret, empty security contexts, the default +ServiceAccount and no NetworkPolicies. Health/readiness pass publicly. Helm +reports release revision 1 while the Deployment reports revision 2, so source +rollback must retain the actual Deployment/ReplicaSet state rather than rely on +Helm history alone. Secret inspection recorded key names and byte sizes only; +no value was read. Full evidence and the target-package diff are in +`docs/evidence/core-hub-coulombcore-inventory-2026-08-20.md`. ## Build the relocatable application package @@ -134,7 +137,7 @@ that this workstation is not the production workplan-UUID registrar. ```task id: CORE-WP-0011-T03 -status: todo +status: wait priority: high ``` @@ -147,6 +150,15 @@ the private target endpoint. Done when the shadow runtime is healthy, data reconciliation is repeatable, and ops-hub plus activity-core smokes pass against railiance01. +Preflight completed 2026-08-20 without applying resources. ESO CRDs and the +working audit-core two-store pattern exist on railiance01, but the `core-hub` +namespace, Core Hub ClusterSecretStores, projected Secrets, and accepted +`rapp-postgres` consumer declaration do not. The exact target image digest +pulls and imports Core Hub, Uvicorn, and Alembic under UID/GID 10001 with a +read-only root filesystem. Package tests, family validation and server dry-run +pass. This task is `wait` on `RPF-WP-0021-T02/T04`; do not substitute placeholder +Secrets or a standing database password. + ## Cut over production traffic ```task @@ -180,7 +192,7 @@ this repo unless the separate absorption workplan has also completed. ## Acceptance -- [ ] Decommission deadline and live source/target inventory are recorded +- [x] Decommission deadline and live source/target inventory are recorded - [x] Governed rapp package renders and passes policy checks - [ ] Shadow restore/reconciliation and consumer smokes pass on railiance01 - [ ] Production traffic and tunnel move with explicit approval and rollback