Files
shard-wiki/research/260613-twiki-deep-dive/findings.md
tegwick ffd5459b3e research: TWiki deep dive (impl, plugin API, ecosystem); UC-40/41
Deep dive into TWiki as the file-based Perl counterpoint to XWiki: flat-file +
RCS store (data/<Web>/<Topic>.txt), Webs/Topics, TWiki Forms storing fields as
%META% in the topic text, TWikiML/variables, TWiki::Func API; the plugin handler
callback surface (initPlugin, commonTagsHandler, before/afterSaveHandler,
afterRenameHandler, REST handlers) and package types (Plugin/Skin/AddOn/Contrib);
per-topic ALLOW/DENY access control (origin of yawex's model); Foswiki fork.

Catalog (now 41 UCs):
- UC-40 attach a file-backed engine's on-disk store directly (dual-path attach)
- UC-41 import an engine's native file history (RCS .txt,v) into the journal
- enrich UC-06 (TWiki per-topic ACL lineage), UC-34 (file-embedded %META%),
  UC-36 (RCS-import vs DB-supplement), UC-38 (TWiki handlers as adapter host)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 23:20:11 +02:00

12 KiB

Findings — TWiki: implementation, plugin API, ecosystem

Date: 2026-06-13 · Status: research draft

Scope: TWiki as prior art for the file-based wiki-application-platform — the counterpoint to XWiki's database/component platform. Two shard-wiki concerns: (1) attaching a structured, file-backed engine as a shard (including attaching its on-disk store directly vs through its runtime), and (2) how TWiki's plugin handler API exposes hooks rich enough to host a federation adapter (INTENT composable integration). Sources: twiki.org dev docs (TWikiPlugins, TWikiForms, TWiki::Func, TWikiAccessControl), Foswiki docs, Wikipedia.

Complements: research/260613-xwiki-deep-dive/ (DB/Java sibling), research/260608-wikiengines-overview/ (landscape), and research/260608-yawex-prior-art/ (yawex borrowed TWiki's per-topic AccessControl).


1. What TWiki is

A structured enterprise wiki and wiki application platform (Peter Thoeny, ~1998), written in Perl 5 (5.10.1+), classically run as CGI. Like XWiki it lets pages become forms/records/apps — but it reaches that with flat text files + RCS, no database. Most of the community forked to Foswiki in October 2008 (from TWiki 4.2.4; Foswiki 1.0 in January 2009); the plugin API and data model below are shared lineage, with minor divergences noted.

2. Implementation architecture

2.1 Storage — flat files + RCS (no DB)

  • Content lives on disk as data/<Web>/<Topic>.txt; the directory tree mirrors the logical Web/Topic hierarchy. Attachments live under pub/<Web>/<Topic>/.
  • History is RCS (<Topic>.txt,v companion files) — the same GNU RCS yawex used. History is real, per-file, and in an open, git-convertible format (unlike XWiki's DB-internal xwikircs).
  • Scales to 300k+ topics on a single server (Yahoo) — file store is not a toy.

2.2 Webs and Topics

  • Topic = page (the unit of content). Web = namespace / collection of topics (can be nested). Webs are the natural shard / root-entity boundary.

2.3 TWiki Forms — structured data, embedded in text

  • A form template is a topic defining fields as a table (one row per field: name, type, size, values). A topic can attach a form; the field values are stored as TWikiMetaData inside the topic .txt (%META:FIELD{...}%), shown as a table on view and edited via fields/radios/checkboxes/lists.
  • Forms + formatted %SEARCH% = TWiki's "database applications" — structured records queried by the SEARCH variable. This is the XWiki XObject/XClass idea, but file-embedded and git-diffable rather than rows in a DB.

2.4 TWikiML / variables (macros)

  • Markup is TWikiML (not Markdown). Dynamic behavior comes from variables %VAR% / %VAR{...}% expanded at render time; %SEARCH% is the query engine.
  • Custom variables are provided by plugins (see §3).

2.5 TWiki::Func — the official API boundary

  • lib/TWiki/Func.pm ("TWikiFuncDotPm") documents all interfaces available to plugins, deliberately abstracting the flat-file assumption: readTopic, saveTopic, getTopicList, getListOfWebs, getWorkArea, saveAttachment, … Plugins are told not to assume flat files and to go through Func.

3. Plugin API — interfaces to extend the core

TWiki extends "without altering core code" by registering Perl handlers that the core calls at defined points in the request/render/save pipeline. A plugin is lib/TWiki/Plugins/<Name>.pm + a documentation topic + an optional Config.spec.

3.1 Handler callbacks (the hook surface)

Phase Handlers
Init / users initPlugin (must return 1), registrationHandler
Tag/variable expansion commonTagsHandler, beforeCommonTagsHandler, afterCommonTagsHandler
Rendering preRenderingHandler, postRenderingHandler (start/endRenderingHandler deprecated)
Edit lifecycle beforeEditHandler, afterEditHandler
Save lifecycle beforeSaveHandler, afterSaveHandler, beforeMergeHandler
Attachments beforeAttachmentSaveHandler, afterAttachmentSaveHandler
Topic mgmt afterRenameHandler, completePageHandler

These are the TWiki analogue of XWiki's ObservationManager events — but synchronous pipeline hooks rather than an async event bus. The save/rename/ attachment handlers are exactly the interception points a federation adapter needs.

3.2 Other extension mechanisms

  • Custom variables/macros — registered via commonTagsHandler (Foswiki adds registerTagHandler); convention %PLUGINNAME_SETTING%.
  • REST handlers — a plugin registers REST handlers invoked via the rest script, for transactions outside the standard view/edit/save scripts. This is the natural remote adapter transport.
  • Config.spec — declares configuration items (BOOLEAN, STRING, SELECT, PATH, PERL) surfaced in the configure web UI.
  • Work areagetWorkArea() gives a plugin a persistent, non-web-accessible data directory.

3.3 Extension package types

Type Role
Plugin handler-based behavior, no core change (lib/TWiki/Plugins/<Name>.pm)
Skin visual appearance only; topic content unchanged (e.g. PrintSkin)
AddOn a script in bin/ callable from a topic
Contrib shared library code, or alternative implementations of core sections (e.g. user management) when something "can't be a plugin because it needs close core access"

4. Access control (origin of yawex's model)

TWiki authorizes via preference settings in topics: ALLOWWEBVIEW / ALLOWWEBCHANGE at web level and ALLOWTOPICVIEW / ALLOWTOPICCHANGE / ALLOWTOPICRENAME (and DENY*) at topic level, with VIEW / CHANGE / RENAME grantable separately. Topic-level settings apply only to that topic. This per-topic ACL is the direct prior art behind yawex's AccessControl (denied/view/form/edit/admin) and a concrete reference for shard-wiki's optional per-page ACL at L4 (spec/ArchitectureBlueprint.md §5).

5. TWiki as a shard — capability profile

Capability TWiki Note
Read TWiki::Func / view script / rest; or read data/*.txt directly
Write saveTopic / save / rest; per-topic granularity
Structured payload TWiki Forms → %META:FIELD% in the text file (git-diffable)
Version/diff RCS .txt,vopen format, git-convertible (cf. XWiki DB)
Merge partial beforeMergeHandler; no git 3-way
Change hooks synchronous save/rename/attachment handlers
Auth model per-web/topic ACL authorize through shard-wiki core; engine ACL is advisory
Direct-store attach ✓✓ data/<Web>/<Topic>.txt + RCS is a folder shard on its own
Federation hooks plugin handlers + REST handlers can host an adapter (UC-38)

6. Mapping to shard-wiki INTENT (compare, do not equate)

6.1 Reinforcements

Observation INTENT principle
Forms store data as %META% in the topic file structured pages can be git-diffable, strengthening UC-34/39 vs XWiki's DB
RCS .txt,v history git-addressable coordination — here history is convertible, not just supplementable (UC-36 → UC-41)
data/<Web>/<Topic>.txt mirrors logic an engine's on-disk store is itself attachable as a folder shard (UC-40)
Plugin save/rename/REST handlers composable integration — TWiki can host an adapter too, generalizing UC-38 beyond XWiki
Per-topic ALLOW/DENY ACL prior art for per-page ACL at L4; lineage TWiki→yawex (UC-06)
Webs as namespaces / shards namespace navigation (UC-22); webs as roots

6.2 Deliberate divergences (design bugs if conflated)

TWiki assumption shard-wiki correction
TWikiML + variable expansion is the page Markdown-first; TWikiML render stays out of core
ACL lives in topic preference settings authorize in core; topic ALLOW/DENY is advisory provenance
History = RCS files next to content coordination journal is the space-level git layer (may import RCS)
Apps = Forms + %SEARCH% rendered by TWiki represent records without depending on TWiki to render/search them
Attach = run TWiki and call it shard-wiki may attach the bare data dir with TWiki offline (UC-40)

6.3 What TWiki teaches that shard-wiki should not lose

  1. File-backed engines are the easy, high-value case — their store is already a folder of text + open-format history; the adapter can often skip the runtime.
  2. Structured data in text beats structured data in a DB for federation — diffable, portable, journal-friendly. Prefer file-embedded metadata where offered.
  3. One backend, two attachment paths (runtime API vs on-disk store) is a real capability/consistency trade-off the adapter contract must express.

7. Use-case seeds → catalog (promoted 2026-06-13)

Seed Catalog UC Disposition
Attach a live engine's on-disk store directly (vs its runtime API) UC-40 (new) dual-path attach; fidelity/consistency trade-off
Import an engine's native file-based history (RCS) into the journal UC-41 (new) history migration with fidelity, vs UC-36 supplementation
Engine hosts adapter via its plugin/handler API UC-38 enriched: TWiki save/rename/REST handlers generalize it beyond XWiki
Structured page carries typed data UC-34 / UC-39 enriched: TWiki Forms %META%, git-diffable
Internal-history engine UC-36 enriched: contrast DB (supplement) vs RCS (import, UC-41)
Authenticated team wiki / per-page ACL UC-06 enriched: TWiki per-topic ACL is the origin of yawex's model

8. Open questions (for spec / workplans)

  1. Dual-path adapters — when does shard-wiki attach an engine's on-disk store directly vs go through its API? Consistency risk of reading live files under a running engine; capability-gate it (UC-40)?
  2. History import fidelity — can RCS .txt,v be converted to git commits preserving author/timestamp, and is that authoritative or a one-time backfill feeding the coordination journal (UC-41, cf. UC-36 Q3)?
  3. File-embedded metadata mapping — map TWiki %META:FIELD% (and XWiki XObjects) onto one structured-metadata page-model representation (shared with xwiki §8 Q1).
  4. TWiki vs Foswiki — target both via one adapter (shared API) or treat as distinct shard types?
  5. ACL provenance — surface a topic's ALLOW/DENY as read-only provenance even though authorization is decided in core?

9. Sources

Source URL
TWiki — TWikiPlugins (handlers, package types) https://twiki.org/cgi-bin/view/TWiki/TWikiPlugins
TWiki — Developing Plugins / EmptyPlugin https://twiki.org/cgi-bin/view/TWiki/TWikiPlugins
TWiki — TWiki::Func module https://twiki.org/cgi-bin/view/TWiki/TWikiFuncModule
TWiki — TWiki Forms https://twiki.org/cgi-bin/view/TWiki/TWikiForms
TWiki — TWiki Access Control https://twiki.org/cgi-bin/view/TWiki/TWikiAccessControl
TWiki — System Requirements (Perl/RCS) https://twiki.org/cgi-bin/view/TWiki/TWikiSystemRequirements
TWiki — Source Code https://twiki.org/cgi-bin/view/TWiki/SourceCode
Foswiki — Why this fork https://foswiki.org/Home/WhyThisFork
Wikipedia — TWiki https://en.wikipedia.org/wiki/TWiki
Wikipedia — Foswiki https://en.wikipedia.org/wiki/Foswiki
shard-wiki — XWiki deep dive research/260613-xwiki-deep-dive/findings.md
shard-wiki — yawex prior art research/260608-yawex-prior-art/findings.md

10. Traceability

This document section Informs (future)
§2 architecture adapter design for file-backed engines
§3 plugin handlers UC-38 engine-side adapter; composable-integration API shape
§4 access control per-page ACL at L4 (spec/ArchitectureBlueprint.md), UC-06
§5 capability profile adapter capability-profile vocabulary (SHARD-WP-0002)
§6 INTENT mapping architecture-blueprint guardrails
§7 UC seeds spec/UseCaseCatalog.md (UC-40, UC-41; UC-06/34/36/38/39 enrichment)
§8 open questions spec — dual-path adapters, history import, structured-metadata model