correction: credential-forward + unified graph; activate SOPS (author-first)

Operator directive: don't diverge architecture to avoid asking for credentials;
provision them upfront via SOPS and keep the existing (unified) graph.

Roadmap reconciliation: Phase 2 = Network/Storage/TLS/DNS/Ingress, so
cert-manager/externaldns/gateway (the credential-gated pieces) ARE Phase 2;
monitoring is Phase 4. Earlier A2/rollout scope was inverted by credential-avoidance.

Reverts (credential-driven): remove clusters/dev/rollout/ + the $patch:delete's;
restore unified base graph (dev = ../base + cluster-vars + SOPS decryption,
R-ENV-02 intact); restore monitoring files (Phase 4). Kept non-credential
improvements: tofu for_each/rejoin, Kyverno parametrization + webhook excludes.

platform/kustomization.yaml now phased (single shared list): Phase-2 set =
kyverno, cilium, longhorn, cert-manager, externaldns, gateway; later components
commented with phase markers.

SOPS activated: .sops.yaml at repo root; bootstrap/sops/secret-templates/*.yaml.example
for all secrets (cloudflare x2, grafana, alertmanager-smtp, keycloak, oauth2-proxy, pia);
bootstrap/sops/CREDENTIALS.md checklist; pre-wired commented cloudflare-api-token lines
in cert-manager + externaldns; filled non-secret ACME email. Agents never touch real
secret values (operator encrypts).

Validated: kubectl kustomize dev(unified)/prod/platform(Phase-2 only), templates inert,
make -C ci gate PASS.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
jakman85andClaude Opus 4.8 committed 2026-08-16 22:09:20 -05:00
1 parent e1c738fa63
commit a108d5ab98
23 files changed
+448 -198

No files matched your search

+40
View File
@@ -152,6 +152,46 @@ until their hand-offs land.
`helm`-installed with a release secret, or CLI/kubectl?) — verify before creating the cilium Kustomization.
4. Create the dev root Kustomization (the actual un-suspend) — deliberately NOT done here.
## CORRECTION — credential-forward, unified graph (operator directive, 2026-08-16)
**Operator pushback:** "Are we making implementation choices solely on the fact that you have to ask
for credentials? It is better to get the credentials upfront (encrypted file) and keep the rollout in
line with the existing architecture." **Correct — and it exposed a scope distortion.**
- **A2 SUPERSEDED / D-P2A REVERTED.** Choosing components by "needs no operator secret" inverted the
roadmap: `roadmap/phases.md` **Phase 2 = Network, Storage, TLS, DNS, Ingress** → the credential-gated
cert-manager/externaldns/gateway ARE the Phase-2 core, while **monitoring is Phase 4** (I'd pulled it
forward). The per-component dev divergence (`clusters/dev/rollout/`) existed only to dodge asking for
the Cloudflare token.
- **Reverted to the existing architecture:** deleted `clusters/dev/rollout/` + the `$patch: delete`s;
restored the unified base graph (dev = ../base + cluster-vars patches + SOPS decryption patches, one
`platform` Kustomization, R-ENV-02 intact — **removes the earlier architect-review flag**). Reverted
the monitoring Grafana/SMTP dodges (it's Phase 4). Kept the non-credential-driven improvements: tofu
for_each/rejoin (F1/F2), and Kyverno parametrization + webhook namespace-excludes (Kyverno IS Phase 2).
- **DECISION D-P2B — phase the unified `platform/kustomization.yaml` (operator-approved).** Components
are enabled in the single shared list **per phase** (the same pattern that deferred kyverno):
Phase-2 set now active = **kyverno, cilium, longhorn, cert-manager, externaldns, gateway**; monitoring/
image-automation (P4), velero (P4, OQ-BKP), kubevirt (P5), keycloak/oauth2-proxy (P6) are commented
with phase markers. dev+prod render the same list. Verified: `kubectl kustomize platform` renders only
the 6 Phase-2 namespaces; dev shows the unified platform+apps Kustomizations; prod builds; gate PASS.
- **DECISION D-SEC1 — provision ALL credentials upfront via SOPS; operator encrypts (both operator-chosen).**
Activated SOPS: `.sops.yaml` installed at repo root (recipient still REPLACE-ME — operator fills after
age-keygen). Authored `bootstrap/sops/secret-templates/*.yaml.example` (cloudflare-api-token ×2 ns,
grafana-admin, alertmanager-smtp, keycloak-admin, oauth2-proxy, pia — all placeholder-only, `.example`
so kustomize/SOPS ignore them) + `bootstrap/sops/CREDENTIALS.md` (end-to-end checklist). Pre-wired
**commented** `- cloudflare-api-token.sops.yaml` lines in cert-manager + externaldns kustomizations
(operator uncomments post-encrypt). Filled the non-secret ACME email ([email protected],
confirm/change). **Agents never touch real secret values** (per `.sops.yaml`).
### Operator TODO to reach Phase-2 deploy (see bootstrap/sops/CREDENTIALS.md)
1. age-keygen → fill root `.sops.yaml` recipient → install `sops-age` on cluster.
2. Provision `cloudflare-api-token` (Zone:DNS:Edit + Zone:Read on keithjackson.dev) in **both**
cert-manager + external-dns; uncomment the two kustomization lines.
3. Confirm ACME email. 4. Push `main` to host Gitea. 5. Create the dev root Kustomization (the un-suspend).
6. (Upfront, optional now) encrypt the Phase-3/4/6 secrets so later phases are credential-ready.
7. **Chart-key verification** (flagged in templates): keycloak + oauth2-proxy `existingSecret` key names,
Keycloak DB secret, and PIA/Gluetun protocol (≠ TCP) — verify at each component's phase.
## KNOWN ISSUES to fix before Phase-2 un-suspend (logged, not yet fixed)
| # | Issue | Impact | Fix |
|---|---|---|---|