chore(release): version packages#85
Merged
Merged
Conversation
✅ Deploy Preview for contentrain-ai ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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 the packages will be published to npm 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
@contentrain/[email protected]
Major Changes
173326c: feat(mcp)!: enforce the field constraints the schema already accepted
A project reported that
items,acceptandmaxSizeare accepted on a field butnever enforced —
emails: ["not-an-email"]andaccept: "image/jpeg"against a.webpboth produced zero errors. The report was right, and the surface was largerthan the three properties it named: 4 of 27 field types had any semantic
validation, three constraints were read by nothing, and none of it blocked a write.
A constraint that isn't a constraint is worse than no constraint — the author stops
looking.
content_savenow validates before committing and refuses to write. It ranplan → commit → validate → report, so an invalid value landed in git, wasauto-merged, and the caller learned about it from a string in
next_stepswhilestatusstill said"committed". Validation now runs on the pending changes andblocks on errors, returning
isErrorand no commit. Warnings still pass — they areheuristics, and a legitimate value can sit outside an approximate pattern. Only the
entries being saved are fatal: a pre-existing bad entry elsewhere in the model does
not hold up an unrelated save.
Array items share the scalar rule set. They ran through a parallel type switch
that knew 10 of the 27 types and checked only
typeof, somin/max/pattern/optionsnever reached an item, anditemsgiven as a FieldDef with a non-objecttype (
{type:'array', items:{type:'string', max:50}}) matched no branch at all —silently unvalidated, while the type emitter rendered it as real. Items now recurse
through the same validator, which also closes the
integersplit where3.7wasrejected inside an array but accepted as a scalar.
17 types were pure
typeofchecks.slugnow uses theSLUG_PATTERNthecodebase already owned — every shipped template declares
slug: { type: 'slug' },so
"Hello World!!"used to validate clean.date/datetimeare parsed (the samecheck
schedule.tsalready did for meta),percentis range-checked, andcolor/phonewarn. Mechanical rules are errors; heuristics are warnings.email/urlkeep their existing warning severity.
ratingis deliberately untouched — its scaleis never declared, so any range would be invented.
uniqueworks on documents. It was gated on a context only the collectionvalidator passed, so it was a no-op exactly where every shipped template declares it.
On singletons it is now rejected at model_save: the model holds one record per
locale, so there is nothing to compare against.
The dead constraints, handled honestly.
acceptis enforced by extension-sniffand says that is what it is.
defaultis coherence-checked at model_save (righttype, within its own
options) but not written into content.maxSizecannot beenforced by MCP — it holds a path, never the bytes — so model_save now says so and
points at the provider, which owns the policy at ingest. The docs claimed all three
worked; they no longer do.
model_save rejects what it will not enforce.
optionson a non-select,itemson a non-array,
accept/maxSizeon a non-media field,min > max, and anuncompilable
patternare now errors instead of silent no-ops. Nestedfields/itemsschemas are validated recursively — they were typedz.unknown()and neverchecked. The field schema is
.strict(): a typo'd constraint (requird: true) usedto be stripped without a word.
BREAKING CHANGE:
content_saverejects content it previously committed. Runcontentrain_validatebefore upgrading to see what would now be blocked.
model_saverejects models it previously accepted (unknown keys,min > max,optionson a non-select,uniqueon a singleton).validateModelDefinitionreturns{ errors, warnings }instead ofstring[].validateFieldValue's message ("Type mismatch:expected string, got number") instead of "must be a string". The field path is
unchanged.
seo.title, nottitle) —a bare name was ambiguous with a top-level field.
@contentrain/typesgainsvalidateSemanticType,validateAcceptandisMediaType;validateFieldValuenow applies semantic andacceptrules.Studio picks all of this up automatically — its
content-validation.tsdelegates tothis validator.
Patch Changes
@contentrain/[email protected]
Minor Changes
173326c: feat(mcp)!: enforce the field constraints the schema already accepted
A project reported that
items,acceptandmaxSizeare accepted on a field butnever enforced —
emails: ["not-an-email"]andaccept: "image/jpeg"against a.webpboth produced zero errors. The report was right, and the surface was largerthan the three properties it named: 4 of 27 field types had any semantic
validation, three constraints were read by nothing, and none of it blocked a write.
A constraint that isn't a constraint is worse than no constraint — the author stops
looking.
content_savenow validates before committing and refuses to write. It ranplan → commit → validate → report, so an invalid value landed in git, wasauto-merged, and the caller learned about it from a string in
next_stepswhilestatusstill said"committed". Validation now runs on the pending changes andblocks on errors, returning
isErrorand no commit. Warnings still pass — they areheuristics, and a legitimate value can sit outside an approximate pattern. Only the
entries being saved are fatal: a pre-existing bad entry elsewhere in the model does
not hold up an unrelated save.
Array items share the scalar rule set. They ran through a parallel type switch
that knew 10 of the 27 types and checked only
typeof, somin/max/pattern/optionsnever reached an item, anditemsgiven as a FieldDef with a non-objecttype (
{type:'array', items:{type:'string', max:50}}) matched no branch at all —silently unvalidated, while the type emitter rendered it as real. Items now recurse
through the same validator, which also closes the
integersplit where3.7wasrejected inside an array but accepted as a scalar.
17 types were pure
typeofchecks.slugnow uses theSLUG_PATTERNthecodebase already owned — every shipped template declares
slug: { type: 'slug' },so
"Hello World!!"used to validate clean.date/datetimeare parsed (the samecheck
schedule.tsalready did for meta),percentis range-checked, andcolor/phonewarn. Mechanical rules are errors; heuristics are warnings.email/urlkeep their existing warning severity.
ratingis deliberately untouched — its scaleis never declared, so any range would be invented.
uniqueworks on documents. It was gated on a context only the collectionvalidator passed, so it was a no-op exactly where every shipped template declares it.
On singletons it is now rejected at model_save: the model holds one record per
locale, so there is nothing to compare against.
The dead constraints, handled honestly.
acceptis enforced by extension-sniffand says that is what it is.
defaultis coherence-checked at model_save (righttype, within its own
options) but not written into content.maxSizecannot beenforced by MCP — it holds a path, never the bytes — so model_save now says so and
points at the provider, which owns the policy at ingest. The docs claimed all three
worked; they no longer do.
model_save rejects what it will not enforce.
optionson a non-select,itemson a non-array,
accept/maxSizeon a non-media field,min > max, and anuncompilable
patternare now errors instead of silent no-ops. Nestedfields/itemsschemas are validated recursively — they were typedz.unknown()and neverchecked. The field schema is
.strict(): a typo'd constraint (requird: true) usedto be stripped without a word.
BREAKING CHANGE:
content_saverejects content it previously committed. Runcontentrain_validatebefore upgrading to see what would now be blocked.
model_saverejects models it previously accepted (unknown keys,min > max,optionson a non-select,uniqueon a singleton).validateModelDefinitionreturns{ errors, warnings }instead ofstring[].validateFieldValue's message ("Type mismatch:expected string, got number") instead of "must be a string". The field path is
unchanged.
seo.title, nottitle) —a bare name was ambiguous with a top-level field.
@contentrain/typesgainsvalidateSemanticType,validateAcceptandisMediaType;validateFieldValuenow applies semantic andacceptrules.Studio picks all of this up automatically — its
content-validation.tsdelegates tothis validator.
[email protected]
Patch Changes
@contentrain/[email protected]
Patch Changes