Files
web/docs/CMS.md
T

4.2 KiB

Classification without a page builder

cms defines small editorial values. cmssqlite stores them in caller-owned SQLite transactions. Neither package owns your content, router, templates, permissions or billing model. Use them alongside typed Go records and coded templates, not as a database-defined application builder.

Two distinct relationships

  • A taxonomy names a flat vocabulary, such as Categories or Topics. A term has a stable ID, editable name/description and an address. Renaming its address preserves aliases; retiring it hides discovery without rewriting old revisions.
  • An explicit link joins two {kind, id} references. Related reads that single edge in either direction. Sharing a term alone does not assert a link.

References contain no titles, URLs, application data or authorization. Resolve each public result through the owning repository using its current published revision and availability. Never render the latest draft merely because an older revision is published. Products may have additional availability/approval rules; editorial links do not bypass them or change prices, entitlements or purchases.

Transactions and publication

Call CreateSchema(ctx, tx) during an explicit application migration. It creates the gwf_cms_* tables, independently of the authentication adapter's schema. There is no automatic migration, connection, worker or request middleware. Enable foreign keys on every connection and use the application's existing SQLite write discipline. Keep backups and schema compatibility in that owner.

Every reader/writer takes a validated namespace. A namespace separates data; it does not authorize the caller. Check permissions before reads and inside the application's mutation boundary where concurrent revocation matters.

Within the same transaction as your content revision and audit:

  1. PutRevision stores the exact revision's immutable term/link selections.
  2. For publication, SetPublished points at that revision. Zero unpublishes.
  3. Commit content, associations, publication and audit together.

Saving a draft does not advance publication. Restore by copying the selected historical association document into a new revision, then publish separately. Terms must exist in the namespace; retired terms remain valid historical values. Applications decide which retired selections may be retained in new edits. External targets can be indexed with an empty published snapshot, but their owning module still determines whether a public link is available.

Taxonomy/term writes use expected revisions (zero for creation). Keep immutable IDs across name changes. Taxonomy addresses are fixed after creation; term addresses retain redirect history. A collision or stale revision returns cms.ErrConflict, not a successful overwrite. Transactions must be rolled back after any mutation error, including a later application audit failure.

Bounds and discovery

  • Each snapshot accepts at most 24 distinct terms and 16 distinct links, without self-links. Validation rejects invalid IDs, control characters and duplicate selections. Text fields have explicit byte bounds; names are not HTML.
  • A namespace has at most 100 taxonomies. Terms pages by stable term ID, at most 200 results per request. Applications should choose their own overall editor limits and search UI rather than loading an unbounded catalog.
  • Members and Related return at most 100 published references per page, ordered by kind/ID. Pass Next for the following page. Publication filtering happens before pagination; never use a mutable title as a cursor.
  • Owning-module visibility can filter further. Continue fetching bounded index pages to fill a visible page and construct a cursor from the last visible item; do not expose private titles or identifiers through error messages.

The package tests use real SQLite transactions, including WAL, race execution, scope isolation, delayed publication, reverse discovery, aliases, retirement, pagination and rollback. Consumer tests still need to prove actual HTTP/API permissions, public visibility, escaping, editor usability and application data preservation. These packages do not claim to provide an entire CMS.