Repository navigation
docs(rfc): RFC-0045 collections stage 4, references and repeaters (#114) - #193
Merged
Merged
Conversation
Draft RFC for reference fields and repeaters: the contract diff (ReferenceField, RepeaterField, SubFieldDefinition, FieldMigration.sub), the entry_refs reverse index with hash-anchored guards, the locale rule (translation groups), render depth and budgets, Studio blocks, strict structured-output schemas, field operations, rollout, tests and threat model. Docs only; generators not run (phase 1 runs contract-change). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
Every upheld and split finding gets a decision, listed in a review log: - references store the translation group id, resolved and guarded per site - entry writes anchor on the collection's definitions - only published referrers lock deletes and moves - resolution is gated per view, and cache tags purge by group - repeater assets are recorded in asset_refs - release closures exclude references - strict output gets its own input (fieldsStrict, clearFields) - every guard filters site_id, and rebuilds join same-site members - the types stay refused until a final enabling step - the update_collection $defs are fixed, and the anyOf plan is dropped - Event addresses come from a Place via targetField Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
Folds in every unresolved finding and new issue from the verification of fe8ac92, extending the review log: - group changes are guarded like deletes, with the planned site's hash - checkBundle gates the new types on import, sync, push, pull and restore, with a one-time per-site rebuild at enable - entry_refs rows carry shared/root_key mirroring resolveFields; one "shown by a published entry" fragment serves guards, live referencedBy and purges - the definitions anchor binds the planned Site's definitions - rows are kept for every stored value; entry_refs joins SITE_TABLES - cloudhal-ref tags are dropped: the purge planner adds referrers' node tags through entry_refs (no new prefixes, no header ids) - repeater asset checks and the purge asset rule are specified - the asset_refs site scoping becomes rollout step 0 - races R1-R11 are listed with their guards - edition chains, emptied items, the conversion context, the fieldsStrict edge cases and the Event address data path are settled Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
Folds in the four blocking clusters and the non-blocking items of the verification of 9e457d1, extending the review log: - one membership rule everywhere, COALESCE(translation.group, id) = G, in an index-friendly form; relinking a node with dependants is refused, and readsOriginal requires an original to own its group - shared is a pure function of localized; the fragment decides who inherits at batch time - delete, move and group-change guards bind the planned pairs, so an unseen field's row forces a retry (R13) - purge closure to the render depth, "used by" pages, index mode for publishes and snapshot mode for rollbacks, release runs (re-planned at run time) and restores, bounded by maxReads/maxTags - set_field_localized flips shared in phase A; conversions into references refuse target deletes until phase C (R12) - an absent capability refuses in the bundle gate (CopySiteOptions, FIELDS_SUPPORTED); importSite stores canonical bodies - races R12-R15, the size-ratchet modules, the test cases and the open questions are added Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
- every delete, move and group change of an entry carries the site anchor, closing R12 for deletes planned before the conversion marker - purges use one method for every publish path: index rows corrected by a hash check against `to`, with a from/to body scan of the entries that differ (an older snapshot publish and writes between snapshot and publish are exact) - `shared` is read from the site row inside the single INSERT ... SELECT at batch time (R16) - the group check and a written-group guard run on any change to translation.group or source - the step-7 job canonicalizes rows; the field-refs.ts:81 skip filter uses item paths; "used by" purges use resolved values - wording, archived-move alignment, size-ratchet modules, phase-2 compatibility notes and the refusal list are completed; review log "Fourth round" Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
- the rows INSERT is a plain INSERT; shared is matched by key or migration.fromKey, and a NULL fails the batch (ConflictError, retry) instead of being skipped by OR IGNORE (R16, rename case) - purges read only the immutable from/to bodies, through snapshot bundles, on every publish path; the hash-check hybrid and index mode are dropped (a probe cannot see referrers edited away or deleted, and cheap whole-site change checks are unsound) - any field-operation marker on from or to purges everything - deletes, moves and group changes anchor on json($.collections), not the site hash, so publishes no longer cause 409s - non-blocking: the written-group guard is exempt for a node's own id; CAS canonicalization runs from phase 2; prefix skip match; the rebuild reads through fromKey; wording fixes - new "Implementation watch list" section; review log "Fifth round" Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
- entryRefsRebuild runs only when its import batch writes the node set (no rebuild on an unchanged import); the step-7 job is per node and anchored on each node's read hash, with no site-wide DELETE (R10, R17); step 0 closes the same asset_refs hole on main - purges use one hash-keyed body cache over both snapshots: one bundle (to's first), then only the missing hashes; per-shard streaming with byte and node budgets; short-circuit without reference definitions; RELEASE_EXECUTOR_COST covers the run-time re-plan - shared prefers the exact key; NULL -> ConflictError only for entry_refs.shared; dedup after canonicalization; SQL NULL for an absent collections; "used by" covers asset-rule entries - stale index-era wording removed; new "Owner decisions" section; review log "Sixth round" Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
The owner accepted the RFC on 2026-11-10 with the three owner decisions ratified: snapshot-only purges with their cost and fallbacks, archiving the last member does not release a lock, and the phase-2 behaviour changes on existing sites. Sets the status, turns "Owner decisions" into "Decisions (2026-11-10)", and links #114 and #196 (fixed by rollout step 0). The docs site lists RFCs from the folder itself (apps/docs/src/lib/pages.ts), so there is no index file to update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft RFC for #114: reference fields and repeaters, the part RFC-0042 §6 left out. Docs only; nothing is implemented.
What it decides
ReferenceFieldandRepeaterFieldtoFieldDefinition, plusSubFieldDefinition, a fixed depth with no recursion: repeater items are ADR-0030's flat objects of scalars. It also addsFieldMigration.subfor sub-field operations. The exact diffs are againstsite.schema.json, with the TS and Rust impact and the fixtures to add.entry_refsreverse index written in each entry's batch and anchored on the new hash, asasset_refsis. Deleting a referenced entry, or moving it out of the collections its referrers allow, is refused. Archiving or unpublishing a target is allowed, and the renderer resolves only what the snapshot shows. Publish warns but never fails. Rollback, restores and imports rebuild the index.localization.fallback.eq/in); sorting or filtering by a referenced entry's field is not offered.EntryPicker,ReferenceList,RepeaterField,FieldControl(extracted) andUsedByList, with accessibility and 390 px layout covered.$refand depth ≤ 4. A strict profile (every property required,nullunions) comes withstrictCost.update_collection's input usesanyOfover its disjoint variants.subparameter addresses repeater sub-fields, and revert drops targets deleted in the meantime.Not verified.
pnpm genand the fixture tests were not run, because the owner's machine was busy with a test-heavy session. Phase 1 runscontract-changefirst.🤖 Generated with Claude Code