mahmoud-consultancy → interimplazaStatus: APPROVED FOR PHASED EXECUTION (planning doc, updated 2026-05-29). This pass is still read-only — no renames, PRs, 1P writes, or git/ns mutations performed here. The owner has approved the §(b) P3 8-step procedure and made three sequencing decisions (below); this document now carries the exact owner click-paths and re-seal/DB commands so execution can fire back-to-back.
Owner decisions (2026-05-29, this revision):
recruitment_db →
interimplaza_db, via the fresh-install + pg_dump/pg_restore path in P3
step 4/restore (not a live ALTER DATABASE). See §(b) P3 DB-rename procedure.The exact owner-facing 1P rename steps (web UI click-path and op item edit
CLI), the O2 re-seal flow, and the DB rename/pg_dump procedure are in §(b) P3
below; the reordered owner-action list is in §(c.1).
Prepared by: adhoc-interimplaza-rename-plan (one-shot swarm agent),
revised by -v2, then -v3 (this revision — owner approval + exact 1P/DB
steps).
The thing called "mahmoud-consultancy" is only a repo name + a GHCR image path + a local directory name + workspace prose. Two premises in the original task brief are wrong and change the plan materially:
The repo is already under mahmoudholding, not theroomyapp.
git remote -v → https://github.com/mahmoudholding/mahmoud-consultancy.git.
gh repo view theroomyapp/mahmoud-consultancy → resolves (via GitHub's
redirect) to mahmoudholding/mahmoud-consultancy. So the repo was already
transferred to the holding org at some earlier point; theroomyapp/...
references in the swarm prompts and root CLAUDE.md are stale redirects
that still happen to work. → Owner decision (i) "keep under theroomyapp or
transfer to mahmoudholding" is moot — it is already on mahmoudholding. The
rename command is gh repo rename interimplaza --repo mahmoudholding/mahmoud-consultancy.
The k8s namespace is NOT mahmoud-consultancy. Staging is
recruitment-staging, prod is recruitment, the Helm chart is
recruitment-platform, and the 1P items are recruitment-platform-secrets-*.
None of these contain the literal mahmoud-consultancy. So a repo rename
does not force a namespace/chart/secret rename — those are an entirely
separate, much riskier piece of work (see P3). Per owner override
(2026-05-29) P3 is now in scope (downtime accepted), executed as its own
backup→re-seal→reinstall migration after P1/P2.
Net: the literal token mahmoud-consultancy (or mahmoud_consultancy)
appears in 259 files, but the operationally-load-bearing occurrences are a
short list (≈10 files). The other ~250 are docs, archived session reports, and
swarm/bus history — cosmetic, batchable, and mostly safe to leave or sweep
lazily.
mahmoud-consultancy)These actually break / change behaviour if the repo or image path changes.
| # | File | Reference | What it controls |
|---|------|-----------|------------------|
| A1 | (local) git remote | https://github.com/mahmoudholding/mahmoud-consultancy.git | push/pull target |
| A2 | mahmoud-consultancy/helm/recruitment-platform/values.yaml:15 | ghcr.io/mahmoudholding/mahmoud-consultancy/backend | backend image pull |
| A3 | …/values.yaml:19 | ghcr.io/mahmoudholding/mahmoud-consultancy/frontend | frontend image pull |
| A4 | …/values.yaml:366 | ghcr.io/mahmoudholding/mahmoud-consultancy/cv-service | cv-service image pull (optional component, off by default) |
| A5 | .github/workflows/ci-backend.yml:15 | IMAGE: ghcr.io/mahmoudholding/mahmoud-consultancy/backend | image push (CI) |
| A6 | .github/workflows/ci-frontend.yml:19 | IMAGE: …/mahmoud-consultancy/frontend | image push (CI) |
| A7 | .github/workflows/deploy-backend.yml:27 | IMAGE: …/mahmoud-consultancy/backend | image ref used in CD |
| A8 | .github/workflows/deploy-frontend.yml:27 | IMAGE: …/mahmoud-consultancy/frontend | image ref used in CD |
| A9 | package.json:47 | git+https://github.com/glorylabs/recruitment-platform.git | STALE repo URL (points at neither org — pre-existing bug, fix opportunistically) |
| A10 | local directory mahmoud-consultancy/ | dir name | every cd, every script path, swarm start-claude.sh PROJECTS array |
Note: the GHCR image org stays
mahmoudholding. Only the middle segmentmahmoud-consultancy→interimplazachanges:ghcr.io/mahmoudholding/interimplaza/{backend,frontend,cv-service}.
mahmoud-consultancyThese use recruitment-platform / recruitment-staging / recruitment /
recruitment-platform-secrets-*. They do not need to change for a repo
rename. They are listed only so the owner understands the namespace decision
(P3) is independent. Touching them is the high-risk path:
_helpers.tpl template names (recruitment-platform.*),
every templates/*.yaml, values.yaml, values-local.yaml.deploy-backend.yml:66, deploy-frontend.yml:73
(NS="recruitment-staging"), and recruitment (prod) across rotation
workflows (rotate-db-password.yml, rotate-jwt.yml, rotate-redis-password.yml),
disaster-recovery.md, setup-vps.sh.recruitment-platform-secrets-{production,staging} (vault InterimPlaza),
seal-secrets.sh, backend-secret name recruitment-platform-backend-secret.Cosmetic-but-coordinating; update so the fleet/docs refer to the new name.
| File | Reference |
|------|-----------|
| CLAUDE.md (root) | corporate structure table, port registry row, Ingress/Issues table (theroomyapp/mahmoud-consultancy) |
| start-claude.sh:27 | PROJECTS=( … mahmoud-consultancy … ) — functional: launcher iterates this |
| .swarm/designqa-eligible:7 | mahmoud-consultancy — functional: design-QA rotation list |
| .swarm/inbox/mahmoud-consultancy | inbox dir name — functional if renamed |
| .swarm/DOD-PROMPT.md (lines 15, 31, 39) | project list + theroomyapp/mahmoud-consultancy repo map |
| .swarm/BUSINESS-PROMPT.md (lines 19, 32, 49) | project list + repo map |
| .swarm/BUS-PROTOCOL.md:9 | workers list |
| SWARM.md | project references |
| .swarm/pending/post-refocus-multi-arch-fleet.task | task body mentions it |
| .swarm/sanity-eligible | NOT present (mahmoud-consultancy is not yet in the sanity rotation — only valideerleeftijd, claimio) |
Note:
sanity-eligibledoes not list mahmoud-consultancy, so no sanity rotation change needed.
docs/, ocs/, repo docs/)Large but low-risk; batch sed + review. Live (non-archive) docs:
docs/README.md, docs/mahmoud-consultancy/README.md,
docs/mahmoud-consultancy/compliance/README.md,
docs/mahmoud-consultancy/disaster-recovery.md,
docs/mahmoud-consultancy/frontend-setup.md, docs/definition-of-done.md,
docs/ci-cd-reference.md, docs/mvp-readiness.md, docs/dod-compliance.md,
docs/human-actions.md, docs/claude-github-app-setup.md,
docs/ops/ci-alternatives-proposal.md,
docs/ops/node-capacity-guardrail-proposal.md.ocs/README.md, ocs/mahmoud-consultancy/README.md.mahmoud-consultancy/README.md, mahmoud-consultancy/CLAUDE.md
(lines 117/146/166: namespace, GHCR path, 1P items),
mahmoud-consultancy/CURRENT_TASK.md, …/docs/frontend-setup.md,
…/docs/compliance/README.md, …/docs/interimplaza/Execution/…,
…/website/website/src/pages/contact.astro, …/bin/readme.md.auditPic/docs/architecture.md,
auditPic/docs/CLUSTER_ACCESS.md, claimio/docs/CLUSTER_ACCESS.md,
valideerleeftijd/{CLAUDE.md,PLAN.md,docs/*}, europeLogin/CLUSTER_ACCESS.md,
developer-portal/{README.md,consultancy.html,docs/workspace/*}.docs/mahmoud-consultancy/,
ocs/mahmoud-consultancy/ (rename dirs → interimplaza/).Leave as-is; rewriting history is noise and risks. ~200 of the 259 files:
mahmoud-consultancy/docs/archive/**, mahmoud-consultancy/bin/SESSION_*,
docs/mahmoud-consultancy/archive/**,
mahmoud-consultancy/archive/old-directories/**..swarm/bus.log, .swarm/logs/*.log, glorylabs/logs/*,
HANDOFF-2026-05-19.md, HANDOFF-2026-05-20.md, docs/audit-2026-05-18.md,
interimplaza.zip (already named interimplaza — a prior export)..idea/*, .obsidian/workspace.json, e2e-results/* (regenerated).GitHub keeps a redirect on rename, so nothing breaks instantly.
gh repo rename interimplaza --repo mahmoudholding/mahmoud-consultancy
(GitHub auto-redirects old URL → no immediate breakage).git -C mahmoud-consultancy remote set-url origin https://github.com/mahmoudholding/interimplaza.gitmahmoud-consultancy/ → interimplaza/,
docs/mahmoud-consultancy/ → docs/interimplaza/,
ocs/mahmoud-consultancy/ → ocs/interimplaza/,
.swarm/inbox/mahmoud-consultancy → .swarm/inbox/interimplaza.start-claude.sh PROJECTS,
.swarm/designqa-eligible, swarm prompts, root CLAUDE.md, SWARM.md.
Fix the stale theroomyapp/ → mahmoudholding/interimplaza while here.package.json repo URL (A9) → mahmoudholding/interimplaza.Risk: low. No running workload touched. Redirect covers any missed git URL. Worktree-isolatable; reversible by renaming back.
The CD pull path and the CI push path must both point at the new image, and an image must EXIST at the new path before CD references it, or the next deploy pulls a 404.
ghcr.io/mahmoudholding/interimplaza/{backend,frontend}), OR re-tag/copy
existing mahmoud-consultancy/* images to interimplaza/* (crane/skopeo).IMAGE: env in ci-backend.yml, ci-frontend.yml,
deploy-backend.yml, deploy-frontend.yml and repository: in
values.yaml (A2–A8) in ONE PR.imagePullSecrets/GHCR visibility on the new path (new package =
may default to private; grant the same pull token).recruitment-staging) and verify
/actuator/health + pods Ready before letting prod CD run.mahmoud-consultancy/* packages in GHCR for a cooldown (cheap
rollback), delete later.Risk: medium. Mitigated by push-before-flip ordering, staging-first, and
keeping old images. Helm chart name (recruitment-platform) is NOT changed
here — release name stays the same so helm upgrade stays in-place.
This is a backup→re-seal→reinstall migration, not an in-place edit. Sealed secrets and PVCs do not move across namespaces, so the new namespace is built fresh alongside the old one and the old one is deleted only after the new one is verified serving. Staging first, then prod in a separate owner-gated window.
| Layer | From | To |
|---|---|---|
| Helm chart dir | helm/recruitment-platform/ | helm/interimplaza/ |
| Chart.yaml name: | recruitment-platform (v1.0.0) | interimplaza |
| _helpers.tpl template defines | recruitment-platform.{name,fullname,chart,labels,selectorLabels,serviceAccountName} | interimplaza.{…} (all 6 defines + every {{ include "recruitment-platform.* }} call in templates/*.yaml) |
| Derived fullname (used for Deployment/Service/SA/Secret names) | recruitment-platform-* (because nameOverride/fullnameOverride are both empty → fullname = chart name) | interimplaza-* |
| Bitnami subchart service hosts | recruitment-platform-postgresql, recruitment-platform-redis-master (values.yaml:197,211) | interimplaza-postgresql, interimplaza-redis-master (these track the release name — re-point backend database.host/redis.host accordingly) |
| Backend secret name | recruitment-platform-backend-secret (backend-secret.yaml, seal-secrets.sh:41, bitnami existingSecret at values.yaml:296,336) | interimplaza-backend-secret |
| k8s namespace (staging) | recruitment-staging (deploy-backend.yml:66, deploy-frontend.yml:73, seal-secrets.sh:46) | interimplaza-staging |
| k8s namespace (prod) | recruitment (rotation workflows, disaster-recovery.md, setup-vps.sh, seal-secrets.sh:44) | interimplaza |
| 1P items (vault InterimPlaza) | recruitment-platform-secrets-{production,staging} | interimplaza-secrets-{production,staging} |
| seal-secrets.sh defaults | OP_VAULT=InterimPlaza (unchanged), OP_ITEM=recruitment-platform-secrets-${ENV} (:50), SECRET_NAME=recruitment-platform-backend-secret (:41), NAMESPACE=recruitment[-staging] (:44,46) | item → interimplaza-secrets-${ENV}; secret → interimplaza-backend-secret; ns → interimplaza[-staging] |
| DB name | recruitment (values.yaml:199, bitnami postgresql.auth.database=recruitment at :290) — DOES contain the old token | interimplaza_db — NOW INCLUDED (owner decision 2026-05-29, decision (v) flipped to "yes"). ⚠️ Verified current name is recruitment (not recruitment_db) — owner's target interimplaza_db is the new name; confirm the owner doesn't instead want bare interimplaza to match the ns/role convention. See DB-rename procedure below. |
DB-rename note (owner decided 2026-05-29: INCLUDE the name rename): the
database name is recruitment and the bitnami admin user / Flyway user is
recruitment, with a DML app role recruitment_app. The role names are baked
into Flyway migrations (V008__app_role.sql → CREATE ROLE recruitment_app,
V010__app_role_password.sql, and the ALTER ROLE "recruitment" WITH CREATEROLE init SQL at values.yaml:315).
recruitment → interimplaza_db) — IN SCOPE. Do
not use a live ALTER DATABASE … RENAME (Postgres requires zero active
connections to that DB). Instead use the fresh-install + dump/restore path:
let the new-ns bitnami install create the DB under the new name, pg_dump the
old DB before deleting the old ns, and pg_restore/psql into the new DB.
The data dump is portable across DB names. Full commands + the brief
data-frozen window are in the DB-rename procedure immediately below.recruitment, recruitment_app) — leave as-is.
Renaming them means rewriting committed Flyway history (forbidden) or adding
ALTER ROLE … RENAME migrations + re-pointing every grant; zero external
benefit, internal-only labels. Flag as explicitly out of scope for P3.
(So: DB name changes to interimplaza_db; the owning role stays
recruitment — set bitnami postgresql.auth.username=recruitment and
postgresql.auth.database=interimplaza_db in the new-ns values.)recruitment → interimplaza_db, dump/restore, data-frozen window)Folded into P3 step 4 / the restore. Runs per env (staging first). The dataset is small on staging, so the freeze window is < 5 min.
Set the new DB name in the new-ns values (part of the P3 PR): bitnami
postgresql.auth.database: interimplaza_db (keep username: recruitment),
and re-point the backend database.name/JDBC URL to interimplaza_db. The
fresh helm install (step 4) then creates an empty interimplaza_db owned by
role recruitment, and Flyway runs its migrations into it.
FREEZE — scale the OLD backend to 0 so no writes land during the dump (this opens the data-frozen window):
kubectl -n recruitment-staging scale deploy/recruitment-platform-backend --replicas=0
Dump the OLD DB (this is the step-1 backup of the 8-step, now naming the target DB explicitly):
kubectl -n recruitment-staging exec recruitment-platform-postgresql-0 -- \
bash -c 'PGPASSWORD="$POSTGRES_PASSWORD" pg_dump -U recruitment -d recruitment \
--no-owner --no-privileges -Fc' \
> /tmp/interimplaza-staging-$(stamp).dump
(-Fc custom format → use pg_restore; or drop -Fc for plain SQL → use
psql. Either is DB-name-agnostic, which is exactly why the rename is safe.)
Restore into the NEW DB in the new ns (after step 4 helm install brought
interimplaza-postgresql up with an empty interimplaza_db):
kubectl -n interimplaza-staging exec -i interimplaza-postgresql-0 -- \
bash -c 'PGPASSWORD="$POSTGRES_PASSWORD" pg_restore -U recruitment \
-d interimplaza_db --no-owner --no-privileges' \
< /tmp/interimplaza-staging-*.dump
(Plain-SQL variant: … psql -U recruitment -d interimplaza_db < dump.sql.)
Flyway may have already created the schema on install; if the restore
conflicts, restore into a DB created with helm install … --set backend.flyway.enabled=false (or scale backend to 0 during install) so the
dump is the sole source of schema+data, then scale up.
UNFREEZE — verify the new ns serves (8-step step 5), then end the freeze:
the new backend is already at its normal replica count from helm install;
the OLD backend stays at 0 (it is about to be deleted in step 7). Total
data-frozen window = dump + restore + verify ≈ < 5 min on staging (small
dataset). Prod's window is sized in its own deferred decision but expected to
stay a few minutes given the dataset size.
The freeze exists so the dump is a consistent point-in-time copy with no writes lost between dump and cutover. Because the OLD ns is deleted only at step 7 (after the NEW ns is verified), a failed restore is a zero-data-loss fallback: scale the OLD backend back to 1 and you are exactly where you started.
Scheduled NOW, in parallel with the auditPic team-dashboard work (owner
decision 2026-05-29) so P2/P3-staging can fire back-to-back once PR-A merges.
Vault, item, and secret names below are verified against
mahmoud-consultancy/scripts/seal-secrets.sh (vault InterimPlaza; items
recruitment-platform-secrets-{staging,production}; secret
recruitment-platform-backend-secret; namespaces recruitment[-staging]).
Do the staging item now; the production item waits for its deferred
window (O3).
O1 — rename the 1P items. Either path works; the field names inside each item are unchanged, so nothing else in the item needs editing.
Option A — 1Password web UI (click-path):
https://mahmoudholdingbv.1password.com.InterimPlaza vault (left sidebar).recruitment-platform-secrets-staging (search box top-left).interimplaza-secrets-staging.recruitment-platform-secrets-production → interimplaza-secrets-production
only when the prod window opens (O3) — not now.Option B — op CLI (requires an authenticated op session — op signin, or
OP_SERVICE_ACCOUNT_TOKEN with write scope):
# staging (do now):
op item edit "recruitment-platform-secrets-staging" \
--vault "InterimPlaza" \
--title "interimplaza-secrets-staging"
# production (defer to the prod window, O3 — do NOT run now):
op item edit "recruitment-platform-secrets-production" \
--vault "InterimPlaza" \
--title "interimplaza-secrets-production"
Verify: op item get "interimplaza-secrets-staging" --vault "InterimPlaza" --format json | jq .title.
O2 — re-seal once the item is renamed. The seal script reads the item name
from OP_ITEM (default recruitment-platform-secrets-${ENV},
seal-secrets.sh:50). Two ways to make it read the new name:
Now / quick (no code change): pass OP_ITEM inline (the script honors the
env override), regenerating the staging sealed manifest from the renamed
item but still targeting the OLD ns recruitment-staging (the manifest is
ns-scoped and the NEW ns doesn't exist yet — that re-seal happens in 8-step
step 3):
cd mahmoud-consultancy
OP_SERVICE_ACCOUNT_TOKEN=<token> \
OP_ITEM=interimplaza-secrets-staging \
./scripts/seal-secrets.sh staging
# → regenerates k8s/sealed-secrets/backend-secrets-staging.yaml, ns=recruitment-staging
git add k8s/sealed-secrets/backend-secrets-staging.yaml
git commit -m "chore(secrets): re-seal staging from renamed 1P item interimplaza-secrets-staging"
This keeps the OLD ns deployable from the renamed item right now, decoupled from the ns swap.
In the P3 PR (permanent): edit seal-secrets.sh:50 default
OP_ITEM=recruitment-platform-secrets-${ENV} →
OP_ITEM=interimplaza-secrets-${ENV} (and, when the ns/chart rename lands,
SECRET_NAME :41 → interimplaza-backend-secret and NAMESPACE :44,46
→ interimplaza[-staging]). After that edit, a plain
./scripts/seal-secrets.sh staging reads the new item with no inline override.
Ns scope reminder: the re-seal done NOW (above) targets the OLD ns
recruitment-staging— correct for keeping the current release deployable. The NEW nsinterimplaza-stagingre-seal is a separate run done in 8-step step 3 (withOP_ITEM+SECRET_NAME+NAMESPACEall overridden to the new values), because a SealedSecret cannot be retargeted across namespaces by edit.
Run for recruitment-staging → interimplaza-staging end-to-end and verify
before even scheduling prod. The old namespace is the rollback artifact and is
kept until step 7.
⏸️ DATA-FROZEN WINDOW (callout). Because the DB name rename is now in scope, step 1's dump must be a consistent point-in-time copy. The window opens when the OLD backend is scaled to 0 (no more writes) and closes when the NEW ns is verified serving (step 5). Target: < 5 min on staging (small dataset). The exact freeze/dump/restore commands are in the DB-rename procedure above; the 8-step below references them at steps 1 and 4. Prod's freeze is sized in its own deferred window decision (O3).
FREEZE + backup the DB in recruitment-staging. Opens the data-frozen
window: scale the OLD backend to 0 (kubectl -n recruitment-staging scale deploy/recruitment-platform-backend --replicas=0), then take a logical dump
of Postgres (note any MinIO bucket if the optional object-store component were
ever enabled — off by default here):
# pod name: the bitnami postgres primary in the OLD ns
kubectl -n recruitment-staging exec -it recruitment-platform-postgresql-0 -- \
bash -c 'PGPASSWORD="$POSTGRES_PASSWORD" pg_dump -U recruitment -d recruitment --no-owner --no-privileges' \
> /tmp/interimplaza-staging-$(stamp).sql
tar czf /tmp/interimplaza-staging-pgdump.tar.gz -C /tmp interimplaza-staging-*.sql
Lands at: the operator's laptop /tmp/interimplaza-staging-pgdump.tar.gz
(copy to the project's offline backup location before proceeding).
Restore path (DB rename in scope): psql -U recruitment -d interimplaza_db < dump.sql into the NEW ns's postgres pod (data dump is DB-name-agnostic —
that is what makes the recruitment → interimplaza_db rename safe). See the
DB-rename procedure above for the full freeze/dump/restore commands. Keep
the dump until prod is also cut over and verified.
OWNER renames the 1P items in the InterimPlaza vault. This is O1 and
runs NOW (in parallel with the auditPic work) — see the exact web-UI
click-path and op item edit CLI in **"Owner-action-NOW: exact 1P rename
OP_ITEM/SECRET_NAME/NAMESPACE references (these go in the P3
PR). Field names inside each item are unchanged.Re-seal secrets under the NEW item names into the NEW namespace.
SealedSecrets are namespace-scoped — you must re-seal, never sed the
namespace field (root CLAUDE.md forbids it; a re-targeted manifest cannot be
decrypted). The O2 re-seal flow (run NOW for the OLD ns, re-run for the
NEW ns at this step) is detailed in the same subsection below. With the
owner's OP_SERVICE_ACCOUNT_TOKEN:
kubectl create namespace interimplaza-staging
OP_SERVICE_ACCOUNT_TOKEN=<token> \
OP_ITEM=interimplaza-secrets-staging \
SECRET_NAME=interimplaza-backend-secret \
NAMESPACE=interimplaza-staging \
./scripts/seal-secrets.sh staging
kubectl apply -f k8s/sealed-secrets/backend-secrets-staging.yaml # now ns-scoped to interimplaza-staging
helm install in the new namespace with the new chart name + new image
path (from P2) + new secret name + new DB name (postgresql.auth.database: interimplaza_db, postgresql.auth.username: recruitment unchanged, backend
database.name/JDBC URL re-pointed — all in the P3 PR's values):
helm install interimplaza ./helm/interimplaza \
-n interimplaza-staging \
-f helm/interimplaza/values-staging.yaml
(New chart name ⇒ new fullname ⇒ bitnami subcharts come up as
interimplaza-postgresql / interimplaza-redis-master; backend config must
already point at those hosts from the scope table.)
Then restore the step-1 dump into the new interimplaza_db (DB-rename
procedure step 4) before unfreezing — pg_restore/psql … -U recruitment -d interimplaza_db. If Flyway-on-install conflicts with the restore, install with
backend scaled to 0 / Flyway disabled so the dump is the sole schema+data
source, then scale up.
Verify the new namespace serves before deleting anything:
kubectl -n interimplaza-staging get pods # backend 1/1, postgres/redis Ready
kubectl -n interimplaza-staging exec deploy/interimplaza-backend -- \
wget -qO- localhost:<containerPort>/actuator/health # expect {"status":"UP"}
DNS / ingress hostname is UNCHANGED — confirm only. Staging already uses
interimplaza.staging.glorylabs.nl (values-staging.yaml:124,135) and prod
uses the brand hosts (glorylabs.nl / www.glorylabs.nl, later
app.interimplaza.nl). The ingress object is namespaced, so the new release
recreates it in the new ns with the same Host: rules — no DNS change, no
cert reissue needed (same hostnames → same TLS secret content, re-sealed in
step 3 if it lived in the backend secret). Verify the new ingress has the
address and the host responds.
Delete the OLD recruitment-staging namespace — only after step 5/6
confirm the new ns is fully serving real traffic:
helm uninstall recruitment-platform -n recruitment-staging
kubectl delete namespace recruitment-staging
This drops the old PVCs; the step-1 dump remains the cold-backup.
Repeat 1–7 for PROD (recruitment → interimplaza) in its own
owner-gated window — scale backend to 0 / accept the brief downtime while
the new ns comes up and the dump restores. Prod uses the prod 1P item, prod
values, and the prod hostnames; otherwise identical ordering.
Risk: high but bounded — old ns retained through step 6 means any failure before deletion is a zero-data-loss fallback to the still-running old release. Downtime is the deliberate cost the owner has accepted (mainly the prod cutover window in step 8).
| # | Decision | Recommendation |
|---|----------|----------------|
| (i) | Keep repo under theroomyapp or transfer to mahmoudholding? | Moot — already on mahmoudholding. Just rename in place; fix the stale theroomyapp/ strings in swarm prompts/CLAUDE.md while renaming. |
| (ii) | Rename the k8s namespace too (P3) or skip? | DECIDED: EXECUTE P3 (owner override 2026-05-29, downtime accepted). Run the §(b) P3 backup→re-seal→reinstall procedure, staging first then prod in a separate window. |
| (iii) | Timeline vs. letting the auditPic team-dashboard API land first? | Sequence after any in-flight auditPic team-dashboard work to avoid cross-repo churn, but P1 (repo/docs rename) is parallel-safe and could run anytime; only P2 (image flip) needs a quiet CD window. Recommend: do P1 now if convenient, schedule P2 for a deliberate staging-verified window. |
| (iv) | (new) Re-tag existing GHCR images vs. rebuild under new path? | Re-tag/copy (crane/skopeo) is faster and preserves the exact deployed digest; rebuild is cleaner provenance. Either works — re-tag recommended for the cutover, rebuild on next normal CI run. |
| (v) | Rename the DB name (recruitment → interimplaza_db) during P3? | DECIDED: YES, INCLUDED (owner 2026-05-29). Via the fresh-namespace install creating a DB named interimplaza_db + pg_dump/pg_restore (no live ALTER DATABASE, which needs zero active connections). Brief data-frozen window (< 5 min staging). DB role names stay recruitment/recruitment_app (baked into Flyway — out of scope). See §(b) DB-rename procedure. |
These steps require the owner — credentials, irreversible go/no-go, or
human-only 1P UI — and gate the rest of P3. Everything else (chart/file edits,
helm install, kubectl) a worker can do once these are cleared. Scheduling
(owner decision 2026-05-29): O1 + O2 run NOW, in parallel with the auditPic
team-dashboard work (front-loaded so P2/P3-staging fire back-to-back when PR-A
merges); O4 is now decided "yes" and folded into P3 (no longer a gate); O3
(prod window) stays deferred until the staging swap is verified.
Listed in execution order:
| # | Owner action | When | Why owner-only |
|---|---|---|---|
| O1 | Rename the 1P item(s) in vault InterimPlaza (exact web-UI click-path + op item edit CLI in §(b) "Owner-action-NOW"). Staging item recruitment-platform-secrets-staging → interimplaza-secrets-staging NOW; prod item only when O3's window opens. | NOW (staging) / P3 step 2 (prod) | 1P writes are owner-gated; no service-account write path in CI. |
| O2 | Re-seal from the renamed item — provide OP_SERVICE_ACCOUNT_TOKEN (or run it personally). NOW: re-seal staging into the OLD ns from the renamed item (quick, decoupled). At P3 step 3: re-seal into the NEW ns. Both flows in §(b) "Owner-action-NOW". | NOW (old-ns) / P3 step 3 (new-ns) | Holds the only credential that reads the vault to seal. |
| O4 | DB-rename: DECIDED YES — new-ns DB named interimplaza_db via dump/restore (decision (v)). No longer a go/no-go gate; remaining owner input is only confirming interimplaza_db vs. bare interimplaza as the final name. | folded into P3 step 4 | Schema/identity decision — owner confirms final DB name. |
| O3 | Prod ns-swap go/no-go window — DEFERRED: decided separately once the staging swap is done and verified. Approve the brief prod downtime + freeze and pick the window for P3 step 8 (and the prod 1P-item rename). | DEFERRED — after staging swap; before P3 step 8 | Accepts the user-visible downtime; irreversible delete of old prod ns at step 7/8. |
gh repo rename mahmoud-consultancy --repo mahmoudholding/interimplaza
to revert; GitHub redirect works in both directions. Local: git remote set-url back, mv dirs back. Docs/control-plane: git revert the PR.IMAGE:/repository: PR and redeploy;
Helm release name unchanged so helm rollback also works to the prior
revision. Verify on recruitment-staging before prod.recruitment[-staging] is still running and serving — abort by simply not
cutting traffic / not deleting it; kubectl delete namespace interimplaza[-staging] to discard the half-built new ns and retry.k8s/sealed-secrets/backend-secrets-${ENV}.yaml (scoped to
recruitment[-staging]) stays valid for the old ns — it is the secret
rollback. The re-sealed new-ns manifest is additive, not a replacement.kubectl create namespace recruitment[-staging], re-seal the old item into it (if 1P item still
renamed, seal from the renamed item but with old SECRET_NAME/NAMESPACE),
helm install recruitment-platform from the pre-P3 chart commit, and
restore the step-1 pg_dump. Hence: keep the step-1 dump until prod is
cut over and verified, and do prod (step 8) only after staging is proven.op item edit (or web UI) to rename items back; trivial
and reversible.Run NOW, in parallel (owner decision 2026-05-29): O1 (rename the staging 1P item) + O2 (re-seal staging into the OLD ns from the renamed item). These are independent of PR-A and front-loaded so the rest fires back-to-back the moment PR-A lands.
Gate for everything else: nothing in P2/P3 executes until the auditPic team-dashboard PR-A merges (itself gated on the org billing clear). Once that lands:
P1 (anytime, parallel-safe) → P2 (deliberate staging-verified CD window) → P3-staging (O1/O2 already done now; then re-seal-into-new-ns → FREEZE+dump → reinstall(new DB interimplaza_db)+restore → verify → unfreeze → delete old ns) → P3-prod (DEFERRED, separate owner-gated window: prod O1/O2 + O3 window + accepted downtime/freeze).
Recommended P3 ns-swap timing: a low-traffic owner-attended maintenance window — staging anytime after P2 is verified; prod is DEFERRED to a deliberate off-hours window (evening / weekend), decided once the staging swap is proven, with the owner present for the prod 1P-item rename + O3 + the brief cutover downtime/freeze.
Reacties