Skip to content

chore(deps): bump the metaobjects group with 6 updates#15

Open
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/npm_and_yarn/metaobjects-8fd40b1ca9
Open

chore(deps): bump the metaobjects group with 6 updates#15
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/npm_and_yarn/metaobjects-8fd40b1ca9

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Jul 18, 2026

Copy link
Copy Markdown
Contributor

Bumps the metaobjects group with 6 updates:

Package From To
@metaobjectsdev/cli 0.15.18 0.16.0
@metaobjectsdev/codegen-ts 0.15.18 0.16.0
@metaobjectsdev/render 0.15.18 0.16.0
@metaobjectsdev/runtime-ts 0.15.18 0.16.0
@metaobjectsdev/sdk 0.15.18 0.16.0
@metaobjectsdev/metadata 0.15.18 0.16.0

Updates @metaobjectsdev/cli from 0.15.18 to 0.16.0

Release notes

Sourced from @​metaobjectsdev/cli's releases.

0.15.21 — migrate-engine + wrong-row-write bug fixes; PK types derived, not hardcoded

Coordinated release: npm 0.15.21 · PyPI 0.15.13 · Maven Central 7.7.11. NuGet stays at 0.15.10 — the C# port needed no fix. It already derived the primary-key type correctly, and became the reference the other three ports were fixed against.

A bug-fix release, sourced from a downstream consumer's adoption report (TypeScript + Cloudflare D1 + uuid primary keys) and then widened by an adversarial review that hunted the same bug classes across the whole codebase. No metadata changes, no new vocabulary — existing metadata generates byte-identical output except where it was previously wrong.

Data loss and destructive migrations

  • Writable mounts performed a WRONG-ROW write/delete. On a TEXT/uuid primary key, DELETE /docs/0123 deleted row '123' (proven against real engines).
  • Every incremental meta migrate rebuilt every uuid-PK table — a false change-column-default that, on SQLite/D1, recreate-and-copies the whole table on every run, forever.
  • drop-view was auto-allowed — an extension's view or a hand-written view got an un-gated DROP VIEW.

Migrations that couldn't be applied, or silently did nothing

  • @autoSet emitted DEFAULT now() on SQLite/D1 — invalid SQL, so any entity with the standard createdAt @autoSet produced an un-appliable migration.
  • Changing field.enum @values never migrated on SQLite — meta migrate said "No schema changes" while production inserts kept violating the stale CHECK.
  • @kind: storedProc projections crashed meta migrate outright.
  • D1 introspection didn't exclude _cf_METADATA, aborting every second-and-later meta migrate --dialect d1.

Silently wrong SQL and types

  • The SQLite emitter dropped index @expr/@where/@orders — a partial UNIQUE index became a FULL UNIQUE constraint, silently rejecting valid inserts.
  • Boolean @default literals were quoted (DEFAULT 'false'), which SQLite stores as TEXT — so WHERE flag = 0 silently matched nothing.

Generated code hardcoded the primary-key type (Java, Kotlin, Python)

An entity declaring @generation: uuid got broken output while its own DTO correctly used UUID. Kotlin's generated code did not even compile. Java rejected uuid path vars with 400; Python's FastAPI router 422'd them before the handler ran. Not a metamodel gap — each port already had the type mapper and was using it a few lines away.

Note

Every migrate fix is now gated by an emit → apply to a real engine → introspect → re-diff must be EMPTY round-trip plus value-semantics probes. The absence of that gate — nothing ever ran the pipeline twice against a real database — is what let this whole class survive a large test suite. Two goldens were found to be encoding the bugs they pinned.

Full detail: CHANGELOG

Changelog

Sourced from @​metaobjectsdev/cli's changelog.

[0.16.0] — 2026-07-14

Coordinated breaking release across all four registries: npm 0.16.0 · PyPI 0.16.0 · NuGet 0.16.0 · Maven Central 7.8.0 (full lockstep; the two angular packages stay on their 0.6.x line).

⚠️ BREAKING — this release bundles two coordinated breaking changes (FR-035 + FR-036). The single change most likely to surprise an adopter: C# and Python now ENFORCE field constraints over HTTP where they were previously decorative — a POST/PATCH that a prior version silently accepted may now return 400 {"error":"validation"}.

FR-035 — present-key PATCH tristate (mutation surface)

The generated PATCH now distinguishes an ABSENT key from an explicit null, identically across all five ports (previously four different behaviors): an absent field is untouched; a present null on a nullable column CLEARS it; a present null on a @required field is 400 {"error":"validation"}; and a PATCH may omit @required fields entirely (no 400). Holds on both the vanilla and the TPH per-subtype update paths.

FR-036 — cross-port constraint-validation enforcement + semantic pins

  • @required string = NON-EMPTY (reject null and "", accept whitespace-only) — Java/Kotlin no longer reject whitespace (the auto-@NotBlank is retired for @NotNull + @Size(min=1)); C# emits [Required(AllowEmptyStrings=true)] + [MinLength(1)]; Python emits min_length=1; TS was already correct.
  • validator.regex @pattern = FULL-MATCH (the whole value must match) — TS + Python now anchor the authored pattern as ^(?:…)$; C# [RegularExpression] is anchored too (it was not a true full-match for ordered-alternation patterns).
  • C# and Python now enforce field constraints over HTTP (both were decorative at the wire tier — C# minimal-API never ran DataAnnotations, Python bound dict[str,Any]). POST and PATCH now validate present values → 400 {"error":"validation"} on all five ports, vanilla + TPH.
  • @maxLength × validator.length @max precedence is strictest-wins (min of the two).
  • A missing @required value-type field on POST now 400s on every port (previously C# accepted a garbage default); a @required field with a server-side @default/@autoSet (or an auto-generated PK) is correctly OPTIONAL on POST (a POST omitting createdAt @default:now() is 201, not 400).

New cross-port conformance gates (validation-conformance + api-contract, both lanes) lock all of the above so it can't silently drift.

[0.15.21] — 2026-07-13

npm 0.15.21 (full lockstep across all 14 @metaobjectsdev/* publish candidates).

Coordinated release: npm 0.15.21 · PyPI 0.15.13 · Maven 7.7.11. NuGet is unchanged at 0.15.10 — the C# port needed no fix (it already derived the primary-key type correctly, and became the reference the other three ports were fixed against).

A bug-fix release, sourced from a downstream consumer's adoption report (TypeScript + Cloudflare D1 + uuid primary keys) and then widened by an adversarial review that hunted the same bug classes across the whole codebase. Several of these fail silently and unsafely — a wrong-row DELETE, a cross-schema DROP VIEW, a partial-unique index becoming fully unique — and several make meta migrate either destroy work or refuse to run at all. No metadata changes; no new vocabulary. Existing metadata generates byte-identical output except where it was previously wrong.

Fixed — data loss and destructive migrations

  • Writable mounts performed a WRONG-ROW write/delete (runtime-ts). Every writable mount coerced the :id path param with a helper that numberifies any numeric-looking string. On a TEXT/uuid primary key that does not merely miss — it hits a different row: proven against real engines, DELETE /docs/0123 deleted row '123' (bun:sqlite, via column affinity), while on libsql the row became permanently unfindable (404 on GET/PATCH/DELETE). All writable mounts (fastify, hono, ObjectManager, M:N) now resolve the id against the primary key's real column type. Also: a successful DELETE on bun:sqlite previously returned 404 after deleting the row.
  • Every incremental meta migrate rebuilt every uuid-PK table. A uuid primary key's physical DEFAULT is synthesized at emit time and deliberately not modelled on the expected side, but introspection read it back as a real default — so the diff reported a false change-column-default for every uuid-PK table, on every run. On SQLite/D1 (no ALTER COLUMN) that recreate-and-copies the whole table, forever. Postgres emitted a bogus ALTER instead.
  • drop-view was auto-allowed. An extension's view (e.g. pg_stat_statements) or any hand-written view got an un-gated DROP VIEW emitted. Now gated behind allow.dropView, extension-owned views are filtered via pg_depend, and the recreate-pair exemption is keyed by (schema, name) — keyed on the bare name, rebuilding reporting.summary un-gated a destructive drop of a hand-written public.summary.

Fixed — migrations that could not be applied, or silently did nothing

  • @autoSet emitted DEFAULT now() on SQLite/D1 — invalid SQL, so any entity with the standard createdAt @autoSet produced a migration that could not be applied at all.
  • Changing field.enum @values never migrated on SQLite. CHECK constraints were create-time-only and no change kind triggered the recreate path, so meta migrate reported "No schema changes" while inserts of the new member kept violating the stale CHECK in production. (--allow drop-check was also rejected by CLI arg validation, making Postgres CHECK evolution ungrantable.)
  • @kind: storedProc projections crashed meta migrate outright; @kind: materializedView silently created a plain view under the materialized view's name.
  • D1 introspection didn't exclude Cloudflare/wrangler tables. _cf_METADATA appears after any write and D1's authorizer denies even pragma_table_info on it, aborting every second-and-later meta migrate --dialect d1; d1_migrations read as an undeclared table, so the diff proposed dropping wrangler's own bookkeeping.
  • Infra-table exclusions used _ as a literal when it is a LIKE wildcard — so '__new_%' also matched an ordinary table named renewals, hiding it from introspection and re-proposing CREATE TABLE forever.

Fixed — silently wrong SQL and types

  • The SQLite emitter dropped index @expr / @where / @orders. An expression index emitted CREATE INDEX x ON t () (invalid SQL), and a partial UNIQUE index became a FULL UNIQUE constraint — silently rejecting inserts the model says are valid.
  • Boolean/numeric @default literals were quoted on SQLite (DEFAULT 'false'), which SQLite stores as TEXT in a numeric column, so WHERE flag = 0 silently matched nothing. Literals containing a quote ("don't") or parentheses ("n/a (unknown)") never round-tripped either.
  • FK constraint names never converged on SQLite (the engine stores none), so a composite FK or @constraintName produced a permanently blocked drop-fk and meta migrate exited 1 forever.
  • @isArray on any scalar but string/uuid generated a Drizzle .array() column against a migrated SCALAR column — the first insert failed, with no drift signal.

Fixed — generated code hardcoded the primary-key type (Java, Kotlin, Python)

... (truncated)

Commits
  • ca54fa0 chore(release): FR-036 coordinated breaking release — 0.16.0 / Maven 7.8.0
  • 2019baf fix(codegen): a hand-authored view no longer aborts meta migrate for the wh...
  • cacbdac fix(migrate): make Postgres views converge; add non-destructive replace + lou...
  • 1bfed37 chore(release): 0.15.21 — npm 0.15.21 · PyPI 0.15.13 · Maven 7.7.11
  • 61e5d8e fix(migrate,runtime,cli): close the migrate-engine + wrong-row-write bug batch
  • 55650ee chore(release): @​metaobjectsdev TypeScript packages 0.15.20
  • 4c90504 fix(cli): verify --templates drift-checks @​kind=email + document output (#193)
  • 3a2944f feat(loader)!: ADR-0042 — bare references are package-local (TS reference port)
  • 1a7b8e0 chore(release): 0.15.19 (npm) — origin.aggregate @​filter + projection/view gu...
  • 08da254 test(cli): fix stale deploy-all agent-context scaffolding assertions → stack-...
  • Additional commits viewable in compare view

Updates @metaobjectsdev/codegen-ts from 0.15.18 to 0.16.0

Release notes

Sourced from @​metaobjectsdev/codegen-ts's releases.

0.15.21 — migrate-engine + wrong-row-write bug fixes; PK types derived, not hardcoded

Coordinated release: npm 0.15.21 · PyPI 0.15.13 · Maven Central 7.7.11. NuGet stays at 0.15.10 — the C# port needed no fix. It already derived the primary-key type correctly, and became the reference the other three ports were fixed against.

A bug-fix release, sourced from a downstream consumer's adoption report (TypeScript + Cloudflare D1 + uuid primary keys) and then widened by an adversarial review that hunted the same bug classes across the whole codebase. No metadata changes, no new vocabulary — existing metadata generates byte-identical output except where it was previously wrong.

Data loss and destructive migrations

  • Writable mounts performed a WRONG-ROW write/delete. On a TEXT/uuid primary key, DELETE /docs/0123 deleted row '123' (proven against real engines).
  • Every incremental meta migrate rebuilt every uuid-PK table — a false change-column-default that, on SQLite/D1, recreate-and-copies the whole table on every run, forever.
  • drop-view was auto-allowed — an extension's view or a hand-written view got an un-gated DROP VIEW.

Migrations that couldn't be applied, or silently did nothing

  • @autoSet emitted DEFAULT now() on SQLite/D1 — invalid SQL, so any entity with the standard createdAt @autoSet produced an un-appliable migration.
  • Changing field.enum @values never migrated on SQLite — meta migrate said "No schema changes" while production inserts kept violating the stale CHECK.
  • @kind: storedProc projections crashed meta migrate outright.
  • D1 introspection didn't exclude _cf_METADATA, aborting every second-and-later meta migrate --dialect d1.

Silently wrong SQL and types

  • The SQLite emitter dropped index @expr/@where/@orders — a partial UNIQUE index became a FULL UNIQUE constraint, silently rejecting valid inserts.
  • Boolean @default literals were quoted (DEFAULT 'false'), which SQLite stores as TEXT — so WHERE flag = 0 silently matched nothing.

Generated code hardcoded the primary-key type (Java, Kotlin, Python)

An entity declaring @generation: uuid got broken output while its own DTO correctly used UUID. Kotlin's generated code did not even compile. Java rejected uuid path vars with 400; Python's FastAPI router 422'd them before the handler ran. Not a metamodel gap — each port already had the type mapper and was using it a few lines away.

Note

Every migrate fix is now gated by an emit → apply to a real engine → introspect → re-diff must be EMPTY round-trip plus value-semantics probes. The absence of that gate — nothing ever ran the pipeline twice against a real database — is what let this whole class survive a large test suite. Two goldens were found to be encoding the bugs they pinned.

Full detail: CHANGELOG

Changelog

Sourced from @​metaobjectsdev/codegen-ts's changelog.

[0.16.0] — 2026-07-14

Coordinated breaking release across all four registries: npm 0.16.0 · PyPI 0.16.0 · NuGet 0.16.0 · Maven Central 7.8.0 (full lockstep; the two angular packages stay on their 0.6.x line).

⚠️ BREAKING — this release bundles two coordinated breaking changes (FR-035 + FR-036). The single change most likely to surprise an adopter: C# and Python now ENFORCE field constraints over HTTP where they were previously decorative — a POST/PATCH that a prior version silently accepted may now return 400 {"error":"validation"}.

FR-035 — present-key PATCH tristate (mutation surface)

The generated PATCH now distinguishes an ABSENT key from an explicit null, identically across all five ports (previously four different behaviors): an absent field is untouched; a present null on a nullable column CLEARS it; a present null on a @required field is 400 {"error":"validation"}; and a PATCH may omit @required fields entirely (no 400). Holds on both the vanilla and the TPH per-subtype update paths.

FR-036 — cross-port constraint-validation enforcement + semantic pins

  • @required string = NON-EMPTY (reject null and "", accept whitespace-only) — Java/Kotlin no longer reject whitespace (the auto-@NotBlank is retired for @NotNull + @Size(min=1)); C# emits [Required(AllowEmptyStrings=true)] + [MinLength(1)]; Python emits min_length=1; TS was already correct.
  • validator.regex @pattern = FULL-MATCH (the whole value must match) — TS + Python now anchor the authored pattern as ^(?:…)$; C# [RegularExpression] is anchored too (it was not a true full-match for ordered-alternation patterns).
  • C# and Python now enforce field constraints over HTTP (both were decorative at the wire tier — C# minimal-API never ran DataAnnotations, Python bound dict[str,Any]). POST and PATCH now validate present values → 400 {"error":"validation"} on all five ports, vanilla + TPH.
  • @maxLength × validator.length @max precedence is strictest-wins (min of the two).
  • A missing @required value-type field on POST now 400s on every port (previously C# accepted a garbage default); a @required field with a server-side @default/@autoSet (or an auto-generated PK) is correctly OPTIONAL on POST (a POST omitting createdAt @default:now() is 201, not 400).

New cross-port conformance gates (validation-conformance + api-contract, both lanes) lock all of the above so it can't silently drift.

[0.15.21] — 2026-07-13

npm 0.15.21 (full lockstep across all 14 @metaobjectsdev/* publish candidates).

Coordinated release: npm 0.15.21 · PyPI 0.15.13 · Maven 7.7.11. NuGet is unchanged at 0.15.10 — the C# port needed no fix (it already derived the primary-key type correctly, and became the reference the other three ports were fixed against).

A bug-fix release, sourced from a downstream consumer's adoption report (TypeScript + Cloudflare D1 + uuid primary keys) and then widened by an adversarial review that hunted the same bug classes across the whole codebase. Several of these fail silently and unsafely — a wrong-row DELETE, a cross-schema DROP VIEW, a partial-unique index becoming fully unique — and several make meta migrate either destroy work or refuse to run at all. No metadata changes; no new vocabulary. Existing metadata generates byte-identical output except where it was previously wrong.

Fixed — data loss and destructive migrations

  • Writable mounts performed a WRONG-ROW write/delete (runtime-ts). Every writable mount coerced the :id path param with a helper that numberifies any numeric-looking string. On a TEXT/uuid primary key that does not merely miss — it hits a different row: proven against real engines, DELETE /docs/0123 deleted row '123' (bun:sqlite, via column affinity), while on libsql the row became permanently unfindable (404 on GET/PATCH/DELETE). All writable mounts (fastify, hono, ObjectManager, M:N) now resolve the id against the primary key's real column type. Also: a successful DELETE on bun:sqlite previously returned 404 after deleting the row.
  • Every incremental meta migrate rebuilt every uuid-PK table. A uuid primary key's physical DEFAULT is synthesized at emit time and deliberately not modelled on the expected side, but introspection read it back as a real default — so the diff reported a false change-column-default for every uuid-PK table, on every run. On SQLite/D1 (no ALTER COLUMN) that recreate-and-copies the whole table, forever. Postgres emitted a bogus ALTER instead.
  • drop-view was auto-allowed. An extension's view (e.g. pg_stat_statements) or any hand-written view got an un-gated DROP VIEW emitted. Now gated behind allow.dropView, extension-owned views are filtered via pg_depend, and the recreate-pair exemption is keyed by (schema, name) — keyed on the bare name, rebuilding reporting.summary un-gated a destructive drop of a hand-written public.summary.

Fixed — migrations that could not be applied, or silently did nothing

  • @autoSet emitted DEFAULT now() on SQLite/D1 — invalid SQL, so any entity with the standard createdAt @autoSet produced a migration that could not be applied at all.
  • Changing field.enum @values never migrated on SQLite. CHECK constraints were create-time-only and no change kind triggered the recreate path, so meta migrate reported "No schema changes" while inserts of the new member kept violating the stale CHECK in production. (--allow drop-check was also rejected by CLI arg validation, making Postgres CHECK evolution ungrantable.)
  • @kind: storedProc projections crashed meta migrate outright; @kind: materializedView silently created a plain view under the materialized view's name.
  • D1 introspection didn't exclude Cloudflare/wrangler tables. _cf_METADATA appears after any write and D1's authorizer denies even pragma_table_info on it, aborting every second-and-later meta migrate --dialect d1; d1_migrations read as an undeclared table, so the diff proposed dropping wrangler's own bookkeeping.
  • Infra-table exclusions used _ as a literal when it is a LIKE wildcard — so '__new_%' also matched an ordinary table named renewals, hiding it from introspection and re-proposing CREATE TABLE forever.

Fixed — silently wrong SQL and types

  • The SQLite emitter dropped index @expr / @where / @orders. An expression index emitted CREATE INDEX x ON t () (invalid SQL), and a partial UNIQUE index became a FULL UNIQUE constraint — silently rejecting inserts the model says are valid.
  • Boolean/numeric @default literals were quoted on SQLite (DEFAULT 'false'), which SQLite stores as TEXT in a numeric column, so WHERE flag = 0 silently matched nothing. Literals containing a quote ("don't") or parentheses ("n/a (unknown)") never round-tripped either.
  • FK constraint names never converged on SQLite (the engine stores none), so a composite FK or @constraintName produced a permanently blocked drop-fk and meta migrate exited 1 forever.
  • @isArray on any scalar but string/uuid generated a Drizzle .array() column against a migrated SCALAR column — the first insert failed, with no drift signal.

Fixed — generated code hardcoded the primary-key type (Java, Kotlin, Python)

... (truncated)

Commits
  • ca54fa0 chore(release): FR-036 coordinated breaking release — 0.16.0 / Maven 7.8.0
  • 361b3e1 fix(fr-036): TS Pin-1 floor robustness — review findings #8 + #10
  • ba93aa8 feat(fr-036): TPH partial-PATCH tristate — scenario + TS codegen + C# referen...
  • 06ab2b0 feat(fr-036): constraint-validation gates + TS reference (Pin 2 full-match, A...
  • fe592c1 feat(fr-035): present-key PATCH tristate — TS port + cross-port gate
  • 29d52fd feat(codegen-ts): typed <Entity>Patch surface for the update path (FR-035, #198)
  • 2019baf fix(codegen): a hand-authored view no longer aborts meta migrate for the wh...
  • cacbdac fix(migrate): make Postgres views converge; add non-destructive replace + lou...
  • 1bfed37 chore(release): 0.15.21 — npm 0.15.21 · PyPI 0.15.13 · Maven 7.7.11
  • 61e5d8e fix(migrate,runtime,cli): close the migrate-engine + wrong-row-write bug batch
  • Additional commits viewable in compare view

Updates @metaobjectsdev/render from 0.15.18 to 0.16.0

Release notes

Sourced from @​metaobjectsdev/render's releases.

0.15.21 — migrate-engine + wrong-row-write bug fixes; PK types derived, not hardcoded

Coordinated release: npm 0.15.21 · PyPI 0.15.13 · Maven Central 7.7.11. NuGet stays at 0.15.10 — the C# port needed no fix. It already derived the primary-key type correctly, and became the reference the other three ports were fixed against.

A bug-fix release, sourced from a downstream consumer's adoption report (TypeScript + Cloudflare D1 + uuid primary keys) and then widened by an adversarial review that hunted the same bug classes across the whole codebase. No metadata changes, no new vocabulary — existing metadata generates byte-identical output except where it was previously wrong.

Data loss and destructive migrations

  • Writable mounts performed a WRONG-ROW write/delete. On a TEXT/uuid primary key, DELETE /docs/0123 deleted row '123' (proven against real engines).
  • Every incremental meta migrate rebuilt every uuid-PK table — a false change-column-default that, on SQLite/D1, recreate-and-copies the whole table on every run, forever.
  • drop-view was auto-allowed — an extension's view or a hand-written view got an un-gated DROP VIEW.

Migrations that couldn't be applied, or silently did nothing

  • @autoSet emitted DEFAULT now() on SQLite/D1 — invalid SQL, so any entity with the standard createdAt @autoSet produced an un-appliable migration.
  • Changing field.enum @values never migrated on SQLite — meta migrate said "No schema changes" while production inserts kept violating the stale CHECK.
  • @kind: storedProc projections crashed meta migrate outright.
  • D1 introspection didn't exclude _cf_METADATA, aborting every second-and-later meta migrate --dialect d1.

Silently wrong SQL and types

  • The SQLite emitter dropped index @expr/@where/@orders — a partial UNIQUE index became a FULL UNIQUE constraint, silently rejecting valid inserts.
  • Boolean @default literals were quoted (DEFAULT 'false'), which SQLite stores as TEXT — so WHERE flag = 0 silently matched nothing.

Generated code hardcoded the primary-key type (Java, Kotlin, Python)

An entity declaring @generation: uuid got broken output while its own DTO correctly used UUID. Kotlin's generated code did not even compile. Java rejected uuid path vars with 400; Python's FastAPI router 422'd them before the handler ran. Not a metamodel gap — each port already had the type mapper and was using it a few lines away.

Note

Every migrate fix is now gated by an emit → apply to a real engine → introspect → re-diff must be EMPTY round-trip plus value-semantics probes. The absence of that gate — nothing ever ran the pipeline twice against a real database — is what let this whole class survive a large test suite. Two goldens were found to be encoding the bugs they pinned.

Full detail: CHANGELOG

Changelog

Sourced from @​metaobjectsdev/render's changelog.

[0.16.0] — 2026-07-14

Coordinated breaking release across all four registries: npm 0.16.0 · PyPI 0.16.0 · NuGet 0.16.0 · Maven Central 7.8.0 (full lockstep; the two angular packages stay on their 0.6.x line).

⚠️ BREAKING — this release bundles two coordinated breaking changes (FR-035 + FR-036). The single change most likely to surprise an adopter: C# and Python now ENFORCE field constraints over HTTP where they were previously decorative — a POST/PATCH that a prior version silently accepted may now return 400 {"error":"validation"}.

FR-035 — present-key PATCH tristate (mutation surface)

The generated PATCH now distinguishes an ABSENT key from an explicit null, identically across all five ports (previously four different behaviors): an absent field is untouched; a present null on a nullable column CLEARS it; a present null on a @required field is 400 {"error":"validation"}; and a PATCH may omit @required fields entirely (no 400). Holds on both the vanilla and the TPH per-subtype update paths.

FR-036 — cross-port constraint-validation enforcement + semantic pins

  • @required string = NON-EMPTY (reject null and "", accept whitespace-only) — Java/Kotlin no longer reject whitespace (the auto-@NotBlank is retired for @NotNull + @Size(min=1)); C# emits [Required(AllowEmptyStrings=true)] + [MinLength(1)]; Python emits min_length=1; TS was already correct.
  • validator.regex @pattern = FULL-MATCH (the whole value must match) — TS + Python now anchor the authored pattern as ^(?:…)$; C# [RegularExpression] is anchored too (it was not a true full-match for ordered-alternation patterns).
  • C# and Python now enforce field constraints over HTTP (both were decorative at the wire tier — C# minimal-API never ran DataAnnotations, Python bound dict[str,Any]). POST and PATCH now validate present values → 400 {"error":"validation"} on all five ports, vanilla + TPH.
  • @maxLength × validator.length @max precedence is strictest-wins (min of the two).
  • A missing @required value-type field on POST now 400s on every port (previously C# accepted a garbage default); a @required field with a server-side @default/@autoSet (or an auto-generated PK) is correctly OPTIONAL on POST (a POST omitting createdAt @default:now() is 201, not 400).

New cross-port conformance gates (validation-conformance + api-contract, both lanes) lock all of the above so it can't silently drift.

[0.15.21] — 2026-07-13

npm 0.15.21 (full lockstep across all 14 @metaobjectsdev/* publish candidates).

Coordinated release: npm 0.15.21 · PyPI 0.15.13 · Maven 7.7.11. NuGet is unchanged at 0.15.10 — the C# port needed no fix (it already derived the primary-key type correctly, and became the reference the other three ports were fixed against).

A bug-fix release, sourced from a downstream consumer's adoption report (TypeScript + Cloudflare D1 + uuid primary keys) and then widened by an adversarial review that hunted the same bug classes across the whole codebase. Several of these fail silently and unsafely — a wrong-row DELETE, a cross-schema DROP VIEW, a partial-unique index becoming fully unique — and several make meta migrate either destroy work or refuse to run at all. No metadata changes; no new vocabulary. Existing metadata generates byte-identical output except where it was previously wrong.

Fixed — data loss and destructive migrations

  • Writable mounts performed a WRONG-ROW write/delete (runtime-ts). Every writable mount coerced the :id path param with a helper that numberifies any numeric-looking string. On a TEXT/uuid primary key that does not merely miss — it hits a different row: proven against real engines, DELETE /docs/0123 deleted row '123' (bun:sqlite, via column affinity), while on libsql the row became permanently unfindable (404 on GET/PATCH/DELETE). All writable mounts (fastify, hono, ObjectManager, M:N) now resolve the id against the primary key's real column type. Also: a successful DELETE on bun:sqlite previously returned 404 after deleting the row.
  • Every incremental meta migrate rebuilt every uuid-PK table. A uuid primary key's physical DEFAULT is synthesized at emit time and deliberately not modelled on the expected side, but introspection read it back as a real default — so the diff reported a false change-column-default for every uuid-PK table, on every run. On SQLite/D1 (no ALTER COLUMN) that recreate-and-copies the whole table, forever. Postgres emitted a bogus ALTER instead.
  • drop-view was auto-allowed. An extension's view (e.g. pg_stat_statements) or any hand-written view got an un-gated DROP VIEW emitted. Now gated behind allow.dropView, extension-owned views are filtered via pg_depend, and the recreate-pair exemption is keyed by (schema, name) — keyed on the bare name, rebuilding reporting.summary un-gated a destructive drop of a hand-written public.summary.

Fixed — migrations that could not be applied, or silently did nothing

  • @autoSet emitted DEFAULT now() on SQLite/D1 — invalid SQL, so any entity with the standard createdAt @autoSet produced a migration that could not be applied at all.
  • Changing field.enum @values never migrated on SQLite. CHECK constraints were create-time-only and no change kind triggered the recreate path, so meta migrate reported "No schema changes" while inserts of the new member kept violating the stale CHECK in production. (--allow drop-check was also rejected by CLI arg validation, making Postgres CHECK evolution ungrantable.)
  • @kind: storedProc projections crashed meta migrate outright; @kind: materializedView silently created a plain view under the materialized view's name.
  • D1 introspection didn't exclude Cloudflare/wrangler tables. _cf_METADATA appears after any write and D1's authorizer denies even pragma_table_info on it, aborting every second-and-later meta migrate --dialect d1; d1_migrations read as an undeclared table, so the diff proposed dropping wrangler's own bookkeeping.
  • Infra-table exclusions used _ as a literal when it is a LIKE wildcard — so '__new_%' also matched an ordinary table named renewals, hiding it from introspection and re-proposing CREATE TABLE forever.

Fixed — silently wrong SQL and types

  • The SQLite emitter dropped index @expr / @where / @orders. An expression index emitted CREATE INDEX x ON t () (invalid SQL), and a partial UNIQUE index became a FULL UNIQUE constraint — silently rejecting inserts the model says are valid.
  • Boolean/numeric @default literals were quoted on SQLite (DEFAULT 'false'), which SQLite stores as TEXT in a numeric column, so WHERE flag = 0 silently matched nothing. Literals containing a quote ("don't") or parentheses ("n/a (unknown)") never round-tripped either.
  • FK constraint names never converged on SQLite (the engine stores none), so a composite FK or @constraintName produced a permanently blocked drop-fk and meta migrate exited 1 forever.
  • @isArray on any scalar but string/uuid generated a Drizzle .array() column against a migrated SCALAR column — the first insert failed, with no drift signal.

Fixed — generated code hardcoded the primary-key type (Java, Kotlin, Python)

... (truncated)

Commits

Updates @metaobjectsdev/runtime-ts from 0.15.18 to 0.16.0

Release notes

Sourced from @​metaobjectsdev/runtime-ts's releases.

0.15.21 — migrate-engine + wrong-row-write bug fixes; PK types derived, not hardcoded

Coordinated release: npm 0.15.21 · PyPI 0.15.13 · Maven Central 7.7.11. NuGet stays at 0.15.10 — the C# port needed no fix. It already derived the primary-key type correctly, and became the reference the other three ports were fixed against.

A bug-fix release, sourced from a downstream consumer's adoption report (TypeScript + Cloudflare D1 + uuid primary keys) and then widened by an adversarial review that hunted the same bug classes across the whole codebase. No metadata changes, no new vocabulary — existing metadata generates byte-identical output except where it was previously wrong.

Data loss and destructive migrations

  • Writable mounts performed a WRONG-ROW write/delete. On a TEXT/uuid primary key, DELETE /docs/0123 deleted row '123' (proven against real engines).
  • Every incremental meta migrate rebuilt every uuid-PK table — a false change-column-default that, on SQLite/D1, recreate-and-copies the whole table on every run, forever.
  • drop-view was auto-allowed — an extension's view or a hand-written view got an un-gated DROP VIEW.

Migrations that couldn't be applied, or silently did nothing

  • @autoSet emitted DEFAULT now() on SQLite/D1 — invalid SQL, so any entity with the standard createdAt @autoSet produced an un-appliable migration.
  • Changing field.enum @values never migrated on SQLite — meta migrate said "No schema changes" while production inserts kept violating the stale CHECK.
  • @kind: storedProc projections crashed meta migrate outright.
  • D1 introspection didn't exclude _cf_METADATA, aborting every second-and-later meta migrate --dialect d1.

Silently wrong SQL and types

  • The SQLite emitter dropped index @expr/@where/@orders — a partial UNIQUE index became a FULL UNIQUE constraint, silently rejecting valid inserts.
  • Boolean @default literals were quoted (DEFAULT 'false'), which SQLite stores as TEXT — so WHERE flag = 0 silently matched nothing.

Generated code hardcoded the primary-key type (Java, Kotlin, Python)

An entity declaring @generation: uuid got broken output while its own DTO correctly used UUID. Kotlin's generated code did not even compile. Java rejected uuid path vars with 400; Python's FastAPI router 422'd them before the handler ran. Not a metamodel gap — each port already had the type mapper and was using it a few lines away.

Note

Every migrate fix is now gated by an emit → apply to a real engine → introspect → re-diff must be EMPTY round-trip plus value-semantics probes. The absence of that gate — nothing ever ran the pipeline twice against a real database — is what let this whole class survive a large test suite. Two goldens were found to be encoding the bugs they pinned.

Full detail: CHANGELOG

Changelog

Sourced from @​metaobjectsdev/runtime-ts's changelog.

[0.16.0] — 2026-07-14

Coordinated breaking release across all four registries: npm 0.16.0 · PyPI 0.16.0 · NuGet 0.16.0 · Maven Central 7.8.0 (full lockstep; the two angular packages stay on their 0.6.x line).

⚠️ BREAKING — this release bundles two coordinated breaking changes (FR-035 + FR-036). The single change most likely to surprise an adopter: C# and Python now ENFORCE field constraints over HTTP where they were previously decorative — a POST/PATCH that a prior version silently accepted may now return 400 {"error":"validation"}.

FR-035 — present-key PATCH tristate (mutation surface)

The generated PATCH now distinguishes an ABSENT key from an explicit null, identically across all five ports (previously four different behaviors): an absent field is untouched; a present null on a nullable column CLEARS it; a present null on a @required field is 400 {"error":"validation"}; and a PATCH may omit @required fields entirely (no 400). Holds on both the vanilla and the TPH per-subtype update paths.

FR-036 — cross-port constraint-validation enforcement + semantic pins

  • @required string = NON-EMPTY (reject null and "", accept whitespace-only) — Java/Kotlin no longer reject whitespace (the auto-@NotBlank is retired for @NotNull + @Size(min=1)); C# emits [Required(AllowEmptyStrings=true)] + [MinLength(1)]; Python emits min_length=1; TS was already correct.
  • validator.regex @pattern = FULL-MATCH (the whole value must match) — TS + Python now anchor the authored pattern as ^(?:…)$; C# [RegularExpression] is anchored too (it was not a true full-match for ordered-alternation patterns).
  • C# and Python now enforce field constraints over HTTP (both were decorative at the wire tier — C# minimal-API never ran DataAnnotations, Python bound dict[str,Any]). POST and PATCH now validate present values → 400 {"error":"validation"} on all five ports, vanilla + TPH.
  • @maxLength × validator.length @max precedence is strictest-wins (min of the two).
  • A missing @required value-type field on POST now 400s on every port (previously C# accepted a garbage default); a @required field with a server-side @default/@autoSet (or an auto-generated PK) is correctly OPTIONAL on POST (a POST omitting createdAt @default:now() is 201, not 400).

New cross-port conformance gates (validation-conformance + api-contract, both lanes) lock all of the above so it can't silently drift.

[0.15.21] — 2026-07-13

npm 0.15.21 (full lockstep across all 14 @metaobjectsdev/* publish candidates).

Coordinated release: npm 0.15.21 · PyPI 0.15.13 · Maven 7.7.11. NuGet is unchanged at 0.15.10 — the C# port needed no fix (it already derived the primary-key type correctly, and became the reference the other three ports were fixed against).

A bug-fix release, sourced from a downstream consumer's adoption report (TypeScript + Cloudflare D1 + uuid primary keys) and then widened by an adversarial review that hunted the same bug classes across the whole codebase. Several of these fail silently and unsafely — a wrong-row DELETE, a cross-schema DROP VIEW, a partial-unique index becoming fully unique — and several make meta migrate either destroy work or refuse to run at all. No metadata changes; no new vocabulary. Existing metadata generates byte-identical output except where it was previously wrong.

Fixed — data loss and destructive migrations

  • Writable mounts performed a WRONG-ROW write/delete (runtime-ts). Every writable mount coerced the :id path param with a helper that numberifies any numeric-looking string. On a TEXT/uuid primary key that does not merely miss — it hits a different row: proven against real engines, DELETE /docs/0123 deleted row '123' (bun:sqlite, via column affinity), while on libsql the row became permanently unfindable (404 on GET/PATCH/DELETE). All writable mounts (fastify, hono, ObjectManager, M:N) now resolve the id against the primary key's real column type. Also: a successful DELETE on bun:sqlite previously returned 404 after deleting the row.
  • Every incremental meta migrate rebuilt every uuid-PK table. A uuid primary key's physical DEFAULT is synthesized at emit time and deliberately not modelled on the expected side, but introspection read it back as a real default — so the diff reported a false change-column-default for every uuid-PK table, on every run. On SQLite/D1 (no ALTER COLUMN) that recreate-and-copies the whole table, forever. Postgres emitted a bogus ALTER instead.
  • drop-view was auto-allowed. An extension's view (e.g. pg_stat_statements) or any hand-written view got an un-gated DROP VIEW emitted. Now gated behind allow.dropView, extension-owned views are filtered via pg_depend, and the recreate-pair exemption is keyed by (schema, name) — keyed on the bare name, rebuilding reporting.summary un-gated a destructive drop of a hand-written public.summary.

Fixed — migrations that could not be applied, or silently did nothing

  • @autoSet emitted DEFAULT now() on SQLite/D1 — invalid SQL, so any entity with the standard createdAt @autoSet produced a migration that could not be applied at all.
  • Changing field.enum @values never migrated on SQLite. CHECK constraints were create-time-only and no change kind triggered the recreate path, so meta migrate reported "No schema changes" while inserts of the new member kept violating the stale CHECK in production. (--allow drop-check was also rejected by CLI arg validation, making Postgres CHECK evolution ungrantable.)
  • @kind: storedProc projections crashed meta migrate outright; @kind: materializedView silently created a plain view under the materialized view's name.
  • D1 introspection didn't exclude Cloudflare/wrangler tables. _cf_METADATA appears after any write and D1's authorizer denies even pragma_table_info on it, aborting every second-and-later meta migrate --dialect d1; d1_migrations read as an undeclared table, so the diff proposed dropping wrangler's own bookkeeping.
  • Infra-table exclusions used _ as a literal when it is a LIKE wildcard — so '__new_%' also matched an ordinary table named renewals, hiding it from introspection and re-proposing CREATE TABLE forever.

Fixed — silently wrong SQL and types

  • The SQLite emitter dropped index @expr / @where / @orders. An expression index emitted CREATE INDEX x ON t () (invalid SQL), and a partial UNIQUE index became a FULL UNIQUE constraint — silently rejecting inserts the model says are valid.
  • Boolean/numeric @default literals were quoted on SQLite (DEFAULT 'false'), which SQLite stores as TEXT in a numeric column, so WHERE flag = 0 silently matched nothing. Literals containing a quote ("don't") or parentheses ("n/a (unknown)") never round-tripped either.
  • FK constraint names never converged on SQLite (the engine stores none), so a composite FK or @constraintName produced a permanently blocked drop-fk and meta migrate exited 1 forever.
  • @isArray on any scalar but string/uuid generated a Drizzle .array() column against a migrated SCALAR column — the first insert failed, with no drift signal.

Fixed — generated code hardcoded the primary-key type (Java, Kotlin, Python)

... (truncated)

Commits
  • ca54fa0 chore(release): FR-036 coordinated breaking release — 0.16.0 / Maven 7.8.0
  • 361b3e1 fix(fr-036): TS Pin-1 floor robustness — review findings #8 + #10
  • 06ab2b0 feat(fr-036): constraint-validation gates + TS reference (Pin 2 full-match, A...
  • fe592c1 feat(fr-035): present-key PATCH tristate — TS port + cross-port gate
  • 1bfed37 chore(release): 0.15.21 — npm 0.15.21 · PyPI 0.15.13 · Maven 7.7.11
  • 61e5d8e fix(migrate,runtime,cli): close the migrate-engine + wrong-row-write bug batch
  • d0e43af fix(migrate,runtime,tanstack): six bugs found by a downstream D1/uuid adopter
  • 55650ee chore(release): @​metaobjectsdev TypeScript packages 0.15.20
  • 1a7b8e0 chore(release): 0.15.19 (npm) — origin.aggregate @​filter + projection/view gu...
  • 3efb53a docs(license): use verbatim official Apache-2.0 text so it's detected as Apac...
  • See full diff in compare view

Updates @metaobjectsdev/sdk from 0.15.18 to 0.16.0

Release notes

Sourced from @​metaobjectsdev/sdk's releases.

0.15.21 — migrate-engine + wrong-row-write bug fixes; PK types derived, not hardcoded

Coordinated release: npm 0.15.21 · PyPI 0.15.13 · Maven Central 7.7.11. NuGet stays at 0.15.10 — the C# port needed no fix. It already derived the primary-key type correctly, and became the reference the other three ports were fixed against.

A bug-fix release, sourced from a downstream consumer's adoption report (TypeScript + Cloudflare D1 + uuid primary keys) and then widened by an adversarial review that hunted the same bug classes across the whole codebase. No metadata changes, no new vocabulary — existing metadata generates byte-identical output except where it was previously wrong.

Data loss and destructive migrations

  • Writable mounts performed a WRONG-ROW write/delete. On a TEXT/uuid primary key, DELETE /docs/0123 deleted row '123' (proven against real engines).
  • Every incremental meta migrate rebuilt every uuid-PK table — a false change-column-default that, on SQLite/D1, recreate-and-copies the whole table on every run, forever.
  • drop-view was auto-allowed — an extension's view or a hand-written view got an un-gated DROP VIEW.

Migrations that couldn't be applied, or silently did nothing

Description has been truncated

Bumps the metaobjects group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [@metaobjectsdev/cli](https://github.com/metaobjectsdev/metaobjects/tree/HEAD/server/typescript/packages/cli) | `0.15.18` | `0.16.0` |
| [@metaobjectsdev/codegen-ts](https://github.com/metaobjectsdev/metaobjects/tree/HEAD/server/typescript/packages/codegen-ts) | `0.15.18` | `0.16.0` |
| [@metaobjectsdev/render](https://github.com/metaobjectsdev/metaobjects/tree/HEAD/server/typescript/packages/render) | `0.15.18` | `0.16.0` |
| [@metaobjectsdev/runtime-ts](https://github.com/metaobjectsdev/metaobjects/tree/HEAD/server/typescript/packages/runtime-ts) | `0.15.18` | `0.16.0` |
| [@metaobjectsdev/sdk](https://github.com/metaobjectsdev/metaobjects/tree/HEAD/server/typescript/packages/sdk) | `0.15.18` | `0.16.0` |
| [@metaobjectsdev/metadata](https://github.com/metaobjectsdev/metaobjects/tree/HEAD/server/typescript/packages/metadata) | `0.15.18` | `0.16.0` |


Updates `@metaobjectsdev/cli` from 0.15.18 to 0.16.0
- [Release notes](https://github.com/metaobjectsdev/metaobjects/releases)
- [Changelog](https://github.com/metaobjectsdev/metaobjects/blob/main/CHANGELOG.md)
- [Commits](https://github.com/metaobjectsdev/metaobjects/commits/v0.16.0/server/typescript/packages/cli)

Updates `@metaobjectsdev/codegen-ts` from 0.15.18 to 0.16.0
- [Release notes](https://github.com/metaobjectsdev/metaobjects/releases)
- [Changelog](https://github.com/metaobjectsdev/metaobjects/blob/main/CHANGELOG.md)
- [Commits](https://github.com/metaobjectsdev/metaobjects/commits/v0.16.0/server/typescript/packages/codegen-ts)

Updates `@metaobjectsdev/render` from 0.15.18 to 0.16.0
- [Release notes](https://github.com/metaobjectsdev/metaobjects/releases)
- [Changelog](https://github.com/metaobjectsdev/metaobjects/blob/main/CHANGELOG.md)
- [Commits](https://github.com/metaobjectsdev/metaobjects/commits/v0.16.0/server/typescript/packages/render)

Updates `@metaobjectsdev/runtime-ts` from 0.15.18 to 0.16.0
- [Release notes](https://github.com/metaobjectsdev/metaobjects/releases)
- [Changelog](https://github.com/metaobjectsdev/metaobjects/blob/main/CHANGELOG.md)
- [Commits](https://github.com/metaobjectsdev/metaobjects/commits/v0.16.0/server/typescript/packages/runtime-ts)

Updates `@metaobjectsdev/sdk` from 0.15.18 to 0.16.0
- [Release notes](https://github.com/metaobjectsdev/metaobjects/releases)
- [Changelog](https://github.com/metaobjectsdev/metaobjects/blob/main/CHANGELOG.md)
- [Commits](https://github.com/metaobjectsdev/metaobjects/commits/v0.16.0/server/typescript/packages/sdk)

Updates `@metaobjectsdev/metadata` from 0.15.18 to 0.16.0
- [Release notes](https://github.com/metaobjectsdev/metaobjects/releases)
- [Changelog](https://github.com/metaobjectsdev/metaobjects/blob/main/CHANGELOG.md)
- [Commits](https://github.com/metaobjectsdev/metaobjects/commits/v0.16.0/server/typescript/packages/metadata)

---
updated-dependencies:
- dependency-name: "@metaobjectsdev/cli"
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: metaobjects
- dependency-name: "@metaobjectsdev/codegen-ts"
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: metaobjects
- dependency-name: "@metaobjectsdev/render"
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: metaobjects
- dependency-name: "@metaobjectsdev/runtime-ts"
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: metaobjects
- dependency-name: "@metaobjectsdev/sdk"
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: metaobjects
- dependency-name: "@metaobjectsdev/metadata"
  dependency-version: 0.16.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: metaobjects
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code labels Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants