# Deploy notes ## Shape Standalone service: commit-SHA images → registry `forgejo.coulomb.social/coulomb/coulomb-social` → `railiance-apps` Helm values → railiance01 (same lane as `vergabe-teilnahme`). Chart/values/ingress live in **`railiance-apps`** (`helm/coulomb-social-values.yaml`, `docs/coulomb-social.md`). ## Host strategy | Host | Role | |------|------| | **`https://app.coulomb.social`** | **Live** Railiance rebuild (app home + spaces) | | **`https://coulomb.social`** | **Bubble.io** until data + self-registration + content ready | | `http://127.0.0.1:8008` | Local OIDC/dev | Apex DNS cutover is **deferred**. Retire Bubble only after an explicit decision. ## Current cluster status | Item | State | |------|--------| | Namespace | `coulomb-social` | | Public host | **`app.coulomb.social`** | | OIDC redirect | `https://app.coulomb.social/auth/callback/` | | Apex Bubble | unchanged | ## Runtime secrets (names only) K8s Secret `coulomb-social-env` (mounted via `envFrom`). | Key | Required | Purpose | |-----|----------|---------| | `SECRET_KEY` | yes | Django secret | | `DATABASE_URL` | yes | Postgres URL | | `USER_ENGINE_PROXY_SECRET` | yes (live UE) | trusted proxy to user-engine | | `FORGEJO_TOKEN` | no | private Forgejo raw/API reads | | `FORGEJO_WEBHOOK_SECRET` | no | push webhook HMAC / shared secret | | `NETKINGDOM_REGISTRATION_URL` | no | enable landing **Create account** when NK ships | ```bash # railiance-apps: make coulomb-social-env-secret-dry-run make coulomb-social-env-secret ``` OIDC is a **public** client — no client secret. Non-secret OIDC / Forgejo base URL settings live in Helm values (`FORGEJO_BASE_URL` defaults to `https://forgejo.coulomb.social` in app settings). ## Health - `GET /healthz` → `{"status":"ok","service":"coulomb-social"}` - Probes use `Host: app.coulomb.social` ## Build / deploy ```bash SHA=$(git rev-parse --short HEAD) docker build -t forgejo.coulomb.social/coulomb/coulomb-social:$SHA . # COULOMB_SOCIAL_IMAGE_TAG=$SHA make coulomb-social-deploy # in railiance-apps # make coulomb-social-ingress-deploy ``` ## Parallel host go-live checklist 1. [x] Helm env / ingress use `app.coulomb.social` 2. [x] KeyCape redirects include `https://app.coulomb.social/auth/callback/` 3. [x] DNS: `app.coulomb.social` resolves; HTTPS live (healthz 200) 4. [x] `curl -fsS https://app.coulomb.social/healthz` 5. [x] Browser Sign in as tegwick → `/app/` (Case A; see `docs/identity/smoke.md`) 6. [ ] Seed demo space + open rendered markdown (operator; steps below) ## Future apex cutover (not now) When Bubble can retire: 1. Point `coulomb.social` A at the cluster (or reverse-proxy) 2. Switch Helm `ALLOWED_HOSTS` / `OIDC_REDIRECT_URI` / ingress host if apex becomes canonical 3. Keep or drop `app.` as redirect alias ## Local verification ```bash make test make run # offline or local OIDC redirect uv run manage.py seed_demo_space # Sign in (dev login) → /app/ → Demo space → rendered markdown ``` --- ## Operator runbook — spaces on app.coulomb.social Product path for **CSOC-WP-0004**. Content model: **ADR-0002**. Detail on read/write/webhook: `docs/spaces-content.md`. Identity smoke: `docs/identity/smoke.md`. ### A. Prerequisites 1. Image includes spaces app (`spaces` migrations + Forgejo client) and is deployed to namespace `coulomb-social`. 2. Member can Sign in (existing LLDAP/KeyCape user, e.g. tegwick). 3. Forgejo reachable from the pod (`FORGEJO_BASE_URL`, default `https://forgejo.coulomb.social`). Public raw needs **no** token; private repos need `FORGEJO_TOKEN` in `coulomb-social-env`. ### B. Demo seed (fastest smoke — uses this repo as content) In-repo fixture (already on `main`): ```text docs/space-fixtures/demo/pages/index.md ``` Public raw check (no auth): ```bash curl -fsS \ "https://forgejo.coulomb.social/coulomb/coulomb-social/raw/branch/main/docs/space-fixtures/demo/pages/index.md" \ | head ``` Seed metadata in the app DB (binds `demo` → that path): ```bash kubectl -n coulomb-social exec deploy/coulomb-social -- \ python manage.py seed_demo_space # optional: --slug demo --title "Demo space" --tenant tenant:coulomb ``` Browser: 1. https://app.coulomb.social/ → **Sign in** (tegwick) 2. Land on `/app/` — **Spaces** lists **Demo space** 3. Open `/app/spaces/demo/` — see rendered markdown from Forgejo 4. Profile menu → **Session details** (`/account/session/`) still works 5. **Edit in Forgejo** / **View source** open the bound file; after a commit, **Refresh content** re-fetches (or configure webhook, section D) ### C. Production-shaped space (dedicated Forgejo repo) ADR-0002: **one repo per space**. 1. In Forgejo, create org (recommended) `coulomb-spaces` (or tenant org later). 2. Create repo e.g. `space-my-space` with branch `main` and layout: ```text pages/ index.md # default landing page .md # optional extra pages assets/ # optional images README.md # optional ``` 3. Bind in the app (Django admin, or shell): ```bash kubectl -n coulomb-social exec -it deploy/coulomb-social -- python manage.py shell ``` ```python from coulomb_social.apps.spaces.models import Space Space.objects.update_or_create( tenant_id="tenant:coulomb", slug="my-space", defaults={ "title": "My space", "forgejo_owner": "coulomb-spaces", "forgejo_repo": "space-my-space", "default_branch": "main", "content_root": "pages", "is_active": True, }, ) ``` 4. If the repo is private, set `FORGEJO_TOKEN` (read-only deploy token) via `railiance-apps` env-secret tooling — **never** commit the token. 5. Open `https://app.coulomb.social/app/spaces/my-space/` as a signed-in member of that tenant. ### D. Optional push webhook (auto cache bust) 1. Put a random secret in cluster env as `FORGEJO_WEBHOOK_SECRET`. 2. Forgejo repo → **Settings → Webhooks → Add webhook → Gitea**: - URL: `https://app.coulomb.social/app/spaces/hooks/forgejo/` - Method POST, content type JSON - Secret: same value as env - Trigger: **Push** 3. Push a commit; confirm response JSON includes `cache_entries_cleared` / `spaces_matched`. Authors can still use **Refresh content** without a webhook. ### E. Env names quick reference | Variable | Secret? | Where | |----------|---------|--------| | `FORGEJO_BASE_URL` | no | settings default / Helm | | `FORGEJO_TOKEN` | yes | `coulomb-social-env` | | `FORGEJO_WEBHOOK_SECRET` | yes | `coulomb-social-env` | | `FORGEJO_TIMEOUT_SECONDS` | no | optional | | `NETKINGDOM_REGISTRATION_URL` | no | enable Create account (residual; NK-WP-0025) | ### F. Smoke checklist (app.coulomb.social) | # | Check | Pass criteria | |---|--------|----------------| | 1 | `GET /healthz` | `{"status":"ok","service":"coulomb-social"}` | | 2 | Landing | Sign in visible; Create account only if registration URL set | | 3 | OIDC login (known user) | tegwick → `/app/` app home (not principal dump) | | 4 | Spaces list | empty state or seeded spaces | | 5 | Space detail | markdown rendered from Forgejo (or clear fail-closed error) | | 6 | Session details | profile menu → `/account/session/` shows issuer/subject/UE id | | 7 | Sign out | session cleared; `/app/` requires login | | 8 | (optional) Edit in Forgejo + Refresh | new commit visible without redeploy | Identity detail and historical evidence: `docs/identity/smoke.md`. Content mechanics: `docs/spaces-content.md`.