Prepare ISSUE-WP-0007 railiance01 migration
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

This commit is contained in:
tegwick 2026-08-19 20:23:28 +02:00
parent 6f93eb7fc0
commit 86973f279a
4 changed files with 190 additions and 64 deletions

View file

@ -14,6 +14,7 @@
| workplan | ISSUE-WP-0004 | finished | — | workplans/ISSUE-WP-0004-align-with-work-record-canon.md | | workplan | ISSUE-WP-0004 | finished | — | workplans/ISSUE-WP-0004-align-with-work-record-canon.md |
| workplan | ISSUE-WP-0005 | finished | — | workplans/ISSUE-WP-0005-connector-alignment-implementation.md | | workplan | ISSUE-WP-0005 | finished | — | workplans/ISSUE-WP-0005-connector-alignment-implementation.md |
| workplan | ISSUE-WP-0006 | ready | — | workplans/ISSUE-WP-0006-forgejo-only-projection-boundary.md | | workplan | ISSUE-WP-0006 | ready | — | workplans/ISSUE-WP-0006-forgejo-only-projection-boundary.md |
| workplan | ISSUE-WP-0007 | ready | — | workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md |
| task | T01 | done | — | workplans/ISSC-WP-0001-rename-and-task-ingestion.md | | task | T01 | done | — | workplans/ISSC-WP-0001-rename-and-task-ingestion.md |
| task | T02 | done | — | workplans/ISSC-WP-0001-rename-and-task-ingestion.md | | task | T02 | done | — | workplans/ISSC-WP-0001-rename-and-task-ingestion.md |
| task | T03 | done | — | workplans/ISSC-WP-0001-rename-and-task-ingestion.md | | task | T03 | done | — | workplans/ISSC-WP-0001-rename-and-task-ingestion.md |
@ -46,3 +47,10 @@
| task | ISSUE-WP-0006-T02 | todo | — | workplans/ISSUE-WP-0006-forgejo-only-projection-boundary.md | | task | ISSUE-WP-0006-T02 | todo | — | workplans/ISSUE-WP-0006-forgejo-only-projection-boundary.md |
| task | ISSUE-WP-0006-T03 | todo | — | workplans/ISSUE-WP-0006-forgejo-only-projection-boundary.md | | task | ISSUE-WP-0006-T03 | todo | — | workplans/ISSUE-WP-0006-forgejo-only-projection-boundary.md |
| task | ISSUE-WP-0006-T04 | todo | — | workplans/ISSUE-WP-0006-forgejo-only-projection-boundary.md | | task | ISSUE-WP-0006-T04 | todo | — | workplans/ISSUE-WP-0006-forgejo-only-projection-boundary.md |
| task | ISSUE-WP-0007-T00 | done | — | workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md |
| task | ISSUE-WP-0007-T01 | done | — | workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md |
| task | ISSUE-WP-0007-T02 | todo | — | workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md |
| task | ISSUE-WP-0007-T03 | todo | — | workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md |
| task | ISSUE-WP-0007-T04 | todo | — | workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md |
| task | ISSUE-WP-0007-T05 | todo | — | workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md |
| task | ISSUE-WP-0007-T06 | todo | — | workplans/ISSUE-WP-0007-rapp-issue-core-railiance01-migration.md |

View file

@ -0,0 +1,24 @@
# WP-0003 topology correction — 2026-08-19
ISSUE-WP-0003 deployed and verified issue-core, but its opening narrative
misidentified the target cluster. Its own 2026-07-02 completion note records
the corrected topology:
- ArgoCD, the `issue-core` namespace, Service, ExternalSecret, and Deployment
were on the CoulombCore k3s cluster.
- The real railiance01 cluster ran activity-core and reached issue-core through
`actcore-issue-core-bridge` plus two ops-bridge forwards via the workstation.
- An authenticated activity-core-shaped request traversed that path and created
external issue 176, so WP-0003's functional proof remains valid for the
historical deployment.
The 2026-08-19 observation that railiance01 has an empty `issue-core` namespace
and no ArgoCD is therefore not evidence that a railiance01 workload was pruned
or silently lost. The workload was never directly deployed there. The defect
was the workplan's stale opening summary and title after its later topology
correction.
ISSUE-WP-0007 supersedes that topology. It keeps the reusable container,
secret, health, and authenticated-ingestion evidence while moving runtime
packaging into `rapp-issue-core` and placing the service directly on
`reef-railiance` / railiance01.

View file

@ -1,7 +1,7 @@
--- ---
id: ISSUE-WP-0003 id: ISSUE-WP-0003
type: workplan type: workplan
title: "Deploy issue-core as a service on railiance01 (ArgoCD GitOps pilot)" title: "Historical CoulombCore deployment and railiance01 bridge (initially mislabeled as railiance01 GitOps)"
domain: infotech domain: infotech
repo: issue-core repo: issue-core
status: finished status: finished
@ -14,6 +14,17 @@ state_hub_workstream_id: "896ace77-21b3-450b-8fb7-254aefc8c570"
# Deploy issue-core as a service on railiance01 (ArgoCD GitOps pilot) # Deploy issue-core as a service on railiance01 (ArgoCD GitOps pilot)
> **Historical topology correction (2026-08-19):** This workplan is finished
> because it did deploy and prove issue-core, but the Deployment and ArgoCD
> Application were on **CoulombCore**, not railiance01. The real railiance01
> consumed the service through the two-hop ops-bridge lane documented in the
> 2026-07-02 completion section. Railiance01 currently has an empty `issue-core`
> namespace and no ArgoCD. See
> `history/2026-08-19-wp-0003-topology-correction.md` and ISSUE-WP-0007 for the
> direct railiance01 migration. The paragraphs below are retained as historical
> evidence; unqualified "railiance01 cluster" claims refer to the mistaken
> topology understanding at the time.
`issue-core` is the authoritative task-lifecycle manager and the REST ingestion `issue-core` is the authoritative task-lifecycle manager and the REST ingestion
target for activity-core's `IssueSink`. Deployment artifacts are on `main` target for activity-core's `IssueSink`. Deployment artifacts are on `main`
(`Dockerfile`, `docker-entrypoint.sh`, `k8s/railiance/`); image (`Dockerfile`, `docker-entrypoint.sh`, `k8s/railiance/`); image

View file

@ -4,17 +4,25 @@ type: workplan
title: "rapp-issue-core: move the runtime off CoulombCore onto railiance01" title: "rapp-issue-core: move the runtime off CoulombCore onto railiance01"
domain: infotech domain: infotech
repo: issue-core repo: issue-core
status: proposed status: ready
owner: unassigned owner: codex
lane: yellow
topic_slug: issue-core topic_slug: issue-core
priority: high priority: high
created: "2026-08-19" created: "2026-08-19"
updated: "2026-08-19" updated: "2026-08-19"
reviewed_at: "2026-08-19"
quality_dor: DoR-Ok
quality_dor_at: "2026-08-19"
quality_dor_by: codex
quality_dor_note: "Goal, ownership, task order, dependencies, safety gates, and verification signals reviewed against the issue-core repo and current rapp family."
depends_on: [] depends_on: []
related: related:
- ISSUE-WP-0003 - ISSUE-WP-0003
- ACTIVITY-WP-0023
- RMGR-WP-0006 - RMGR-WP-0006
- RMGR-WP-0007 - RMGR-WP-0007
state_hub_workstream_id: "a2bc717a-64cf-45fa-8a9d-59d3bc9e96c7"
--- ---
# ISSUE-WP-0007 — rapp-issue-core: move the runtime onto railiance01 # ISSUE-WP-0007 — rapp-issue-core: move the runtime onto railiance01
@ -26,11 +34,13 @@ workstation's `18765` to railiance01, so railiance01 reaches issue-core *through
a laptop* that is forwarding to CoulombCore. When CoulombCore goes, issue-core a laptop* that is forwarding to CoulombCore. When CoulombCore goes, issue-core
goes with it, and deleting the tunnel is not a migration. goes with it, and deleting the tunnel is not a migration.
## Start here: ISSUE-WP-0003 says this is already done. It is not. ## Start here: what ISSUE-WP-0003 actually proved
`ISSUE-WP-0003` is `status: finished` and states that "the railiance01 cluster `ISSUE-WP-0003` is `status: finished` and its opening summary incorrectly says
now reconciles `issue-core` through ArgoCD; External Secrets Operator reads the that railiance01 reconciles `issue-core` through ArgoCD. Its own 2026-07-02
OpenBao-backed runtime Secret and the Deployment is live on port 8765." completion section records the topology correction: the Deployment and ArgoCD
Application were on **CoulombCore**, while railiance01 reached them through the
two-hop ops-bridge lane.
Checked on 2026-08-19 against the railiance01 cluster Checked on 2026-08-19 against the railiance01 cluster
(`~/.kube/config-railiance01`, bridge tunnel `k3s-api-railiance01`, local (`~/.kube/config-railiance01`, bridge tunnel `k3s-api-railiance01`, local
@ -42,14 +52,11 @@ Checked on 2026-08-19 against the railiance01 cluster
| Reconciled by ArgoCD | **No ArgoCD** — the cluster has no `applications` resource type | | Reconciled by ArgoCD | **No ArgoCD** — the cluster has no `applications` resource type |
| issue-core serving | Serving from **CoulombCore**: `-L 18765:10.43.103.154:8765`, `/healthz``{"status":"ok","version":"0.2.1"}` | | issue-core serving | Serving from **CoulombCore**: `-L 18765:10.43.103.154:8765`, `/healthz``{"status":"ok","version":"0.2.1"}` |
Whatever was stood up under WP-0003 is gone — most plausibly the railiance01 No railiance01 deployment was silently lost: the first deployment landed on the
cluster was rebuilt without it, since ArgoCD itself is absent. **Task T00 is to wrong cluster and was then deliberately bridged to railiance01. The correction
establish what actually happened before rebuilding**, because if the deployment is recorded in `history/2026-08-19-wp-0003-topology-correction.md` and at the
was lost silently once it will be lost silently again, and a GitOps controller top of WP-0003. Treat its container, secret, service, and authenticated-ingest
that no longer exists is a different starting point than one that drifted. evidence as prior art, but do not resume its ArgoCD topology.
Do not treat WP-0003 as prior art to resume. Treat it as a record that needs
correcting once this workplan establishes the truth.
## Why a `rapp-` wrapper rather than `k8s/railiance/` in this repo ## Why a `rapp-` wrapper rather than `k8s/railiance/` in this repo
@ -79,8 +86,9 @@ rmgr rapp validate --path ../rapp-issue-core --family-root ..
rmgr rapp place --path ../rapp-issue-core --reef reef-railiance rmgr rapp place --path ../rapp-issue-core --reef reef-railiance
``` ```
`--rail`, `--classification`, `--criticality`, and `--package-type` are The reviewed values for this workload are `rail-kubernetes`,
decisions, not defaults to accept blindly — settle them in T01. See `manifest-managed-platform-service`, `confidential`, and `high`. It remains a
private cluster service. See
`repo-manager/docs/RailianceAppDeploymentGuide.md` (RMGR-WP-0006) and `repo-manager/docs/RailianceAppDeploymentGuide.md` (RMGR-WP-0006) and
`RMGR-WP-0007` (greenfield rapp wrap efficiency). `RMGR-WP-0007` (greenfield rapp wrap efficiency).
@ -95,107 +103,184 @@ Migration is not done when a pod is Running. These reach issue-core today:
are retired by this work; the second one should not be recreated in any form. are retired by this work; the second one should not be recreated in any form.
- Anything reading `http://127.0.0.1:18765` on the workstation. - Anything reading `http://127.0.0.1:18765` on the workstation.
## Tasks ## Scope and human gate
In scope: create and register `rapp-issue-core`; transfer the runtime package;
deploy it privately on railiance01; prove health, auth, Forgejo creation,
failure, and rollback; cut optional REST consumers over; then remove the legacy
bridge and tunnels.
Out of scope: changing issue-core domain behaviour, adding Postgres, selecting
Knative, granting public exposure, changing activity-core's fleet-wide default
away from State Hub, or storing secret values in repo/Hub evidence.
This is a yellow-lane production migration. T02/T03 are reversible file work.
The T04 live cluster apply and the T05 removal of bridge/tunnel infrastructure
require explicit implementation authorization; tunnel removal additionally
requires the recorded direct-path 201 gate.
## T00 — Correct the historical topology record
```task ```task
id: ISSUE-WP-0007-T00 id: ISSUE-WP-0007-T00
status: todo status: done
priority: high priority: high
state_hub_task_id: "a195fe94-0231-4dd8-b75e-94f50fec86bc"
``` ```
**Establish what happened to the WP-0003 deployment.** Before rebuilding: **Correct the WP-0003 topology record.** Done 2026-08-19. WP-0003's own
was ArgoCD removed deliberately, was the cluster rebuilt, or did the completion evidence shows that ArgoCD and the `issue-core` Deployment were on
Application drift and get pruned? Check railiance01 cluster history, the CoulombCore, not railiance01; railiance01 consumed the service through a
`issue-core` namespace's remaining objects, and the OpenBao-backed two-hop bridge. Added a prominent correction to WP-0003 and recorded the
ExternalSecret referenced by WP-0003. Record the finding, and correct finding in `history/2026-08-19-wp-0003-topology-correction.md`. This was a
`ISSUE-WP-0003` — a workplan asserting a production deployment that does not recording/topology error, not evidence of a railiance01 workload being pruned.
exist will mislead the next reader exactly as it misled this one.
Deliverable: a short `history/` note. If the cause turns out to be a ## T01 — Settle the packaging decisions
platform-side defect rather than an issue-core one, route it to `risk-nexus`
as a finding rather than absorbing it here.
```task ```task
id: ISSUE-WP-0007-T01 id: ISSUE-WP-0007-T01
status: todo status: done
priority: high priority: high
state_hub_task_id: "2ab2dd49-1c69-4f8e-a807-ce078d2899ce"
``` ```
**Settle the packaging decisions.** `--rail` (`rail-kubernetes` vs **Settle the packaging decisions.** Done 2026-08-19 against the current repo,
`rail-knative`), `--package-type`, `--classification`, `--criticality`, and the live rapp family, and `RailianceAppDeploymentGuide.md`:
whether issue-core needs `--dedicated-postgres` or consumes `rapp-postgres` as
a consumer (it has a database; check which pattern the other rapps that need - primary rail: `rail-kubernetes` — this is a long-running private API; it has
one actually use). Decide against the existing `k8s/railiance/` manifests so no request-activation, scale-to-zero, or revision-traffic requirement;
the wrapper starts from something real. - package type: `manifest-managed-platform-service` — absorb the current
Kustomize manifests rather than inventing a Helm chart;
- data classification: `confidential` — issue titles/bodies and mapping
metadata may contain internal work context;
- criticality: `high` — external tracker projection fails when it is down, but
the file/State-Hub work-record spine continues;
- database: **none for the production wrapper** — the production backend is
Forgejo; SQLite is an optional offline/local backend, so do not pass
`--dedicated-postgres` and remove any generated Postgres-consumer draft;
- exposure: private; no Ingress or public grant.
Reviewed scaffold command:
```bash
UV_CACHE_DIR=/tmp/issue-core-rmgr-cache uv run --directory ../repo-manager \
rmgr rapp wrap --path ../rapp-issue-core --app issue-core \
--ownership-repo issue-core --from-app ../issue-core \
--rail rail-kubernetes \
--package-type manifest-managed-platform-service \
--classification confidential --criticality high \
--purpose "Package and operate the issue-core external-tracker connector on Railiance."
```
## T02 — Scaffold and register rapp-issue-core
```task ```task
id: ISSUE-WP-0007-T02 id: ISSUE-WP-0007-T02
status: todo status: todo
priority: high priority: high
state_hub_task_id: "e0427de0-dfac-4848-ba2d-1421167eb704"
``` ```
**Scaffold `rapp-issue-core` via `rmgr rapp wrap`,** then **Scaffold `rapp-issue-core` via `rmgr rapp wrap`,** then
`rmgr rapp validate --family-root ..`. Do not hand-author the layout; the `rmgr rapp validate --path ../rapp-issue-core --family-root ..`. Remove the
validator encodes the family conventions and will reject a bespoke tree. generated Postgres-consumer draft because this deployment uses Forgejo, then
Register the new repo the normal way (write the files, commit, run the revalidate. Do not hand-author the baseline layout; the validator encodes the
consistency check) rather than by hand. family conventions and will reject a bespoke tree. Register the new repo the
normal file-first way and run its consistency check rather than creating Hub
records by hand.
## T03 — Transfer the runtime package
```task ```task
id: ISSUE-WP-0007-T03 id: ISSUE-WP-0007-T03
status: todo status: todo
priority: high priority: high
state_hub_task_id: "d6e5e2ac-7f42-412f-8143-91531f5155e8"
``` ```
**Port the runtime.** Move `Dockerfile` / image build and the `k8s/railiance/` **Port the runtime package.** Keep `Dockerfile`, `docker-entrypoint.sh`, source,
tree into the wrapper's shape: manifests, secret references (OpenBao-backed tests, and `.forgejo/workflows/image.yaml` in `issue-core`; the app repo builds
ExternalSecret — custody stays with the platform, never in this repo), and publishes the image. Move `k8s/railiance/` into the wrapper's manifest
NetworkPolicy, Service. Image `0.2.1` is what is serving today; decide whether shape, including the private Service, ServiceAccount, default-deny plus explicit
to rebuild or promote the existing digest. NetworkPolicy, and OpenBao-backed secret references. Pin a Forgejo OCI image by
immutable digest; do not reuse the retired Gitea registry tag as the release
contract.
`issue-core` keeps its domain code and loses its deployment artifacts. That Delete `issue-core/k8s/railiance/` and retire `docs/argocd-gitops.md` only after
deletion is part of the task, not a follow-up — two sources of deployment truth the wrapper contains an equivalent, validated runtime contract and retained
is the failure this split exists to prevent. handoff. Two active sources of deployment truth are not allowed.
## T04 — Place, deploy, and prove the direct service
```task ```task
id: ISSUE-WP-0007-T04 id: ISSUE-WP-0007-T04
status: todo status: todo
priority: high priority: high
state_hub_task_id: "21974fbd-4962-4732-b407-c531bb2ebfe6"
``` ```
**Deploy to railiance01 and prove it.** `rmgr rapp place --reef reef-railiance`, **Place, deploy, and prove it on railiance01.** Run `rmgr rapp place --path
then live evidence in the wrapper: cold start, `/healthz` 200 from *inside* the ../rapp-issue-core --reef reef-railiance --family-root ..`, then deploy through
cluster (not through a laptop forward), dependency-failure behaviour, and the wrapper's reviewed apply surface. Credential custody remains in OpenBao:
rollback. Follow `rapp-qonto/tools/verify_live.sh` as the shape — reversible, route `ISSUE_CORE_API_KEY` through catalog `issue-core-ingestion-api-key` and
secret-free. route the Forgejo PAT through the concrete platform/OpenBao lane (never log or
commit either value).
Record secret-free live evidence in the wrapper for: rollout and Ready state;
image digest match; `/healthz` 200 from inside the cluster; unauthenticated
`POST /issues/` rejected; authenticated controlled `POST /issues/` returning
**201 through `forgejo-inbox`**; dependency failure returning a bounded 503;
NetworkPolicy presence; and rollback to the previous immutable digest. Follow
the reversible `rapp-qonto/tools/verify_live.sh` evidence style.
Evidence that the service answers only via an ops-bridge tunnel does not count. Evidence that the service answers only via an ops-bridge tunnel does not count.
That is the condition being retired. That is the condition being retired.
## T05 — Cut consumers over and retire tunnels
```task ```task
id: ISSUE-WP-0007-T05 id: ISSUE-WP-0007-T05
status: todo status: todo
priority: high priority: high
state_hub_task_id: "3fdbd9ab-3e3f-4ac0-8763-77278a1cc6e6"
``` ```
**Cut consumers over, then retire the tunnels.** Point activity-core's **Cut consumers over, then retire the tunnels.** Point activity-core's optional
`IssueSink` at the in-cluster address; ask ops-warden to update catalog id REST `IssueSink` endpoint directly at the new in-cluster Service and remove its
`activity-core-issue-sink` if the routing pointer changes. Only once consumers bridge Deployment/Service. Keep the fleet default `ISSUE_SINK_TYPE=state-hub`;
are on the new address, ask ops-bridge to remove `issue-core-coulombcore` and `rest` remains an explicit external-projection opt-in, not a global cutover.
Prove one controlled activity-core-shaped request returns 201 before asking
ops-warden to update catalog id `activity-core-issue-sink`.
Inventory any other consumers of workstation port `18765`. Only once they are
cut over, ask ops-bridge to remove `issue-core-coulombcore` and
`issue-core-railiance01` from `~/.config/bridge/tunnels.yaml`. `issue-core-railiance01` from `~/.config/bridge/tunnels.yaml`.
Order matters: removing the tunnels first takes issue-core down for everyone Order matters: removing the tunnels first takes issue-core down for everyone
still pointed at `127.0.0.1:18765`. still pointed at `127.0.0.1:18765`.
## T06 — Close out and notify dependants
```task ```task
id: ISSUE-WP-0007-T06 id: ISSUE-WP-0007-T06
status: todo status: todo
priority: medium priority: medium
state_hub_task_id: "668e37dc-8ebe-46cc-9a27-905440b1240c"
``` ```
**Close out.** Update `SCOPE.md` and `WORK-RECORDS.md`; correct `ISSUE-WP-0003` **Close out.** Update `SCOPE.md`, retire the obsolete ArgoCD runbook, sync both
per T00; tell ops-warden and ops-bridge that CoulombCore has one fewer repos' work records, and tell activity-core, ops-warden, and ops-bridge that the
dependency. Remaining CoulombCore services after this: `core-hub-staging` and direct Service is authoritative and CoulombCore has one fewer dependency.
`inter-hub`. Remaining CoulombCore services after this: `core-hub-staging` and `inter-hub`.
## Implementation order and gates
1. T02 may create/register the wrapper, but does not bind compute or apply.
2. T03 must leave a schema-valid, digest-pinned, secret-free runtime package.
3. T04 binds and deploys only after T03 validation and the OpenBao references
are confirmed; its 201 smoke is the promotion gate.
4. T05 changes consumers only after T04; tunnel retirement is last.
5. T06 closes only after direct-path evidence and tunnel removal are recorded.
## Notes for whoever picks this up ## Notes for whoever picks this up
@ -205,6 +290,4 @@ dependency. Remaining CoulombCore services after this: `core-hub-staging` and
(tunnel `k3s-api-railiance01`, local `16444`). There is no CoulombCore (tunnel `k3s-api-railiance01`, local `16444`). There is no CoulombCore
kubeconfig any more — its `k3s-api` tunnel was removed on 2026-08-19, so kubeconfig any more — its `k3s-api` tunnel was removed on 2026-08-19, so
inspecting the *current* deployment needs that tunnel restored first. inspecting the *current* deployment needs that tunnel restored first.
- This workplan was drafted from outside issue-core (during ops-warden's - Reviewed 2026-08-19 in issue-core and promoted from `proposed` to `ready`.
CoulombCore retirement sweep). The tasks are stated as findings and decisions
rather than a fixed design, because the owning repo should make the calls.