diff --git a/SCOPE.md b/SCOPE.md index 37598fd..2eff49d 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -19,9 +19,9 @@ Learnings update both SCOPE and INTENT where necessary. |-------|-------| | Code | Python package scaffold (`src/shard_wiki/`, smoke tests only) | | Intent | `INTENT.md` established; authorization-in-core amendments drafted | -| Research | yawex prior art; c2 origins; federation concepts; wikiengines overview (`research/260608-*/`); XWiki/TWiki/Foswiki deep dives (`research/260613-*/`); Xanadu + ZigZag + Roam + Obsidian + Notion + Joplin + Logseq + local-first workspaces (Anytype/AFFiNE/AppFlowy) + Trilium + Wiki.js + Federated Wiki + Wikibase + git-forge wikis + TiddlyWiki + ikiwiki + Quip deep dives & shard-spectrum synthesis (`research/260614-*/`) | +| Research | yawex prior art; c2 origins; federation concepts; wikiengines overview (`research/260608-*/`); XWiki/TWiki/Foswiki deep dives (`research/260613-*/`); Xanadu + ZigZag + Roam + Obsidian + Notion + Joplin + Logseq + local-first workspaces (Anytype/AFFiNE/AppFlowy) + Trilium + Wiki.js + Federated Wiki + Wikibase + git-forge wikis + TiddlyWiki + ikiwiki + Quip + MojoMojo deep dives & shard-spectrum synthesis (`research/260614-*/`) | | Demand | NetKingdom integration asks captured, not yet negotiated | -| Spec | Architecture blueprint drafted; UseCaseCatalog 80 UCs from research; PRD/TSD scaffolds | +| Spec | Architecture blueprint drafted; UseCaseCatalog 81 UCs from research; PRD/TSD scaffolds | | Work | `SHARD-WP-0001` active (6 tasks); `SHARD-WP-0002` active (16 tasks: T1–T10 federation + T11–T16 adapter contract); `SHARD-WP-0003` active (9 engine dives); `SHARD-WP-0004` active (8 computational-knowledge dives) | ## In Scope (today) diff --git a/research/260614-mojomojo-deep-dive/README.md b/research/260614-mojomojo-deep-dive/README.md new file mode 100644 index 0000000..d0d9271 --- /dev/null +++ b/research/260614-mojomojo-deep-dive/README.md @@ -0,0 +1,15 @@ +# 260614 — MojoMojo deep dive + +Deep dive on **MojoMojo**: a **Perl Catalyst / DBIx::Class** DB-backed wiki — hierarchical +pages, attachments, inline (AJAX) editing, Markdown content, and **page history in +relational version tables**. The classic **MVC DB-backed** contrast to the file-store +classics: no file store, no real content API → attach by reading the **relational store +directly**. + +- `findings.md` — architecture, the DB schema shape, capability profile, INTENT mapping, UC + seed (UC-81), architecture notes for SHARD-WP-0002, open questions, sources, traceability. + +Catalog yield: UC-81 (attach a **DB-backed wiki with no file store/API** by reading its +relational store directly — pages + version tables — and importing DB-resident history to the +journal). Enriched UC-02/40/36/34. Feeds SHARD-WP-0002 T13 (history portability), T14 +(direct-DB binding). diff --git a/research/260614-mojomojo-deep-dive/findings.md b/research/260614-mojomojo-deep-dive/findings.md new file mode 100644 index 0000000..0677035 --- /dev/null +++ b/research/260614-mojomojo-deep-dive/findings.md @@ -0,0 +1,133 @@ +# MojoMojo — deep dive (findings) + +**Date:** 2026-06-14 · **Source:** SHARD-WP-0003 T8 · **Subject:** MojoMojo, a Perl +Catalyst wiki/CMS. + +## Why this dive + +The file-store classics (TWiki, Foswiki, Oddmuse, UseMod) keep pages as files; the modern +SaaS keep them behind APIs. MojoMojo is the **classic relational-DB-backed** wiki — a +Catalyst MVC app over **DBIx::Class** with pages and their history in **SQL tables**, and +**no file store and no first-class content API**. It anchors the *"attach by reading the +database directly"* hard case the adapter contract must account for (T13/T14). + +## 1. Architecture + +- **Stack:** Perl **Catalyst** (MVC web framework) + **DBIx::Class** (ORM) over a relational + DB (SQLite / PostgreSQL / MySQL). Templating via Template Toolkit. +- **Content:** **Markdown** (Text::MultiMarkdown) is the page markup — so the *body* is + Markdown, but it lives **in a DB column**, not a file. +- **Pages are hierarchical:** a **path tree** (`/parent/child`) modeled as rows with + parent/lineage relations — structure is relational, not directory-based. +- **Versioning:** each page edit creates a **new version row** (a `page_version`-style + table) — full revision history lives in **DB version tables**, with author/timestamp. +- **Features:** inline **AJAX editing**, **attachments** (stored as DB rows / blobs + + metadata), diffs, RSS feeds, full-text search, per-page permissions. + +## 2. The attach problem — DB or nothing + +MojoMojo exposes its content through the **web app** (HTML) and the **database**; there is +**no clean REST/GraphQL content API** and **no file store**. So a shard adapter has two +realistic paths: + +1. **Direct relational read** (preferred): read the `page` + `page_version` (+ `content`, + `attachment`) tables via DBIx::Class schema — pages, the path tree, and **full history** + are all there, importable to the coordination journal (UC-41-style history import, but + from **DB version rows** rather than RCS/git). +2. **HTML scrape** (fallback): parse rendered pages — lossy, last resort. + +This makes MojoMojo the **direct-DB-read** binding archetype: the canonical store is a +relational schema, and the adapter's job is to map that schema to the wiki page model + +journal. + +## 3. Capability profile + +| Dimension (synthesis spectrum) | MojoMojo | +|--------------------------------|----------| +| Attachment mode | **direct DB read** (relational); HTML-scrape fallback; no file store, no API | +| Addressing granularity | page (row); path tree via lineage rows | +| Content identity | DB page id; path as human key | +| Identity vs placement | row id vs path lineage (separable) | +| Structure | **relational**: page rows + parent/lineage; attachments as rows | +| History | **DB version tables** (per-edit version rows, author/timestamp) | +| Merge model | app-level last-writer; DB transactions | +| Native query | SQL over the schema (not a wiki query language) | +| Translation | **Markdown body in a DB column** — minimal translation, but extraction needed | +| Write granularity | page (row) per save | +| Operational envelope | a Perl app + its DB; direct DB access needs credentials | +| Access grant | per-page permissions in DB; app auth | +| Content opacity | transparent if you can read the DB | +| Provenance | author/timestamp on version rows | + +## 4. INTENT mapping + +### Reinforcements + +- **Backend-neutral page model**: the body is **Markdown** — once extracted from the DB + column it maps directly; the adapter's work is **schema→page-model**, not format + translation. +- **History portability** (T13): DB **version rows** are a third history-source shape beside + git commits and RCS files — importable to the journal as discrete revisions with + author/timestamp. +- **Graceful degradation**: even with only DB read (no API), MojoMojo is a usable + read/projection/backup shard; with DB write it could be write-through, but carefully + (app invariants). + +### Divergences (boundaries / notes) + +- **No file store, no API** ⇒ the **direct-DB-read** binding is a first-class attach mode the + contract must name (alongside file-store, in-engine host, external-API, CRDT, P2P) — or a + sub-mode of "external store" where the medium is **a relational schema** (T14). Reading a + third-party app's DB is **coupling to its schema** (versioned, may drift across MojoMojo + versions) — a stated risk (UC-43 backend-swap analogue at the schema level). +- **Writing by direct DB** risks violating app invariants (lineage, version counters, + search index) — default to **read/projection/overlay**; write-through only with the app's + cooperation. + +### What to keep + +1. **Direct-DB-read as a named binding** for DB-backed engines with no file/API (UC-81), + mapping a **relational schema → wiki page model + journal**. +2. **DB version rows as a history source** for the journal (T13), beside git and RCS. +3. **Schema-coupling caution** — treat the schema as a versioned interface that can drift + (relates UC-43). + +## 5. UC seed + +| # | Seed | Disposition | +|---|------|-------------| +| UC-81 | Attach a **DB-backed wiki with no file store / no API** (MojoMojo) by reading its **relational store directly** (page + version tables), mapping schema → page model and **importing DB-resident history** to the journal | **new** | +| — | DB attach vs file attach | enrich **UC-02** / **UC-40** | +| — | DB version-table history import | enrich **UC-36** | +| — | relational page rows / lineage as structure | enrich **UC-34** | + +## 6. Architecture notes for SHARD-WP-0002 + +- **T14 (binding):** add **direct relational read** as a binding (or external-store sub-mode + whose medium is a SQL schema) for DB-backed engines lacking a file store or API; HTML + scrape is the lossy fallback. Schema is a **versioned coupling** (drift risk, UC-43). +- **T13 (history portability):** **DB version rows** = a history source alongside git commits + and RCS revisions — import as discrete journal entries (author/timestamp). +- **T11 (capability):** "has-file-store" / "has-API" are **absent** here; "has-readable-DB" + is the capability — a sparse profile relying on schema knowledge. + +## 7. Open questions + +1. Does shard-wiki sanction **direct third-party DB reads** as a binding, or restrict them + (schema coupling/drift) to a documented best-effort mode? How is schema drift across + MojoMojo versions handled (UC-43)? +2. Is **write-through by direct DB** ever allowed (risking app invariants), or are DB-backed + no-API engines read/projection/overlay/backup only? + +## 8. Sources + +- MojoMojo — github.com/mojomojo/mojomojo; metacpan MojoMojo (Catalyst app, DBIx::Class + schema: Page / PageVersion / Content / Attachment) +- Catalyst + DBIx::Class framework docs (architecture context) +- prior: `research/260613-twiki-deep-dive/` (file-store classic contrast, UC-40/41) + +## 9. Traceability + +New UC **UC-81** carries the marker **⊙** in the wikiengines column of +`spec/UseCaseCatalog.md`. Enriched: UC-02, UC-40, UC-36, UC-34. Architecture cross-refs: +SHARD-WP-0002 T14 (direct-DB binding), T13 (DB version-row history), T11. diff --git a/research/README.md b/research/README.md index 07f95f5..5f2337e 100644 --- a/research/README.md +++ b/research/README.md @@ -33,4 +33,5 @@ when multiple files or sources are involved. Findings here inform `spec/` and | 2026-06-14 | `260614-forge-wikis-deep-dive/` | Gitea · GitLab · GitHub wikis — a wiki is a separate `.wiki.git` of Markdown; git-clone universal, wiki API capability-varying (GitHub git-only); git IS the store (resolves UC-68 race); the home case; UC-76/77 | | 2026-06-14 | `260614-tiddlywiki-deep-dive/` | TiddlyWiki — entire wiki (content + app) in one self-contained HTML file = whole-file write-granularity extreme; Node `.tid` file-per-tiddler substrate (git-diffable); tiddler/field records, filter-expression query; UC-78 | | 2026-06-14 | `260614-ikiwiki-deep-dive/` | ikiwiki — wiki compiler: git-canonical Markdown source → static HTML (derived publish/projection); git-distributed clone federation + XML-RPC pinger (third federation flavor); UC-79 | -| 2026-06-14 | `260614-quip-deep-dive/` | Salesforce Quip — closed-SaaS live docs + embedded spreadsheets/live apps; REST + lossy HTML import/export; Salesforce enterprise ACL; external-API payload-format facet + inline-object page model; UC-80 | \ No newline at end of file +| 2026-06-14 | `260614-quip-deep-dive/` | Salesforce Quip — closed-SaaS live docs + embedded spreadsheets/live apps; REST + lossy HTML import/export; Salesforce enterprise ACL; external-API payload-format facet + inline-object page model; UC-80 | +| 2026-06-14 | `260614-mojomojo-deep-dive/` | MojoMojo — Perl Catalyst/DBIx::Class DB-backed wiki; pages + history in SQL tables, no file store/API → direct-DB-read binding; DB version rows as history source; UC-81 | \ No newline at end of file diff --git a/spec/UseCaseCatalog.md b/spec/UseCaseCatalog.md index 6cbe04c..f4ec95a 100644 --- a/spec/UseCaseCatalog.md +++ b/spec/UseCaseCatalog.md @@ -17,7 +17,8 @@ Promoted from `research/260608-c2-wiki-origins/`, `research/260614-forge-wikis-deep-dive/`, and `research/260614-tiddlywiki-deep-dive/`, and `research/260614-ikiwiki-deep-dive/`, and -`research/260614-quip-deep-dive/`. +`research/260614-quip-deep-dive/`, and +`research/260614-mojomojo-deep-dive/`. See InfoTechPrimers on coulomb.social for use-case catalog conventions. ## Conventions @@ -52,7 +53,11 @@ history, not gatekeeping. Aligns with L0 in `spec/ArchitectureBlueprint.md`. **Goal:** Attach a repository, directory, or other backend as a shard of a root entity. **Source:** intent, yawex **Notes:** yawex `Conf::TestWiki / FriendsWiki` foreshadows multiple roots/shards. -Preserve shard sovereignty and adapter capability profile. +Preserve shard sovereignty and adapter capability profile. Attach paths now span a wide +range: file-store clone (UC-40/UC-76), in-engine host (UC-38/50), external-API (UC-57/80), +CRDT-replica (UC-64), P2P (UC-65), and — for a **DB-backed engine with no file store/API** — +**direct relational read** of its schema (UC-81, +`research/260614-mojomojo-deep-dive/findings.md` §2). **Priority:** MVP ### UC-03 — Project a remote shard page locally @@ -1121,6 +1126,24 @@ lossy export. Feeds SHARD-WP-0002 T11 (payload-format + content-opacity), T12 (i objects), T14. **Priority:** Later +### UC-81 — Attach a DB-backed wiki with no file store/API by reading its store directly + +**Actor:** Maintainer / adapter +**Goal:** Attach a **relational-DB-backed wiki with no file store and no content API** +(MojoMojo) by **reading its database directly** — mapping the **page + version tables** to +the wiki page model and **importing DB-resident history** to the coordination journal. +**Source:** wikiengines, intent +**Notes:** MojoMojo is a Perl Catalyst / DBIx::Class app whose pages, path tree, and full +revision history live in **SQL tables** (`page`/`page_version`/`content`/`attachment`); the +body is **Markdown in a column** (`research/260614-mojomojo-deep-dive/findings.md` §1, §2). +The **direct-DB-read** binding is the archetype for DB-backed engines lacking file/API +access (HTML scrape is the lossy fallback). **DB version rows** are a third history source +beside git commits and RCS files (T13). Caution: reading a third-party schema is a +**versioned coupling** that can drift across engine versions (UC-43); writing by direct DB +risks app invariants → default read/projection/overlay. Feeds SHARD-WP-0002 T14 (direct-DB +binding), T13. +**Priority:** Later + --- ## B. Knowledge work and collaboration @@ -1398,6 +1421,7 @@ CamelCase and `[[free links]]`. Markdown-first link semantics TBD. | UC-78 | | | | ⊡ | ✓ | | UC-79 | | | ✓ | ⊟ | ✓ | | UC-80 | | | | ◧ | ✓ | +| UC-81 | | | | ⊙ | ✓ | | UC-08 | ✓ | | | | UC-09 | ✓ | | | | UC-10 | ✓ | | | @@ -1985,6 +2009,31 @@ default to read/projection/overlay given rate limits + lossy export. Architectur lossy-exportable" content-opacity tier, inline-embedded-object page model, enterprise-ACL binding. +### mojomojo mapping + +(⊙ UC-81 lineage = the **MojoMojo deep dive**, `research/260614-mojomojo-deep-dive/findings.md`.) + +| MojoMojo mechanism (findings §) | Catalog UC | +|---------------------------------|------------| +| Catalyst/DBIx::Class app; pages + history in SQL tables; no file store/API (§1, §2) | UC-81 (new) | +| Direct relational read (page/version tables) vs file attach (§2) | UC-02 / UC-40 (enriched) | +| DB version rows = history source for the journal (§1, §4) | UC-36 (enriched) | +| Relational page rows + parent/lineage as structure (§1) | UC-34 (enriched) | +| Markdown body in a DB column → extract, minimal translation (§1) | links UC-42 | +| Schema is a versioned coupling that can drift (§4) | links UC-43 | + +Note: MojoMojo is the **classic relational-DB-backed wiki** — a Perl Catalyst / DBIx::Class +app whose pages, path tree, and full revision history live in **SQL tables**, with **no file +store and no content API**. It anchors the **direct-DB-read** binding: the canonical store is +a relational schema, and the adapter maps **schema → wiki page model + journal** (the body is +**Markdown in a column**, so extraction not format-translation is the work). **DB version +rows** become a third **history source** beside git commits and RCS files (T13). **Boundary +recorded:** reading a third-party schema is a **versioned coupling** that can drift (UC-43), +and writing by direct DB risks app invariants → default read/projection/overlay; HTML scrape +is the lossy last resort. Architecture logged for `SHARD-WP-0002` (T14/T13/T11): direct-DB +binding (or external-store-via-SQL-schema sub-mode), DB-version-row history import, sparse +"has-readable-DB" capability profile. + --- ## Open questions @@ -2063,5 +2112,9 @@ binding. sub-object with provenance (preferred) or a flattened static Markdown table — can overlays target a spreadsheet cell or only prose — and given HTML-only lossy interchange, is Quip ever write-through or read/projection/overlay/backup by default? (Quip dive §8.) +29. Does shard-wiki sanction **direct third-party DB reads** as a binding (UC-81), or + restrict them (schema coupling/drift, UC-43) to a best-effort mode — and is + **write-through by direct DB** ever allowed, or are DB-backed no-API engines + read/projection/overlay/backup only? (MojoMojo dive §7.) 23. How does shard-wiki **honor/surface a shard's path-based access rules** (UC-06) in a projection without re-implementing its ACL engine? (Wiki.js dive §9.) \ No newline at end of file diff --git a/workplans/SHARD-WP-0003-engine-dives-batch.md b/workplans/SHARD-WP-0003-engine-dives-batch.md index 951be84..5f17f0a 100644 --- a/workplans/SHARD-WP-0003-engine-dives-batch.md +++ b/workplans/SHARD-WP-0003-engine-dives-batch.md @@ -164,7 +164,7 @@ profile). ```task id: SHARD-WP-0003-T8 -status: todo +status: done priority: low state_hub_task_id: "42222ccd-4b91-4dfa-900d-3b94e1f246f4" ```