Repository navigation
chore(release): version packages - #209
Merged
Merged
Conversation
github-actions
Bot
force-pushed
the
changeset-release/main
branch
7 times, most recently
from
November 13, 2026 12:57
5437f12 to
926b2a4
Compare
github-actions
Bot
force-pushed
the
changeset-release/main
branch
from
November 13, 2026 16:12
926b2a4 to
5dff098
Compare
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.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or setup this action to publish automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@cloudhal/[email protected]
Minor Changes
41d783a: RFC-0045 rollout step 3a: the renderer resolves reference and repeater fields. Both types stay refused on every write path until rollout step 7, so nothing changes for existing sites.
@cloudhal/astro-renderer.entryFieldsresolves a reference to cards (RenderedField.references:ReferencedEntrywith group id, id, collection, locale, slug, title, summary, the graphpathto link with (the locale middleware localizes it), the canonicalurl, cover image andfromFallbackLocale), in stored order, bypickMember's locale rule among the members the source's view shows, gates included.depth: 2adds each card's own fields, with their references as cards without fields. Resolution is breadth-first over a visited set of groups, onegroupMemberscall per level, and spends the request's 200 targets (PlaceholderBudget.references;placeholderBudget()includes it); past the budget the rest resolve to nothing, with oneconsole.warnper request.RenderedField.items), like fields; empty items are left out.valuekeeps only the resolved group ids.GraphSource.groupMembers?andGraphSource.referencedBy?onSnapshotSource(in memory: gate-independent indexes built once per snapshot, filtered per view) andLiveSource(oneentry_refsread expanded by thesharedrule, each candidate resolved like the snapshot's index).referencedBylists entries whose resolved values name the group, exactly as each page resolves them (a translation reads its original only while the view shows it), newest first with ties by id, at most 100.GraphSource.conversionEntries?builds the entry maps of a text ↔ reference conversion while one runs (rollout step 4 adds the conversions).EntryFields.astrodraws references as links (langon a fallback-locale card, aul.ch-referencesfor several) and repeaters as anol.ch-itemsof nesteddls. Old theme copies get both with no change of their own.GET /__cloudhal/featuresanswers{ "gates": 2, "fields": 2 }.@cloudhal/core-ts.getGroupMembersandreferrerCandidates(the live renderer's reads, bysite_id);conversionEntries,conversionTargets,conversionCollectionsandfoldTextin./fields;resolveFieldstakes an optional fourth argument with the conversion maps (ConvertContext.entries).Patch Changes
@cloudhal/[email protected]
Patch Changes
@cloudhal/[email protected]
Patch Changes
@cloudhal/[email protected]
Patch Changes
bb43a16: RFC-0045 rollout step 4: the four field operations work on reference and repeater fields. The types themselves stay refused on every production write path until step 7 (
fields_unsupported, now from the dry run's check of the definitions the operation ends with); the shared suites enable them withSiteGraphStoreOptions.fieldTypes. Nothing changes for operations on the nine existing types.subon all four operations (FieldOperation.sub,FieldMigration.sub): with it,rename_field,change_field_typeandremove_fieldrename, convert or remove one sub-field of a repeater in every item. An item left empty is dropped, and a list left empty is no value.set_field_localizedrefusessub(sub-fields share their repeater'slocalized). Readers, writers and the rows read items through the marker; a top-level reader ignores a sub-field rename'sfromKey(renamedFrom).change_field_typeinputs:collections,maxItems,subFieldsanditemLabel, each refused where the target type does not take it. A reference changes to a reference only to switchmultiple. A conversion that carries ids over may only widen the target collections. A repeater converts to text or to a reference only with exactly one matching sub-field.fields/conversions-references.ts): reference single ↔ multiple, text ↔ reference (through the prefetchedConvertContext.entriesmaps, never the entry's own group), multiline text → repeater, repeater → text, and multiple reference ↔ repeater. The maps are read once per operation pass, and byEntryEngine.writewhile such a conversion runs.fields/text-reference.ts), per value, from theentry_refsrows that phase C's pending check reads too: each operation pass loads the path's rows once, and a person's write reads its node's. A value with its row is kept; a legacy id-shaped text is written as a reference when its group is usable, else reported; a value that does not convert keeps its rows as they are. Readers use a display rule. Rebuilds (pull, push, import, restore) read a converting path through its earlier type. The renderer's conversion maps read archived entries too, so an archived target lends its title.set_field_localizedupdates the rows'sharedin the batch of its site write (phase A, and the revert's).FieldRevertResult.dropped.unconvertibleand keep the operation running.continueFieldOperationandrevertFieldOperationtakeonInvalid: "clear"to drop them, as do the admin API's continue and revert routes (in the body) andcloudhal fields continue|revert --clear.multipleon a type change to a type that has none is ignored, as before.cloudhal fields retypetakes--collections a,b,--max-items nand--sub-fields <file.json>, and every action takes--sub <sub-field>. The admin API's operation route parses the same inputs. MCP's operation tools take them with rollout step 5.dda55ee: RFC-0045 rollout step 5: reference and repeater fields over MCP. The two types stay refused on every production write path until step 7 (
fields_unsupported), and the field inputs do not list them there; a store withSiteGraphStoreOptions.fieldTypesgets tools that do. Nothing changes for the nine existing types, except as listed.list_collectionsreturns, besidefieldsSchema, its strict profilefieldsSchemaStrict(every key required,nullfor "leave as it is") andstrictCost(properties,depth,enumValues,unions). Reference targets are named by their collections' labels.create_entry/update_entrytakefieldsStrict, for strict structured output, instead offields(invalidwhen both are given):nullor a missing key leaves a value as it is (on create, no value);nullsub-values in repeater items are stripped, and items left empty are dropped and reported indroppedItems.update_entryalso takesclearFields(set and clear of one key isinvalid, an unknown keyunknown_field); on create it isinvalid. A given reference or repeater value replaces the whole value.NodeWriteOptions.dryRunoncreateContentEntry/updateContentEntry, anddeleteContentEntry(entry, { dryRun }), throw the plan-time refusals (values, links, references, a release hold, gates, assets, terms) and write nothing. Socreate_entryandupdate_entryrefuse reference targets (unknown_entry), repeater items and the references cap before anyone is asked, anddelete_entryrefusesentry_referencedwith the published referrers. Behaviour change: those prechecks now also run the store's translation-link and canonical-id checks, which the handler ran anyway.venue → "Main hall" (entry_…, Places),speakers: 2 items → 3 items (added "Ada Lovelace", Speaker; changed item 1: person → "Grace Hopper" (entry_…, People)), quoted and truncated.list_references(content:read) withdirection: "to"(referrers, published first, with the members that show them) or"from"(the groups an entry names, its original's inherited ones included). 110 → 111 tools. The API'sGET …/entries/:entryId/referencesand the tool share core-ts's newlistReferrers(andlistReferenceTargets,referenceCard).list_entriesreturns each entry'sgroupId, the value a reference stores.get_translation_sourcelists a localized repeater's text and rich-text sub-values by item path (speakers/0/talk) with the source'ssourceRev;save_translationtakes them back with thatsourceRev(conflictwhen the source changed) and folds them into a copy of the source's list, keeping each item's other sub-values (core-tstranslatedItemValues). Once the translation holds its own list for that repeater, item paths are refused and the list is sent whole; a whole list given together with item paths must have the source's length (translation_shape_mismatch, new code, 409 in the API). A path naming no such value is refused. Keys whose first part is not a repeater (og/image) stay plain keys.normalizeEntryFieldsis exported from@cloudhal/core-ts: MCP's approval prompts read stored values through the markers exactly as the store does.continueFieldOperationwithonInvalid: "clear"reports the values it drops as cleared, without the stored request'sfield_values_unconvertiblerefusal.rename_fieldover MCP: the old and the new key are one field; removing either removes both, so the writer's move cannot bring the value back, and setting one while removing the other isinvalid.sub(rename_field,change_field_type,remove_field),collections,maxItems,subFieldsanditemLabelonchange_field_type, andonInvalid: "clear"on a continuation; results carryunconvertible.defineTools({ referenceTypes })anddefaultToolList(referenceTypes):createCloudhalMcpServerpasses whether its store hasfieldTypes.3678855: RFC-0045 rollout step 6a: reference and repeater fields in Studio's entry editor. The two types stay refused on every production write path until step 7 (
fields_unsupported), so no production collection can define them yet and Studio looks unchanged there.GET /api/sites/:siteId/entries/groups?ids=a,b(content:read, in the playground's allow-list): each translation group's members in the site, any status, as{groupId, id, title, collection, status, locale}cards (core-tsgetGroupMembersandreferenceCard); a group with no member left answers[]. One to 100 well-formed group ids (the per-entry reference cap), 400 otherwise, 404 for an unknown site. Studio reads the chosen targets' titles and states through it.fieldLabel,fieldHelpandoptionLabel(@cloudhal/core-ts/fields) also take a repeater's sub-field definitions.ReferenceListandEntryPickeroverGET …/entries/pick), repeaters (RepeaterField, focus after add and remove, an undo toast, item errors by path), and a "Used by" card fromGET …/entries/:id/references, with the new@cloudhal/uiblocksFieldControl,RepeaterField,ReferenceList,EntryPickerandUsedByList. They load with the lazy fields chunk; the initial bundle is unchanged.b7ac2e9: RFC-0045 rollout step 6b: Studio's fields builder, delete dialog and publish warnings for reference and repeater fields. Both types stay refused on every production write path until step 7, and the builder offers them only where the server takes them, so production Studio is unchanged.
/api/instancereportsfeatures.referenceFields: true when the store accepts reference and repeater fields (SiteGraphStoreOptions.fieldTypes, MCP's rule).DELETE /api/sites/:siteId/entries/:entryId?rev=&dryRun=1runs the store's delete plan and writes nothing:{ dryRun: true }, or the plan's refusal (entry_referencedwith its referrers,field_operation_running, …).GET /api/sites/:siteId/entries/reference-issues(content:read, in the playground's allow-list):referenceIssuesover the working copy, the first 50 with each holder's title, and the total.Updated dependencies [3b8e846]
Updated dependencies [41d783a]
Updated dependencies [9aa67d3]
Updated dependencies [bb43a16]
Updated dependencies [dda55ee]
Updated dependencies [3678855]
Updated dependencies [4a5633d]
@cloudhal/[email protected]
Patch Changes
bb43a16: RFC-0045 rollout step 4: the four field operations work on reference and repeater fields. The types themselves stay refused on every production write path until step 7 (
fields_unsupported, now from the dry run's check of the definitions the operation ends with); the shared suites enable them withSiteGraphStoreOptions.fieldTypes. Nothing changes for operations on the nine existing types.subon all four operations (FieldOperation.sub,FieldMigration.sub): with it,rename_field,change_field_typeandremove_fieldrename, convert or remove one sub-field of a repeater in every item. An item left empty is dropped, and a list left empty is no value.set_field_localizedrefusessub(sub-fields share their repeater'slocalized). Readers, writers and the rows read items through the marker; a top-level reader ignores a sub-field rename'sfromKey(renamedFrom).change_field_typeinputs:collections,maxItems,subFieldsanditemLabel, each refused where the target type does not take it. A reference changes to a reference only to switchmultiple. A conversion that carries ids over may only widen the target collections. A repeater converts to text or to a reference only with exactly one matching sub-field.fields/conversions-references.ts): reference single ↔ multiple, text ↔ reference (through the prefetchedConvertContext.entriesmaps, never the entry's own group), multiline text → repeater, repeater → text, and multiple reference ↔ repeater. The maps are read once per operation pass, and byEntryEngine.writewhile such a conversion runs.fields/text-reference.ts), per value, from theentry_refsrows that phase C's pending check reads too: each operation pass loads the path's rows once, and a person's write reads its node's. A value with its row is kept; a legacy id-shaped text is written as a reference when its group is usable, else reported; a value that does not convert keeps its rows as they are. Readers use a display rule. Rebuilds (pull, push, import, restore) read a converting path through its earlier type. The renderer's conversion maps read archived entries too, so an archived target lends its title.set_field_localizedupdates the rows'sharedin the batch of its site write (phase A, and the revert's).FieldRevertResult.dropped.unconvertibleand keep the operation running.continueFieldOperationandrevertFieldOperationtakeonInvalid: "clear"to drop them, as do the admin API's continue and revert routes (in the body) andcloudhal fields continue|revert --clear.multipleon a type change to a type that has none is ignored, as before.cloudhal fields retypetakes--collections a,b,--max-items nand--sub-fields <file.json>, and every action takes--sub <sub-field>. The admin API's operation route parses the same inputs. MCP's operation tools take them with rollout step 5.Updated dependencies [3b8e846]
Updated dependencies [41d783a]
Updated dependencies [9aa67d3]
Updated dependencies [bb43a16]
Updated dependencies [dda55ee]
Updated dependencies [3678855]
Updated dependencies [b7ac2e9]
Updated dependencies [4a5633d]
@cloudhal/[email protected]
Patch Changes
9aa67d3: RFC-0045 rollout step 3b: publishes purge the pages that show references. Nothing changes for sites without reference definitions. Their publish purge plans are the same, with no bundle read. Their release runs send the plan stored at pin time, as before, with no re-plan; the only addition is one read of the published site node, to tell them apart.
The referrer closure (
references/purge.ts, called byplanCachePurge).fromandtosnapshots' bodies, never the working copy orentry_refs.Reads and budgets. A publish that changes no entry and no shown asset reads nothing. Otherwise the closure keeps one hash-keyed cache:
to's, elsefrom's), streamed and cut down as each shard is parsed;A passed budget purges everything:
maxBodyBytes, 32 MB);maxNodes, 50,000);maxReads, shard reads included);maxTags).So does any field-operation marker on either snapshot's site node, for sites that hold references or convert from them.
readSnapshotBundle(SnapshotReader.readSnapshotBundle,SiteGraphStore.readSnapshotBundle,readSnapshotBundlein bundles) takes optionalmaxBytes,maxNodes,keep,only(bodies node by node) andspent(a shared byte total). A passed budget throwsBundleBudgetErrorbefore the shard is parsed. No new cache tags.Release runs on sites with references re-plan their purge at run time (
references/release-purge.ts), from the pointer they moved to the snapshot they made, instead of sending the plan stored at pin time.publishReleasenow returns (publishedSite). That costs one blob read per run with a purger, except on a first publish; the read is counted, never refused. If it fails, the working row decides.refreshSearch,labelOf, the re-plan) are charged to one allowance per invocation, shared by the cron's ticks (ScheduledTickOptions.releaseBlobs): 350 on Workers Free, 3,000 on Paid. "Publish now" sizes it from the deployment's tick budget (ReleaseServiceandSchedulesDeps.tickBudget).CachePurgeOptions.references: false): for these sites it is the expected outcome only.RELEASE_EXECUTOR_COSTis 26 (it countsrefreshSearchandrecordPurgenow).@cloudhal/cloudflare: the cron handler passes onereleaseBlobsallowance to both ticks of its invocation (cronTick); the alarm and the request backstop run one tick each, with the default allowance.Updated dependencies [41d783a]
Updated dependencies [9aa67d3]
Updated dependencies [bb43a16]
Updated dependencies [dda55ee]
Updated dependencies [3678855]
Updated dependencies [b7ac2e9]
Updated dependencies [4a5633d]
@cloudhal/[email protected]
Patch Changes
@cloudhal/[email protected]
Patch Changes
3b8e846: Two new contract roots for signed release bundles (RFC-0046), with golden fixtures and the matching Rust types (
ReleaseManifest,ReleaseStatement):release-manifest(cloudhal.release-manifest@1): the manifest of a release bundle. It lists every built Worker module and static asset by size and SHA-256, with the binding templates, feature levels, migration range and rollback facts a remote deployer needs before it uploads anything.signing.signatureisrelease-statement.sigfor project releases;manifest.sigis a legacy form for development keys only.release-statement(cloudhal.release-statement@1): the small canonical document a release signs (Ed25519, at most 4096 bytes). It names the version, channel, commit and key id, and pins the SHA-256 and size ofmanifest.jsonand of the tarball.Both roots reference
common.schema.jsononly forSchemaVersionandTimestamp, so a deployer can keep an identical copy under its own$id. The package root exports only the release-specific typesReleaseManifest,WorkerArtifact,BindingTemplate,ReleaseStatementandStatementAsset. The local definitions of the two roots stay local: generic names such asSiteIdorCapabilitymean something else in the rest of the contracts. A test pins their fingerprints. The release signing key and the steps for verifying a release by hand are indocs/security/release-signing-keys.md. Nothing changes for existing contracts.@cloudhal/[email protected]
Patch Changes
41d783a: RFC-0045 rollout step 3a: the renderer resolves reference and repeater fields. Both types stay refused on every write path until rollout step 7, so nothing changes for existing sites.
@cloudhal/astro-renderer.entryFieldsresolves a reference to cards (RenderedField.references:ReferencedEntrywith group id, id, collection, locale, slug, title, summary, the graphpathto link with (the locale middleware localizes it), the canonicalurl, cover image andfromFallbackLocale), in stored order, bypickMember's locale rule among the members the source's view shows, gates included.depth: 2adds each card's own fields, with their references as cards without fields. Resolution is breadth-first over a visited set of groups, onegroupMemberscall per level, and spends the request's 200 targets (PlaceholderBudget.references;placeholderBudget()includes it); past the budget the rest resolve to nothing, with oneconsole.warnper request.RenderedField.items), like fields; empty items are left out.valuekeeps only the resolved group ids.GraphSource.groupMembers?andGraphSource.referencedBy?onSnapshotSource(in memory: gate-independent indexes built once per snapshot, filtered per view) andLiveSource(oneentry_refsread expanded by thesharedrule, each candidate resolved like the snapshot's index).referencedBylists entries whose resolved values name the group, exactly as each page resolves them (a translation reads its original only while the view shows it), newest first with ties by id, at most 100.GraphSource.conversionEntries?builds the entry maps of a text ↔ reference conversion while one runs (rollout step 4 adds the conversions).EntryFields.astrodraws references as links (langon a fallback-locale card, aul.ch-referencesfor several) and repeaters as anol.ch-itemsof nesteddls. Old theme copies get both with no change of their own.GET /__cloudhal/featuresanswers{ "gates": 2, "fields": 2 }.@cloudhal/core-ts.getGroupMembersandreferrerCandidates(the live renderer's reads, bysite_id);conversionEntries,conversionTargets,conversionCollectionsandfoldTextin./fields;resolveFieldstakes an optional fourth argument with the conversion maps (ConvertContext.entries).9aa67d3: RFC-0045 rollout step 3b: publishes purge the pages that show references. Nothing changes for sites without reference definitions. Their publish purge plans are the same, with no bundle read. Their release runs send the plan stored at pin time, as before, with no re-plan; the only addition is one read of the published site node, to tell them apart.
The referrer closure (
references/purge.ts, called byplanCachePurge).fromandtosnapshots' bodies, never the working copy orentry_refs.Reads and budgets. A publish that changes no entry and no shown asset reads nothing. Otherwise the closure keeps one hash-keyed cache:
to's, elsefrom's), streamed and cut down as each shard is parsed;A passed budget purges everything:
maxBodyBytes, 32 MB);maxNodes, 50,000);maxReads, shard reads included);maxTags).So does any field-operation marker on either snapshot's site node, for sites that hold references or convert from them.
readSnapshotBundle(SnapshotReader.readSnapshotBundle,SiteGraphStore.readSnapshotBundle,readSnapshotBundlein bundles) takes optionalmaxBytes,maxNodes,keep,only(bodies node by node) andspent(a shared byte total). A passed budget throwsBundleBudgetErrorbefore the shard is parsed. No new cache tags.Release runs on sites with references re-plan their purge at run time (
references/release-purge.ts), from the pointer they moved to the snapshot they made, instead of sending the plan stored at pin time.publishReleasenow returns (publishedSite). That costs one blob read per run with a purger, except on a first publish; the read is counted, never refused. If it fails, the working row decides.refreshSearch,labelOf, the re-plan) are charged to one allowance per invocation, shared by the cron's ticks (ScheduledTickOptions.releaseBlobs): 350 on Workers Free, 3,000 on Paid. "Publish now" sizes it from the deployment's tick budget (ReleaseServiceandSchedulesDeps.tickBudget).CachePurgeOptions.references: false): for these sites it is the expected outcome only.RELEASE_EXECUTOR_COSTis 26 (it countsrefreshSearchandrecordPurgenow).@cloudhal/cloudflare: the cron handler passes onereleaseBlobsallowance to both ticks of its invocation (cronTick); the alarm and the request backstop run one tick each, with the default allowance.bb43a16: RFC-0045 rollout step 4: the four field operations work on reference and repeater fields. The types themselves stay refused on every production write path until step 7 (
fields_unsupported, now from the dry run's check of the definitions the operation ends with); the shared suites enable them withSiteGraphStoreOptions.fieldTypes. Nothing changes for operations on the nine existing types.subon all four operations (FieldOperation.sub,FieldMigration.sub): with it,rename_field,change_field_typeandremove_fieldrename, convert or remove one sub-field of a repeater in every item. An item left empty is dropped, and a list left empty is no value.set_field_localizedrefusessub(sub-fields share their repeater'slocalized). Readers, writers and the rows read items through the marker; a top-level reader ignores a sub-field rename'sfromKey(renamedFrom).change_field_typeinputs:collections,maxItems,subFieldsanditemLabel, each refused where the target type does not take it. A reference changes to a reference only to switchmultiple. A conversion that carries ids over may only widen the target collections. A repeater converts to text or to a reference only with exactly one matching sub-field.fields/conversions-references.ts): reference single ↔ multiple, text ↔ reference (through the prefetchedConvertContext.entriesmaps, never the entry's own group), multiline text → repeater, repeater → text, and multiple reference ↔ repeater. The maps are read once per operation pass, and byEntryEngine.writewhile such a conversion runs.fields/text-reference.ts), per value, from theentry_refsrows that phase C's pending check reads too: each operation pass loads the path's rows once, and a person's write reads its node's. A value with its row is kept; a legacy id-shaped text is written as a reference when its group is usable, else reported; a value that does not convert keeps its rows as they are. Readers use a display rule. Rebuilds (pull, push, import, restore) read a converting path through its earlier type. The renderer's conversion maps read archived entries too, so an archived target lends its title.set_field_localizedupdates the rows'sharedin the batch of its site write (phase A, and the revert's).FieldRevertResult.dropped.unconvertibleand keep the operation running.continueFieldOperationandrevertFieldOperationtakeonInvalid: "clear"to drop them, as do the admin API's continue and revert routes (in the body) andcloudhal fields continue|revert --clear.multipleon a type change to a type that has none is ignored, as before.cloudhal fields retypetakes--collections a,b,--max-items nand--sub-fields <file.json>, and every action takes--sub <sub-field>. The admin API's operation route parses the same inputs. MCP's operation tools take them with rollout step 5.dda55ee: RFC-0045 rollout step 5: reference and repeater fields over MCP. The two types stay refused on every production write path until step 7 (
fields_unsupported), and the field inputs do not list them there; a store withSiteGraphStoreOptions.fieldTypesgets tools that do. Nothing changes for the nine existing types, except as listed.list_collectionsreturns, besidefieldsSchema, its strict profilefieldsSchemaStrict(every key required,nullfor "leave as it is") andstrictCost(properties,depth,enumValues,unions). Reference targets are named by their collections' labels.create_entry/update_entrytakefieldsStrict, for strict structured output, instead offields(invalidwhen both are given):nullor a missing key leaves a value as it is (on create, no value);nullsub-values in repeater items are stripped, and items left empty are dropped and reported indroppedItems.update_entryalso takesclearFields(set and clear of one key isinvalid, an unknown keyunknown_field); on create it isinvalid. A given reference or repeater value replaces the whole value.NodeWriteOptions.dryRunoncreateContentEntry/updateContentEntry, anddeleteContentEntry(entry, { dryRun }), throw the plan-time refusals (values, links, references, a release hold, gates, assets, terms) and write nothing. Socreate_entryandupdate_entryrefuse reference targets (unknown_entry), repeater items and the references cap before anyone is asked, anddelete_entryrefusesentry_referencedwith the published referrers. Behaviour change: those prechecks now also run the store's translation-link and canonical-id checks, which the handler ran anyway.venue → "Main hall" (entry_…, Places),speakers: 2 items → 3 items (added "Ada Lovelace", Speaker; changed item 1: person → "Grace Hopper" (entry_…, People)), quoted and truncated.list_references(content:read) withdirection: "to"(referrers, published first, with the members that show them) or"from"(the groups an entry names, its original's inherited ones included). 110 → 111 tools. The API'sGET …/entries/:entryId/referencesand the tool share core-ts's newlistReferrers(andlistReferenceTargets,referenceCard).list_entriesreturns each entry'sgroupId, the value a reference stores.get_translation_sourcelists a localized repeater's text and rich-text sub-values by item path (speakers/0/talk) with the source'ssourceRev;save_translationtakes them back with thatsourceRev(conflictwhen the source changed) and folds them into a copy of the source's list, keeping each item's other sub-values (core-tstranslatedItemValues). Once the translation holds its own list for that repeater, item paths are refused and the list is sent whole; a whole list given together with item paths must have the source's length (translation_shape_mismatch, new code, 409 in the API). A path naming no such value is refused. Keys whose first part is not a repeater (og/image) stay plain keys.normalizeEntryFieldsis exported from@cloudhal/core-ts: MCP's approval prompts read stored values through the markers exactly as the store does.continueFieldOperationwithonInvalid: "clear"reports the values it drops as cleared, without the stored request'sfield_values_unconvertiblerefusal.rename_fieldover MCP: the old and the new key are one field; removing either removes both, so the writer's move cannot bring the value back, and setting one while removing the other isinvalid.sub(rename_field,change_field_type,remove_field),collections,maxItems,subFieldsanditemLabelonchange_field_type, andonInvalid: "clear"on a continuation; results carryunconvertible.defineTools({ referenceTypes })anddefaultToolList(referenceTypes):createCloudhalMcpServerpasses whether its store hasfieldTypes.3678855: RFC-0045 rollout step 6a: reference and repeater fields in Studio's entry editor. The two types stay refused on every production write path until step 7 (
fields_unsupported), so no production collection can define them yet and Studio looks unchanged there.GET /api/sites/:siteId/entries/groups?ids=a,b(content:read, in the playground's allow-list): each translation group's members in the site, any status, as{groupId, id, title, collection, status, locale}cards (core-tsgetGroupMembersandreferenceCard); a group with no member left answers[]. One to 100 well-formed group ids (the per-entry reference cap), 400 otherwise, 404 for an unknown site. Studio reads the chosen targets' titles and states through it.fieldLabel,fieldHelpandoptionLabel(@cloudhal/core-ts/fields) also take a repeater's sub-field definitions.ReferenceListandEntryPickeroverGET …/entries/pick), repeaters (RepeaterField, focus after add and remove, an undo toast, item errors by path), and a "Used by" card fromGET …/entries/:id/references, with the new@cloudhal/uiblocksFieldControl,RepeaterField,ReferenceList,EntryPickerandUsedByList. They load with the lazy fields chunk; the initial bundle is unchanged.4a5633d: RFC-0045 rollout step 7a: two fixes ahead of enabling reference and repeater fields. Both types stay refused on every production write path until step 7b; nothing changes for the nine existing types.
entry_refsrows through a person's unrelated write, such as a title edit. Before, the write dropped them, and the target's delete guard under-blocked. The writer holds the rows at the old type's paths, the same ones the import rebuild keeps (one helper,oldShapePairs), so the rows no longer depend on which touched the entry last.source_statusof its last insert, so publishing the holder left the target deletable and unpublishing left it locked. The write now updates the held rows'source_statusin the same batch, anchored on the entry's new hash.get_translation_sourcereturns the source's whole list for that key underfields(in the source's order, with every sub-value) instead of item paths, and names it in the newwholeListsoutput: send it back whole, translated.save_translationalready refused item paths there (translation_shape_mismatch); its hint and the tool descriptions now say what to send.save_translationalso checks a givensourceRevagainst whole repeater lists (conflictwhen the source moved on); without one they save as before. New core-ts export:translationSourceValues.Updated dependencies [3b8e846]
[email protected]
Patch Changes
@cloudhal/[email protected]
Patch Changes
9aa67d3: RFC-0045 rollout step 3b: publishes purge the pages that show references. Nothing changes for sites without reference definitions. Their publish purge plans are the same, with no bundle read. Their release runs send the plan stored at pin time, as before, with no re-plan; the only addition is one read of the published site node, to tell them apart.
The referrer closure (
references/purge.ts, called byplanCachePurge).fromandtosnapshots' bodies, never the working copy orentry_refs.Reads and budgets. A publish that changes no entry and no shown asset reads nothing. Otherwise the closure keeps one hash-keyed cache:
to's, elsefrom's), streamed and cut down as each shard is parsed;A passed budget purges everything:
maxBodyBytes, 32 MB);maxNodes, 50,000);maxReads, shard reads included);maxTags).So does any field-operation marker on either snapshot's site node, for sites that hold references or convert from them.
readSnapshotBundle(SnapshotReader.readSnapshotBundle,SiteGraphStore.readSnapshotBundle,readSnapshotBundlein bundles) takes optionalmaxBytes,maxNodes,keep,only(bodies node by node) andspent(a shared byte total). A passed budget throwsBundleBudgetErrorbefore the shard is parsed. No new cache tags.Release runs on sites with references re-plan their purge at run time (
references/release-purge.ts), from the pointer they moved to the snapshot they made, instead of sending the plan stored at pin time.publishReleasenow returns (publishedSite). That costs one blob read per run with a purger, except on a first publish; the read is counted, never refused. If it fails, the working row decides.refreshSearch,labelOf, the re-plan) are charged to one allowance per invocation, shared by the cron's ticks (ScheduledTickOptions.releaseBlobs): 350 on Workers Free, 3,000 on Paid. "Publish now" sizes it from the deployment's tick budget (ReleaseServiceandSchedulesDeps.tickBudget).CachePurgeOptions.references: false): for these sites it is the expected outcome only.RELEASE_EXECUTOR_COSTis 26 (it countsrefreshSearchandrecordPurgenow).@cloudhal/cloudflare: the cron handler passes onereleaseBlobsallowance to both ticks of its invocation (cronTick); the alarm and the request backstop run one tick each, with the default allowance.dda55ee: RFC-0045 rollout step 5: reference and repeater fields over MCP. The two types stay refused on every production write path until step 7 (
fields_unsupported), and the field inputs do not list them there; a store withSiteGraphStoreOptions.fieldTypesgets tools that do. Nothing changes for the nine existing types, except as listed.list_collectionsreturns, besidefieldsSchema, its strict profilefieldsSchemaStrict(every key required,nullfor "leave as it is") andstrictCost(properties,depth,enumValues,unions). Reference targets are named by their collections' labels.create_entry/update_entrytakefieldsStrict, for strict structured output, instead offields(invalidwhen both are given):nullor a missing key leaves a value as it is (on create, no value);nullsub-values in repeater items are stripped, and items left empty are dropped and reported indroppedItems.update_entryalso takesclearFields(set and clear of one key isinvalid, an unknown keyunknown_field); on create it isinvalid. A given reference or repeater value replaces the whole value.NodeWriteOptions.dryRunoncreateContentEntry/updateContentEntry, anddeleteContentEntry(entry, { dryRun }), throw the plan-time refusals (values, links, references, a release hold, gates, assets, terms) and write nothing. Socreate_entryandupdate_entryrefuse reference targets (unknown_entry), repeater items and the references cap before anyone is asked, anddelete_entryrefusesentry_referencedwith the published referrers. Behaviour change: those prechecks now also run the store's translation-link and canonical-id checks, which the handler ran anyway.venue → "Main hall" (entry_…, Places),speakers: 2 items → 3 items (added "Ada Lovelace", Speaker; changed item 1: person → "Grace Hopper" (entry_…, People)), quoted and truncated.list_references(content:read) withdirection: "to"(referrers, published first, with the members that show them) or"from"(the groups an entry names, its original's inherited ones included). 110 → 111 tools. The API'sGET …/entries/:entryId/referencesand the tool share core-ts's newlistReferrers(andlistReferenceTargets,referenceCard).list_entriesreturns each entry'sgroupId, the value a reference stores.get_translation_sourcelists a localized repeater's text and rich-text sub-values by item path (speakers/0/talk) with the source'ssourceRev;save_translationtakes them back with thatsourceRev(conflictwhen the source changed) and folds them into a copy of the source's list, keeping each item's other sub-values (core-tstranslatedItemValues). Once the translation holds its own list for that repeater, item paths are refused and the list is sent whole; a whole list given together with item paths must have the source's length (translation_shape_mismatch, new code, 409 in the API). A path naming no such value is refused. Keys whose first part is not a repeater (og/image) stay plain keys.normalizeEntryFieldsis exported from@cloudhal/core-ts: MCP's approval prompts read stored values through the markers exactly as the store does.continueFieldOperationwithonInvalid: "clear"reports the values it drops as cleared, without the stored request'sfield_values_unconvertiblerefusal.rename_fieldover MCP: the old and the new key are one field; removing either removes both, so the writer's move cannot bring the value back, and setting one while removing the other isinvalid.sub(rename_field,change_field_type,remove_field),collections,maxItems,subFieldsanditemLabelonchange_field_type, andonInvalid: "clear"on a continuation; results carryunconvertible.defineTools({ referenceTypes })anddefaultToolList(referenceTypes):createCloudhalMcpServerpasses whether its store hasfieldTypes.4a5633d: RFC-0045 rollout step 7a: two fixes ahead of enabling reference and repeater fields. Both types stay refused on every production write path until step 7b; nothing changes for the nine existing types.
entry_refsrows through a person's unrelated write, such as a title edit. Before, the write dropped them, and the target's delete guard under-blocked. The writer holds the rows at the old type's paths, the same ones the import rebuild keeps (one helper,oldShapePairs), so the rows no longer depend on which touched the entry last.source_statusof its last insert, so publishing the holder left the target deletable and unpublishing left it locked. The write now updates the held rows'source_statusin the same batch, anchored on the entry's new hash.get_translation_sourcereturns the source's whole list for that key underfields(in the source's order, with every sub-value) instead of item paths, and names it in the newwholeListsoutput: send it back whole, translated.save_translationalready refused item paths there (translation_shape_mismatch); its hint and the tool descriptions now say what to send.save_translationalso checks a givensourceRevagainst whole repeater lists (conflictwhen the source moved on); without one they save as before. New core-ts export:translationSourceValues.Updated dependencies [3b8e846]
Updated dependencies [41d783a]
Updated dependencies [9aa67d3]
Updated dependencies [bb43a16]
Updated dependencies [dda55ee]
Updated dependencies [3678855]
Updated dependencies [4a5633d]
@cloudhal/[email protected]
Patch Changes
@cloudhal/[email protected]
Patch Changes