Add revision-aware CMS taxonomies and relationships
This commit is contained in:
+74
@@ -0,0 +1,74 @@
|
||||
<!-- 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.
|
||||
@@ -8,6 +8,15 @@ application concern belongs in the shared module.
|
||||
|
||||
## Gamertan accounts and commerce
|
||||
|
||||
- Typed content needs shared categories and relationships without becoming a
|
||||
page builder. The `cms`/`cmssqlite` boundary separates application-owned bodies
|
||||
and products from immutable editorial associations. Keeping associations and
|
||||
publication in the content transaction prevents a draft save from changing
|
||||
public reverse links. Stable references avoid rewriting purchases on a project
|
||||
rename. Consumer HTTP tests caught compiled article snapshots shadowing CMS
|
||||
revisions and catalog pickers showing newer draft titles; those are application
|
||||
routing/visibility responsibilities, not extra policy in this package.
|
||||
|
||||
- Personal identity editing is not instance administration. `OwnProfileRepository`
|
||||
derives self-access from the active session; `ProfileEdit` is a trusted internal
|
||||
command, never a browser request model. SQLite schema 11 adds a monotonic
|
||||
|
||||
@@ -26,7 +26,7 @@ The packages are ordinary Go imports. Pin the current preview and verify its
|
||||
module checksum:
|
||||
|
||||
```bash
|
||||
go get gamertan.com/web/requestmeta@v0.1.0-preview.26
|
||||
go get gamertan.com/web/requestmeta@v0.1.0-preview.27
|
||||
go mod verify
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user