75 lines
4.2 KiB
Markdown
75 lines
4.2 KiB
Markdown
<!-- SPDX-License-Identifier: MPL-2.0 -->
|
|
|
|
# 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.
|