Introduce tenant-scoped Space/SpaceMembership with list and detail views. Document markdown-in-Forgejo as content SoR (ADR-0002). Run migrations on container start so app.coulomb.social picks up the new tables.
4.2 KiB
ADR-0002 — Space content as markdown in Forgejo
| Field | Value |
|---|---|
| Status | Provisional (accepted for T04 vertical slice; revisit write path) |
| Date | 2026-08-12 |
| Deciders | bernd |
| Workplan | CSOC-WP-0004-T03 |
Context
coulomb.social co-creation spaces need durable page/artefact content. Bubble stores opaque page graphs. The rebuild should:
- keep content agent- and human-editable in git,
- version and review changes like normal software,
- avoid making Postgres the system of record for long-form prose,
- align with Forgejo already hosting fleet code on railiance01.
Identity and space metadata stay in the app DB (Space, memberships).
Decision
1. Canonical content form
- Markdown (CommonMark + limited GFM: tables, fenced code, images).
- Static assets (images, attachments) live beside markdown under a content root.
- Postgres stores metadata and binding only — never full page bodies as SoR.
2. Repository layout (v1)
One Forgejo repository per space under a dedicated org (recommended:
coulomb-spaces or tenant-scoped org later).
<forgejo_owner>/<forgejo_repo>/
README.md # optional space intro
pages/
index.md # default landing page
<page-slug>.md
assets/ # images etc. referenced from pages
Field on Space |
Meaning |
|---|---|
forgejo_owner |
org/user |
forgejo_repo |
repo name |
default_branch |
usually main |
content_root |
default pages |
Branch policy (v1): app reads from default_branch only. PRs for review
are a human/Forgejo workflow; the app does not merge PRs in v1.
Monorepo alternative (deferred): single repo with spaces/<slug>/… —
rejected for v1 to keep permissions and migration packages simple.
3. Read path (T04)
- App resolves
Spaceby tenant + slug (authz already enforced). - If binding incomplete → empty state (no silent Bubble fetch).
- Fetch file via Forgejo raw/contents API (preferred) or shallow cache:
- HTTP GET with service token from env/OpenBao.
- Cache rendered HTML or raw markdown in memory/disk with short TTL + optional webhook invalidation later.
- Render markdown → HTML with a locked-down sanitizer (no raw script).
- Fail closed on 404/403/network errors with operator-visible reason.
4. Write path (T05 — provisional)
v1 preference: edit in Forgejo (web UI or git) + app refresh.
- Lowest security surface (no app-held write credentials required if public-read internal repos use deploy token read-only).
- Optional later: in-app editor → commit as bot user via API.
Not in v1: bidirectional live sync with Bubble.
5. Mapping from Bubble (later CSOC-WP-0001)
| Bubble concept | Target |
|---|---|
| Space / room-like container | Space row + Forgejo repo |
| Page / chunk prose | pages/<slug>.md |
| Attachments | assets/… |
| Permissions | SpaceMembership + NetKingdom groups (refine later) |
Export scripts should emit markdown files + a manifest JSON for binding fields.
6. Secrets
| Secret | Storage |
|---|---|
| Forgejo API token (read, later write) | K8s Secret / OpenBao — env e.g. FORGEJO_TOKEN |
| Forgejo base URL | non-secret config e.g. FORGEJO_BASE_URL=https://forgejo.coulomb.social |
Never commit tokens. Never render tokens in Session details.
Consequences
Positive
- Content is git-native and agent-friendly.
- Clear boundary: app = membership + UX; Forgejo = document history.
- Migration can ship repos per space without rewriting history into SQL.
Negative / follow-ups
- Need Forgejo org, tokens, and network reachability from the app pod.
- Offline/local dev needs a stub or fixture markdown path.
- Search and cross-space queries need a separate index later.
Open questions (non-blocking for T04)
- Org name:
coulomb-spacesvs per-tenant org. - Private repos only vs public read for some community spaces.
- When to add webhook-driven cache purge.
- Whether user OAuth to Forgejo is required for in-app write (T05).
References
- CSOC-WP-0004, Space model in
coulomb_social.apps.spaces - ADR-0001 NetKingdom identity
- Host posture:
docs/deploy.md(app.coulomb.social)