Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 63291@bnt-lap001 Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
12 KiB
| id | type | title | domain | repo | status | flavor | owner | topic_slug | created | updated | related | state_hub_workstream_id | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| RPF-WP-0044 | workplan | ArgoCD phase B: adopt the four existing Applications on railiance01 | financials | railiance-platform | ready | planning | railiance-platform | railiance | 2026-09-21 | 2026-09-21 |
|
98140775-3b9a-5cf9-9af6-722502d487dc |
The founder, Bernd Worsch, decided ArchitectureBlueprint §5.6 on 2026-09-21,
exercising GOVERN @ estate: option 1, adopt properly. Phase A installed
Argo CD Core v3.5.3 on railiance01 (record:
the-custodian/docs/kubernetes-change-gate-decision.md). This plan is phase B:
bring the four Applications in argocd/applications/ under that ArgoCD, one
at a time, each with its own founder go-ahead. Terms follow SecurityCanon
Mode of Authority v0.2.0 (draft).
This plan changes nothing live. Every task that would change railiance01
is wait on the founder. Each live step is ADMINISTER @ realm:kubernetes/railiance01
(bootstrap) or CONSTRUCT @ railiance-platform with the merge as the gate,
both activation=APPROVED.
Related, kept separate: RPF-WP-0043 onboards rapp-policy-nexus, which is
not one of these four. It needs T02 of this plan (a working root app on
railiance01) before its own T04. Phase C, retiring coulombcore's ArgoCD, is
not planned here (T08).
Read-only evidence, 2026-09-21
Full record: docs/evidence/argocd-phase-b-adoption-diff-2026-09-21.json.
Rendered locally (helm template, kubectl kustomize), then kubectl diff
client-side and --server-side dry run over ssh railiance01. Nothing was
applied.
| App | Live spec diff | Would prune | Repo credential | Blocker |
|---|---|---|---|---|
| openbao-secretstore | none (1 ClusterSecretStore) | nothing | none, public | none |
| issue-core | none after repointing | nothing | new: rapp-issue-core is private |
declared path issue-core.git k8s/railiance no longer exists |
| target-revenue | none on Deployment/Service/Ingress/ExternalSecret/Cluster | nothing | none, public | CNPG Cluster not in railiance-tenants whitelist; two Sync-hook Jobs |
| external-secrets | none (39 objects, 20 CRDs) | nothing now | none, public Helm repo | cluster-wide blast radius; CRDs must never be pruned |
Nothing is pruned at adoption because no live object carries an ArgoCD tracking annotation; ArgoCD only prunes what it tracks. The one change every adoption makes is that tracking annotation, on metadata only, so no rollout.
Sync settings found: railiance-apps-root and all four children declare
automated: {prune: true, selfHeal: true}; none has a finalizer. Applying
argocd/bootstrap/ as committed would therefore adopt all four at once. T01
removes that before anything is applied.
Also found: the external-secrets Helm release is stuck at revision 7,
pending-upgrade, since 2026-07-07 (values identical to the Application);
issue-core is now server-side applied by rapp-issue-core;
target-revenue runs a mutable image tag (0.1.4). ArgoCD on railiance01
has 0 AppProjects, 0 Applications, 0 repository Secrets, and there is no
argocd CLI on the node, so the commands below use kubectl against the
Application resource. Not verified: repo-server egress to Forgejo and
charts.external-secrets.io; T02 proves it.
Neutralise automated sync and fix the declared state
id: RPF-WP-0044-T01
status: wait
priority: high
state_hub_task_id: "2d7230f5-50c8-5eee-a050-1501ce5af62a"
Waits on the founder's choice of layout. Repository-only; applying
nothing. But coulombcore's ArgoCD still syncs argocd/applications/ on
main, so an edit there is a live change on coulombcore.
- Option A (recommended): a railiance01-only source path,
argocd/railiance01/applications/, starting empty, and the railiance01 root pointing at it.argocd/applications/is left untouched for coulombcore until phase C. No commit in this plan then reaches coulombcore. - Option B: edit
argocd/applications/in place. Every change also lands on coulombcore's ArgoCD; needs its own go-ahead and a coulombcore read first.
Declared changes (Option A):
- Root app for railiance01 with no
automatedblock and pathargocd/railiance01/applications. railiance-tenants: addpostgresql.cnpg.io/ClustertonamespaceResourceWhitelist(target-revenue).- Child Application drafts kept in this workplan until their task; each
without
automated, without finalizers, withtargetRevisionpinned to a commit or chart version. issue-coredraft repointed torapp-issue-core.git, pathmanifests.- Add
argocd/repositories/rapp-issue-core.repository.sops.yaml.template(no value). Markissue-core.repository.sops.yaml.templateobsolete.
AppProjects and the root are applied by hand (T02), not synced by the root, so these edits change nothing live until T02.
Apply the AppProjects and the root app, automated sync off (live)
id: RPF-WP-0044-T02
status: wait
priority: high
state_hub_task_id: "7d97ee9c-b2fb-520f-8468-3ecf7eea6c01"
Waits on the founder's go-ahead. Depends on T01.
ssh railiance01 'kubectl apply --dry-run=server -f -' < <(kubectl kustomize argocd/bootstrap)
ssh railiance01 'kubectl apply -f -' < <(kubectl kustomize argocd/bootstrap)
ssh railiance01 'kubectl -n argocd get appprojects,applications'
Expect three AppProjects and railiance-apps-root Synced with zero children
(the path is empty). A ComparisonError means the repo-server cannot reach
Forgejo: stop and fix egress before any app task. No repository Secret is
needed; coulomb/railiance-platform is public.
Rollback: kubectl -n argocd delete application railiance-apps-root (no
finalizer, no children), then delete the three AppProjects. Nothing else is
touched.
Per-app procedure (T03–T06)
Every adoption task follows the same steps. <app> and <sha> vary.
- Diff. Re-run the evidence render and
kubectl diff --server-sideat the commit or chart version being pinned. Any spec change, any missing whitelist kind, or a different image: stop. - Merge the child Application (no
automated) into the railiance01 path, then sync the root by hand so it creates the child object only:ssh railiance01 'kubectl -n argocd patch application railiance-apps-root --type merge -p "{\"operation\":{\"initiatedBy\":{\"username\":\"founder-approved\"},\"sync\":{\"revision\":\"<sha>\",\"prune\":false}}}"' - ArgoCD's own diff: read
kubectl -n argocd get application <app> -o jsonpath='{.status.sync.status} {.status.health.status}'and.status.resources. Only metadata differences are acceptable. - Manual sync, prune off, hooks skipped (
applystrategy):
Then verify Synced/Healthy and run the owner's live check.ssh railiance01 'kubectl -n argocd patch application <app> --type merge -p "{\"operation\":{\"initiatedBy\":{\"username\":\"founder-approved\"},\"sync\":{\"revision\":\"<sha>\",\"prune\":false,\"syncStrategy\":{\"apply\":{}}}}}"' - Prove it: Synced and Healthy for at least 24 hours (7 days for
external-secrets). Only then, with a second go-ahead, a merge adds
automated: {selfHeal: true};prune: trueis a third step once the app's tracked set is confirmed complete. - Record
docs/evidence/<date>-<app>-argocd-adoption.json.
Rollback:
- R1, before automated sync: revert the merge, then
kubectl -n argocd delete application <app>. No finalizer, so nothing cascades; the workload keeps running. Tracking annotations stay and are harmless. - R2, after automated sync: revert the automated-sync commit first and
sync the root by hand, then R1. Never hand-patch a child while the root
self-heals; that is
BREAK_GLASS, recorded and reconciled into git. - Workload restore: only once ArgoCD no longer manages the app, with the previous deploy method named in the task.
Adopt openbao-secretstore (lowest risk)
id: RPF-WP-0044-T03
status: wait
priority: high
state_hub_task_id: "6d5fc801-e361-579b-bcd8-6fe719a82e94"
Waits on the founder's go-ahead. Depends on T02. One object,
ClusterSecretStore/openbao, zero diff, public source. It is the store
issue-core's ExternalSecret reads, so adopt it before issue-core. The 24
other ClusterSecretStores on railiance01 are not in the kustomization and stay
untracked (declared gap, RPF-WP-0043-T05). Live check:
kubectl get clustersecretstore openbao stays Valid, and
externalsecret/issue-core-runtime stays SecretSynced. Workload restore:
kubectl apply -f argocd/platform-addons/openbao-secretstore/openbao.clustersecretstore.yaml.
Adopt issue-core (from rapp-issue-core)
id: RPF-WP-0044-T04
status: wait
priority: high
state_hub_task_id: "0e619658-0453-51ed-b9a0-bed28b5544fd"
Waits on the founder's go-ahead, and on two preconditions:
rapp-issue-coreagrees (hub message) that ArgoCD owns production and itsmake deploystops being a production path; it would fight self-heal. Image releases become commits tomanifests/30-runtime.yaml.- A CCR for the ArgoCD repository credential, source at
platform/operators/argocd/repositories/rapp-issue-core, read-only deploy token. Applied withmake argocd-repo-apply; no value is handled in this plan.
Zero diff against live for both the raw manifests/ and the rendered output
(digest sha256:a56c80cc…b92cf). All kinds are in the railiance-tenants
whitelist. Live check: rapp-issue-core make verify-live. Workload restore:
rapp-issue-core make rollback.
Adopt target-revenue
id: RPF-WP-0044-T05
status: wait
priority: medium
state_hub_task_id: "d418068a-6fb0-5416-aac5-d23c93924d9c"
Waits on the founder's go-ahead. Preconditions: T01 item 2 (CNPG
Cluster whitelisted) applied to the AppProject by hand, and target-revenue
confirms the two Sync-hook Jobs (target-revenue-migrate,
target-revenue-bootstrap-binky) are safe to re-run against production. They
are absent live and would run on every sync with the default hook strategy.
The adoption sync uses the apply strategy, which skips them. Once automated
sync is enabled they run on each sync, so the second go-ahead depends on that
confirmation. Ask target-revenue to pin an image digest instead of 0.1.4.
Live check: https://revenue.coulomb.social health and the CNPG cluster
healthy. Workload restore: kubectl apply -k k8s/railiance from the previous
target-revenue commit.
Adopt external-secrets (highest risk)
id: RPF-WP-0044-T06
status: wait
priority: medium
state_hub_task_id: "4ca54868-c31f-5e3d-b7d3-a15b84c15f80"
Waits on the founder's go-ahead. Zero diff, but ESO serves every
ExternalSecret on the cluster (25 ClusterSecretStores). Before the merge,
add crds.annotations: {argocd.argoproj.io/sync-options: "Prune=false,Delete=false"}
to the values and re-run the diff; pruning a CRD would delete every
ExternalSecret and store. Adopt with ServerSideApply=true as declared.
Watch for drift on caBundle fields injected by the cert-controller; if
ArgoCD shows it, add ignoreDifferences before enabling self-heal. After
adoption, retire the stale pending-upgrade Helm release record (its
sh.helm.release.v1.external-secrets.v* Secrets) under a separate go-ahead;
ArgoCD does not track them. Live check: all ClusterSecretStores keep their
current Valid state (two, openbao-activity-core and
openbao-email-connect, are already ValidationFailed). Workload restore:
helm template 0.16.1 with the same values, kubectl apply --server-side.
Turn the root back to the production lane
id: RPF-WP-0044-T07
status: wait
priority: medium
state_hub_task_id: "844ff115-def2-55ca-ab01-413ba7e6857d"
Waits on the founder's go-ahead. After T03–T06 are proven, restore
automated: {prune: true, selfHeal: true} on railiance-apps-root, as the
change-gate decision's production row expects. From then on a merge to the
railiance01 path is a live production change, and RPF-WP-0043-T04
(policy-nexus) can use it.
Plan phase C: retire coulombcore's ArgoCD
id: RPF-WP-0044-T08
status: todo
priority: low
state_hub_task_id: "55d1382f-5862-5321-a1c9-96767764ba43"
Planning only. Needs a read-only check of coulombcore's ArgoCD, outside this
session's scope. Under Option A, retiring it also removes argocd/applications/.
Also hand back to the cluster layer: the phase A install is not declared in
any repository and its pods have no resource requests (BestEffort).