Skip to content

feat(core-ts,api,renderer): collection invariants, registry API, feed/sitemap (RFC-0040 step 2) - #85

Merged
Madraka merged 1 commit into
mainfrom
feat/collections-store
Oct 22, 2026
Merged

Madraka merged 1 commit into
mainfrom
feat/collections-store

Conversation

@Madraka

@Madraka Madraka commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

RFC-0040 / ADR-0042, step 2 of 4. Stacked on #84; GitHub retargets it to main once #84 merges.

Store (store/collection-paths.ts, new):

  • New collection: the first entry of a new collection, or an entry moved into one, claims its default prefix /<collection>. It is refused when that prefix overlaps:

    • another collection's permalink (path_conflict);
    • a taxonomy archive (path_conflict);
    • /search, media or a locale prefix (reserved_path).

    The SQL race guards (configuredPrefixFree, noArchiveOverlapping) join the entry's batch. This closes RFC-0038's gap.

  • Site update:

    • declaring a new key without a permalink runs the same check;
    • a declared key that still has entries, or that a taxonomy names, cannot be dropped (collection_in_use), with a NOT EXISTS guard on the CAS.
  • Not enforced here: the store does not require a declaration, so push, import and seed keep working.

API:

  • GET /api/sites/:id/collections (content:read)
  • PUT /:key { settings, rev } (site:settings, ?dryRun=1)
  • DELETE /:key?rev= (site:settings)
  • POST entries into an unregistered collection fails with 422 collection_undeclared.
  • The new routes are in the scope table and the playground allow-list.

Renderer:

  • Feeds leave out collections with feed: false, and the sitemap leaves out those with sitemap: false. The defaults are unchanged.
  • collectionLabel and collectionSettings are re-exported from ./routing (additive only).

Permalink reset keeps the declaration:

  • MCP set_collection_permalink's nextSite and Studio's withPrefixes keep {};
  • the RFC-0038 tests were updated to match;
  • the new error codes get MCP hints.

Tests, one package at a time:

  • core-ts: the RFC-0038 and RFC-0040 suites, 48/48 on sqlite, D1 and DO. The rest of the suite passes except the Durable Object search tests, which hit local EADDRNOTAVAIL (machine port exhaustion, as in feat(contracts,core-ts): collection registry (RFC-0040 step 1) #84).
  • astro-renderer: 258/258.
  • api: 393/393 after the playground fix.
  • mcp-server: 145/145.
  • Studio: collection-settings 3/3.
  • cli: old-theme-compat ✓.

Also: biome errors clean, size:check ok, changeset added.

Refs #71

🤖 Generated with Claude Code

…/sitemap (RFC-0040 step 2)

Store: the first entry of a new collection (or an entry moved into one)
claims its default prefix and is refused with path_conflict or
reserved_path when it overlaps a configured permalink, a taxonomy
archive, /search or a locale prefix, with SQL race guards in the
entry's batch; this closes RFC-0038's gap. A site update that declares
a collection runs the same check, and a declared collection with
entries or named by a taxonomy cannot be undeclared
(collection_in_use).

API: GET/PUT/DELETE /api/sites/:id/collections (content:read,
site:settings), PUT with ?dryRun=1; entries in a collection outside the
registry are refused (collection_undeclared, 422). Allowed in the
playground.

Renderer: feed:false and sitemap:false keep a collection out of feeds
and sitemap.xml; collectionLabel/collectionSettings re-exported.

Permalink reset (MCP set_collection_permalink, Studio) keeps the
collection declared.

Refs #71 (RFC-0040, ADR-0042)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
@Madraka
Madraka force-pushed the feat/collections-store branch from 2d14fcc to 3c4453e Compare October 22, 2026 19:38
Base automatically changed from feat/collections-contract to main October 22, 2026 19:53
@Madraka
Madraka merged commit 97ec88e into main Oct 22, 2026
4 checks passed
@Madraka
Madraka deleted the feat/collections-store branch October 22, 2026 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant