Prepare digest-pinned Coulomb workspace with retained content PVC

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a10e2d-a5ef-7e92-b03d-b1694e915680
This commit is contained in:
tegwick 2026-10-06 16:44:19 +02:00
parent 1f68e62f1c
commit 9023da946f
8 changed files with 180 additions and 7 deletions

View file

@ -12,6 +12,7 @@
| workplan | RAPPS-WP-0002 | finished | — | workplans/RAPPS-WP-0002-railiance01-activity-core-backup-automation.md |
| workplan | RAPPS-WP-0003 | finished | — | workplans/RAPPS-WP-0003-policy-nexus-production-binding.md |
| workplan | RAPPS-WP-0014 | blocked | — | workplans/RAPPS-WP-0014-vergabe-invited-pilot.md |
| workplan | RAPPS-WP-0015 | active | — | workplans/RAPPS-WP-0015-coulomb-personal-content-release.md |
| task | RAPPS-WP-0001-T01 | done | — | workplans/RAPPS-WP-0001-cnpg-backup-scheduledbackup-coverage.md |
| task | RAPPS-WP-0001-T02 | done | — | workplans/RAPPS-WP-0001-cnpg-backup-scheduledbackup-coverage.md |
| task | RAPPS-WP-0001-T03 | done | — | workplans/RAPPS-WP-0001-cnpg-backup-scheduledbackup-coverage.md |
@ -31,3 +32,7 @@
| task | RAPPS-WP-0014-T01 | done | — | workplans/RAPPS-WP-0014-vergabe-invited-pilot.md |
| task | RAPPS-WP-0014-T02 | done | — | workplans/RAPPS-WP-0014-vergabe-invited-pilot.md |
| task | RAPPS-WP-0014-T03 | wait | — | workplans/RAPPS-WP-0014-vergabe-invited-pilot.md |
| task | RAPPS-WP-0015-T01 | progress | — | workplans/RAPPS-WP-0015-coulomb-personal-content-release.md |
| task | RAPPS-WP-0015-T02 | progress | — | workplans/RAPPS-WP-0015-coulomb-personal-content-release.md |
| task | RAPPS-WP-0015-T03 | wait | — | workplans/RAPPS-WP-0015-coulomb-personal-content-release.md |
| task | RAPPS-WP-0015-T04 | wait | — | workplans/RAPPS-WP-0015-coulomb-personal-content-release.md |

View file

@ -1,10 +1,10 @@
apiVersion: v2
name: coulomb-social
description: |
coulomb.social — co-creation platform (NetKingdom identity shell).
Standalone Django app; content migration deferred.
coulomb.social — co-creation workspace with NetKingdom identity.
Django app with persistent single-writer Markdown content.
type: application
version: 0.1.0
version: 0.2.0
appVersion: "0.1.0"
keywords:
- django

View file

@ -18,8 +18,15 @@ app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{- define "coulomb.image" -}}
{{- if .Values.image.digest -}}
{{- if not (regexMatch "^sha256:[a-f0-9]{64}$" .Values.image.digest) -}}
{{- fail "image.digest must be a sha256 registry digest" -}}
{{- end -}}
{{- printf "%s@%s" .Values.image.repository .Values.image.digest -}}
{{- else -}}
{{- if not .Values.image.tag -}}
{{- fail "image.tag is required — pin it in helm/coulomb-social-values.yaml" -}}
{{- end -}}
{{- printf "%s:%s" .Values.image.repository .Values.image.tag -}}
{{- end -}}
{{- end -}}

View file

@ -0,0 +1,17 @@
{{- if .Values.persistence.content.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "coulomb.fullname" . }}-content
labels: {{- include "coulomb.labels" . | nindent 4 }}
{{- if .Values.persistence.content.retain }}
annotations:
helm.sh/resource-policy: keep
{{- end }}
spec:
accessModes: [ReadWriteOnce]
storageClassName: {{ .Values.persistence.content.storageClass | quote }}
resources:
requests:
storage: {{ .Values.persistence.content.size | quote }}
{{- end }}

View file

@ -7,11 +7,22 @@ spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels: {{- include "coulomb.selectorLabels" . | nindent 6 }}
{{- if and .Values.persistence.content.enabled (ne (int .Values.replicaCount) 1) }}
{{- fail "Persistent content requires replicaCount=1 (single writer)" }}
{{- end }}
{{- if and .Values.persistence.content.enabled (ne .Values.deploymentStrategy "Recreate") }}
{{- fail "Persistent content requires Recreate strategy" }}
{{- end }}
{{- if and .Values.persistence.content.enabled (ne (index .Values.env "CONTENT_ROOT") .Values.persistence.content.mountPath) }}
{{- fail "CONTENT_ROOT must match the persistent content mountPath" }}
{{- end }}
strategy:
type: RollingUpdate
type: {{ .Values.deploymentStrategy }}
{{- if eq .Values.deploymentStrategy "RollingUpdate" }}
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
{{- end }}
template:
metadata:
labels: {{- include "coulomb.selectorLabels" . | nindent 8 }}
@ -59,16 +70,29 @@ spec:
failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
{{- end }}
resources: {{- toYaml .Values.resources | nindent 12 }}
{{- if .Values.persistence.media.enabled }}
{{- if or .Values.persistence.content.enabled .Values.persistence.media.enabled }}
volumeMounts:
{{- if .Values.persistence.content.enabled }}
- name: content
mountPath: {{ .Values.persistence.content.mountPath | quote }}
{{- end }}
{{- if .Values.persistence.media.enabled }}
- name: media
mountPath: /app/media
{{- end }}
{{- end }}
{{- if .Values.persistence.media.enabled }}
{{- if or .Values.persistence.content.enabled .Values.persistence.media.enabled }}
volumes:
{{- if .Values.persistence.content.enabled }}
- name: content
persistentVolumeClaim:
claimName: {{ include "coulomb.fullname" . }}-content
{{- end }}
{{- if .Values.persistence.media.enabled }}
- name: media
persistentVolumeClaim:
claimName: {{ include "coulomb.fullname" . }}-media
{{- end }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector: {{- toYaml . | nindent 8 }}

View file

@ -1,10 +1,14 @@
image:
digest: ""
repository: forgejo.coulomb.social/coulomb/coulomb-social
tag: ""
pullPolicy: IfNotPresent
replicaCount: 1
# Required single-writer content plane; avoid rolling surge/concurrent writes.
deploymentStrategy: Recreate
service:
type: ClusterIP
port: 80
@ -54,6 +58,13 @@ probes:
failureThreshold: 3
persistence:
content:
enabled: false
storageClass: local-path
size: 2Gi
mountPath: /app/var/content
# Keep PVC across release uninstall; backup/restore is a separate obligation.
retain: true
media:
enabled: false

View file

@ -3,7 +3,8 @@
image:
repository: forgejo.coulomb.social/coulomb/coulomb-social
tag: "7fcd0cf"
tag: "ac7bac1852c9"
digest: "sha256:bf975939e22b9b0a5d9ac05584ae6265ba201169df6dc48e506ec684b30a9c58"
# Public host: app.coulomb.social (parallel to Bubble on apex coulomb.social).
# Apex cutover is deferred until data + self-registration are ready.
@ -11,6 +12,7 @@ env:
DJANGO_SETTINGS_MODULE: coulomb_social.settings.prod
ALLOWED_HOSTS: app.coulomb.social,localhost
CSRF_TRUSTED_ORIGINS: https://app.coulomb.social
CONTENT_ROOT: /app/var/content
DEFAULT_TENANT_ID: "tenant:coulomb"
OIDC_ENABLED: "true"
OIDC_ISSUER: https://kc.coulomb.social
@ -25,3 +27,14 @@ env:
probes:
hostHeader: app.coulomb.social
path: /healthz
# One writable local-path volume; Recreate prevents concurrent old/new writers.
replicaCount: 1
deploymentStrategy: Recreate
persistence:
content:
enabled: true
storageClass: local-path
size: 2Gi
mountPath: /app/var/content
retain: true

View file

@ -0,0 +1,96 @@
---
id: RAPPS-WP-0015
type: workplan
title: "Coulomb-social persistent personal workspace release"
domain: financials
repo: railiance-apps
status: active
owner: codex
topic_slug: railiance-apps
created: "2026-10-06"
updated: "2026-10-06"
related:
- CSOC-WP-0008
state_hub_workstream_id: "79abacf8-361e-51ab-829d-40dec8e142d1"
---
# RAPPS-WP-0015 — Personal Coulomb workspace
Owning deployment change for CSOC-WP-0008. Prepare a reviewed upgrade from
7fcd0cf to the tested app with static assets and a 2Gi retained local-path
CONTENT_ROOT PVC. Use one replica and Recreate to prevent concurrent old/new
filesystem writers. Existing OIDC, PostgreSQL and secret references stay in use.
## T01 — Prepare immutable source image
```task
id: RAPPS-WP-0015-T01
status: done
priority: high
state_hub_task_id: "e17488d4-60b8-58b7-a5d8-fbcdc55e1f0c"
```
Source repo runs make check; collect static assets in the container image;
exclude private local data from Docker context. Build/publish SHA-tagged image
with revision label and registry digest. Verify the image serves the real
clipboard asset through production settings without developer static hosting.
## T02 — Validate persistent single-writer chart
```task
id: RAPPS-WP-0015-T02
status: done
priority: high
state_hub_task_id: "4e38dd8e-761b-58c8-8005-8490a49767ab"
```
Content PVC/mount/CONTENT_ROOT wiring, fsGroup 10001, keep policy and Recreate.
Reject multiple replicas, rolling writer strategy and root/mount mismatch.
Helm lint/render, server dry-run and diff; confirm resource/disk headroom and
that coulomb-social is not currently ArgoCD-managed. Publish the review branch.
## T03 — Approved upgrade and recovery point
```task
id: RAPPS-WP-0015-T03
status: wait
priority: high
state_hub_task_id: "2ce05439-70dc-53cf-b704-5118687857cb"
```
Founder approves exact image digest, chart diff, 2Gi PVC and brief Recreate
interruption: ADMINISTER @ realm:kubernetes/railiance01, activation=APPROVED.
Capture a private pre-upgrade DB recovery point through the documented owner
backup path. Apply from railiance01 with Helm --atomic, preserve existing
tegwick identity and migration data. Do not run legacy env
secret-building scripts or dump live Secret objects. No apex cutover.
## T04 — Personal sign-in and content acceptance
```task
id: RAPPS-WP-0015-T04
status: wait
priority: high
state_hub_task_id: "8bc4962a-d0d4-57cd-bf2b-295658b88765"
```
User signs in interactively as existing personal tegwick account. Confirm local
Member matches verified issuer/subject, grant only that member the nominated
workspace, and smoke page CRUD/duplicate/clipboard. Prove PVC write ownership,
restart durability and paired DB/content restore before real productive transfer.
CSOC-WP-0008 continues actual ReichelAg reconciliation and user review.
## Prepared evidence — 2026-10-06
Source ac7bac1852c9, make check: 88 passed. Container production WhiteNoise
serves /static/spaces/copy-content.js HTTP 200, 2909 bytes, ClipboardItem present.
Published immutable registry digest:
sha256:bf975939e22b9b0a5d9ac05584ae6265ba201169df6dc48e506ec684b30a9c58.
Chart 0.2.0 pins that digest; lint and server dry-run pass; unsafe multiple
replicas, RollingUpdate and CONTENT_ROOT mismatch are refused.
The user's actual login fails unknown client_id. Guarded read-only inspection
confirms the public coulomb-social client is absent. CSOC-WP-0008-T11 prepares
its restoration and shared KeyCape restart; no live change has been made.
Existing completed apps-pg daily backup is not a paired application restore.
T03/T04 remain waiting for exact live approval and personal acceptance.