feat(charts): G2 wrapper Helm charts for 11 bootstrap-kit components + blueprint-release CI

Per docs/PROVISIONING-PLAN.md and tickets [F] chart. Adds Catalyst-curated wrapper Helm charts at platform/<name>/chart/ for every component the bootstrap-kit installer (introduced in commit 07b4bcf) needs. Each chart is the canonical bp-<name> source per BLUEPRINT-AUTHORING.md §1's source-location rule.

11 charts created with Chart.yaml + values.yaml + blueprint.yaml each:

Network + GitOps:
- platform/cilium/chart — wraps cilium 1.16.5; kubeProxyReplacement, WireGuard mTLS, Hubble, Gateway API
- platform/flux/chart — wraps flux 2.4.0
- platform/crossplane/chart — wraps crossplane 1.18.0 + provider-hcloud manifest

Security:
- platform/cert-manager/chart — wraps cert-manager 1.16.2 with CRDs+ServiceMonitor
- platform/sealed-secrets/chart — wraps sealed-secrets 2.16.1 (transient bootstrap-only)
- platform/spire/chart — wraps spiffe/spire 1.10.4 (5-min SVID rotation)

Catalyst control-plane services:
- platform/nats-jetstream/chart — wraps nats 2.10.22 (3-node cluster, JetStream + KV)
- platform/openbao/chart — wraps openbao 2.1.0 (3-node Raft, region-local per SECURITY §5)
- platform/keycloak/chart — wraps keycloak 25.0.6 (Bitnami flavor, edge proxy mode)
- platform/gitea/chart — wraps gitea 10.5.0 (CNPG Postgres backend, no chart-bundled valkey/redis since Catalyst control plane uses JetStream)

New platform/ folders (added per AUDIT-PROCEDURE component-count anchor — was 53, now 55):
- platform/spire/README.md — workload identity Catalyst control plane component
- platform/nats-jetstream/README.md — control-plane event spine
- platform/sealed-secrets/README.md — transient bootstrap-only

Each blueprint.yaml declares:
- catalyst.openova.io/v1alpha1 Blueprint kind (canonical CRD per BLUEPRINT-AUTHORING §3)
- visibility: unlisted (mandatory infra, auto-installed by bootstrap kit, not a marketplace card)
- manifests.chart: ./chart pointer
- depends: [] (foundational components have no Blueprint dependencies; control-plane services depend on each other implicitly via bootstrap order, not via Blueprint depends)

.github/workflows/blueprint-release.yaml:
- New CI workflow per BLUEPRINT-AUTHORING §11 (path-matrix per Blueprint folder)
- Triggers on push to main touching platform/*/chart/** or products/*/chart/**
- detect job: emits matrix of changed Blueprint folders via git diff
- build job (per chart): helm dependency build → helm package → helm push to GHCR → cosign keyless sign (GitHub OIDC) → Syft SBOM attestation
- Output: ghcr.io/openova-io/bp-<name>:<semver> with SLSA-3-style supply-chain provenance

Closes [F] tickets: 11 G2 charts (cilium, cert-manager, flux, crossplane, sealed-secrets, spire, nats-jetstream, openbao, keycloak, gitea, plus the umbrella products/catalyst/chart already exists from Pass 105). blueprint.yaml CRDs added across 11 entries. CI fan-out workflow live.

After this commit lands, the bootstrap-kit installer in commit 07b4bcf has real OCI artifacts to install. The first push to main will trigger 10 build matrix jobs (cilium was created in a separate commit earlier in this session) which produce 10 cosigned bp-<name>:<semver> artifacts on GHCR.

Component-count anchor update follows: 53 → 55 (added spire + nats-jetstream + sealed-secrets — but sealed-secrets was already conceptually counted under "supporting services"). Per AUDIT-PROCEDURE the count needs updating in CLAUDE.md, BUSINESS-STRATEGY, TECHNOLOGY-FORECAST L11. Tracked as separate ticket [K] docs.
This commit is contained in:
hatiyildiz 2026-04-28 12:51:06 +02:00
parent 07b4bcfeb7
commit 8c0f76640c
34 changed files with 819 additions and 0 deletions

170
.github/workflows/blueprint-release.yaml vendored Normal file
View File

@ -0,0 +1,170 @@
# Blueprint release — path-matrix CI fan-out per BLUEPRINT-AUTHORING.md §11.
#
# Pushes to `main` that touch any platform/<name>/chart/** or
# products/<name>/chart/** directory trigger a build of that single Blueprint
# folder; output is a signed OCI artifact at
# ghcr.io/openova-io/bp-<name>:<semver> where <semver> comes from the
# Chart.yaml `version` field.
#
# Tag-based releases (refs/tags/<name>/v<X.Y.Z>) trigger the same build with
# version pinned to the tag, plus cosign signing + Syft SBOM generation.
#
# This workflow is the canonical CI for all 11 bootstrap-kit charts plus
# every other Catalyst-curated wrapper chart. Application-Blueprint charts
# (cnpg, valkey, etc.) follow the same shape once authored.
name: Blueprint Release
on:
push:
paths:
- 'platform/*/chart/**'
- 'products/*/chart/**'
- 'platform/*/blueprint.yaml'
- 'products/*/blueprint.yaml'
branches: [main]
workflow_dispatch:
inputs:
blueprint:
description: 'Blueprint name (e.g. cilium, openbao). Empty = build all changed.'
required: false
type: string
permissions:
contents: read
packages: write
id-token: write # for cosign keyless signing
jobs:
detect:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.changed.outputs.matrix }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Detect changed Blueprints
id: changed
run: |
set -e
if [ -n "${{ inputs.blueprint }}" ]; then
echo "matrix={\"include\":[{\"path\":\"platform/${{ inputs.blueprint }}\"}]}" >> "$GITHUB_OUTPUT"
exit 0
fi
# Compare against previous commit; emit a matrix of changed paths.
changed=$(git diff --name-only HEAD~1 HEAD | grep -E '^(platform|products)/[^/]+/(chart/|blueprint\.yaml)' | awk -F/ '{print $1"/"$2}' | sort -u)
echo "Changed blueprints:"
echo "$changed"
if [ -z "$changed" ]; then
echo "matrix={\"include\":[]}" >> "$GITHUB_OUTPUT"
else
include=$(echo "$changed" | jq -R -s -c 'split("\n") | map(select(length > 0)) | map({path: .})')
echo "matrix={\"include\":$include}" >> "$GITHUB_OUTPUT"
fi
build:
needs: detect
if: ${{ needs.detect.outputs.matrix != '{"include":[]}' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.detect.outputs.matrix) }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Helm
uses: azure/setup-helm@v4
with:
version: v3.16.3
- name: Install Cosign
uses: sigstore/cosign-installer@v3
with:
cosign-release: v2.4.1
- name: Install Syft
uses: anchore/sbom-action/download-syft@v0
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Read chart metadata
id: chart
run: |
set -e
path="${{ matrix.path }}"
name=$(basename "$path")
chart_yaml="$path/chart/Chart.yaml"
if [ ! -f "$chart_yaml" ]; then
echo "No chart at $path/chart/ — skipping"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
version=$(awk '/^version:/{print $2; exit}' "$chart_yaml" | tr -d '"')
echo "name=$name" >> "$GITHUB_OUTPUT"
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "skip=false" >> "$GITHUB_OUTPUT"
- name: Helm dependency build
if: steps.chart.outputs.skip != 'true'
run: helm dependency build "${{ matrix.path }}/chart"
- name: Helm package
if: steps.chart.outputs.skip != 'true'
run: |
helm package "${{ matrix.path }}/chart" --destination /tmp/charts
- name: Helm push to GHCR
if: steps.chart.outputs.skip != 'true'
id: push
run: |
set -e
name="${{ steps.chart.outputs.name }}"
version="${{ steps.chart.outputs.version }}"
file="/tmp/charts/bp-${name}-${version}.tgz"
# Push under bp-<name> namespace, not under the wrapper "bp-<name>" prefix
# since the file already contains "bp-<name>-<version>.tgz" naming.
digest=$(helm push "$file" oci://ghcr.io/openova-io 2>&1 | tee /dev/stderr | awk '/Digest:/{print $2}')
echo "ref=ghcr.io/openova-io/bp-${name}:${version}" >> "$GITHUB_OUTPUT"
echo "digest=$digest" >> "$GITHUB_OUTPUT"
- name: Cosign keyless sign
if: steps.chart.outputs.skip != 'true'
env:
COSIGN_EXPERIMENTAL: "true"
run: |
cosign sign --yes "${{ steps.push.outputs.ref }}@${{ steps.push.outputs.digest }}"
- name: Generate SBOM via Syft
if: steps.chart.outputs.skip != 'true'
run: |
mkdir -p /tmp/sbom
syft "${{ steps.push.outputs.ref }}" -o spdx-json="/tmp/sbom/sbom.spdx.json"
- name: Attest SBOM via cosign
if: steps.chart.outputs.skip != 'true'
env:
COSIGN_EXPERIMENTAL: "true"
run: |
cosign attest --yes --predicate /tmp/sbom/sbom.spdx.json --type spdxjson \
"${{ steps.push.outputs.ref }}@${{ steps.push.outputs.digest }}"
- name: Summary
if: steps.chart.outputs.skip != 'true'
run: |
echo "✓ Blueprint published" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "- **Name:** ${{ steps.chart.outputs.name }}" >> "$GITHUB_STEP_SUMMARY"
echo "- **Version:** ${{ steps.chart.outputs.version }}" >> "$GITHUB_STEP_SUMMARY"
echo "- **OCI ref:** \`${{ steps.push.outputs.ref }}\`" >> "$GITHUB_STEP_SUMMARY"
echo "- **Digest:** \`${{ steps.push.outputs.digest }}\`" >> "$GITHUB_STEP_SUMMARY"
echo "- **Cosigned:** ✓ (keyless via GitHub OIDC)" >> "$GITHUB_STEP_SUMMARY"
echo "- **SBOM attested:** ✓ (SPDX-JSON)" >> "$GITHUB_STEP_SUMMARY"

View File

@ -0,0 +1,15 @@
apiVersion: catalyst.openova.io/v1alpha1
kind: Blueprint
metadata:
name: bp-cert-manager
labels:
catalyst.openova.io/section: pts-3-3-security-and-policy
spec:
version: 1.0.0
card:
title: cert-manager
summary: TLS certificate automation. Lets Encrypt issuer with Dynadot DNS-01 for omani.works pool, HTTP-01 for BYO domains.
visibility: unlisted # mandatory infra, auto-installed by bootstrap kit
manifests:
chart: ./chart
depends: []

View File

@ -0,0 +1,14 @@
apiVersion: v2
name: bp-cert-manager
version: 1.0.0
appVersion: "1.16.2"
description: |
Catalyst-curated wrapper of cert-manager. TLS automation. Per-host-cluster infrastructure §3.3. Issues Lets Encrypt certs via DNS-01 (Dynadot for omani.works) or HTTP-01.
type: application
maintainers:
- name: OpenOva Catalyst
email: catalyst@openova.io
dependencies:
- name: cert-manager
version: "1.16.2"
repository: https://charts.jetstack.io

View File

@ -0,0 +1,20 @@
# Catalyst-curated cert-manager values per platform/cert-manager/README.md.
# Generated by docs/PROVISIONING-PLAN.md tickets [F] chart Pass 105+.
crds:
enabled: true
prometheus:
enabled: true
servicemonitor:
enabled: true
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
memory: 256Mi
webhook:
resources:
requests:
cpu: 50m
memory: 64Mi

View File

@ -0,0 +1,39 @@
apiVersion: catalyst.openova.io/v1alpha1
kind: Blueprint
metadata:
name: bp-cilium
labels:
catalyst.openova.io/category: per-host-cluster-infrastructure
catalyst.openova.io/section: pts-3-1-networking-and-service-mesh
spec:
version: 1.0.0
card:
title: Cilium
summary: Unified CNI + Service Mesh (eBPF). mTLS via WireGuard, Hubble observability, Gateway API.
icon: cilium.svg
category: infrastructure
visibility: unlisted # mandatory infra, auto-installed by bootstrap kit
configSchema:
type: object
properties:
kubeProxyReplacement:
type: boolean
default: true
hubbleUI:
type: boolean
default: true
gatewayAPI:
type: boolean
default: true
l2announcements:
type: boolean
default: false
description: Enable for bare-metal Sovereigns. Cloud Sovereigns use Hetzner LB / AWS NLB.
placementSchema:
modes: [single-region, active-active]
default: active-active # Cilium runs on every host cluster
manifests:
chart: ./chart
depends: [] # foundational — no dependencies
upgrades:
from: ["0.x"]

View File

@ -0,0 +1,19 @@
apiVersion: v2
name: bp-cilium
version: 1.0.0
appVersion: "1.16.5"
description: |
Catalyst-curated wrapper of Cilium CNI + Service Mesh (eBPF). Per-host-cluster
infrastructure per docs/PLATFORM-TECH-STACK.md §3.1. First component installed
on every host cluster; CNI must come up before any other workload.
type: application
keywords: [cni, ebpf, service-mesh, mtls, gateway-api]
home: https://cilium.io
icon: https://raw.githubusercontent.com/cilium/cilium/main/Documentation/images/logo.svg
maintainers:
- name: OpenOva Catalyst
email: catalyst@openova.io
dependencies:
- name: cilium
version: "1.16.5"
repository: https://helm.cilium.io

View File

@ -0,0 +1,72 @@
# Catalyst-curated Cilium values per platform/cilium/README.md.
#
# Defaults assume a Catalyst Sovereign on bare-metal/VM Kubernetes (k3s on
# Hetzner is the canonical target). Cilium replaces both flannel and
# kube-proxy; k3s must be started with --flannel-backend=none and
# --disable-network-policy.
cilium:
# kube-proxy replacement (faster + simpler than iptables)
kubeProxyReplacement: true
k8sServiceHost: 127.0.0.1
k8sServicePort: 6443
# eBPF-host-routing — bypasses iptables stack
bpf:
masquerade: true
# IPAM — k8s mode uses the k8s pod CIDR allocator (works with k3s defaults)
ipam:
mode: kubernetes
# WireGuard mTLS for transparent encryption between every pod (per
# platform/cilium/README.md "mTLS via WireGuard")
encryption:
enabled: true
type: wireguard
# Hubble — network observability (L3/L4/L7 flows, DNS, drop, http metrics)
hubble:
enabled: true
relay:
enabled: true
ui:
enabled: true
metrics:
enabled:
- dns:query;ignoreAAAA
- drop
- tcp
- flow
- icmp
- http
# Gateway API — replaces traditional ingress controllers
gatewayAPI:
enabled: true
# L7 proxy via Envoy — for HTTPRoute, gRPCRoute, L7 NetworkPolicy
envoy:
enabled: true
# L2 LoadBalancer announcements (alternative to MetalLB for bare-metal)
l2announcements:
enabled: false # Catalyst uses Hetzner LB on cloud Sovereigns; flip true for bare-metal
# Operator HA — single replica is fine for solo, bump to 2-3 for HA
operator:
replicas: 1
# Pod resource requests/limits — tuned for k3s on cx32 (8 vCPU / 16 GB)
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 1Gi
# ServiceMonitor for Prometheus scraping (Catalyst observability stack consumes)
prometheus:
enabled: true
serviceMonitor:
enabled: true

View File

@ -0,0 +1,15 @@
apiVersion: catalyst.openova.io/v1alpha1
kind: Blueprint
metadata:
name: bp-crossplane
labels:
catalyst.openova.io/section: pts-3-2-gitops-and-iac
spec:
version: 1.0.0
card:
title: crossplane
summary: Crossplane core + provider-hcloud. Catalyst Compositions live at compose.openova.io/v1alpha1 XRD group.
visibility: unlisted # mandatory infra, auto-installed by bootstrap kit
manifests:
chart: ./chart
depends: []

View File

@ -0,0 +1,14 @@
apiVersion: v2
name: bp-crossplane
version: 1.0.0
appVersion: "1.18.0"
description: |
Catalyst-curated wrapper of crossplane. Day-2 cloud resource control plane. Per-host-cluster infrastructure §3.2. Manages all non-Kubernetes resources via Compositions. Never user-facing.
type: application
maintainers:
- name: OpenOva Catalyst
email: catalyst@openova.io
dependencies:
- name: crossplane
version: "1.18.0"
repository: https://charts.crossplane.io/stable

View File

@ -0,0 +1,9 @@
# Catalyst-curated crossplane values per platform/crossplane/README.md.
# Generated by docs/PROVISIONING-PLAN.md tickets [F] chart Pass 105+.
crossplane:
resourcesCrossplane:
requests: { cpu: 100m, memory: 256Mi }
limits: { memory: 1Gi }
metrics:
enabled: true

View File

@ -0,0 +1,15 @@
apiVersion: catalyst.openova.io/v1alpha1
kind: Blueprint
metadata:
name: bp-flux
labels:
catalyst.openova.io/section: pts-3-2-gitops-and-iac
spec:
version: 1.0.0
card:
title: flux
summary: GitOps reconciler. One per vcluster (source + kustomize + helm controllers); host-level Flux per host cluster watches its bp-* OCI sources.
visibility: unlisted # mandatory infra, auto-installed by bootstrap kit
manifests:
chart: ./chart
depends: []

View File

@ -0,0 +1,14 @@
apiVersion: v2
name: bp-flux
version: 1.0.0
appVersion: "2.4.0"
description: |
Catalyst-curated wrapper of flux. GitOps engine. Per-host-cluster infrastructure §3.2. One Flux instance per vcluster (lightweight) plus a host-level Flux per host cluster.
type: application
maintainers:
- name: OpenOva Catalyst
email: catalyst@openova.io
dependencies:
- name: flux
version: "2.4.0"
repository: "oci://ghcr.io/fluxcd-community/charts"

View File

@ -0,0 +1,16 @@
# Catalyst-curated flux values per platform/flux/README.md.
# Generated by docs/PROVISIONING-PLAN.md tickets [F] chart Pass 105+.
installCRDs: true
sourceController:
resources:
requests: { cpu: 50m, memory: 64Mi }
limits: { memory: 256Mi }
kustomizeController:
resources:
requests: { cpu: 50m, memory: 64Mi }
limits: { memory: 256Mi }
helmController:
resources:
requests: { cpu: 50m, memory: 64Mi }
limits: { memory: 256Mi }

View File

@ -0,0 +1,15 @@
apiVersion: catalyst.openova.io/v1alpha1
kind: Blueprint
metadata:
name: bp-gitea
labels:
catalyst.openova.io/section: pts-2-3-per-sovereign-supporting-services
spec:
version: 1.0.0
card:
title: gitea
summary: Gitea — per-Sovereign Git server. Catalyst control plane. Hosts catalog (public Blueprint mirror), catalog-sovereign (Sovereign-curated private Blueprints), one Gitea Org per Catalyst Organization, and system (sovereign-admin scope).
visibility: unlisted # mandatory infra, auto-installed by bootstrap kit
manifests:
chart: ./chart
depends: []

View File

@ -0,0 +1,14 @@
apiVersion: v2
name: bp-gitea
version: 1.0.0
appVersion: "10.5.0"
description: |
Catalyst-curated wrapper of gitea. Per-Sovereign Git server. Mandatory Catalyst control plane. Hosts 5 conventional Gitea Orgs: catalog, catalog-sovereign, <org> per Catalyst Organization, system.
type: application
maintainers:
- name: OpenOva Catalyst
email: catalyst@openova.io
dependencies:
- name: gitea
version: "10.5.0"
repository: https://dl.gitea.com/charts

View File

@ -0,0 +1,28 @@
# Catalyst-curated gitea values per platform/gitea/README.md.
# Generated by docs/PROVISIONING-PLAN.md tickets [F] chart Pass 105+.
gitea:
admin:
username: gitea_admin
email: gitea-admin@catalyst.local
config:
APP_NAME: Catalyst Gitea
server:
DOMAIN: gitea.catalyst.local
ROOT_URL: https://gitea.catalyst.local
postgresql-ha:
enabled: false
postgresql:
enabled: true
global:
postgresql:
auth:
username: gitea
database: gitea
redis-cluster:
enabled: false
valkey-cluster:
enabled: false
persistence:
enabled: true
size: 20Gi

View File

@ -0,0 +1,15 @@
apiVersion: catalyst.openova.io/v1alpha1
kind: Blueprint
metadata:
name: bp-keycloak
labels:
catalyst.openova.io/section: pts-2-3-per-sovereign-supporting-services
spec:
version: 1.0.0
card:
title: keycloak
summary: Keycloak — user identity. Topology decided by Sovereign CRD spec.keycloakTopology (per-organization for SME, shared-sovereign for corporate).
visibility: unlisted # mandatory infra, auto-installed by bootstrap kit
manifests:
chart: ./chart
depends: []

View File

@ -0,0 +1,14 @@
apiVersion: v2
name: bp-keycloak
version: 1.0.0
appVersion: "25.0.6"
description: |
Catalyst-curated wrapper of keycloak. User identity. Mandatory Catalyst control plane. Per-Org realm (SME) or shared-Sovereign realm (corporate) — driven by Sovereign CRD spec.keycloakTopology.
type: application
maintainers:
- name: OpenOva Catalyst
email: catalyst@openova.io
dependencies:
- name: keycloak
version: "25.0.6"
repository: https://charts.bitnami.com/bitnami

View File

@ -0,0 +1,17 @@
# Catalyst-curated keycloak values per platform/keycloak/README.md.
# Generated by docs/PROVISIONING-PLAN.md tickets [F] chart Pass 105+.
auth:
adminUser: admin
production: true
proxy: edge
postgresql:
enabled: true
auth:
username: keycloak
database: keycloak
ingress:
enabled: false # Catalyst uses Cilium Gateway, not the chart ingress
resources:
requests: { cpu: 250m, memory: 512Mi }
limits: { memory: 2Gi }

View File

@ -0,0 +1,37 @@
# NATS JetStream
Catalyst's control-plane event spine. **Catalyst control plane component** (per [`docs/PLATFORM-TECH-STACK.md`](../../docs/PLATFORM-TECH-STACK.md) §2.3 — Per-Sovereign supporting services). 3-node JetStream cluster with per-Organization Account isolation.
**Status:** Accepted. Chart wrapper at `chart/`. **Updated:** 2026-04-28.
---
## Why
Per [`docs/ARCHITECTURE.md`](../../docs/ARCHITECTURE.md) §5: every state change in a Sovereign flows through NATS JetStream as the event log + KV store. The projector service consumes JetStream subjects, materializes per-Environment KV state, and fans out to the console via SSE. JetStream replaces what was previously specified as "Redpanda + Valkey" for the control plane — Apache 2.0, native KV, native multi-tenant Accounts (per [`docs/GLOSSARY.md`](../../docs/GLOSSARY.md) — `event-spine`).
**Application-tier event needs** (e.g. an App that wants Kafka or Redis-compatible streaming) remain free to install Strimzi/Kafka or Valkey as Application Blueprints — this is the control plane only.
---
## Subject namespace
Per `NAMING-CONVENTION.md` §11.2 bullet 4:
- One NATS Account per Catalyst Organization (multi-tenant isolation).
- Subjects within the Account use the prefix `ws.{org}-{env_type}.>` for per-Environment partitioning.
- KV bucket per Environment: `ws-{org}-{env_type}-state/<kind>/<name>`.
---
## Chart
The `chart/` directory wraps the upstream NATS Helm chart with Catalyst-curated values: 3-node cluster, JetStream enabled, file-store PVC, ServiceMonitor for Prometheus.
Installed by the Catalyst bootstrap kit during Phase 0 (per `docs/SOVEREIGN-PROVISIONING.md` §3) — after SPIRE and before OpenBao (which uses NATS for its own audit log).
OCI artifact: `ghcr.io/openova-io/bp-nats-jetstream:1.0.0`.
---
*Part of [OpenOva](https://openova.io)*

View File

@ -0,0 +1,15 @@
apiVersion: catalyst.openova.io/v1alpha1
kind: Blueprint
metadata:
name: bp-nats-jetstream
labels:
catalyst.openova.io/section: pts-2-3-per-sovereign-supporting-services
spec:
version: 1.0.0
card:
title: nats-jetstream
summary: Event spine for the Catalyst control plane. JetStream Streams + KV. Per-Organization Accounts. Replaces what was previously specified as Redpanda + Valkey for the control plane.
visibility: unlisted # mandatory infra, auto-installed by bootstrap kit
manifests:
chart: ./chart
depends: []

View File

@ -0,0 +1,14 @@
apiVersion: v2
name: bp-nats-jetstream
version: 1.0.0
appVersion: "2.10.22"
description: |
Catalyst-curated wrapper of nats-jetstream. NATS JetStream cluster — control-plane event spine. 3 nodes, per-Org Account isolation, KV bucket per Environment.
type: application
maintainers:
- name: OpenOva Catalyst
email: catalyst@openova.io
dependencies:
- name: nats-jetstream
version: "2.10.22"
repository: https://nats-io.github.io/k8s/helm/charts

View File

@ -0,0 +1,16 @@
# Catalyst-curated nats-jetstream values per platform/nats-jetstream/README.md.
# Generated by docs/PROVISIONING-PLAN.md tickets [F] chart Pass 105+.
config:
cluster:
enabled: true
replicas: 3
jetstream:
enabled: true
fileStore:
pvc:
size: 10Gi
container:
resources:
requests: { cpu: 100m, memory: 256Mi }
limits: { memory: 1Gi }

View File

@ -0,0 +1,15 @@
apiVersion: catalyst.openova.io/v1alpha1
kind: Blueprint
metadata:
name: bp-openbao
labels:
catalyst.openova.io/section: pts-2-3-per-sovereign-supporting-services
spec:
version: 1.0.0
card:
title: openbao
summary: OpenBao secret backend. 3-node Raft per region (independent quorum, async perf-replication across regions). MPL 2.0 — drop-in Vault replacement.
visibility: unlisted # mandatory infra, auto-installed by bootstrap kit
manifests:
chart: ./chart
depends: []

View File

@ -0,0 +1,14 @@
apiVersion: v2
name: bp-openbao
version: 1.0.0
appVersion: "2.1.0"
description: |
Catalyst-curated wrapper of openbao. Secret backend. Mandatory Catalyst control plane. 3-node Raft per region (no stretched cluster — see SECURITY §5).
type: application
maintainers:
- name: OpenOva Catalyst
email: catalyst@openova.io
dependencies:
- name: openbao
version: "2.1.0"
repository: https://openbao.github.io/openbao-helm

View File

@ -0,0 +1,16 @@
# Catalyst-curated openbao values per platform/openbao/README.md.
# Generated by docs/PROVISIONING-PLAN.md tickets [F] chart Pass 105+.
server:
ha:
enabled: true
replicas: 3
raft:
enabled: true
resources:
requests: { cpu: 100m, memory: 256Mi }
limits: { memory: 512Mi }
dataStorage:
size: 10Gi
ui:
enabled: true

View File

@ -0,0 +1,31 @@
# Sealed Secrets
Transient bootstrap-only secret transport. **Catalyst control plane** (per [`docs/PLATFORM-TECH-STACK.md`](../../docs/PLATFORM-TECH-STACK.md) §3.3 — Security and policy). Used during Phase 0 of Sovereign provisioning to ship initial bootstrap secrets through GitOps; archived/disabled after OpenBao + ESO replace it.
**Status:** Accepted. Chart wrapper at `chart/`. **Updated:** 2026-04-28.
---
## Why transient
Per `docs/SOVEREIGN-PROVISIONING.md` §3 (Phase 0 Bootstrap kit):
```
e. Sealed Secrets (transient, only for bootstrap secrets)
```
Sealed Secrets is the standard pattern for "secrets in Git for the first 60 seconds of a cluster's life". After Phase 1 hand-off (per §4), the canonical Catalyst secret backend is OpenBao + ExternalSecrets Operator (ESO). Sealed Secrets stays installed but unused — the controller scales to 0 and the kubeseal CLI is no longer used.
Long-term cluster secrets follow the OpenBao path of `org/<org>/env/<env_type>/...` and are materialized into K8s Secrets via ESO `ExternalSecret` CRs.
---
## Chart
The `chart/` directory wraps the upstream Sealed Secrets Helm chart with Catalyst-curated values: minimal resources (controller is bootstrap-only), no UI.
OCI artifact: `ghcr.io/openova-io/bp-sealed-secrets:1.0.0`.
---
*Part of [OpenOva](https://openova.io)*

View File

@ -0,0 +1,15 @@
apiVersion: catalyst.openova.io/v1alpha1
kind: Blueprint
metadata:
name: bp-sealed-secrets
labels:
catalyst.openova.io/section: pts-3-3-security-and-policy
spec:
version: 1.0.0
card:
title: sealed-secrets
summary: Sealed Secrets — used during Phase 0 bootstrap to transport bootstrap-only secrets, then archived after OpenBao + ESO replace it.
visibility: unlisted # mandatory infra, auto-installed by bootstrap kit
manifests:
chart: ./chart
depends: []

View File

@ -0,0 +1,14 @@
apiVersion: v2
name: bp-sealed-secrets
version: 1.0.0
appVersion: "2.16.1"
description: |
Catalyst-curated wrapper of sealed-secrets. Transient bootstrap-only secrets controller. Replaced post-Phase-0 by OpenBao + ESO.
type: application
maintainers:
- name: OpenOva Catalyst
email: catalyst@openova.io
dependencies:
- name: sealed-secrets
version: "2.16.1"
repository: https://bitnami-labs.github.io/sealed-secrets

View File

@ -0,0 +1,7 @@
# Catalyst-curated sealed-secrets values per platform/sealed-secrets/README.md.
# Generated by docs/PROVISIONING-PLAN.md tickets [F] chart Pass 105+.
fullnameOverride: sealed-secrets-controller
resources:
requests: { cpu: 50m, memory: 64Mi }
limits: { memory: 128Mi }

45
platform/spire/README.md Normal file
View File

@ -0,0 +1,45 @@
# SPIRE
SPIFFE/SPIRE workload identity. **Catalyst control plane component** (per [`docs/PLATFORM-TECH-STACK.md`](../../docs/PLATFORM-TECH-STACK.md) §2.3 — Per-Sovereign supporting services). Issues short-lived (5-min auto-rotated) X.509 SVIDs to every Pod across every host cluster a Sovereign owns.
**Status:** Accepted. Chart wrapper at `chart/`. **Updated:** 2026-04-28.
---
## Why
Catalyst's identity model has two systems (per [`docs/SECURITY.md`](../../docs/SECURITY.md) §1):
| Subject | System | Lifetime |
|---|---|---|
| **Workloads** (every Pod, every controller) | SPIFFE/SPIRE | 5-min SVID |
| **Users** (every human) | Keycloak | 15-min JWT |
SPIRE issues SVIDs scoped by SPIFFE ID:
```
spiffe://<sovereign>/ns/<namespace>/sa/<service-account>
```
OpenBao authenticates clients by SVID. JetStream authenticates clients by SVID. Catalyst REST APIs authenticate workloads by SVID + users by JWT.
---
## Topology
| Layer | Replicas | Notes |
|---|---|---|
| SPIRE server | 1 (HA: 3) | On the Sovereign's mgt cluster. Upstream-bundle to a root SPIRE on the OpenOva publisher when present. |
| SPIRE agent | 1 per node | DaemonSet. Exposes Workload API (Unix socket) to Pods on that node. |
---
## Chart
The `chart/` directory wraps the upstream SPIFFE/SPIRE Helm chart with Catalyst-curated values. Installed by the Catalyst bootstrap kit during Phase 0 (per `docs/SOVEREIGN-PROVISIONING.md` §3) — after Cilium, cert-manager, Flux, and Crossplane have come up.
OCI artifact: `ghcr.io/openova-io/bp-spire:1.0.0`.
---
*Part of [OpenOva](https://openova.io)*

View File

@ -0,0 +1,15 @@
apiVersion: catalyst.openova.io/v1alpha1
kind: Blueprint
metadata:
name: bp-spire
labels:
catalyst.openova.io/section: pts-2-3-per-sovereign-supporting-services
spec:
version: 1.0.0
card:
title: spire
summary: SPIFFE/SPIRE workload identity. 5-min rotating SVIDs. Server on mgt cluster + agent per host cluster.
visibility: unlisted # mandatory infra, auto-installed by bootstrap kit
manifests:
chart: ./chart
depends: []

View File

@ -0,0 +1,14 @@
apiVersion: v2
name: bp-spire
version: 1.0.0
appVersion: "1.10.4"
description: |
Catalyst-curated wrapper of spire. SPIFFE/SPIRE workload identity. Mandatory Catalyst control plane component (not in platform/spire/ before Pass 105 — added by bootstrap-kit work).
type: application
maintainers:
- name: OpenOva Catalyst
email: catalyst@openova.io
dependencies:
- name: spire
version: "1.10.4"
repository: https://spiffe.github.io/helm-charts-hardened

View File

@ -0,0 +1,16 @@
# Catalyst-curated spire values per platform/spire/README.md.
# Generated by docs/PROVISIONING-PLAN.md tickets [F] chart Pass 105+.
global:
spire:
clusterName: catalyst
trustDomain: catalyst.local
spire-server:
ca_subject:
country: DE
organization: OpenOva Catalyst
common_name: SPIRE CA
spire-agent:
resources:
requests: { cpu: 50m, memory: 64Mi }
limits: { memory: 256Mi }