Skip to content

RFC-0041 / ADR-0043: Typed custom fields per collection (accepted) - #93

Merged
Madraka merged 2 commits into
mainfrom
rfc/typed-custom-fields
Oct 22, 2026
Merged

Madraka merged 2 commits into
mainfrom
rfc/typed-custom-fields

Conversation

@Madraka

@Madraka Madraka commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Stage 2 of #71, written from RFC-0040's "Stage 2 (sketch)". Status: Draft, open for discussion; nothing is implemented.

Key decisions

  • Contract: optional Site.collections.<key>.fields, 1–30 definitions in nine types: text, richText, number, boolean, date, datetime ({at, timeZone}, RFC-0008), url, image (an asset id of the same site), select. No schemaVersion bump.
  • Values stay in ContentEntry.fields, up to 256 KB per entry.
  • Checker: one eval-free module, @cloudhal/core-ts/fields, built on validateProps (ADR-0030), checks values for the store, API and MCP. It also emits a JSON Schema that OpenAI and Anthropic strict modes both accept.
  • requiredToPublish is checked at review and publish, like required_term; drafts save freely.
  • Localization: decided per field up front. Non-localized values live on the translation group's original only.
  • Where definitions live: on the site node, capped at 200 fields per site and 256 KB for collections, from size measurements. A Collection node kind is the fallback.
  • Changing definitions: a plain edit can never lose data. rename_field, change_field_type, set_field_localized and remove_field are explicit operations, each with a dry run, a snapshot and approval, applied in guarded batches.
  • Studio: a lazy generated form and a fields builder; +0 kB on the initial load.
  • MCP: list_collections returns field schemas and create_entry/update_entry check fields in precheck. There are four new tools and no new scopes.
  • Renderer: additive API (resolveFields, EntryFields.astro), so old themes keep working.
  • Rollout: six PRs.

Schema check: the diff was applied with fixtures. pnpm gen (TS + Rust) and the fixture tests passed, then it was reverted. One finding: Rust writes 0 as 0.0, so the Rust core will need canonical number output (RFC 8785) before it writes nodes.

The 10 open questions, with recommended defaults, are at the end of the RFC.

🤖 Generated with Claude Code

Stage 2 of #71, from RFC-0040's sketch: nine closed field types on
Site.collections.<key>.fields, values in ContentEntry.fields, one
eval-free checker for store, API and MCP, requiredToPublish, per-field
localization, and explicit snapshotted operations for rename, type
change, localization change and removal. The schema diff was checked
with pnpm gen (TypeScript and Rust) and reverted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
@Madraka Madraka added the rfc A design proposal in docs/rfcs label Oct 22, 2026
Halil accepted RFC-0041 with every open question decided as
recommended. ADR-0043 records the decision. AGENTS.md rule 2 and the
contract-change skill now allow a domain discriminator other than
`kind` (field definitions use `type`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
@Madraka Madraka changed the title RFC-0041: Typed custom fields per collection (draft) RFC-0041 / ADR-0043: Typed custom fields per collection (accepted) Oct 22, 2026
@Madraka
Madraka merged commit 356a6d2 into main Oct 22, 2026
4 checks passed
@Madraka
Madraka deleted the rfc/typed-custom-fields branch October 22, 2026 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rfc A design proposal in docs/rfcs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant