openova/platform/wordpress-tenant/chart
e3mrah f6757c7c93
feat(docs): lean documentation strategy — consolidate 16 docs into 7 canonical + 3 subdirs (#2094)
* docs(arch): consolidate ARCHITECTURE + PLATFORM-TECH-STACK + NAMING + EPICS-1-6 + BOOTSTRAP-KIT-EXPANSION → docs/ARCHITECTURE.md (lean doc strategy)

Single canonical "how OpenOva works" doc per founder's lean-doc strategy.
2926 source lines → 1110 consolidated lines, no semantic loss.

Sections:
 §1  High-level model (Catalyst/Sovereign/Org/Env/Application/Blueprint)
 §2  Repo layout
 §3  Tech stack by layer (CNI/GitOps/IaC/event-spine/data/secrets/identity/...)
 §4  Naming conventions (dimensions, patterns, labels, DOMAINS-CANON)
 §5  Catalyst control plane (rules, CRDs, controllers, cutover, identity, surfaces)
 §6  Per-host-cluster infrastructure
 §7  Application Blueprints
 §8  Multi-region topology (1 cpx52/region, WireGuard-over-public-IPs, ClusterMesh)
 §9  Bootstrap-kit slot ordering (full 48-slot canonical list)
 §10 EPIC-level design overview (EPIC-0 through EPIC-6)
 §11 Per-chart DESIGN.md inventory
 §12 OAM influence
 §13 Read further

Stale literal fixes:
 - omantel.openova.io → omantel.biz / <sovereign>.<tld> / t38.omani.works (7 instances)
 - SPIRE marked DEFERRED / opt-in only (PR #665, TBD-V29 #2055)
 - failover-controller marked REPLACED by bp-continuum

New PR refs wired into §3:
 - PR #665   SPIRE deferral
 - PR #2071  bp-cnpg-pair synchronous remote_apply (zero-tx-loss multi-region)
 - PR #2087  bp-cnpg-pair pre-merge guard
 - PR #2093  bp-cnpg-pair pre-merge guard

New stack components added to §3:
 - bp-cnpg-pair  (synchronous remote_apply ReplicaCluster across ClusterMesh)
 - bp-continuum  (lease-based failover orchestrator)
 - bp-self-sovereign-cutover (8-tether pivot, ADR-0002, Principle #11)

Source docs (to be deleted by orchestrator in final PR):
 - docs/PLATFORM-TECH-STACK.md
 - docs/NAMING-CONVENTION.md
 - docs/EPICS-1-6-unified-design.md
 - docs/BOOTSTRAP-KIT-EXPANSION-PLAN.md

* docs(principles): consolidate INVIOLABLE-PRINCIPLES + ANTI-PATTERN-CATALOG → docs/PRINCIPLES.md (lean doc strategy)

* docs(dod): consolidate 5-PILLAR-DOD + DOMAINS-CANON + SOVEREIGN-MULTI-REGION-DOD + PERSONAS-AND-JOURNEYS → docs/DOD.md (lean doc strategy)

* docs(runbooks+status+glossary): consolidate 5 runbooks → RUNBOOKS.md + refresh STATUS.md + fold banned-terms into GLOSSARY.md (lean doc strategy)

Part 1 — Runbook consolidation:
- NEW docs/RUNBOOKS.md with 7 numbered sections (provisioning, day-2 ops,
  Blueprint authoring, chart conventions, demo walk, failover, troubleshooting)
- Folds BLUEPRINT-AUTHORING / CHART-AUTHORING / DEMO-RUNBOOK /
  RUNBOOK-OPERATIONS / RUNBOOK-PROVISIONING into one canonical surface
- Documents dual-annotation requirement for charts with enabled.default: false
  (GUARD 1 #2087 no-upstream + GUARD 2 #2093 smoke-render) with bp-network-policies:1.0.1
  dead-reserve incident as the live evidence
- All admin.<fqdn> legacy URL refs → console.<fqdn>/bss (BSS lives in operator console)
- All openova.io / omantel.omani.works test commands → canonical t<NN>.omani.works
- Cites PRs #2076 (docs migration), #2082 (no-auto-close-keyword), #2087, #2093

Part 2 — STATUS.md refresh (renamed from IMPLEMENTATION-STATUS.md):
- Header dated 2026-05-20 (was 2026-04-29; 22 days stale per audit)
- Adds 🟦 CODE-COMPLETE state for "controllers + CRDs + tests landed,
  awaiting fresh-prov walk" (per 5-pillar DoD)
- Pillar 3 marked CODE-COMPLETE (PRs #2071/#2072/#2073/#2074/#2075/#2053)
- Adds 3 new CRDs verified in products/catalyst/chart/crds/:
  CNPGPair, PDM, Sandbox
- Sandbox controller chain CODE-COMPLETE
  (PRs #1615/#1618/#1621/#1622/#1626/#1631/#1632)
- SPIRE marked DEFERRED — opt-in only (PRs #665, #2056, #2061)
- New §6 CI / supply-chain guards table: hollow-chart (#2087),
  smoke-render (#2093), no-auto-close-keyword (#2082), observability-toggle,
  subchart 4-step, Flux version-pin replay
- New §9 Pillar-status table — Pillars 1/2/3/4 CODE-COMPLETE, Pillar 5 🚧
- Pillar 1 (PRs #2038 V18, #2043 V18-D), Pillar 2 (PR #2029 V20),
  Pillar 3 (per above), Pillar 4 (Sandbox chain)

Part 3 — GLOSSARY.md folded as single source of truth for banned terms:
- Header dated 2026-05-20, notes "single source of truth for banned terms"
  and "no separate BANNED-TERMS.md"
- Existing 11 banned-terms rows rewritten with italicized qualifiers
- NEW Forbidden test domains subsection:
  openova.io (mothership-only), omantel.openova.io (hallucinated),
  Nova Cloud (predecessor brand), eventforge.io (hallucinated),
  admin.<fqdn> (dead BSS URL)
- SPIFFE/SPIRE identity row + acronym row marked deferred per PR #665
  with TBD-V29 (#2055) re-introduction roadmap
- Cross-links updated: IMPLEMENTATION-STATUS → STATUS,
  SOVEREIGN-PROVISIONING + BLUEPRINT-AUTHORING → RUNBOOKS.md

CLAUDE.md NOT touched. Source files NOT deleted (orchestrator owns deletion).
No push, no PR. Manifest at /tmp/merge-D-runbooks-status-glossary-manifest.txt.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: assemble lean doc strategy — delete legacy sources, move ledger/sessions/archive, ADR-0004, rewrite cross-refs

Per founder direction 2026-05-20 + user-global ~/.claude/CLAUDE.md §11.

This is the orchestrator commit on top of the four cherry-picked consolidation
commits (ARCHITECTURE, PRINCIPLES, DOD, RUNBOOKS+STATUS+GLOSSARY). It:

1. Deletes 15 legacy source docs (now folded into the 7 canonical):
   PLATFORM-TECH-STACK, NAMING-CONVENTION, EPICS-1-6-unified-design,
   BOOTSTRAP-KIT-EXPANSION-PLAN, INVIOLABLE-PRINCIPLES, ANTI-PATTERN-CATALOG,
   5-PILLAR-DOD, DOMAINS-CANON, SOVEREIGN-MULTI-REGION-DOD,
   PERSONAS-AND-JOURNEYS, BLUEPRINT-AUTHORING, CHART-AUTHORING,
   DEMO-RUNBOOK, RUNBOOK-OPERATIONS, RUNBOOK-PROVISIONING.

2. Moves transient + historical docs into proper subdirs:
   - docs/ledger/{TRUST,TRACKER}.md (cron-refreshed live state)
   - docs/sessions/{2026-05-17-convergence,2026-05-19-20-trust-recovery,
     2026-05-20-trust-audit,2026-05-20-walk-runbook}.md
   - docs/archive/{validation-log,orchestrator-state,omantel-handover-wbs}.md

3. Adds docs/adr/0004-cnpg-sync-replication.md (Pillar 3 zero-tx-loss decision)
   + docs/adr/README.md index.

4. Updates CLAUDE.md reading-order + repo-structure block to match the
   lean strategy and current core/ tree (controllers/, marketplace/, etc.).

5. Sweeps all .md files + .github/workflows + scripts to repoint old doc
   paths to the new canonical homes. ADR cross-references kept intact
   (ADRs are immutable historical artifacts).

Operator-side cron scripts that still write to the old paths
(/home/openova/bin/refresh-dod-dashboard.sh, refresh-wbs.sh and
openova-private/bin/trust-audit.sh) need a one-line path update —
flagged in the PR body.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(bootstrap-kit): update repo-root sentinel to docs/PRINCIPLES.md

The bootstrap-kit Go test used `docs/INVIOLABLE-PRINCIPLES.md` as its
repo-root sentinel; the file no longer exists after the lean-doc
consolidation (it's now `docs/PRINCIPLES.md`). Update the walker to
match the new canonical filename.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: hatiyildiz <269457768+hatiyildiz@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 14:40:01 +04:00
..
templates fix(bp-cnpg-pair): switch to synchronous replication (remote_apply) for Pillar 3 zero-tx-loss (Refs #2064) (#2071) 2026-05-20 10:10:49 +04:00
tests fix(bp-cnpg-pair): switch to synchronous replication (remote_apply) for Pillar 3 zero-tx-loss (Refs #2064) (#2071) 2026-05-20 10:10:49 +04:00
Chart.yaml fix(bp-cnpg-pair): switch to synchronous replication (remote_apply) for Pillar 3 zero-tx-loss (Refs #2064) (#2071) 2026-05-20 10:10:49 +04:00
README.md feat(docs): lean documentation strategy — consolidate 16 docs into 7 canonical + 3 subdirs (#2094) 2026-05-20 14:40:01 +04:00
values.yaml fix(bp-cnpg-pair): switch to synchronous replication (remote_apply) for Pillar 3 zero-tx-loss (Refs #2064) (#2071) 2026-05-20 10:10:49 +04:00

bp-wordpress-tenant

Catalyst Blueprint scratch chart that installs a turnkey, SSO-pre-wired WordPress instance per SME tenant inside the SME's vcluster.

This is a scratch chart — there is no first-party Helm chart published by the WordPress project (the upstream ships only a Docker image at wordpress:6-php8.3-apache). The common library subchart is declared as a Helm dependency so the BLUEPRINT-AUTHORING.md hollow- chart guard (issue #181) is satisfied; bp-newapi follows the same pattern.

What it provisions

Resource Purpose
Deployment (single replica) The WordPress Pod. Two initContainers: one seeds wp-content/ from the image onto the PVC; the other downloads + installs openid-connect-generic (Keycloak SSO) and pg4wp (Postgres adapter) from wordpress.org / GitHub.
Service (ClusterIP, :80) In-vcluster service for the ingress to target.
Ingress (Traefik, host wordpress.<smeDomain>) Customer-facing entry point. cert-manager issues TLS via the operator-supplied ClusterIssuer.
PersistentVolumeClaim (10Gi default, RWO) Backs /var/www/html/wp-content so themes, plugins, and uploads persist across pod restarts and image upgrades. helm.sh/resource-policy: keep so helm uninstall never drops customer content.
Cluster.postgresql.cnpg.io (1 instance, 10Gi) Tenant-isolated Postgres provisioned by bp-cnpg. The CNPG-emitted <cluster>-app Secret carries the password.
Secret wordpress-database-secret (placeholder) Reflector-managed bridge that the WordPress Pod reads via secretKeyRef. Populated by the post-install db-secret-sync Job.
Job <release>-db-secret-sync (post-install/upgrade) Mirrors <cluster>-app.password into wordpress-database-secret.password. Eliminates the otech30-class Reflector race documented in bp-gitea.
Job <release>-oidc-config (post-install/upgrade) Runs the canonical wordpress:cli image: wp core install (idempotent), wp plugin install openid-connect-generic --activate (idempotent), wp option update openid_connect_generic_settings <json> with the per-tenant Keycloak realm + client + secret, wp option update default_role, wp theme activate, wp option update siteurl/home. Idempotent — re-running on helm upgrade is safe.
Job <release>-admin-user (post-install/upgrade, hook weight 15) Pre-seeds the SME admin into wp_users + wp_usermeta with the administrator role + the SSO email mapping. The user can log in via Keycloak only.
NetworkPolicy Restricts egress to: bp-cnpg :5432, Keycloak :8443/:8080, kube-dns, and HTTPS to public IPs (for plugin/theme fetches at first install). Ingress allowed only from the configured ingress namespace (default traefik).
ServiceAccount Default SA for the WordPress Pod. The post-install Jobs use a dedicated SA + Role + RoleBinding scoped to the tenant namespace.

Boot sequence (per docs/PRINCIPLES.md #2)

helm install
  ├─ pre-install: namespace, ServiceAccount, Role/RoleBinding hooks (weight 0)
  ├─ install:     Deployment, Service, Ingress, PVC, NetworkPolicy,
  │               Cluster.postgresql.cnpg.io, wordpress-database-secret (empty)
  ├─ post-install hook weight 5:  db-secret-sync Job
  │     └─ waits for CNPG <cluster>-app, PATCHes wordpress-database-secret
  ├─ post-install hook weight 10: oidc-config Job (wp-cli)
  │     └─ wp core install, wp plugin install openid-connect-generic
  │        --activate, wp option update openid_connect_generic_settings,
  │        wp theme activate, wp option update siteurl/home
  └─ post-install hook weight 15: admin-user Job
        └─ INSERT/UPDATE wp_users row for the SME admin's email

After all hooks complete, the SME admin browses to https://wordpress.<smeDomain> → openid-connect-generic redirects to Keycloak → returns to /wp-admin authenticated as administrator. No WP install wizard, no manual config.

Required values

Value Description
smeDomain The SME tenant's domain (e.g. acme.<otech-fqdn> or BYO acme.com). Used to derive the default ingress host as wordpress.<smeDomain>.
oidc.issuerURL Discovery URL of the per-tenant Keycloak realm. Example: https://keycloak.acme.<otech-fqdn>/realms/sme-acme. The wp-cli Job derives the OIDC endpoint_* URLs from this.
oidc.clientSecretName K8s Secret carrying the OIDC client secret (key client-secret). Provisioned by bp-keycloak's tenant-realm ConfigMap (PR #918) at the same time as the realm import.
adminUser.email Email of the SME admin (must match the email claim Keycloak issues for that user). The admin-user Job pre-seeds a wp_user with this email and the administrator role.

Back-compat (chart 0.1.x): keycloak.{realmURL,clientID,clientSecretName} is still accepted as an alias when the modern oidc.* block is at its values.yaml defaults. New overlays MUST emit oidc.* — the legacy block is removed in chart 0.3.0.

Override surface

All other values have sensible defaults; common overrides include:

Value Default Notes
global.imageRegistry "" Set to the Sovereign's Harbor proxy-cache hostname post-handover.
wordpress.image.tag 6-php8.3-apache The chart pins the manifest-list digest alongside; change tag+digest together.
database.cnpgClusterName wordpress-db Per-tenant unique within the SME namespace.
database.cluster.storageSize 10Gi Postgres storage size.
persistence.wpContent.size 10Gi wp-content PVC size.
persistence.wpContent.storageClass local-path Set to a RWX class if you want to scale replicas > 1.
defaultTheme twentytwentyfive Any wordpress.org theme slug bundled with the official image.
ingress.tls.issuer letsencrypt-prod cert-manager ClusterIssuer.

See values.yaml for the full schema, including NetworkPolicy egress peers, OIDC role mapping, and probe tuning.

Why Postgres (and not MySQL)?

Issue #800 specifies "bp-cnpg Postgres in tenant namespace". The official wordpress image targets MySQL/MariaDB; we run it against Postgres via the pg4wp mu-plugin (a wp-content/db.php drop-in that intercepts wpdb at the PHP level and translates queries). This keeps the SME tenant footprint to one database operator (bp-cnpg) instead of sprouting a separate MySQL operator per SME — see the upstream project at https://github.com/PostgreSQL-For-Wordpress/postgresql-for-wordpress.

The pg4wp install is performed by the same wp-plugin-install initContainer that installs openid-connect-generic, so the chart needs no special image build.

Capabilities gate

Cluster.postgresql.cnpg.io is rendered behind a Capabilities check on postgresql.cnpg.io/v1, so a cold install before bp-cnpg is reconciling skips the Cluster CR (and the Pod waits in Pending/CrashLoopBackOff until bp-cnpg lands and the Cluster is re-rendered on the next reconcile). The Sovereign's bootstrap order MUST land bp-cnpg before bp-wordpress-tenant.