state-hub/deploy/railiance/apps/charts/state-hub/values.yaml
tegwick e96ef197cf feat: add API-only preflight signing delivery and rotation acceptance
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a06ed7-828d-7ca0-a8d4-0c3e5a0c4102
2026-09-05 16:39:02 +02:00

197 lines
5.8 KiB
YAML

image:
repository: forgejo.coulomb.social/coulomb/state-hub
tag: ""
pullPolicy: IfNotPresent
imagePullSecrets: []
replicaCount: 1
namespace:
create: true
labels:
railiance.io/postgres-client: state-hub-db
railiance.io/layer: s5-app
service:
type: ClusterIP
port: 8000
targetPort: 8000
config:
enabled: true
name: state-hub-config
corsOrigins: "http://localhost:3000,http://127.0.0.1:3000,http://localhost:3001,http://127.0.0.1:3001"
sbomNexusUrl: ""
sbomNexusReadMode: legacy
sbomNexusWriteMode: legacy
# CUST-WP-0067-T03. "unknown" is the honest default for a chart that could be
# installed anywhere; the production values set this to primary.
instanceRole: unknown
instanceLabel: ""
# STATE-WP-0084-T02. The OpenBao Kubernetes auth role binds to this name and
# not to `default`, so this is load-bearing, not cosmetic.
serviceAccount:
create: true
name: state-hub
secret:
name: state-hub-env
# Forge read credential for deriving private repositories (STATE-WP-0084,
# MASON-WP-0003). Disabled by default: a hub without it still derives every
# public repository, so this is added capability, not a prerequisite.
#
# There is no agent injector and no secrets-store CSI driver on this cluster, so
# the pod authenticates to OpenBao itself with its projected ServiceAccount
# token and reads the KV path. Nothing here is the credential; these are only
# coordinates. Rotating the token in OpenBao needs no chart change and no
# redeploy.
forgeRead:
enabled: false
openbao:
# Matches every existing ClusterSecretStore on this cluster.
addr: http://openbao.openbao.svc:8200
authMount: kubernetes
role: state-hub-forge-derivation
# KV v2: the read path carries the `data/` infix, mount `platform`.
secretPath: platform/data/workloads/state-hub/forge-derivation
secretKey: FORGE_READ_TOKEN
# Audience for the projected ServiceAccount token.
#
# Empty renders no audience, giving the token the API server's audience —
# what the four existing external-secrets roles use, and what an OpenBao
# Kubernetes auth role with no bound audience will accept. A token with an
# audience the role does not bind is rejected at TokenReview, so this must
# not be set to "openbao" until the role binds that audience.
#
# Worth revisiting: with no audience, a copy of this token is a credential
# for the cluster API. Binding `openbao` on the role and setting it here
# narrows it to OpenBao alone. Either way the token is short-lived and
# kubelet-rotated, which the legacy auto-mounted token is not.
audience: ""
expirationSeconds: 3600
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1000m
memory: 2Gi
ingress:
enabled: false
className: traefik
host: state-hub.coulomb.social
tls: true
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
cert-manager.io/cluster-issuer: letsencrypt-prod
# Database migrations (STATE-WP-0083-T07). Runs as a Helm pre-install/pre-upgrade
# hook rather than an init container: an init container runs per pod, so more
# than one replica means concurrent `alembic upgrade` with no locking. A hook
# runs once per release and fails the upgrade if the migration fails.
migrations:
enabled: true
backoffLimit: 1
resources:
requests:
cpu: 50m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
# Classification allowed-values (CUST-WP-0067-T09). The API validates repo
# classification against the-custodian canon; a container has no such checkout,
# so the file travels with the release as a ConfigMap. Without it every
# classification write fails with a 500.
classificationAllowed:
enabled: true
name: state-hub-classification-allowed
mountPath: /etc/state-hub/classification
# MCP layer (CUST-WP-0067-T08). Runs from the same image with a different
# command, as a stateless HTTP client over the API service. ClusterIP only —
# it proxies an unauthenticated API, so it must never gain an Ingress.
mcp:
enabled: false
replicaCount: 1
transport: sse
# Defaults to the in-cluster API Service; override only to point elsewhere.
apiBase: ""
service:
port: 8001
targetPort: 8001
probes:
enabled: true
liveness:
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
readiness:
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
probes:
enabled: true
path: /state/health
port: 8000
liveness:
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
readiness:
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
# STATE-WP-0081-T04. The image and all writable runtime state are independent
# of root. Keep these defaults restrictive so API, MCP, and migration pods have
# the same security posture in every installation.
podSecurityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
nodeSelector: {}
tolerations: []
affinity: {}
# Legacy consistency sweep settings. Kept only for rollback compatibility;
# production uses Forge-derived reconciliation and must leave this disabled.
sweep:
enabled: false
hostname: ""
hostPath: /home/tegwick
sshHostPath: /home/tegwick/.ssh
# RPF-WP-0035-T04: API-only, separately owned ESO Secret; no secret values here.
renamePreflight:
enabled: false
secretName: state-hub-rename-preflight