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.
6.6 KiB
| id | title | status | date | deciders | related | workplans | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ADR-0004 | Thin git content plane, PageOps, and supported upgrades | accepted | 2026-08-13 | bernd |
|
|
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:
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
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
- Now: assets live beside markdown in the content tree (paths or simple
digests in frontmatter
visual/ refs). - 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.
- Do not adopt markitect-main’s large assets package as runtime.
5. Authorization ownership
- Authn remains NetKingdom OIDC (ADR-0001).
- 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).
- 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. - 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 repo’s 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)
- Define a
ContentPlane/ PageOps port in coulomb; ship Filesystem+Git adapter first. - Index cards into Postgres on write and on git pull/webhook.
- Wire markitect live
resolve_includeson view/export. - Prototype explode/implode in product against the same tree.
- Document export: zip/tar of tree without DB dump.
- When approaching B/C: migration runbook + round-trip tests from a real space tree.
References
docs/architecture/ArchitectureBlueprint.md(D1–D4)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)