generated from coulomb/repo-seed
research: MojoMojo deep dive (Perl Catalyst DB-backed wiki); UC-81
SHARD-WP-0003 T8. Classic relational-DB-backed wiki: Catalyst/DBIx::Class app, pages + path tree + full history in SQL tables, Markdown body in a column, no file store and no content API. Anchors the direct-DB-read binding (map schema -> page model + journal); DB version rows = a third history source beside git commits and RCS files. UC-81. Enriched UC-02/40/36/34. Marks T8 done. Feeds SHARD-WP-0002 T14/T13/T11. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
15
research/260614-mojomojo-deep-dive/README.md
Normal file
15
research/260614-mojomojo-deep-dive/README.md
Normal file
@@ -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).
|
||||
133
research/260614-mojomojo-deep-dive/findings.md
Normal file
133
research/260614-mojomojo-deep-dive/findings.md
Normal file
@@ -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.
|
||||
@@ -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 |
|
||||
| 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 |
|
||||
Reference in New Issue
Block a user