Skip to content

chore: version packages - #414

Merged
cuibonobo merged 1 commit into
mainfrom
changeset-release/main
Oct 13, 2026
Merged

cuibonobo merged 1 commit into
mainfrom
changeset-release/main

Conversation

@cuibonobo

@cuibonobo cuibonobo commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

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

@haverstack/[email protected]

Minor Changes

  • #443 ffefedd Thanks @cuibonobo! - APIAdapter no longer defines flush() or close(). Both were no-ops, and both are optional on StackAdapter, so Stack skips them already; a caller invoking them directly on an APIAdapter can drop the call.

  • #443 ffefedd Thanks @cuibonobo! - A discovery or auth handshake response that is empty or not JSON now throws APIAdapterError naming the endpoint, as every other success response does, rather than a SyntaxError or TypeError.

  • #444 ddad23c Thanks @cuibonobo! - Only a refused credential is reported as an authentication failure. A handshake step answering a bare 5xx now throws APIAdapterError rather than APIAdapterHandshakeError, and a renewal that fails on a dropped connection or a server error surfaces as that APIAdapterConnectionError or APIAdapterError rather than as APIAdapterReauthError. A change feed whose renewal fails that way keeps reconnecting instead of stopping.

Patch Changes

  • #443 d82f64e Thanks @cuibonobo! - Errors for a response missing its body now name the endpoint exactly as it was requested, encoded path and query string included.

  • #436 90d800a Thanks @cuibonobo! - StackRecordAdapter.subscribeChanges() takes SubscribeOptions, the same options a subscriber passes to subscribe(). SubscribeChangesOptions is gone from @haverstack/core/adapter; it had the same fields, and Stack already forwarded every one of them, the subscriber's own onError included. A new MutateOptions type in @haverstack/core/adapter names the options every version-bumping adapter mutation takes. GrantContent and InstallRequest are now derived from TypeGrant.

  • #443 e18ddb7 Thanks @cuibonobo! - Split the adapter into one module per layer. The package exports are unchanged.

  • #442 59f34ce Thanks @cuibonobo! - @haverstack/wire-types no longer restates shapes @haverstack/core already defines, and its auth handshake types share one prefix:

    • AuthChallengeRequest and AuthTokenRequest are removed. Use WireAuthChallengeRequest and WireAuthTokenRequest, re-exported from @haverstack/core/wire, where the parsers that return them live.
    • AuthChallengeResponse and AuthTokenResponse are renamed WireAuthChallengeResponse and WireAuthTokenResponse to match. Their shape is unchanged.
    • WireActor and WireChangeActor are now aliases of core's Actor and ChangeActor. Their shape is unchanged.
    • WireAssociationEditsRequest is removed; nothing referenced it.
  • Updated dependencies [7d30040, 98401c0, a40cee0, fdca4ca, c427f43, 90d800a, 7d30040, da5148b, 44fc3f6, d0b7950, f616aaa, 9b4adef, 59f34ce, 89e0a07, 55c33ba]:

@haverstack/[email protected]

Minor Changes

  • #449 a40cee0 Thanks @cuibonobo! - Migrations are declared steps. migration(from, to, steps) takes a list built from rename, map, add, drop and derive, replacing the function form, and checks the list against both handles' schemas when it runs: a step naming a field that is not there, a carried field the target would refuse, or a required field nothing produces throws StackMigrationError. Migration carries its steps.

    A collection's content filter or sort now spans the older versions its migrations translate it to, rather than only the handle's version. A key across a rename or add translates; one across a derive, or a sort across a map, narrows that version and sets skipped.older as before. Two query shapes carry it, each gated by a new capability that is a cap on keys: filter.contentByType (a content predicate per typeId, never beside content or contentPresent) and sort.contentFieldByType (a sort field or a reduced constant per typeId). StackCapabilities gains filter.contentByType and sort.contentFieldByType; local adapters declare 64, and normalizeCapabilities() reads an absent or malformed cap as 0. parseQueryBody() accepts both shapes. Conformance fixtures pin both shapes and their 400s, and the adapter conformance suite checks them.

  • #433 fdca4ca Thanks @cuibonobo! - enum is a field kind: { kind: 'enum', values: [...] } replaces { kind: 'string', enum: [...] }. defineType() refuses the enum key on any field. isCompatible() now checks enums: a required enum accepts only an enum candidate whose values it lists all of, and a required string or text accepts an enum. An enum becoming a plain string is additive; a string becoming an enum needs a version bump. A typed read types an enum field as its listed values or any other string (StoredContentOf, UnlistedValue) and no longer throws on an unlisted value, since an enum can widen in place; typed writes still take only the listed values (ContentOf, PatchOf). migration() types both sides as StoredContentOf, so a step carries an unlisted value through. A typed subscribe() delivers a record that migrateAll() moves off the handle's version without its record, instead of throwing in the dispatcher. Conformance fixtures pin a 422 for a value outside the list and a 409 for removing values. The adapter conformance suite checks that an enum field sorts by value.

Patch Changes

@haverstack/[email protected]

Minor Changes

  • Released for a breaking change in @haverstack/blob-adapter-disk, @haverstack/core, @haverstack/record-adapter-sqlite.

Patch Changes

@haverstack/[email protected]

Minor Changes

  • Released for a breaking change in @haverstack/core.

Patch Changes

@haverstack/[email protected]

Minor Changes

  • Released for a breaking change in @haverstack/core.

Patch Changes

@haverstack/[email protected]

Minor Changes

  • #415 f616aaa Thanks @cuibonobo! - A type handle carries what defineType() takes: typeHandle({ id, name, schema, migratesFrom }), with migratesFrom given as a handle or a TypeId. defineType(handle) and a manifest's types take it as written. Migrations are typed values built with migration(from, to, fn), where fn is checked as the first handle's content to the second's, and are passed to Stack.open(adapter, { migrations }). migratesFrom must name an earlier version of the same family, and typeHandle() and defineType() refuse anything else. migration() checks that pairing within a family and builds a step into another family without it, so an app's own type can migrate into a commons type. Stack.open() refuses a set of migrations it could not walk: a duplicate from, a malformed TypeId, a step backwards within a family, or a cycle. registerMigration() and MigrationFn are removed. @haverstack/commons drops CommonsType; its exports are plain type handles.

Patch Changes

  • #446 d0b7950 Thanks @cuibonobo! - Typed access goes through collections. client.collection(handle) returns a Collection typed by the handle's content, with one signature per verb — get, query, subscribe, create, mutate, patchContent, associate, dissociate, amendAssociations, grantAccess, revokeAccess, amendAccess, delete, undelete and restoreVersion — every one returning a typed record without a re-read. A collection spans the handle's whole family and migrates each record in memory to the handle's version. A record stored at a newer version is a misfit: query() reports it in misfits and keeps the page and cursor, get() throws MisfitError, and subscribe() carries it as misfit. A content write to a record at an older version commits its migration as a write of its own first. collection() refuses a handle whose migratesFrom has no migration passed to Stack.open().

    The handle-first overloads of get, query, create, mutate, patchContent and subscribe are removed, with TypedRecord, TypedQuery, TypedChange, TypedChangeSet and TypedSubscribeOptions. PatchOf is removed: a collection's patch type is ContentPatch<C>, derived from its content type, and StoredContent<C> is what its reads return.

  • Updated dependencies [7d30040, 98401c0, a40cee0, fdca4ca, c427f43, 90d800a, 7d30040, da5148b, 44fc3f6, d0b7950, f616aaa, 9b4adef, 89e0a07, 55c33ba]:

@haverstack/[email protected]

Minor Changes

  • #439 7d30040 Thanks @cuibonobo! - Grantees are checked by one validator, whether they arrive as a permission element, in a _grant record, or as a grantType()/listTypeGrants()/revokeType() target:

    • A permission element's grantee errors carry the failing field's path (permissions[0].grantee.entityId rather than permissions[0].grantee).
    • A group grantee missing both groupId and role reports both problems, on every surface.
    • A grant target's refusal is still a 400, now naming every problem after Invalid grant target:.
    • Every grantee message ends with a period, like the other association messages. The _grant fixtures that pin these messages are updated to match.

    revokeType() now matches a stored grant's actions as a set, so the order they were named in, or an action named twice, no longer stops a revoke from matching.

  • #449 a40cee0 Thanks @cuibonobo! - Migrations are declared steps. migration(from, to, steps) takes a list built from rename, map, add, drop and derive, replacing the function form, and checks the list against both handles' schemas when it runs: a step naming a field that is not there, a carried field the target would refuse, or a required field nothing produces throws StackMigrationError. Migration carries its steps.

    A collection's content filter or sort now spans the older versions its migrations translate it to, rather than only the handle's version. A key across a rename or add translates; one across a derive, or a sort across a map, narrows that version and sets skipped.older as before. Two query shapes carry it, each gated by a new capability that is a cap on keys: filter.contentByType (a content predicate per typeId, never beside content or contentPresent) and sort.contentFieldByType (a sort field or a reduced constant per typeId). StackCapabilities gains filter.contentByType and sort.contentFieldByType; local adapters declare 64, and normalizeCapabilities() reads an absent or malformed cap as 0. parseQueryBody() accepts both shapes. Conformance fixtures pin both shapes and their 400s, and the adapter conformance suite checks them.

  • #433 fdca4ca Thanks @cuibonobo! - enum is a field kind: { kind: 'enum', values: [...] } replaces { kind: 'string', enum: [...] }. defineType() refuses the enum key on any field. isCompatible() now checks enums: a required enum accepts only an enum candidate whose values it lists all of, and a required string or text accepts an enum. An enum becoming a plain string is additive; a string becoming an enum needs a version bump. A typed read types an enum field as its listed values or any other string (StoredContentOf, UnlistedValue) and no longer throws on an unlisted value, since an enum can widen in place; typed writes still take only the listed values (ContentOf, PatchOf). migration() types both sides as StoredContentOf, so a step carries an unlisted value through. A typed subscribe() delivers a record that migrateAll() moves off the handle's version without its record, instead of throwing in the dispatcher. Conformance fixtures pin a 422 for a value outside the list and a 409 for removing values. The adapter conformance suite checks that an enum field sorts by value.

  • #439 7d30040 Thanks @cuibonobo! - A record id using the reserved _ prefix is now refused as Invalid ID "<id>": uses the reserved "_" prefix., the same Invalid <field> "<value>": <reason>. shape every other record-ID refusal uses. The error-bad-request-id-reserved-prefix fixture pins the new wording.

  • #413 9b4adef Thanks @cuibonobo! - StackValidationError's message header names what was validated: record content keeps "Content validation failed", a type schema reads "Schema validation failed", and argument checks read "Invalid arguments". associate()/dissociate() and grantAccess()/revokeAccess() report list errors under associations/permissions, the parameter the caller passed, rather than changes. deserializeError() keeps the header a server sent.

  • #441 6d6ab03 Thanks @cuibonobo! - Replace getVersionsAfterMutateFixtures with getVersionsSequenceFixtures: one sequence that reads the version history before and after a restore, a migration and an association, so the order those reads depend on is part of the data. The history now includes the version 2 snapshot a record at version 3 holds.

Patch Changes

  • #439 d0b7369 Thanks @cuibonobo! - Correct the stated reason in the error-reserved-content-key fixture's description. The refusal and its response are unchanged.

  • #440 07f1fbd Thanks @cuibonobo! - Split the fixtures into one module per endpoint group. The package exports are unchanged.

  • #442 59f34ce Thanks @cuibonobo! - @haverstack/wire-types no longer restates shapes @haverstack/core already defines, and its auth handshake types share one prefix:

    • AuthChallengeRequest and AuthTokenRequest are removed. Use WireAuthChallengeRequest and WireAuthTokenRequest, re-exported from @haverstack/core/wire, where the parsers that return them live.
    • AuthChallengeResponse and AuthTokenResponse are renamed WireAuthChallengeResponse and WireAuthTokenResponse to match. Their shape is unchanged.
    • WireActor and WireChangeActor are now aliases of core's Actor and ChangeActor. Their shape is unchanged.
    • WireAssociationEditsRequest is removed; nothing referenced it.
  • Updated dependencies [a40cee0, 9b4adef, 59f34ce]:

@haverstack/[email protected]

Minor Changes

  • #439 7d30040 Thanks @cuibonobo! - Grantees are checked by one validator, whether they arrive as a permission element, in a _grant record, or as a grantType()/listTypeGrants()/revokeType() target:

    • A permission element's grantee errors carry the failing field's path (permissions[0].grantee.entityId rather than permissions[0].grantee).
    • A group grantee missing both groupId and role reports both problems, on every surface.
    • A grant target's refusal is still a 400, now naming every problem after Invalid grant target:.
    • Every grantee message ends with a period, like the other association messages. The _grant fixtures that pin these messages are updated to match.

    revokeType() now matches a stored grant's actions as a set, so the order they were named in, or an action named twice, no longer stops a revoke from matching.

  • #449 a40cee0 Thanks @cuibonobo! - Migrations are declared steps. migration(from, to, steps) takes a list built from rename, map, add, drop and derive, replacing the function form, and checks the list against both handles' schemas when it runs: a step naming a field that is not there, a carried field the target would refuse, or a required field nothing produces throws StackMigrationError. Migration carries its steps.

    A collection's content filter or sort now spans the older versions its migrations translate it to, rather than only the handle's version. A key across a rename or add translates; one across a derive, or a sort across a map, narrows that version and sets skipped.older as before. Two query shapes carry it, each gated by a new capability that is a cap on keys: filter.contentByType (a content predicate per typeId, never beside content or contentPresent) and sort.contentFieldByType (a sort field or a reduced constant per typeId). StackCapabilities gains filter.contentByType and sort.contentFieldByType; local adapters declare 64, and normalizeCapabilities() reads an absent or malformed cap as 0. parseQueryBody() accepts both shapes. Conformance fixtures pin both shapes and their 400s, and the adapter conformance suite checks them.

  • #433 fdca4ca Thanks @cuibonobo! - enum is a field kind: { kind: 'enum', values: [...] } replaces { kind: 'string', enum: [...] }. defineType() refuses the enum key on any field. isCompatible() now checks enums: a required enum accepts only an enum candidate whose values it lists all of, and a required string or text accepts an enum. An enum becoming a plain string is additive; a string becoming an enum needs a version bump. A typed read types an enum field as its listed values or any other string (StoredContentOf, UnlistedValue) and no longer throws on an unlisted value, since an enum can widen in place; typed writes still take only the listed values (ContentOf, PatchOf). migration() types both sides as StoredContentOf, so a step carries an unlisted value through. A typed subscribe() delivers a record that migrateAll() moves off the handle's version without its record, instead of throwing in the dispatcher. Conformance fixtures pin a 422 for a value outside the list and a 409 for removing values. The adapter conformance suite checks that an enum field sorts by value.

  • #445 c427f43 Thanks @cuibonobo! - Export isAuthorityAssociation from @haverstack/core, for apps that split a journal entry's association changes between amendAssociations() and amendAccess(), and partitionAssociations and AUTHORITY_ASSOCIATION_KINDS from @haverstack/core/adapter, for storage engines that keep both halves in one table.

  • #436 90d800a Thanks @cuibonobo! - StackRecordAdapter.subscribeChanges() takes SubscribeOptions, the same options a subscriber passes to subscribe(). SubscribeChangesOptions is gone from @haverstack/core/adapter; it had the same fields, and Stack already forwarded every one of them, the subscriber's own onError included. A new MutateOptions type in @haverstack/core/adapter names the options every version-bumping adapter mutation takes. GrantContent and InstallRequest are now derived from TypeGrant.

  • #439 7d30040 Thanks @cuibonobo! - A record id using the reserved _ prefix is now refused as Invalid ID "<id>": uses the reserved "_" prefix., the same Invalid <field> "<value>": <reason>. shape every other record-ID refusal uses. The error-bad-request-id-reserved-prefix fixture pins the new wording.

  • #447 44fc3f6 Thanks @cuibonobo! - A collection's filter.content, filter.contentPresent and sort.contentField are typed from its content type: a typo'd field, a value outside an enum, an object value (which never matches) or a nested sort field no longer compiles. Adds ContentPathOf<C> and SortableFieldOf<C>.

    A collection query with a content filter or sort reaches only records stored at the handle's version, since a predicate in the handle's shape cannot be translated into another version's. Its first page sets skipped.older or skipped.newer when records at another version match the rest of the query.

  • #446 d0b7950 Thanks @cuibonobo! - Typed access goes through collections. client.collection(handle) returns a Collection typed by the handle's content, with one signature per verb — get, query, subscribe, create, mutate, patchContent, associate, dissociate, amendAssociations, grantAccess, revokeAccess, amendAccess, delete, undelete and restoreVersion — every one returning a typed record without a re-read. A collection spans the handle's whole family and migrates each record in memory to the handle's version. A record stored at a newer version is a misfit: query() reports it in misfits and keeps the page and cursor, get() throws MisfitError, and subscribe() carries it as misfit. A content write to a record at an older version commits its migration as a write of its own first. collection() refuses a handle whose migratesFrom has no migration passed to Stack.open().

    The handle-first overloads of get, query, create, mutate, patchContent and subscribe are removed, with TypedRecord, TypedQuery, TypedChange, TypedChangeSet and TypedSubscribeOptions. PatchOf is removed: a collection's patch type is ContentPatch<C>, derived from its content type, and StoredContent<C> is what its reads return.

  • #415 f616aaa Thanks @cuibonobo! - A type handle carries what defineType() takes: typeHandle({ id, name, schema, migratesFrom }), with migratesFrom given as a handle or a TypeId. defineType(handle) and a manifest's types take it as written. Migrations are typed values built with migration(from, to, fn), where fn is checked as the first handle's content to the second's, and are passed to Stack.open(adapter, { migrations }). migratesFrom must name an earlier version of the same family, and typeHandle() and defineType() refuse anything else. migration() checks that pairing within a family and builds a step into another family without it, so an app's own type can migrate into a commons type. Stack.open() refuses a set of migrations it could not walk: a duplicate from, a malformed TypeId, a step backwards within a family, or a cycle. registerMigration() and MigrationFn are removed. @haverstack/commons drops CommonsType; its exports are plain type handles.

  • #413 9b4adef Thanks @cuibonobo! - StackValidationError's message header names what was validated: record content keeps "Content validation failed", a type schema reads "Schema validation failed", and argument checks read "Invalid arguments". associate()/dissociate() and grantAccess()/revokeAccess() report list errors under associations/permissions, the parameter the caller passed, rather than changes. deserializeError() keeps the header a server sent.

  • #431 89e0a07 Thanks @cuibonobo! - Stack and ScopedStack accept an internal write expectation on every write verb — the record's Type family, and on a content write its exact version — checked against the read each write already makes, so a typed write is refused before anything lands and costs no extra round trip. A typed mutate() or patchContent() now uses it: a record of another family is not found, and one stored at another version of the family is still refused with StackBadRequestError. ScopedStack.amendAssociations() and amendAccess() take their options third and surface fourth, as Stack's do.

Patch Changes

  • #437 98401c0 Thanks @cuibonobo! - Organize the ./wire, ./did and ./adapter subpath modules into folders of their own. The subpath exports are unchanged.

  • #438 da5148b Thanks @cuibonobo! - Split Stack and ScopedStack into folders of smaller modules — the StackClient interface and its option types, the migration registry, system Type definitions, write invariants, app installs, type grants, attachment cleanup, scope authority and the scoped change feed each live in a file of their own — and fold logic the two classes repeated into shared helpers. The public API and behaviour are unchanged.

  • #450 55c33ba Thanks @cuibonobo! - README: "Writing an app" covers collections, typed migrations and app installs, and the quick start works through a collection.

@haverstack/[email protected]

Minor Changes

  • #449 a40cee0 Thanks @cuibonobo! - Migrations are declared steps. migration(from, to, steps) takes a list built from rename, map, add, drop and derive, replacing the function form, and checks the list against both handles' schemas when it runs: a step naming a field that is not there, a carried field the target would refuse, or a required field nothing produces throws StackMigrationError. Migration carries its steps.

    A collection's content filter or sort now spans the older versions its migrations translate it to, rather than only the handle's version. A key across a rename or add translates; one across a derive, or a sort across a map, narrows that version and sets skipped.older as before. Two query shapes carry it, each gated by a new capability that is a cap on keys: filter.contentByType (a content predicate per typeId, never beside content or contentPresent) and sort.contentFieldByType (a sort field or a reduced constant per typeId). StackCapabilities gains filter.contentByType and sort.contentFieldByType; local adapters declare 64, and normalizeCapabilities() reads an absent or malformed cap as 0. parseQueryBody() accepts both shapes. Conformance fixtures pin both shapes and their 400s, and the adapter conformance suite checks them.

Patch Changes

  • #445 d8ef10d Thanks @cuibonobo! - filter.search no longer drops a NOT written inside a quoted phrase: "cats (not dogs" searches for the phrase as typed.

  • #445 dd7cba0 Thanks @cuibonobo! - Concurrent writes to one record no longer lose updates: mutateRecord, restoreVersion and commitMigration read and check the record inside the transaction that writes it, so a content patch applies to the content as it stands rather than to an earlier read.

  • #445 af5bc5c Thanks @cuibonobo! - Remove redundant code from the bundled SQLite record logic: unused barrel exports, local aliases of core's native sort fields, and repeated not-found/version-read/row-hydration code.

  • #445 2d9da43 Thanks @cuibonobo! - Internal restructure of the bundled SQLite record logic: the full-text and content indexes move into their own module. No behavior change.

  • Updated dependencies [7d30040, 98401c0, a40cee0, fdca4ca, c427f43, 90d800a, 7d30040, da5148b, 44fc3f6, d0b7950, f616aaa, 9b4adef, 89e0a07, 55c33ba]:

@haverstack/[email protected]

Minor Changes

  • #449 a40cee0 Thanks @cuibonobo! - Migrations are declared steps. migration(from, to, steps) takes a list built from rename, map, add, drop and derive, replacing the function form, and checks the list against both handles' schemas when it runs: a step naming a field that is not there, a carried field the target would refuse, or a required field nothing produces throws StackMigrationError. Migration carries its steps.

    A collection's content filter or sort now spans the older versions its migrations translate it to, rather than only the handle's version. A key across a rename or add translates; one across a derive, or a sort across a map, narrows that version and sets skipped.older as before. Two query shapes carry it, each gated by a new capability that is a cap on keys: filter.contentByType (a content predicate per typeId, never beside content or contentPresent) and sort.contentFieldByType (a sort field or a reduced constant per typeId). StackCapabilities gains filter.contentByType and sort.contentFieldByType; local adapters declare 64, and normalizeCapabilities() reads an absent or malformed cap as 0. parseQueryBody() accepts both shapes. Conformance fixtures pin both shapes and their 400s, and the adapter conformance suite checks them.

Patch Changes

  • #445 d8ef10d Thanks @cuibonobo! - filter.search no longer drops a NOT written inside a quoted phrase: "cats (not dogs" searches for the phrase as typed.

  • #436 90d800a Thanks @cuibonobo! - StackRecordAdapter.subscribeChanges() takes SubscribeOptions, the same options a subscriber passes to subscribe(). SubscribeChangesOptions is gone from @haverstack/core/adapter; it had the same fields, and Stack already forwarded every one of them, the subscriber's own onError included. A new MutateOptions type in @haverstack/core/adapter names the options every version-bumping adapter mutation takes. GrantContent and InstallRequest are now derived from TypeGrant.

  • #445 dd7cba0 Thanks @cuibonobo! - Concurrent writes to one record no longer lose updates: mutateRecord, restoreVersion and commitMigration read and check the record inside the transaction that writes it, so a content patch applies to the content as it stands rather than to an earlier read.

  • #445 af5bc5c Thanks @cuibonobo! - Remove redundant code from the bundled SQLite record logic: unused barrel exports, local aliases of core's native sort fields, and repeated not-found/version-read/row-hydration code.

  • #445 2d9da43 Thanks @cuibonobo! - Internal restructure of the bundled SQLite record logic: the full-text and content indexes move into their own module. No behavior change.

  • Updated dependencies [7d30040, 98401c0, a40cee0, fdca4ca, c427f43, 90d800a, 7d30040, da5148b, 44fc3f6, d0b7950, f616aaa, 9b4adef, 89e0a07, 55c33ba]:

@haverstack/[email protected]

Minor Changes

  • #449 a40cee0 Thanks @cuibonobo! - Migrations are declared steps. migration(from, to, steps) takes a list built from rename, map, add, drop and derive, replacing the function form, and checks the list against both handles' schemas when it runs: a step naming a field that is not there, a carried field the target would refuse, or a required field nothing produces throws StackMigrationError. Migration carries its steps.

    A collection's content filter or sort now spans the older versions its migrations translate it to, rather than only the handle's version. A key across a rename or add translates; one across a derive, or a sort across a map, narrows that version and sets skipped.older as before. Two query shapes carry it, each gated by a new capability that is a cap on keys: filter.contentByType (a content predicate per typeId, never beside content or contentPresent) and sort.contentFieldByType (a sort field or a reduced constant per typeId). StackCapabilities gains filter.contentByType and sort.contentFieldByType; local adapters declare 64, and normalizeCapabilities() reads an absent or malformed cap as 0. parseQueryBody() accepts both shapes. Conformance fixtures pin both shapes and their 400s, and the adapter conformance suite checks them.

  • #413 9b4adef Thanks @cuibonobo! - StackValidationError's message header names what was validated: record content keeps "Content validation failed", a type schema reads "Schema validation failed", and argument checks read "Invalid arguments". associate()/dissociate() and grantAccess()/revokeAccess() report list errors under associations/permissions, the parameter the caller passed, rather than changes. deserializeError() keeps the header a server sent.

  • #442 59f34ce Thanks @cuibonobo! - @haverstack/wire-types no longer restates shapes @haverstack/core already defines, and its auth handshake types share one prefix:

    • AuthChallengeRequest and AuthTokenRequest are removed. Use WireAuthChallengeRequest and WireAuthTokenRequest, re-exported from @haverstack/core/wire, where the parsers that return them live.
    • AuthChallengeResponse and AuthTokenResponse are renamed WireAuthChallengeResponse and WireAuthTokenResponse to match. Their shape is unchanged.
    • WireActor and WireChangeActor are now aliases of core's Actor and ChangeActor. Their shape is unchanged.
    • WireAssociationEditsRequest is removed; nothing referenced it.

Patch Changes

@cuibonobo
cuibonobo force-pushed the changeset-release/main branch 18 times, most recently from 07e1554 to c66f141 Compare October 13, 2026 14:49
@cuibonobo
cuibonobo force-pushed the changeset-release/main branch from c66f141 to 05e000e Compare October 13, 2026 19:28
@cuibonobo
cuibonobo merged commit 7b806bb into main Oct 13, 2026
9 checks passed
@cuibonobo
cuibonobo deleted the changeset-release/main branch October 13, 2026 22:01
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