coulomb-social/docs/adr/ADR-0004-content-plane-thin-git-upgrades.md
tegwick ce65b359af Add ADR-0003 and ADR-0004 for page SoR and thin git content plane
Accept page-centric markdown SoR with dual authoring, live includes, and
lazy projections; accept thin dir+git plane with PageOps and supported
upgrades to shard-wiki and kontextual. Demote ADR-0002 Forgejo-as-SoR.
2026-08-13 10:04:46 +02:00

189 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: ADR-0004
title: Thin git content plane, PageOps, and supported upgrades
status: accepted
date: 2026-08-13
deciders: bernd
related:
- ADR-0001
- ADR-0002
- ADR-0003
- docs/architecture/ArchitectureBlueprint.md
workplans:
- CSOC-WP-0004
- CSOC-WP-0006
---
# ADR-0004 — Thin git content plane, PageOps, and supported upgrades
## Status
**Accepted** (2026-08-13).
Pairs with **ADR-0003** (what a page is and how authors work). This ADR decides
**where content lives**, how the app talks to it, and how the plane may grow.
## Context
Content needs a store that:
- keeps **user data as files** in **git**,
- starts **simple** for stage-1 transfer,
- can later gain wiki federation or ECM-class power **without rewriting** the
product UI or stranding exports.
Candidates considered:
| Option | Role |
|--------|------|
| **A** Thin directory + markdown + git | Start here |
| **B** shard-wiki | Wiki orchestration / multi-shard later |
| **C** kontextual-engine | Scale, rich media, governed assets later |
Also: shared **asset-store** extraction, and who owns content-plane PolicyGateway.
## Decision
### 1. Default content plane (stage-1 and near term)
**Start thin (A):**
- A **directory tree** of markdown pages and assets.
- Tree is **secured in git** (commits via product, operator, or linked remote).
- Illustrative layout:
```text
spaces/<space-slug>/
pages/<page-slug>.md
assets/…
```
Exact layout may evolve; the invariant is **files + git**, not “opaque DB rows
for prose.”
**Forgejo / remote git** (including ADR-0002-style bindings) may host or mirror
the tree; they are **transports/remotes**, not a second product ontology.
### 2. PageOps boundary
All product code accesses content through a **narrow PageOps** façade (names
illustrative):
| Op | Purpose |
|----|---------|
| list/get/put/archive page | CRUD |
| copy / transfer page | Stage-1 must features |
| explode / implode | Outline-editor flexibility (ADR-0003) |
| resolve_view | Live includes/derived for display |
| pin / unpin / refresh_pinned | Explicit freeze + stale workflow |
| project_field / regenerate / lock | Title/abstractor/visual lifecycle |
| put_visual / get_asset | Binaries |
**Rule:** UI and product services **must not** call shard-wiki, kontextual, or
Forgejo APIs ad hoc from templates — only PageOps. Swapping the content-plane
**adapter** upgrades the backend without rewriting cards and flows.
### 3. Supported upgrade path
```text
A thin dir + git (+ markitect-tool)
│ when wiki / federation / multi-shard matters
B shard-wiki adapter (same markdown as shard material)
│ when scale / rich multi-format media / heavy governance
C kontextual-engine upgrade (migration tooling; markdown remains portable)
```
| Upgrade | When | Invariant |
|---------|------|-----------|
| **→ shard-wiki** | Wiki features, multi-shard, overlays become product-relevant | Exportable markdown tree remains valid; markitect still structures docs |
| **→ kontextual** | Ambitious structure, scale, rich media, audit/lineage | Supported **upgrade of the information base**; user export of markdown+assets still required where content is document-shaped |
Upgrades are **planned migrations**, not emergency rewrites. Feasibility should
be re-checked with export/import sketches when approaching B or C.
### 4. Assets
1. **Now:** assets live **beside** markdown in the content tree (paths or simple
digests in frontmatter `visual` / refs).
2. **Later:** extract a shared **asset-store** (seed from kontextual BlobStorage
ideas) when a **second fleet consumer** needs the same API — **not** a
stage-1 gate.
3. Do **not** adopt markitect-mains large assets package as runtime.
### 5. Authorization ownership
1. **Authn** remains NetKingdom OIDC (ADR-0001).
2. **Do not** create a long-lived coulomb-specific PolicyGateway ownership
stream. Prefer **NetKingdom consolidation** so authorization decisioning for
app resources is the obvious platform path (flex-auth / NK as one story).
3. **Until consolidation lands:** coulomb enforces coarse product authz
(authenticated session, `tenant_id`, SpaceMembership). Content plane fails
closed if a PDP is configured and denies or is required but unavailable for
sensitive ops.
4. Content-plane engines (shard-wiki, kontextual) must accept **external**
principal identity (e.g. issuer/subject + groups), not their own user
directories.
### 6. markitect-tool on every plane
Regardless of A/B/C:
- parse, validate, query, **live include**, explode/implode, and future
derived-slot tooling live in **markitect-tool**;
- the plane stores and serves files (or equivalent); markitect does not host
multi-user product sessions.
## Consequences
### Positive
- Fastest path to stage-1 with true user-owned files and git history.
- Clear upgrade story reduces fear of “too simple forever” without overbuilding.
- PageOps keeps UI stable across backend generations.
- Authz consolidation direction avoids duplicate IAM mini-platforms.
### Negative / costs
- Thin plane must still implement solid git/write, conflict, and cache-bust
behavior for a good product feel.
- Copy/transfer/explode semantics are coulomb+markitect work on the tree.
- Upgrade tooling to B/C is real future cost (accepted as supported path).
- NK authz consolidation is a **platform dependency** outside this repos sole
control.
### Neutral
- ADR-0002 Forgejo demo path can remain for public raw fixtures and optional
remotes.
- asset-store extraction is explicit **later** work (possible ADR-0005).
## Non-goals
- Implementing full shard-wiki or kontextual integration in stage-1.
- Bundling a wiki UI or ECM UI in coulomb (headless planes only).
- Replacing NetKingdom with app-local accounts.
- Making Postgres the content SoR.
## Implementation guidance (non-normative)
1. Define a `ContentPlane` / PageOps port in coulomb; ship **Filesystem+Git**
adapter first.
2. Index cards into Postgres on write and on git pull/webhook.
3. Wire markitect live `resolve_includes` on view/export.
4. Prototype explode/implode in product against the same tree.
5. Document export: zip/tar of tree without DB dump.
6. When approaching B/C: migration runbook + round-trip tests from a real
space tree.
## References
- `docs/architecture/ArchitectureBlueprint.md` (D1D4)
- `docs/architecture/spike-checklist.md` (A chosen; B/C upgrade sketches)
- ADR-0003 (page model, live/pin, authoring)
- ADR-0002 (Forgejo vertical slice; demoted as exclusive SoR)
- shard-wiki INTENT (Coulomb as intended consumer)
- kontextual-engine (upgrade target; blob port for later asset-store)