rapp-canned-prompts/manifests/runtime.yaml

170 lines
4.8 KiB
YAML
Raw Normal View History

Package canned-prompts for Railiance Registers the repo with State Hub (agents / practice, prefix RCP-WP) and fills in the rapp shape. declarations/rapp.yaml declares a manifest-managed platform service owned by canned-prompts, bound to rail-kubernetes and reef-railiance, with rollout, smoke and rollback contracts. The image pin says `pending-publication` rather than carrying a placeholder digest. The image builds and was verified locally (canned-prompts CANP-WP-0006-T06) but has never been pushed, so no registry digest exists. A placeholder shaped like a real digest would be worse than a sentinel: it could be mistaken for something deployable. manifests/ follows the rapp-sbom-nexus shape: namespace labelled for the postgres client, external secrets from OpenBao, a migration Job, and the runtime Deployment with a ClusterIP-only Service, dedicated ServiceAccount and default-deny plus runtime NetworkPolicies. Three choices worth stating. Credentials arrive as mounted files, never env vars — an env var holding a password is visible in kubectl describe, in crash dumps, and to anything that can read /proc. Migrations run as a Job rather than at start-up, so a schema rollback stays separate from a code rollback and replicas do not race. Liveness points at /healthz, which checks only that the process is up: pointing it at a database-dependent path would restart every replica during a database blip. Egress is PostgreSQL and DNS only. A package arrives by publish; the registry never reaches out, so it is given no path to. tools/smoke.sh checks what only the cluster can answer and calls canned-prompts' service/tools/smoke.py for health and migration head, rather than holding a second opinion about whether the service is healthy. RCP-WP-0002 carries the two operator actions that block a first rollout — publishing the image and provisioning database roles — and records per-publisher identity as a decision belonging upstream, which this repo must not paper over with cluster configuration implying finer control than exists. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bjefh8NUiEiahN4JLwoSKM Assistant: claude-code Assistant-Model: opus Assistant-Process: 388925@bnt-lap001 Assistant-Session: 3507023f-e0fd-4a1e-9d90-a0d4217d1502
2026-09-06 21:44:17 +02:00
apiVersion: apps/v1
kind: Deployment
metadata:
name: canned-prompts
namespace: canned-prompts
labels:
app.kubernetes.io/name: canned-prompts
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: canned-prompts
template:
metadata:
labels:
app.kubernetes.io/name: canned-prompts
app.kubernetes.io/part-of: canned-prompts
spec:
automountServiceAccountToken: false
serviceAccountName: canned-prompts
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: canned-prompts
Publish the image, pin it by digest, and request the database RCP-WP-0002-T01 done. Published forgejo.coulomb.social/coulomb/canned-prompts:0.1.0 and pinned sha256:e0ded3c7fe25... in declarations/rapp.yaml and both manifests. Pinned by digest rather than tag: a tag can be moved, and live-image-digest-match would then pass against something that is no longer what this repo reviewed. Verified after the push by fetching the manifest back by digest rather than trusting the push output. readiness_state draft -> declared. Not deployed, so not `deployed`. T02 requested rather than performed. rapp-postgres now carries consumers/canned-prompts.yaml against its documented PostgresConsumer shape, and its agent has the request. `make provision-consumers`, which mints the OpenBao credentials, was deliberately not run: credential issuance belongs to that repo's operator, and running it from the consuming side would take a decision that is not this repo's, however available the script is. T03 and T04 move to wait behind it. Also corrected a check of my own: I briefly read the cluster list as lacking platform-pg-2 and suspected the manifests targeted a host that does not exist. That was my own truncated output. platform-pg-2 is present and healthy, and the postgres-client label matches what sbom-nexus actually carries in the cluster rather than only what its repo says. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bjefh8NUiEiahN4JLwoSKM Assistant: claude-code Assistant-Model: opus Assistant-Process: 388925@bnt-lap001 Assistant-Session: 3507023f-e0fd-4a1e-9d90-a0d4217d1502
2026-09-07 08:43:35 +02:00
image: forgejo.coulomb.social/coulomb/canned-prompts@sha256:e0ded3c7fe2548c910445deaa31ec42e84f129a92aa324841e231a53fee1f123
Package canned-prompts for Railiance Registers the repo with State Hub (agents / practice, prefix RCP-WP) and fills in the rapp shape. declarations/rapp.yaml declares a manifest-managed platform service owned by canned-prompts, bound to rail-kubernetes and reef-railiance, with rollout, smoke and rollback contracts. The image pin says `pending-publication` rather than carrying a placeholder digest. The image builds and was verified locally (canned-prompts CANP-WP-0006-T06) but has never been pushed, so no registry digest exists. A placeholder shaped like a real digest would be worse than a sentinel: it could be mistaken for something deployable. manifests/ follows the rapp-sbom-nexus shape: namespace labelled for the postgres client, external secrets from OpenBao, a migration Job, and the runtime Deployment with a ClusterIP-only Service, dedicated ServiceAccount and default-deny plus runtime NetworkPolicies. Three choices worth stating. Credentials arrive as mounted files, never env vars — an env var holding a password is visible in kubectl describe, in crash dumps, and to anything that can read /proc. Migrations run as a Job rather than at start-up, so a schema rollback stays separate from a code rollback and replicas do not race. Liveness points at /healthz, which checks only that the process is up: pointing it at a database-dependent path would restart every replica during a database blip. Egress is PostgreSQL and DNS only. A package arrives by publish; the registry never reaches out, so it is given no path to. tools/smoke.sh checks what only the cluster can answer and calls canned-prompts' service/tools/smoke.py for health and migration head, rather than holding a second opinion about whether the service is healthy. RCP-WP-0002 carries the two operator actions that block a first rollout — publishing the image and provisioning database roles — and records per-publisher identity as a decision belonging upstream, which this repo must not paper over with cluster configuration implying finer control than exists. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bjefh8NUiEiahN4JLwoSKM Assistant: claude-code Assistant-Model: opus Assistant-Process: 388925@bnt-lap001 Assistant-Session: 3507023f-e0fd-4a1e-9d90-a0d4217d1502
2026-09-06 21:44:17 +02:00
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8000
env:
# The URL arrives as a mounted file, never as an env var: an env var
# holding a password shows up in `kubectl describe`, in crash dumps,
# and to anything that can read /proc.
- name: CANNED_PROMPTS_DATABASE_URL_FILE
value: /var/run/secrets/postgres-runtime/url
- name: CANNED_PROMPTS_PUBLISH_TOKEN_FILE
value: /var/run/secrets/publish/token
- name: CANNED_PROMPTS_TENANT
value: railiance
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
readinessProbe:
httpGet:
path: /readyz
port: http
periodSeconds: 5
livenessProbe:
# /healthz deliberately checks only that the process is up. Pointing
# liveness at a database-dependent path would restart every replica
# during a database blip, turning a brief outage into an outage plus
# a thundering herd.
httpGet:
path: /healthz
port: http
periodSeconds: 20
startupProbe:
httpGet:
path: /readyz
port: http
failureThreshold: 30
periodSeconds: 2
resources:
requests:
cpu: 25m
memory: 96Mi
limits:
cpu: 500m
memory: 384Mi
volumeMounts:
- name: postgres-runtime
mountPath: /var/run/secrets/postgres-runtime
readOnly: true
- name: publish
mountPath: /var/run/secrets/publish
readOnly: true
volumes:
- name: postgres-runtime
secret:
defaultMode: 0440
secretName: canned-prompts-postgres-runtime
items:
- key: url
path: url
- name: publish
secret:
defaultMode: 0440
secretName: canned-prompts-publish-token
optional: true
items:
- key: token
path: token
---
apiVersion: v1
kind: Service
metadata:
name: canned-prompts
namespace: canned-prompts
spec:
# ClusterIP only. No Ingress, no LoadBalancer: this registry is reachable
# from inside the cluster and nowhere else, which is what
# `private-service-only` in the smoke contract asserts.
type: ClusterIP
selector:
app.kubernetes.io/name: canned-prompts
ports:
- name: http
port: 8000
targetPort: http
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: canned-prompts
namespace: canned-prompts
automountServiceAccountToken: false
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: canned-prompts-default-deny
namespace: canned-prompts
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: canned-prompts-runtime
namespace: canned-prompts
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: canned-prompts
policyTypes: [Ingress, Egress]
ingress:
- from:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 8000
egress:
# PostgreSQL and DNS only. The service fetches nothing: a package arrives
# by publish, never by the registry reaching out, so it needs no egress to
# the internet and is not given any.
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: databases
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53