coulomb-social/docs/architecture/ArchitectureBlueprint.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

16 KiB
Raw Blame History

Architecture Blueprint — coulomb.social content & platform

Field Value
Status draft — decisions recorded 2026-08-13
Product coulomb.social rebuild (coulomb-social)
Related stage-1 cut, capability maps, authoring, stale/derived, upgrade path
Non-goals Implementing UI chrome here; full markitect feature build in this doc

0. Decision log (2026-08-13)

# Topic Decision
D1 Content plane Start thin: directory + markdown files, secured in git. Supported upgrade path: thin → shard-wiki (when wiki/federation matters) via markitect-shaped content; then → kontextual (structure, scale, rich media) as a supported upgrade of the information base.
D2 asset-store Extract later. Stage-1 may use local files next to markdown (and/or temporary blob helpers); do not block on a new repo.
D3 PolicyGateway / content authz ownership Do not invent a parallel owner. Prefer NetKingdom consolidation so identity and authorization decisioning for app resources become the obvious path (flex-auth / NK as one story). Until that lands, coulomb uses coarse product authz (session + SpaceMembership + tenant); content plane stays fail-closed when a PDP is wired.
D4 Structure UX Aspire to outline-editor flexibility: explode one markdown into smaller connected documents; implode selection(s) back into one file. Default = live (spreadsheet-like: includes/derived resolve to current inputs automatically). Pin only when the user freezes a snapshot.

Earlier freezes (unchanged): NetKingdom identity, Railiance deploy, markdown SoR + DB cache, markitect-tool not host, page-first, dual authoring, lazy projections + lock, stage-1 cut.


1. Architectural aim

Deliver a co-creation product where:

  1. Identity (users, groups, tenants) is NetKingdom — not reimplemented.
  2. Runtime is Railiance — not reimplemented.
  3. User-owned content is markdown (+ assets) in a git-secured directory tree, exportable without the app database.
  4. The database is a cache / projection for cards, memberships, search speed.
  5. markitect-tool makes markdown structured and operable (parse, include, explode/implode, later derived slots) — not the product host.
  6. coulomb owns co-creation UI (cards, spaces, outline-oriented editing, copy/transfer).
  7. Knowledge work stays fluent: top-down and bottom-up; live reuse by default; pin when freezing matters.
  8. Growth does not strand data: thin git base → shard-wiki → kontextual are supported upgrades, not rewrites from a proprietary store.

2. Non-negotiable rules

# Rule
R1 Markdown (frontmatter + body + backmatter) + assets under a directory tree are the exportable SoR.
R2 App DB holds projections and app linkage only; disposable for content bodies.
R3 Authn/IdP = NetKingdom; coulomb maps OIDC → Member; no password store.
R4 Authz: prefer NetKingdom-consolidated decisioning; no second user directory; no permanent coulomb-specific PolicyGateway fiefdom.
R5 markitect-main is legacy reference, not a runtime foundation.
R6 markitect-tool is the markdown structure dependency.
R7 Default content plane = thin dir+git. PageOps hide the plane; upgrades swap adapters.
R8 Stage-1 must: onboarding; spaces/pages with Title / Abstractor / Visual; page copy; page transfer.
R9 Pages first — address / live-transclude / explode-implode / promote; not a priori chunk storage.
R10 Live by default for includes and other formula-like derived content; pin freezes a snapshot; pinned/stale use badge → alternative → replace | keep + lock.
R11 Explode / implode (outline-editor flexibility) are first-class structure operations (markitect primitives + coulomb UX).
R12 asset-store extraction is deferred; assets may live beside markdown until then.

3. System shape

                         ┌──────────────────────────┐
                         │   NetKingdom             │
                         │   OIDC · groups · tenants│
                         │   (authz consolidation →)│
                         └────────────┬─────────────┘
                                      │ principal
                                      ▼
┌─────────────────────────────────────────────────────────────┐
│  coulomb.social (product)                                   │
│  • Cards, spaces, dual authoring, outline explode/implode   │
│  • PageOps; live resolve; pin when asked                    │
│  • Railiance deploy                                         │
└───────────────┬─────────────────────────────┬───────────────┘
                │ cache                       │ PageOps
                ▼                             ▼
        ┌───────────────┐         ┌───────────────────────────┐
        │ Postgres      │         │ Content plane             │
        │ projections   │         │  ★ A thin dir + git       │
        └───────────────┘         │    (default / stage-1)    │
                                  │  ↗ B shard-wiki upgrade   │
                                  │  ↗ C kontextual upgrade   │
                                  └─────────────┬─────────────┘
                                                │
                                  ┌─────────────▼─────────────┐
                                  │ markitect-tool            │
                                  │ structure · include LIVE  │
                                  │ explode/implode · query   │
                                  │ pin/derived (proposed)    │
                                  └─────────────┬─────────────┘
                                                ▼
                                  ┌───────────────────────────┐
                                  │ Assets (files next to md) │
                                  │ later: shared asset-store │
                                  └───────────────────────────┘

PageOps (store-agnostic)

Op Meaning
list_pages / get_page / put_page / archive_page CRUD
copy_page / transfer_page Duplicate / re-home
explode_page / implode_pages Outline-style split/join (markitect)
resolve_view Live includes/derived for display (default)
pin_slot / unpin / refresh_pinned Freeze snapshot; stale → alternative → replace|keep
project_field / regenerate / lock Title/abstractor/visual lifecycle
put_visual / get_asset Binary next to tree (later asset-store)

Upgrade path (supported)

Stage now     A  dir + .md + assets  (+ git)
                │  markitect-tool always
                │
When wiki /     B  same markdown becomes shard-wiki shard(s)
 federation     │  PageOps adapter swap; export tree still valid
                │
When scale /    C  kontextual KnowledgeAsset + blobs
 rich media /   │  markdown remains portable representation
 governance     │  PageOps adapter swap; migration tooling required

Requirement: every upgrade preserves user export of markdown+assets; no dead-end proprietary body store.

4. Information model (product)

Concept Representation
Page One markdown file (or connected set after explode)
Space Directory / container + metadata page
Tree Git-secured directory layout
Card UI projection (title, abstractor, visual, actions, stale)
Outline Headings / exploded connected docs — not Bubble chunk rows
Live include mkt:include resolves current source (default)
Pinned derived Optional frozen snapshot; explicit refresh
Member / tenant NetKingdom + app session

4.1 Outline editor flexibility (explode / implode)

Aspire to outline-editor UX powered by markitect explode / implode (and related compose/include):

Action User intent Markitect analogue
Explode Split a large page into smaller connected documents (sections as pages or files) mkt explode (+ connectivity via includes/refs)
Implode Merge selected docs/sections back into one markdown file mkt implode / compose
Navigate outline Treat structure as editable hierarchy Headings + connected pages view

Connectivity after explode: prefer live includes or content references so the outline stays one logical document until the user pins or permanently severs links.

4.2 Live by default (spreadsheet metaphor)

Live (default) Pinned (exception)
Includes / formula-like derived Resolve to current inputs on view/export Stored snapshot until refresh
Body of a normal page User text as written n/a
Projections (title/abstractor/visual) Lazy fill then persist; regenerate on demand Lock freezes; stale offers alternative
Stale pinned / locked derived Badge → generate alternative → replace or keep

Spreadsheet rule: formulas stay live unless the user pastes values (pin).
Pinning is deliberate, not the default co-creation mode.

4.3 Dual authoring + lazy projections

Unchanged intent: top-down and bottom-up both natural; missing display fields lazy-fill then persist; regenerate + lock per field.
See authoring-modes-and-lazy-projections.md, stale-derived-content.md.

5. Content plane — decided start + upgrades

5.1 Default: A — thin directory + git

spaces/<space-slug>/
  pages/<page-slug>.md
  assets/…
# entire tree in git (user- or service-mediated commits)
Why Simplest SoR; user data is files; matches “secured in git”
coulomb role PageOps over filesystem/git; DB indexes cards
markitect role Parse, live include, explode/implode, validate

5.2 Upgrade B — shard-wiki

When multi-shard wiki behavior, overlays, or federation become product-relevant:

  • Ingest the same markdown tree (or git repo) as a shard.
  • PageOps adapter targets shard-wiki; UI unchanged.
  • markitect-tool remains structure layer for resolve/explode.

5.3 Upgrade C — kontextual-engine

When asset identity, scale, rich multi-format media, audit/lineage, or ECM-class governance dominate:

  • Supported migration of the information base into kontextual assets/blobs.
  • Markdown remains the portable authoring/export form where applicable.
  • Not required for stage-1.

5.4 What we do not do now

  • Do not build coulomb on markitect-main.
  • Do not require kontextual or shard-wiki for first productive transfer.
  • Do not extract asset-store before a second consumer (D2).

6. Assets (deferred extract)

  • Stage-1: files under assets/ (or equivalent) in the content tree; optional simple content-addressing later.
  • asset-store shared repo: later (seed from kontextual BlobStorage when extracted).
  • Visual field stores a ref into that tree (or future store).

7. Identity & access control

Browser → NetKingdom OIDC → coulomb session
            ├─ product: tenant_id, SpaceMembership (and future NK groups)
            └─ long-term: NetKingdom-consolidated authz (flex-auth / NK)
                 so PolicyGateway ownership becomes trivial or unused
Now Target
Session + membership + tenant isolation Same + NK-group claims
Content plane fail-closed if PDP present PDP = consolidated NK story
No coulomb-owned IdP Unchanged

D3: Avoid multi-team thrash on “who owns PolicyGateway”; push consolidation in NetKingdom so apps only pass principal + resource attributes.

8. Deploy sketch (Railiance)

Component Deploy
coulomb-social Existing chart; app.coulomb.social
Content tree Volume or git-backed storage accessible to the app; git is SoR discipline
Assets Beside markdown until asset-store
NetKingdom Existing KeyCape / Authelia

9. Stage-1 product scope

Must:

  • Onboarding (NetKingdom)
  • Spaces/pages: Title, Abstractor, Visual, body
  • Copy, transfer
  • Cards; dual authoring; lazy projections
  • Content as dir+git via PageOps
  • Live includes when markitect is wired; pin optional

Aspire early (structure UX):

  • Outline-oriented explode / implode

Later: social, marketplace, monetization, shard-wiki/kontextual upgrades, asset-store extract.

10. ADRs

ADR Topic Status
ADR-0001 NetKingdom identity accepted
ADR-0002 Forgejo vertical slice partly superseded by 0003/0004
ADR-0003 Page-centric markdown SoR, authoring, live/pin accepted
ADR-0004 Thin git plane, PageOps, upgrades B/C accepted
ADR-0005 asset-store extraction later
NetKingdom authz consolidation platform (NK)

Markitect-tool: live include (done), explode/implode (done), pin/derived proposal (proposed-stale-derived-and-include-pinning.md).

11. Spikes (narrowed)

With D1D4, prioritize:

  1. Thin tree layout + git write path (PageOps on files).
  2. markitect parse + live include in get/view.
  3. Explode/implode UX prototype on real pages.
  4. Lazy title/abstractor + stale replace|keep.
  5. Export zip/tar of tree without DB.

Defer deep shard-wiki/kontextual spikes except export/import round-trip sketches that prove upgrade feasibility.

Full list remains in spike-checklist.md (update scorecard: A = chosen start).

12. Closed discussion prompts

Prompt Resolution
A vs B vs C for start A; B/C = supported upgrades
asset-store now? Later
PolicyGateway owner Consolidate under NetKingdom; dont fork ownership
Chunk UX Outline editor + explode/implode, not chunk tables
Live vs pin default Live; pin is explicit

13. Working recommendation (frozen)

Layer Decision
Product UI coulomb cards, spaces, outline explode/implode, dual authoring
Markdown structure markitect-tool; live includes by default
Identity / deploy NetKingdom / Railiance; authz → NK consolidation
Content plane Thin dir + git now
Upgrades → shard-wiki → kontextual (supported, markdown-preserving)
Assets Beside tree now; asset-store later
Derived/stale Live default; pin + badge → alternative → replace|keep
markitect-main Avoid

References

coulomb-social

  • docs/architecture/2026-08-12-content-substrate-exploration.md
  • docs/architecture/transclusion-and-chunks.md
  • docs/architecture/authoring-modes-and-lazy-projections.md
  • docs/architecture/stale-derived-content.md
  • docs/architecture/spike-checklist.md
  • docs/capability/stage-1-cutover.md
  • docs/capability/model-v0.yaml
  • docs/capability/existing-bubble-capability-map.md
  • docs/decisions/2026-08-12-feature-cut-stage-1.md

fleet

  • markitect-tool: transform-compose-include, explode-implode, content-references, proposed-stale-derived-and-include-pinning.md
  • shard-wiki: INTENT (Coulomb as consumer; upgrade target)
  • kontextual: blob-storage, asset-registry (upgrade + later asset-store seed)
  • markitect-main: successor-gap (legacy only)