Skip to content

feat: typed custom fields contract and checker (RFC-0041 step 1) - #94

Merged
Madraka merged 1 commit into
mainfrom
feat/fields-contract
Oct 22, 2026
Merged

Madraka merged 1 commit into
mainfrom
feat/fields-contract

Conversation

@Madraka

@Madraka Madraka commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Step 1 of RFC-0041's rollout (ADR-0043). No behaviour change: nothing reads the new module yet.

Contract

  • site.schema.json gains an optional CollectionSettings.fields (1–30 items).
  • FieldDefinition is a oneOf of nine variants with discriminator type: text, richText, number, boolean, date, datetime, url, image, select. Labels, options and the migration marker are new $defs.
  • content-entry.schema.json changes only the fields description.
  • Fixtures: 2 valid (every type and option, plus a minimal one) and 28 invalid. TS and Rust are regenerated; Rust emits #[serde(tag = "type", deny_unknown_fields)] enum FieldDefinition.

@cloudhal/core-ts/fields (Worker-safe, eval-free, rule 6)

  • checkFieldDefinitions and fieldDefinitionChanges: reserved keys, uniqueness, caps (30 per collection, 200 per site, 256 KB for collections), and the §6 guard (field_change_needs_operation).
  • fieldsPropsSchema plus checkFieldValues: compiled to ADR-0030's props subset for validateProps, with per-type checks (date, datetime {at, timeZone}, URL schemes, asset id, select), changed-only checking, refusal of unknown keys, and the 256 KB cap.
  • checkRequiredToPublish: for review and publish.
  • fieldsJsonSchema: limited to what OpenAI and Anthropic strict modes accept, with a golden file.
  • resolveFields: localized values fall back to the original's (fromOriginal); non-localized values come from the original.

Decisions where the RFC was ambiguous

  • validateProps caps strings at 10,000 characters, so the 50,000 limit for richText is checked in code.
  • Removing a key or option needs counting stored values, which fieldDefinitionChanges reports for step 2.
  • The value conversion table is left to step 3.

Checks

  • core-contracts: 478 tests.
  • New field tests: 82.
  • cargo test and clippy pass.
  • Packaging, size check and no drift pass.

Changeset: minor, like RFC-0040 step 1, so this moves the fixed group to 0.5.0.

🤖 Generated with Claude Code

…C-0041 step 1)

- site.schema.json: optional CollectionSettings.fields (1–30), the
  FieldDefinition union of nine types with discriminator `type`
  (ADR-0043), labels, options and the migration marker; 2 valid and
  28 invalid fixtures; TS and Rust regenerated.
- @cloudhal/core-ts/fields (Worker-safe, eval-free): definition checks
  and caps, compiling to ADR-0030's props subset for validateProps,
  per-type value checks, the requiredToPublish check, a JSON Schema
  for agents within OpenAI and Anthropic strict modes, and
  resolveFields for localization.

Nothing reads the module yet: no behaviour change. 82 new tests;
cargo test and clippy pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
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