Skip to content

Do not serve a collection that requires an unsupported feature - #103

Open
harmony7 wants to merge 2 commits into
mainfrom
feat/index-metadata-requires
Open

harmony7 wants to merge 2 commits into
mainfrom
feat/index-metadata-requires

Conversation

@harmony7

@harmony7 harmony7 commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Summary

The CLI that publishes and the server in the deployed Wasm binary can have different versions. For example, a user installs a later version and publishes, but does not deploy the app again. Or a staged service version, a rolled-back version, or a second app reads the same storage. If a later version adds a feature that changes the index, the settings, or the key layout, an older server does not recognize the updated data structure and serves the collection incorrectly.

This PR adds a check to the server, so that later features can make older servers fail closed. The check must be in 8.0, so that all 8.x servers have it.

Changes

  • IndexMetadata.requires (src/models/server/index.ts): the features that the server must support to serve the collection. It is stored as a comma-separated string in the metadata of the index entry, for example hidden,brotli-dictionary. Thus a feature name must not contain a comma. encodeIndexMetadata() throws if it does. A later CLI adds a feature only if the published content uses it. Thus, if the content does not use a new feature, older servers continue to serve it.
  • Server check (src/server/publisher-server/index.ts): if requires has a feature that is not in SUPPORTED_INDEX_FEATURES, the server does not serve the collection (the same result as a collection that does not exist), and it logs the features. The check applies to all collections, also the default collection. SUPPORTED_INDEX_FEATURES is empty in this version, and nothing writes requires yet.
  • Keep unknown fields: decodeIndexMetadata() keeps the fields that it does not know, and encodeIndexMetadata() writes them again. Before, collections promote and collections update-expiration removed them. Without this change, an 8.0 promote of a collection that a later version published would remove requires from the copy, and the copy would fail open.
  • collections list shows requires, and a warning if this version does not support a feature.
  • CLAUDE.md: how to add a feature.

Why feature names and not a minimum version: with a minimum version, the CLI must set it at each publish. Then a CLI upgrade without a deploy stops the site, also if the content does not use a new feature.

The first user of this will probably be hidden files (#102).

Tests

  • Unit tests (test/unit/metadata.test.js): decode and encode, lowercase keys (S3), unknown fields, getUnsupportedIndexFeatures(), and the comma rule.
  • End-to-end test (test/e2e/local.test.js): publish with --local, add requires: 'future-feature' and an unknown field to the index metadata, promote the collection, and serve. The server returns 404, promote keeps both fields, and collections list shows the feature. Without the source changes, all three tests fail.
  • npm test: 83 pass. Local end-to-end tests: 18 pass.

🤖 Generated with Claude Code

@harmony7

Copy link
Copy Markdown
Member Author

The value of this comes later: when 8.1 or 8.2 adds the first feature, every server from 8.0 on already knows to refuse content it can't serve correctly, and every 8.0 CLI keeps the new fields when it promotes or updates a collection.

@harmony7
harmony7 requested review from a team and kailan and removed request for a team October 17, 2026 08:35
harmony7 and others added 2 commits October 22, 2026 09:15
The CLI that publishes and the server in the deployed Wasm binary can
have different versions. If a later version adds a feature that changes
the index, the settings, or the key layout, an older server ignores the
change and serves the collection incorrectly.

Add "requires" to IndexMetadata: the features that the server must
support to serve the collection. A later CLI adds a feature only if the
published content uses it. PublisherServer does not serve a collection
that requires a feature that is not in SUPPORTED_INDEX_FEATURES. This
version supports no features, and nothing writes "requires" yet. The
check must be in 8.0, so that 8.x servers have it.

decodeIndexMetadata() now keeps the fields that it does not know, so
that promote and update-expiration do not remove "requires" or fields
that a later version adds. collections list shows "requires".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The metadata keeps the names as one string, separated by commas.
encodeIndexMetadata() now throws for a name with a comma. Document the
rule in the code and in CLAUDE.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@harmony7
harmony7 force-pushed the feat/index-metadata-requires branch from b3bd98a to 19a04fc Compare October 22, 2026 00:17
@harmony7
harmony7 requested a review from kpfleming October 22, 2026 09:22
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