diff --git a/.changeset/adr-0097-openapi-upstream-classify.md b/.changeset/adr-0097-openapi-upstream-classify.md deleted file mode 100644 index 0c6cbb0d5..000000000 --- a/.changeset/adr-0097-openapi-upstream-classify.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@objectstack/connector-openapi': minor ---- - -feat(connector-openapi): degrade + retry on an unreachable remote spec URL (#3049 follow-up) - -The `openapi` provider fetches `providerConfig.spec` when it is an http(s) URL. -That fetch previously threw plain on any failure, so a momentarily-unreachable -spec endpoint aborted the whole app boot. It now classifies the fault the same -way `connector-mcp` classifies its connect path (ADR-0097): - -- **Network error** (DNS / connection refused / timeout) or a **transient HTTP - status** (`408` / `429` / `5xx`, mirroring the `retryableStatusCodes` - convention) throws `ConnectorUpstreamUnavailableError` — the materializer - degrades the instance (`state: 'degraded'` on `GET /connectors`, dispatch - fails clearly) and retries with backoff plus on every `metadata:reloaded`. -- A **wrong URL** (non-retryable `4xx`) or an **unparseable document** stays a - plain, fatal configuration fault. - -Inline and file-path (`#3016`) specs do no boot I/O and are unaffected. diff --git a/.changeset/approver-type-org-membership-level.md b/.changeset/approver-type-org-membership-level.md deleted file mode 100644 index d4e1899b0..000000000 --- a/.changeset/approver-type-org-membership-level.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -"@objectstack/spec": minor -"@objectstack/plugin-approvals": minor -"@objectstack/lint": minor ---- - -feat(approvals): rename the `role` approver type to `org_membership_level` (#3133) - -`ApproverType.role` was the last platform surface projecting the reserved word -"role" (ADR-0090 D3). It is not covered by D3's better-auth exception: that -exception protects better-auth's own `sys_member.role` **column**, which we do -not own — `ApproverType` is our own enum, an authoring surface, and D3 mandates -that the projection of that concept is spelled `org_membership_level` and -labelled "organization membership", **never "role"**. - -The sentence licensing the leak was also false: ADR-0090 D3 claims -`sys_member.role` is "already relabelled `org_membership_level` in the platform -projection", but `org_membership_level` existed nowhere in the codebase and -ADR-0057 D7 lists that relabel under "Deferred (evidence-gated, P4)". The -projection never landed, so the word reached authors. - -The name manufactured a real, silent failure — "hotcrm class": every other -surface renamed to `position` (`sys_role`, `ShareRecipientType.role`, -`ctx.roles[]`), so `{ type: 'role', value: 'sales_manager' }` reads as the -legacy spelling of a position. It resolves against the membership tier, finds -no member row, falls back to an inert `role:sales_manager` literal, and the -request waits forever on an approver that cannot exist. - -- **spec**: `ApproverType` gains `org_membership_level`; `role` stays as a - deprecated alias for one window (a published 15.x flow keeps loading) with - `DEPRECATED_APPROVER_TYPES` + `canonicalApproverType()` as the single source - for the mapping. Removed in the next major. -- **plugin-approvals**: resolves on the canonical type and warns on the - deprecated spelling. The `type:value` fallback literal keeps the **authored** - spelling — stored `sys_approval_approver` rows and `pending_approvers` slots - from 15.x carry `role:`, and rewriting it would orphan them. -- **lint**: `approval-role-not-membership-tier` → `approval-approver-not-membership-tier` - (the rule id carried the reserved word too), plus a new - `approval-approver-type-deprecated`. The two are mutually exclusive: a bad - *value* wins, because prescribing `org_membership_level` for a position name - would be wrong advice — the fix there is `position`. - -Authoring `type: 'role'` keeps working and now says so out loud. Rewrite it as -`org_membership_level`; if the value is an org position, the fix is `position`. diff --git a/.changeset/betterauth-adapter-system-writes.md b/.changeset/betterauth-adapter-system-writes.md deleted file mode 100644 index d9371813c..000000000 --- a/.changeset/betterauth-adapter-system-writes.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -"@objectstack/plugin-auth": patch ---- - -fix(plugin-auth): run better-auth adapter WRITES as system context so #2948 doesn't strip readonly identity columns (#3164) - -The better-auth ObjectQL adapter wrapped the engine so its READS carried -`isSystem` (to bypass the control-plane org-scope read hook), but its WRITES -passed through with no context. The static-`readonly` UPDATE strip (#2948) runs -on any non-system update — and since the adapter carries no caller context, -`!ctx?.isSystem` was `true`, so the strip silently DROPPED better-auth's own -writes to readonly `sys_user` columns: `email` (change-email), `banned` / -`ban_reason` / `ban_expires` (admin ban). Those operations returned success but -never persisted. - -`withSystemReadContext` is renamed to `withSystemContext` (a deprecated alias is -kept for one release) and now injects `isSystem` on `insert` / `update` / -`delete` as well as reads. This is correct because these are the identity -authority's own writes — user-context writes to `managedBy: 'better-auth'` tables -are already rejected upstream by the ADR-0092 identity write guard, so the -adapter path only ever carries better-auth's internal writes. - -Found while implementing #3043 (the INSERT-side readonly strip). This is its -UPDATE-side dual: #3043 relocated the insert strip to the external ingress -precisely because internal writers (this adapter included) don't declare -`isSystem`; the pre-existing engine-level UPDATE strip has no such relocation, so -the adapter had to declare its writes system. diff --git a/.changeset/bulk-update-validation-rules.md b/.changeset/bulk-update-validation-rules.md deleted file mode 100644 index a15675d28..000000000 --- a/.changeset/bulk-update-validation-rules.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@objectstack/objectql": patch -"@objectstack/spec": patch ---- - -Enforce validation rules, `requiredWhen`, and per-option `visibleWhen` on multi-row updates (#3106). The bulk branch of `engine.update` (`options.multi` → `driver.updateMany`) previously never called `evaluateValidationRules`, so every object-level rule (`script`, `state_machine`, `format`, `cross_field`, `json_schema`, `conditional`), field-level `requiredWhen`, and per-option `visibleWhen` check was a silent no-op there. The engine now reads the row-scoped match set (the same AST the write binds, one query shared with the `readonlyWhen` bulk strip) and evaluates the payload against each matched row's prior state; any error-severity violation rejects the whole batch with `ValidationError` (annotated with the failing record id) before anything is written. Schemas needing no prior state (`format`/`json_schema`-only) are evaluated once against the payload with no fetch, and rule-free schemas are unaffected. Behavior change: bulk writes that previously slipped past declared rules now throw. Doc comments in `rule-validator.ts` and `validation.zod.ts` no longer overstate coverage and name the remaining `events: ['delete']` gap (tracked separately). diff --git a/.changeset/bulk-write-hardening.md b/.changeset/bulk-write-hardening.md deleted file mode 100644 index e32a7e46b..000000000 --- a/.changeset/bulk-write-hardening.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -"@objectstack/core": patch -"@objectstack/objectql": patch -"@objectstack/rest": patch -"@objectstack/metadata-protocol": patch ---- - -fix: harden the bulk-write path — retries, idempotency, contracts, and summary visibility (#3147–#3152) - -Six reliability fixes to the batched seed/import + `engine.insert(array)` path -introduced by the #2678 bulk-write rework: - -- **#3151** `bulkWrite` validates that `writeBatch` returns one record per input - row (a short/long/non-array return is degraded per-row, not backfilled as - phantom success); `engine.insert(array)` likewise rejects a short driver - `bulkCreate` return instead of padding afterInsert with `undefined`. -- **#3150** wraps the two remaining un-retried write points (seed - `writeRecord`/`resolveDeferredUpdates`, import's no-`createManyData` - fallback) in `withTransientRetry`; `defaultIsTransientError` short-circuits - definitive logical errors to non-transient. -- **#3148** import `resolveRef` flushes pending creates on a same-object miss so - a later row can reference an earlier same-file CREATE, and no longer - negatively caches a miss. -- **#3149** threads an `attempt` counter through `bulkWrite`; seed rechecks by - `externalId` and import by `matchFields` before re-writing, so a - commit-then-lost-response retry cannot duplicate a batch. -- **#3147** `recomputeSummaries` retries transient failures and, on exhaustion, - surfaces `SummaryRecomputeError` (`ERR_SUMMARY_RECOMPUTE`) instead of a - silent warn; seed/import recover it to a warning without re-writing. -- **#3152** autonumbers are assigned after validation, so a batch that dies in - validation consumes no sequence value (no number-range gaps). diff --git a/.changeset/cli-strip-arg-separator.md b/.changeset/cli-strip-arg-separator.md deleted file mode 100644 index b7e858905..000000000 --- a/.changeset/cli-strip-arg-separator.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -"@objectstack/cli": patch ---- - -fix(cli): tolerate the `--` separator pnpm injects when forwarding script args (#3114) - -The AGENTS.md-documented backend-debug flow `pnpm dev -- --fresh -p ` failed at -the repo root with an opaque `Unexpected arguments: -p, 44637` (exit 2 + a help dump). - -pnpm appends forwarded args to a script **verbatim, including the `--`**, and each -nested `pnpm --filter` hop preserves it, so the showcase's `objectstack dev ---seed-admin` ran as `objectstack dev --seed-admin -- --fresh -p 44637`. oclif reads -`--` as POSIX end-of-flags, so everything after it became positional: `--fresh` was -silently swallowed as the `package` arg and `-p 44637` overflowed the arg list. Every -flag the user asked for was dropped — the failure was opaque precisely because the -`--` looks inert. - -A `preparse` hook now drops `--` separators before oclif parses argv, so the -npm-style `-- ` form and the bare form behave identically, for every command -and both bins (`run.js`, `run-dev.js`). No `os` command takes passthrough args (none -sets `strict = false`, none reads raw argv), so a `--` carries no meaning here and is -always a package-manager artifact. - -Note this is not fixable via oclif's `'--': false` parser option: that keeps -flag-parsing on past the separator but re-appends the `--` into argv, so strict -commands fail with `Unexpected argument: --` instead. - -Tradeoff: a `-`-prefixed token can no longer be forced to parse as a positional -value. Every `os` positional is a config path, a metadata / datasource / package -name, or an id — none start with `-`. diff --git a/.changeset/dev-loop-dx-p2.md b/.changeset/dev-loop-dx-p2.md deleted file mode 100644 index 081ef6eae..000000000 --- a/.changeset/dev-loop-dx-p2.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@objectstack/objectql": patch -"@objectstack/metadata": patch -"@objectstack/runtime": patch -"@objectstack/plugin-auth": patch -"@objectstack/cli": patch ---- - -Dev-loop DX fixes from the 15.1 third-party evaluation (P2 batch): - -- **Hot-added objects are now queryable without a restart.** Adding a `*.object.ts` under `os dev` used to recompile "green" while every query answered `no such table` (or `not registered`) until a manual restart: the artifact reload never notified the ObjectQL registry, tables were only created at boot, and seeds only loaded from the boot-time bundle. The `metadata:reloaded` payload now carries the parsed artifact; ObjectQL ingests the object definitions and re-runs the idempotent schema sync (same `skipSchemaSync` opt-out as boot), and the runtime loads seeds for first-seen objects (dev, single-tenant). `os dev` also prints `✚ new object(s): …` on recompile. -- **Dev admin credentials stay visible.** The `os dev` startup banner only showed `admin@objectos.ai / admin123` on the boot that actually seeded it; with the persistent default DB every later boot hid it, and the Console login page never knew it existed. The hint now re-arms on every dev boot for as long as the account still verifies against the default password, and `GET /api/v1/auth/config` exposes a dev-gated `devSeedAdmin` field (never present outside `NODE_ENV=development`) so the login page can show it. -- **`os doctor` reference analysis understands current metadata shapes.** Objects bound through `defineView` containers (`list`/`listViews`/`form`/`formViews` → `data.object`, subform `childObject`, lookup form fields) and app navigation (`objectName`, nested `children`, `areas`) were reported as "defined but not referenced". The collector now walks the canonical shapes (plus flow node `config.object`/`objectName`) and the orphan-view check descends into containers. diff --git a/.changeset/flow-registration-schema-aware-validation.md b/.changeset/flow-registration-schema-aware-validation.md deleted file mode 100644 index 935bbb557..000000000 --- a/.changeset/flow-registration-schema-aware-validation.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -"@objectstack/service-automation": minor ---- - -feat(automation): schema-aware flow-condition validation at registration (#1928) - -`registerFlow` now runs the same schema-aware condition checks as -`objectstack build` — so a flow registered dynamically (via the API / Studio, -bypassing the build lint) still gets the guardrail. When the host wires an -object-schema resolver, a flow condition that references an unknown field, -likely-typos a field name, or does arithmetic/ordering on a text/boolean field -against a number is surfaced as an **advisory warning** (logged), pointing at -the object's real schema. - -- New `AutomationEngine.setObjectSchemaResolver(resolver)` bridge (mirrors - `setFunctionResolver`); `AutomationServicePlugin` wires it to - `objectql.registry.getObject` in `start()`, before the flow pull, so - registry-sourced flows are covered too. -- **Strictly additive / zero regression**: the fatal set is unchanged (syntax, - brace-in-CEL, unknown-function still throw); everything the schema pass adds is - logged, never thrown, and the whole thing is a no-op when no resolver is wired. - Flow conditions bind fields flat, so the check runs in `flattened` scope - (flow variables stay `dyn` and are never flagged; equality is runtime-safe). - -Builds on the tier-4 type-soundness check in `@objectstack/formula` / -`@objectstack/lint` (#1928). diff --git a/.changeset/flow-trigger-observability.md b/.changeset/flow-trigger-observability.md deleted file mode 100644 index 5f4cf09e6..000000000 --- a/.changeset/flow-trigger-observability.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@objectstack/service-automation': minor -'@objectstack/trigger-record-change': minor -'@objectstack/lint': minor -'@objectstack/cli': minor -'@objectstack/objectql': patch -'@objectstack/runtime': patch -'@objectstack/plugin-audit': patch ---- - -Flow trigger observability — kill the four-layer silence around record-change flows that never fire (2026-07-17 third-party eval). - -A misauthored auto-launched flow (wrong `objectName`, missing `requires: ['automation','triggers']`, failing start condition) produced ZERO output at every layer: the engine's own registration/binding logs land inside the CLI's boot-quiet stdout window (which swallows debug/info/warn — only error/fatal reach stderr), and each "didn't happen" path was itself silent. Fixes: - -- **Startup banner `Flows:` section** (`os serve`/`os dev`/`os start`): flow count, bound-to-trigger count, registered trigger types, draft count — plus loud `⚠` lines for flows declared with no automation engine enabled (`requires` missing), flows whose trigger type has no registered trigger, and bound record-change flows targeting an unknown object (dead binding). Printed after stdout is restored, so it is immune to the boot-quiet window. -- **Trigger-fired run failures now log at ERROR** (stderr — always visible): the automation engine no longer drops the AutomationResult of a trigger-fired execution; condition-evaluation faults and node failures surface with the flow name. Condition-not-met skips stay at debug (high-frequency, intentional). -- **`RecordChangeTrigger` probes object existence at bind time** and warns when a flow's `objectName` matches no registered object (exact-name matching), instead of silently arming a hook that can never fire. -- **`kernel:bootstrapped` binding audit** in the automation plugin: warns per enabled-but-unbound triggered flow with the reason, and reports registered/bound/draft counts (`AutomationEngine.getTriggerBindingAudit()`, extended `getFlowRuntimeStates()` with `status`/`triggerType`/`object`). -- **`os validate` flow-wiring advisories** (`@objectstack/lint` `validateFlowTriggerReadiness`): warns when a record-triggered flow targets an object the stack does not define, and when an auto-triggered flow's status is `draft` (authored or defaulted — draft flows still fire; declare `active` or `obsolete`). -- Removed leftover boot-debug writes (`registerApp`/`AppPlugin`/`StandaloneStack`/`AuditPlugin` stderr noise) that previous debugging of this same silence had left behind. diff --git a/.changeset/i18n-inline-label-default-locale.md b/.changeset/i18n-inline-label-default-locale.md deleted file mode 100644 index 076e60d2c..000000000 --- a/.changeset/i18n-inline-label-default-locale.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -"@objectstack/cli": patch ---- - -fix(cli): treat an inline `label:` as the default-locale source in i18n coverage - -A fresh `npm create objectstack` scaffold reported 4 `i18n/missing-object` / -`i18n/missing-field` errors for its own `_note` object, even though the -template authors `label: 'Note'`, `pluralLabel: 'Notes'`, `label: 'Title'` and -`label: 'Body'` inline. The only way to silence them was to commit an `en` -bundle restating strings the metadata already carries. - -The inline `label:` *is* the default-locale text: the runtime resolver falls -back to it when a bundle has no entry (`translateObject`), and `os i18n -extract` seeds bundles from it. Coverage now honours that contract — an inline -label satisfies the default locale, and a bundle is what *other* locales need. -Keys with no source string anywhere are no longer reported as i18n gaps; a -missing label is already `required/label`'s finding. - -Non-default locales are unaffected: they still warn for every untranslated key -(`os lint` on `examples/app-todo` reports the same 79 warnings as before, with -its 39 default-locale errors gone). `os lint --include-platform` drops the -platform baseline's default-locale errors for the same reason — the platform -ships English labels inline — while keeping its non-default-locale warnings. diff --git a/.changeset/lint-hide-platform-baseline.md b/.changeset/lint-hide-platform-baseline.md deleted file mode 100644 index ebb8f8b24..000000000 --- a/.changeset/lint-hide-platform-baseline.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@objectstack/cli": patch ---- - -`os lint` no longer buries the user's own signal under the platform i18n baseline. A fresh scaffold reported 800+ `i18n/missing-metadataForm` errors — translation keys for platform built-in metadata forms (email_template, …) that the platform packages already ship at runtime. Those are now hidden by default and folded into one summary line (`platform built-ins: N i18n issue(s) hidden`); pass `--include-platform` to audit them, and read `hiddenPlatform` in `--json` output. User-authored metadata coverage is reported unchanged. diff --git a/.changeset/logger-esm-file-destination.md b/.changeset/logger-esm-file-destination.md deleted file mode 100644 index 0ae3935b2..000000000 --- a/.changeset/logger-esm-file-destination.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@objectstack/core": patch ---- - -**`createLogger({ file })` now actually writes the file under ESM.** `openFileStream` loaded `fs` with a lazy `require()` to keep the browser-safe logger entry out of the `fs` bundle graph; esbuild rewrites that to its `__require` shim in the ESM output, which throws `Dynamic require of "fs" is not supported`, and a bare `catch {}` swallowed it. Since the workspace is `type: module`, every Node ESM consumer — `os serve`, `os dev` — silently got no file logging at all, while the CJS build kept working. The builtin now loads via `process.getBuiltinModule` (opaque to bundlers, works in both module systems, with a `require` fallback for Node < 20.16), and a `file` destination that cannot be opened reports itself on stderr instead of disappearing. - -Turning the destination back on also fixed three faults that were unreachable while it never opened: `child()` opened a second stream per child and orphaned it, destroying a child logger closed the stream its parent and siblings were still writing to, and an async open failure (e.g. an unwritable path) hit an `'error'` event with no listener and took the process down. diff --git a/.changeset/logger-honors-no-color.md b/.changeset/logger-honors-no-color.md deleted file mode 100644 index 5b95d7482..000000000 --- a/.changeset/logger-honors-no-color.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@objectstack/core": patch ---- - -fix(core): ObjectLogger honors NO_COLOR and TTY detection before emitting ANSI colors - -The kernel/plugin logger (`ctx.logger`, wired by `os serve` / `os dev`) colorized its -`pretty`-format level tags unconditionally, so `NO_COLOR=1` runs and piped/CI output -still carried ANSI escapes (e.g. `\x1b[31m…ERROR\x1b[0m`), breaking plain-text log -scanners (see scripts/publish-smoke.sh, which had to strip ANSI before grepping). - -Per the no-color.org convention, color is now emitted only when the destination stream -(stdout, or stderr for error/fatal) is an interactive TTY **and** `NO_COLOR` is unset or -empty — any non-empty `NO_COLOR` value disables color. Interactive terminals keep the -existing colorized output. The optional file destination now always receives plain text. diff --git a/.changeset/metadata-register-notifies-watchers.md b/.changeset/metadata-register-notifies-watchers.md deleted file mode 100644 index f77d1ad86..000000000 --- a/.changeset/metadata-register-notifies-watchers.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@objectstack/spec": patch -"@objectstack/metadata": patch -"@objectstack/objectql": patch ---- - -**`MetadataManager.register()` / `unregister()` now announce to `subscribe()` watchers.** Both updated the registry, persisted to writable loaders and published to realtime, but never fired the watch callbacks — so `subscribe()` looked like it covered every write while silently missing all of them. Only the `saveMetaItem` path (via the repository watch stream) and the filesystem watcher ever reached a subscriber. Runtime consumers that cache metadata — notably ObjectQL's SchemaRegistry bridge, the component that decides what is queryable — went stale on every other write until the process restarted. - -Announcing is now the **default**, so a new call site is correct without knowing this contract exists. This is a contract fix rather than a bug fix: the one live behavior change is that runtime datasource writes (`datasource-admin`) now reach the HMR SSE stream, which subscribes to every registered type. `unregisterPackage()` / `bulkUnregister()` also announce their deletes now — correct, but latent, since neither has a production caller today. - -Bulk ingest opts out explicitly with the new `MetadataWriteOptions` (`{ notify: false }`) — boot-time filesystem priming, artifact ingest, and ObjectQL's registry bridge, each of which either runs before consumers cache anything or announces the whole batch once (as the artifact reload path does via `metadata:reloaded`). The bridge in particular MUST stay silent: it copies objects out of the SchemaRegistry, and announcing would feed them back through a handler that re-registers under `_packageId ?? 'metadata-service'`, overwriting the true package provenance of every object whose body carries no `_packageId`. - -Additive only — `register(type, name, data)` and `unregister(type, name)` keep working unchanged. - -Fixes #3112. diff --git a/.changeset/ownership-record-model-field.md b/.changeset/ownership-record-model-field.md deleted file mode 100644 index 1fab1f596..000000000 --- a/.changeset/ownership-record-model-field.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -"@objectstack/spec": minor -"@objectstack/cli": patch ---- - -fix(spec): declare `ownership` as a first-class ObjectSchema field (#3175) - -The object-level record-ownership model — `ownership: 'user' | 'org' | 'none'`, -which drives the registry's `owner_id` auto-provisioning (`applySystemFields`) — -was read by the engine via `(schema as any).ownership` while `ObjectSchema.create()` -**rejected** it as an unknown top-level key (ADR-0032 / #1535). So a tested engine -opt-out (`ownership: 'org' | 'none'` on catalog / junction tables) could not be -set through the sanctioned authoring path, and the same `ownership` word was read -elsewhere as the unrelated package-contribution kind (`own` / `extend`). - -- **spec**: `ObjectSchema` now declares `ownership: z.enum(['user','org','none']).optional()`. - Authoring the record-ownership opt-out validates cleanly; the registry reads it - off the typed schema (no `as any`). A retired `ownership: 'own'` / `'extend'` - value fails with guidance pointing at the record-ownership model and noting that - `own`/`extend` is the contribution kind (`registerObject`), not an object-schema value. -- **cli**: the `object` scaffold no longer emits the now-invalid `ownership: 'own'` - (owner injection is the default), and `objectstack info` labels the record model - with the correct `user` default. - -No runtime behavior change: `applySystemFields` and its `owner_id` injection logic -are unchanged — this makes the property the engine already honors legally authorable -and consistently typed. diff --git a/.changeset/perf-timing-per-request-gating.md b/.changeset/perf-timing-per-request-gating.md deleted file mode 100644 index 946787a94..000000000 --- a/.changeset/perf-timing-per-request-gating.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -"@objectstack/observability": minor -"@objectstack/plugin-hono-server": minor -"@objectstack/runtime": minor ---- - -feat(observability): admin-gated per-request `Server-Timing` via `X-OS-Debug-Timing` (#2408) - -Perf-tuning mode was previously global-only (`serverTiming` option / -`OS_SERVER_TIMING`), which discloses internal phase durations — a mild -backend-fingerprinting surface — to every caller. This adds the per-request -gating path from the design so an operator can pull a single request's -`Server-Timing` breakdown on a live environment without turning the header on -for everyone. - -- **observability**: a request-scoped disclosure gate (`runWithPerfDisclosure`, - `allowPerfDisclosure`, `isPerfDisclosureAllowed`, `PerfDisclosureGate`) kept - separate from the pure `PerfTiming` collector and pinned to its own - `Symbol.for` store so the middleware and dispatcher share it across module - copies. -- **plugin-hono-server**: the Server-Timing middleware is registered by default - (unless `serverTiming: false`). It runs the collector when timing is global - **or** the request sends `X-OS-Debug-Timing: 1`, and emits the header only - when the gate is open. `OS_PERF_TIMING=1` now also enables global mode. -- **runtime**: after resolving the execution context, the dispatcher opens the - gate for admin/service/system principals, so ordinary callers never receive - the header even if they send the debug header. - -Existing global-mode behavior is unchanged. diff --git a/.changeset/publish-drafts-org-scope.md b/.changeset/publish-drafts-org-scope.md deleted file mode 100644 index be88095c7..000000000 --- a/.changeset/publish-drafts-org-scope.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@objectstack/metadata-protocol": patch ---- - -Publish/discard package drafts in the draft's own org scope, fixing `no_draft` after saving a draft via Studio. - -Studio "Save Draft" (`PUT /meta/:type/:name?mode=draft`) never threads the session's `activeOrganizationId`, so the draft row is written env-wide (`organization_id = NULL`). "Publish" (`POST /packages/:id/publish-drafts`) resolves the active org and passed it to `promoteDraft`, which looked the draft up with a strict `organization_id = ` equality — so it 404'd (`[no_draft] No pending draft exists …`) on the env-wide row it could never match, even though `listDrafts` had already surfaced that draft to the publish CTA (PR #1852's `$or`). `discardPackageDrafts` had the same latent gap. - -`listDrafts` now projects each draft's own `organizationId`, and `publishPackageDrafts` / `discardPackageDrafts` promote / delete each draft in that scope (env-wide stays env-wide, per-org stays per-org). Seed-body capture and the ADR-0067 revert-plan pre-state read are scoped the same way. - -Fixes #3115. diff --git a/.changeset/readonly-static-insert-strip.md b/.changeset/readonly-static-insert-strip.md deleted file mode 100644 index fdd40f79e..000000000 --- a/.changeset/readonly-static-insert-strip.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -"@objectstack/metadata-protocol": patch -"@objectstack/spec": patch ---- - -fix(metadata-protocol): strip static `readonly` on INSERT at the data-write ingress (#3043) - -#2948/#3003 made static `readonly: true` fields server-enforced on UPDATE (a -non-system PATCH forging `approval_status: 'approved'` is silently stripped in -the engine), but INSERT was exempt. For approval/status/verdict columns that -exemption was the *shorter* attack: instead of the #3003 draft-then-PATCH move, a -non-system caller could `POST` a record already `approval_status: 'approved'` in -one step — and the UPDATE-only strip never reached it. - -The strip now also runs on INSERT, but at the **external data-write ingress** -(`DataProtocol.createData` / `createManyData` / `batchData` / `cloneData`) rather -than in the engine. That seam is the single point every external programmatic -create funnels through — the REST CRUD route, the GraphQL/MCP dispatcher -(`bridge.create` → `callData` → `createData`), and bulk import — while **trusted -internal writers** (better-auth's adapter, the metadata repository, the seed -loader) call `engine.insert` directly and bypass it. Enforcing at the ingress -protects every caller/agent path at once without stripping the internal writers -that legitimately seed read-only columns on create (identity provisioning, -provenance stamps, event-log cursors) — the blast radius an engine-level insert -strip would have. - -- **Caller-forged only, at the ingress.** The payload here is raw caller input - (the security middleware stamps `owner_id` / `organization_id` later, inside - `engine.insert`), so only keys the caller actually sent are dropped; server - stamps are added afterwards and are unaffected. -- **Re-derives the default.** A stripped field falls back to its declared - `defaultValue` in the engine (a forged `approval_status` becomes `draft`, not - NULL). -- **System-context exempt.** `isSystem` writes still seed read-only columns. -- **Silent** (HTTP 2xx), per-row on batch/import. `readonlyWhen` stays - INSERT-exempt (a conditional lock needs a prior record). -- **Author-defined business objects only.** Platform objects (`managedBy` set, - or the `sys_` namespace) carry their own field-write governance that a silent - strip must not pre-empt — e.g. ADR-0086 REJECTS (403) a forged - `managed_by:'package'` on `sys_permission_set`, and #3004 rejects a forged - `owner_id`; several of those columns are `readonly`, so stripping them here - would swallow the payload the guard is meant to reject. The #3043 threat is app - approval/status fields, never `sys_` — the same boundary `applySystemFields` - uses for ownership. - -Behavior change: a non-system create through the data API (REST / GraphQL / MCP / -import) can no longer seed a `readonly` column from the payload. Flows that -legitimately write read-only columns at creation must run with a system context -(`isSystem`), the same requirement the UPDATE strip already imposes. diff --git a/.changeset/remove-dead-metadata-props-2377.md b/.changeset/remove-dead-metadata-props-2377.md deleted file mode 100644 index 24fb4240c..000000000 --- a/.changeset/remove-dead-metadata-props-2377.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -"@objectstack/spec": minor ---- - -feat(spec)!: remove dead author-facing metadata properties (#2377, ADR-0049 enforce-or-remove) - -Breaking spec-surface removal, versioned as `minor` per the launch-window changeset -policy (a `major` would promote the whole fixed-group monorepo; breaking cleanups ride -the minor line, as with #2402 → 11.1.0). - -Removes a batch of spec properties that parsed but had **no runtime consumer** — -authoring them was a false affordance (especially dangerous for AI-authored -metadata). Verified dead against the liveness ledger (`packages/spec/liveness/*.json`) -and a repo-wide grep of readers. This is the follow-up slice to #2402. - -## Removed (each was `dead` + no reader anywhere) - -- **field** (`field.zod.ts`): `vectorConfig` (+ `VectorConfigSchema` + types), - `fileAttachmentConfig` (+ `FileAttachmentConfigSchema` + types), `dependencies`. - Vector fields keep the live flat `dimensions` prop; file/image fields keep the - live flat `multiple`/`accept`/`maxSize` siblings. -- **object** (`object.zod.ts`): `versioning` (+ `VersioningConfigSchema`), - `softDelete` (+ `SoftDeleteConfigSchema`), `search` (+ `SearchConfigSchema`), - `recordName`, `keyPrefix`. Each is now a **rejecting tombstone** in - `UNKNOWN_KEY_GUIDANCE` carrying the upgrade prescription. -- **action** (`action.zod.ts`): `timeout` (server uses `body.timeoutMs`; no - action-level timeout is enforced). -- **agent** (`agent.zod.ts`): `planning.strategy`, `planning.allowReplan` - (only `planning.maxIterations` is read by the runtime). -- **dataset** (`dataset.zod.ts`): `measures.certified` (declared-but-unenforced - governance flag — never compiled into the Cube). - -Liveness ledgers, the ledger README table, and `api-surface.json` are updated; -the removed sub-schema keys are dropped from `json-schema.manifest.json`. - -## Migration - -- **field/agent/dataset/action props**: authoring them is now silently stripped - (they never did anything). Remove them. Vector → set flat `dimensions`; - file/image → set flat `multiple`/`accept`/`maxSize`. -- **object props**: `ObjectSchema.create()` now throws a located error naming the - replacement — `versioning`/`softDelete` → hard deletes + `Field.trackHistory` / - `lifecycle`; `search` → `searchableFields`; `recordName` → an `autonumber` - `Field` designated as `nameField`; `keyPrefix` → remove (never had an effect). - -## Deliberately NOT removed (dead, but entangled — a scoped follow-up) - -`field.index`/`columnName`/`referenceFilters` and object -`tags`/`active`/`isSystem`/`abstract`/`enable.searchable`/`enable.trash`/`enable.mru` -and `agent.tenantId` are surfaced in the Studio metadata-authoring forms -(`*.form.ts`) — removing them cascades into i18n bundle regeneration, so they are -deferred. `action.type:'form'` has a dedicated build-time lint (`lint-view-refs.ts`) -and a first-party showcase usage, so it needs a UX decision. `field.columnName` -additionally has an ADR-0062 D7 lint. These stay `dead` + `authorWarn` in the -ledgers. diff --git a/.changeset/scaffold-default-connector-executors.md b/.changeset/scaffold-default-connector-executors.md deleted file mode 100644 index ca3707fd4..000000000 --- a/.changeset/scaffold-default-connector-executors.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -"create-objectstack": minor ---- - -feat(create-objectstack): the blank scaffold ships the three generic connector executors by default - -`npm create objectstack` now generates an `objectstack.config.ts` that wires the -`rest`, `openapi`, and `mcp` connector executor plugins (ADR-0022/0023/0024 + -ADR-0097) into `plugins:`, alongside `requires: ['automation']`. This closes the -last authoring gap in the ADR-0097 promise that integrations are expressible -**and executable** as pure metadata: an author (human or AI) can now add a -declarative `connectors:` entry naming `provider: 'rest' | 'openapi' | 'mcp'` -and have it materialize into a live, dispatchable connector at boot — with no -host-code edit. - -- `plugins:` — `new ConnectorRestPlugin()`, `new ConnectorOpenApiPlugin()`, - `new ConnectorMcpPlugin()` (zero-arg = contribute the provider factory only). -- `requires: ['automation']` — the automation service performs the - materialization and owns the registry the executors register into. It is also - a hard dependency of the connector plugins, so a scaffold that lists them in - `plugins:` without it fails boot; automation ships transitively via - `@objectstack/cli`. -- deps — `@objectstack/connector-rest`, `@objectstack/connector-openapi`, - `@objectstack/connector-mcp`. -- Security (#3055): declarative `mcp` stdio transports stay denied by default — - opt in per host with `new ConnectorMcpPlugin({ declarativeStdio: ['node'] })`. - -Brand connectors (Slack, …) remain marketplace/opt-in. diff --git a/.changeset/scaffold-gitignore-survives-publish.md b/.changeset/scaffold-gitignore-survives-publish.md deleted file mode 100644 index 67fb4c2b0..000000000 --- a/.changeset/scaffold-gitignore-survives-publish.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"create-objectstack": patch ---- - -Scaffolded projects ship with a `.gitignore` again — `npx create-objectstack` produced none, leaving `node_modules/` and `.env` un-ignored for every new user. - -`npm pack` / `pnpm pack` strip `.gitignore` from a tarball unconditionally, at every depth. The blank template committed one at `src/templates/blank/.gitignore` and the build faithfully copied it to `dist/templates/blank/.gitignore`, but `files: ["dist"]` publishing dropped it on the way to the registry — so the file was present in the repo, present in every local build, and absent from all 11 files of a real scaffold. Verified against the published 15.1.1 tarball, which ships `dist/templates/blank/.dockerignore` and no `.gitignore`. - -The template is now committed as `_gitignore` (a name npm does not strip) and restored to `.gitignore` when the template is copied, via a `TEMPLATE_FILE_ALIASES` map in the new `template-copy.ts`. Only `.gitignore` is aliased: the strip list is `.gitignore` and `.npmrc`, not "every dotfile" — `.dockerignore` packs fine and stays literal. - -The restored ignore rules also cover `.env` / `.env.*`, which they never did. The template README has users write `OS_AUTH_SECRET` and `OS_SECRET_KEY` into a `.env`, and `docker-compose.yml` calls that file "never committed" — but only the prose said so, and `.dockerignore` was the only file that listed it. - -A packing ratchet in `template-consistency.test.ts` guards both halves: it packs the real package, scaffolds from the extracted tarball with the real copy logic, and asserts every template file lands under its intended name. Source-level assertions cannot see this class of bug — the file only vanishes at publish. diff --git a/.changeset/scaffold-pnpm11-build-approvals.md b/.changeset/scaffold-pnpm11-build-approvals.md deleted file mode 100644 index 5472aa39a..000000000 --- a/.changeset/scaffold-pnpm11-build-approvals.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -"create-objectstack": patch ---- - -fix(create-objectstack): the blank scaffold declares pnpm build approvals, so a fresh `pnpm install` no longer exits 1 on pnpm 11 - -pnpm 11 turned an unapproved dependency build script from a warning into a hard -error. The blank template declared no build approvals, so the very first command -a new user runs failed on any current pnpm: - -``` -npx create-objectstack myapp && cd myapp && pnpm install -# [ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: better-sqlite3@12.11.1, esbuild@0.28.1 -# exit 1 -``` - -The scaffold now ships a `pnpm-workspace.yaml` approving the two packages it -actually depends on building — `better-sqlite3` (the native sqlite driver behind -`@objectstack/driver-sql`) and `esbuild` (compiles `objectstack.config.ts`). - -Both approval keys are present because pnpm reads them by version, and neither -alone covers the supported range: - -- `allowBuilds` (a package → boolean map) — the only key pnpm 11 honors, and - understood back to pnpm 10.31. `onlyBuiltDependencies` alone still errors. -- `onlyBuiltDependencies` (a list) — pnpm 10.0–10.30, which ignore `allowBuilds`. - -npm and yarn ignore the file, so the npm install path is unaffected. Both -packages ship prebuilt binaries, so this was an install-time hard stop rather -than a runtime defect — the project ran fine once installed. - -This is the #3091 failure class (in-repo settings masking what users resolve) -and was caught by the publish smoke gate added in #3100, which installs the -release candidate the way a user does — on whatever pnpm corepack hands a fresh -machine. diff --git a/.changeset/scaffold-skill-catalog-boundary.md b/.changeset/scaffold-skill-catalog-boundary.md deleted file mode 100644 index 5d4168b7d..000000000 --- a/.changeset/scaffold-skill-catalog-boundary.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"create-objectstack": patch ---- - -Stop leaking repo-internal skills into scaffolded projects. The scaffolder (and the docs) advertised `npx skills add objectstack-ai/framework --all`, and the skills CLI's `--all` implies `--skill '*'` — which includes even `metadata.internal` skills — so repo-internal tooling like `.claude/skills/dogfood-verification` landed in every new project's `.agents/skills/`. All install commands are now scoped to the published catalog via the `/skills` subpath (`npx skills add objectstack-ai/framework/skills --all`), the internal skill is additionally marked `metadata.internal: true` to hide it from interactive discovery, and a template-consistency ratchet plus a scaffold-e2e assertion keep the boundary from regressing. diff --git a/.changeset/seed-replay-lookup-corruption.md b/.changeset/seed-replay-lookup-corruption.md deleted file mode 100644 index 230f31fd6..000000000 --- a/.changeset/seed-replay-lookup-corruption.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -"@objectstack/metadata-protocol": patch -"@objectstack/runtime": patch ---- - -fix(seed): replaying seeds no longer corrupts lookup natural keys on the upsert update path - -Every dev-server restart replayed package seeds in upsert mode, and any record whose -lookup/master_detail was authored as a natural key could have that reference overwritten -with NULL on the update path (`NOT NULL constraint failed` on required columns; silent -link loss on nullable ones). Four fixes: - -- An unresolved reference now leaves the column untouched (deferred to pass 2) or drops - the record loudly — it is never written as NULL over an existing row. -- DB-side reference resolution probes the target dataset's declared `externalId` (e.g. - `email`) before falling back to `name` and `id`, matching how in-memory resolution - already keyed records. -- A rejected update (e.g. a `state_machine` rule vetoing the replay) no longer severs - natural-key resolution for downstream child datasets. -- Replays are idempotent: an upsert/update whose declared fields already match the - existing row is skipped instead of rewritten (no more `updated_at` churn or lifecycle - re-validation on every boot). diff --git a/.changeset/server-timing-perf-spans-2408.md b/.changeset/server-timing-perf-spans-2408.md deleted file mode 100644 index a9f86aaf0..000000000 --- a/.changeset/server-timing-perf-spans-2408.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -"@objectstack/observability": patch -"@objectstack/driver-sql": patch -"@objectstack/runtime": patch -"@objectstack/plugin-hono-server": patch ---- - -feat(observability): decompose `Server-Timing` into auth / db / hooks / serialize spans (perf-tuning mode) - -The opt-in `Server-Timing` header now breaks a request's server time into the phases that actually explain it, so an operator can open DevTools → Network → Timing and see where the time went without standing up an external tracing backend: - -- **`db`** — total SQL time with a **query count**. The SQL driver wires knex's `query` / `query-response` events (keyed by `__knexQueryUid`) and folds each query into one aggregate member (`db;dur=210;desc="6 queries"`) — the query count is the number most useful for spotting N sequential round-trips. Timing is attributed to the originating request via `AsyncLocalStorage`, so it is correct under concurrency and never cross-attributes. SQL text is never emitted, only durations and a count. -- **`auth`** — identity / session resolution in the dispatcher, the prime suspect for unexplained data-API overhead. -- **`hooks`** — total business-hook execution time with a hook count, fed through the engine's existing `HookMetricsRecorder` seam (wired from the runtime, so `@objectstack/objectql`'s lean `core` tier stays observability-free). -- **`serialize`** — response JSON encoding in the HTTP adapter. - -Adds `countServerTiming(name, dur, unit)` (and `PerfTiming.count`) to fold high-frequency phases into a single aggregate member instead of flooding the header. Every phase is a no-op when perf-tuning is off (`serverTiming: true` / `OS_SERVER_TIMING=true`), so there is zero measurable overhead on the normal path. - -Closes #2408. diff --git a/.changeset/state-machine-initial-states.md b/.changeset/state-machine-initial-states.md deleted file mode 100644 index 4556cf1ce..000000000 --- a/.changeset/state-machine-initial-states.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -"@objectstack/spec": minor -"@objectstack/objectql": minor ---- - -feat(validation): `state_machine.initialStates` enforces the FSM entry point on INSERT (#3165) - -A `state_machine` rule's `transitions` only governs UPDATE — on INSERT the rule -was a no-op, and a `select` field permits ANY declared option as the initial -value. So a record could be born mid-flow (created already `approved`), skipping -the whole state machine. This was the gap #3043's mitigation idea assumed didn't -exist (declared ≠ enforced, ADR-0049). - -`state_machine` rules gain an optional `initialStates: string[]` — the states a -record may be CREATED in. When set, an insert whose (defaulted) state-field value -is outside the list is rejected server-side with `code: 'invalid_initial_state'`. -Omit it to keep the legacy behavior (no initial-state check on insert). A missing -/ empty value is left to required-validation; `transitions` (UPDATE) is -unaffected. Enforced at the same `evaluateValidationRules(..., 'insert')` seam the -engine already runs after field defaults. diff --git a/.changeset/tidy-views-guard.md b/.changeset/tidy-views-guard.md deleted file mode 100644 index 29236abdd..000000000 --- a/.changeset/tidy-views-guard.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@objectstack/spec": patch -"@objectstack/lint": patch -"@objectstack/cli": patch ---- - -Reject view containers that define no views. A flat list-view object (`{ name, label, type, columns, ... }`) parses to an empty `ViewSchema` container because Zod strips unknown keys — zero views register and the Console silently renders nothing. `defineView()` now throws on a zero-view container, and `os validate` gains a `view-container-shape` check (`validateViewContainers` in `@objectstack/lint`) that reports flat or empty `views: []` entries pre-parse with a wrap-it fix hint. diff --git a/.changeset/tier4-type-soundness-warnings.md b/.changeset/tier4-type-soundness-warnings.md deleted file mode 100644 index 628827e21..000000000 --- a/.changeset/tier4-type-soundness-warnings.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -"@objectstack/formula": minor -"@objectstack/lint": minor ---- - -feat(formula,lint): advisory type-soundness warnings for formula/predicate expressions (#1928 tier 4) - -Closes the last open guardrail from #1928. A `Field.formula` or record-scoped -predicate that uses a **text or boolean field with an arithmetic (`+ - * / %`) -or ordering (`< > <= >=`) operator against a number** faults the runtime -overload and silently evaluates to `null` (e.g. `record.title * 2`, -`record.is_active + 1`). The build now surfaces this as a **non-blocking -warning** with the offending field and a corrective message. - -Honours the ADR-0032 design law — the checker only flags what the runtime -would also fail: - -- Number / currency / percent / date / datetime fields are declared `dyn`, so - the cases the runtime rescues never warn — `record.amount / 100` (the #1930 - `registerOperator` fix), `record.due == today()` and numeric-string / ISO-date - values (the string-hydration retry), and numeric-coded `select` option values. -- Equality (`==` / `!=`) is excluded: a heterogeneous equality is runtime-safe - (evaluates to `false`), never a fault. - -New `firstTypeMismatch(source, fieldCelTypes, scope)` export in -`@objectstack/formula` (and an optional `fieldTypes` hint on -`validateExpression`); `@objectstack/lint`'s `validateStackExpressions` threads -each object's field types into every checked site: - -- **record-scoped** sites (`record.`) — formula fields, validation rules, - action / hook / sharing predicates; -- **flattened** flow / automation conditions (bare `field`) — where flow - variables stay `dyn` and are never flagged, and equality stays runtime-safe. - -Warnings are advisory in `objectstack build` / `validate` (fatal only under -`--strict`), matching the tier-3 channel. diff --git a/.changeset/trim-validation-delete-event.md b/.changeset/trim-validation-delete-event.md deleted file mode 100644 index 67dca51bc..000000000 --- a/.changeset/trim-validation-delete-event.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@objectstack/spec": patch ---- - -Remove the dead `'delete'` member from the validation-rule `events` enum (#3184). The rule evaluator only runs on the insert/update write path — `engine.delete` never invokes it — so a rule declaring `events: ['delete']` was a silent no-op (flagged in #3106 and `docs/audits/2026-06-validationschema-property-liveness.md`). The enum now admits only `insert`/`update`; guard deletions with a `beforeDelete` lifecycle hook instead. No shipped metadata declares `events: ['delete']`; any off-spec metadata that did now fails loudly at `os validate` / registration rather than parsing and doing nothing. Also narrows the two hand-written mirrors (`rule-validator.ts` `BaseRule`, `metadata-protocol` JSON-schema form helper — whose stale `type` enum listing removed `unique`/`async`/`custom` variants is corrected in the same pass), updates the doc comments, the published data skill, and the hand-written validation doc. diff --git a/.changeset/view-metadata-type-schema-runtime-shapes.md b/.changeset/view-metadata-type-schema-runtime-shapes.md deleted file mode 100644 index ac5117881..000000000 --- a/.changeset/view-metadata-type-schema-runtime-shapes.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@objectstack/spec": patch ---- - -**The `view` metadata type-schema now validates all three runtime `view` shapes instead of stripping two of them to `{}`.** `metadata-type-schemas.ts` mapped `view` to the aggregate container `ViewSchema` (`{ list, form, listViews, formViews }`, every slot optional). Zod strips unknown keys, so the two non-container shapes a `view` body actually carries at runtime — a standalone **ViewItem record** (`{ name, object, viewKind, config }`) and a **console personalization overlay** (raw view config + identity inherited by `normalizeViewMetadata`, #2555) — both strip-parsed to `{}`. That made the `422` check in `saveMetaItem` and read-time `computeMetadataDiagnostics` a **no-op** for those shapes: a broken `config` (e.g. a kanban missing `groupByField`) saved with a false `200` and badged valid, and the view create-seed test validated against nothing. - -`view` now maps to a new `ViewMetadataSchema` — a union over the three shapes, each validated genuinely: - -1. **defineView container** — non-empty (`ViewSchema` refined to require at least one of `list`/`form`/`listViews`/`formViews`; an empty container is rejected, mirroring `defineView`). -2. **ViewItem record** — `ViewItemSchema`; the nested `config` is validated against ListView/FormView. -3. **Flattened personalization overlay** — inline ListView/FormView config plus optional identity fields. Structural guards pin `config`/`list`/`form`/`listViews`/`formViews` to `undefined` so a malformed record or container can never be rescued through this lenient branch with its real payload silently stripped. - -All members strip-parse (no `.strict()`), so auxiliary Studio round-trip keys (`isPinned`, `sortOrder`, …) still ride along without a false `422`, and `saveMetaItem` keeps persisting the body verbatim. `z.toJSONSchema()` emits the schema as an `anyOf` of the four members, which `/api/v1/meta/types/view` serves to Studio's SchemaForm. - -Fixes #3095. diff --git a/examples/app-crm/CHANGELOG.md b/examples/app-crm/CHANGELOG.md index a4abb372a..5708fb82c 100644 --- a/examples/app-crm/CHANGELOG.md +++ b/examples/app-crm/CHANGELOG.md @@ -1,5 +1,27 @@ # @objectstack/example-crm +## 4.0.90 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [515f11a] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/runtime@15.2.0 + ## 4.0.89 ### Patch Changes diff --git a/examples/app-crm/package.json b/examples/app-crm/package.json index 9097ec6a0..131609c9e 100644 --- a/examples/app-crm/package.json +++ b/examples/app-crm/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/example-crm", - "version": "4.0.89", + "version": "4.0.90", "description": "Minimal CRM example — a smoke-test workspace that exercises the metadata loading pipeline (objects → views → app → dashboard → hook → flow → seed). For a full-featured enterprise CRM see https://github.com/objectstack-ai/hotcrm.", "license": "Apache-2.0", "private": true, diff --git a/examples/app-showcase/CHANGELOG.md b/examples/app-showcase/CHANGELOG.md index 291fc0a6c..a6e15c8e4 100644 --- a/examples/app-showcase/CHANGELOG.md +++ b/examples/app-showcase/CHANGELOG.md @@ -1,5 +1,35 @@ # @objectstack/example-showcase +## 0.3.12 + +### Patch Changes + +- Updated dependencies [41e703b] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [515f11a] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/connector-openapi@15.2.0 + - @objectstack/spec@15.2.0 + - @objectstack/runtime@15.2.0 + - @objectstack/driver-sql@15.2.0 + - @objectstack/cloud-connection@15.2.0 + - @objectstack/connector-mcp@15.2.0 + - @objectstack/connector-rest@15.2.0 + - @objectstack/connector-slack@15.2.0 + - @objectstack/service-datasource@15.2.0 + ## 0.3.11 ### Patch Changes diff --git a/examples/app-showcase/package.json b/examples/app-showcase/package.json index fba1e6e6b..4a99be56e 100644 --- a/examples/app-showcase/package.json +++ b/examples/app-showcase/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/example-showcase", - "version": "0.3.11", + "version": "0.3.12", "description": "Kitchen-sink showcase workspace — exercises every metadata type, every view type, every chart type, and the major end-to-end capability chains (security, automation, analytics). Built for demonstration, debugging, and coverage-driven verification.", "license": "Apache-2.0", "private": true, diff --git a/examples/app-todo/CHANGELOG.md b/examples/app-todo/CHANGELOG.md index 5cb1024d7..2af51d735 100644 --- a/examples/app-todo/CHANGELOG.md +++ b/examples/app-todo/CHANGELOG.md @@ -1,5 +1,35 @@ # @objectstack/example-todo +## 4.0.90 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [515f11a] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/objectql@15.2.0 + - @objectstack/metadata@15.2.0 + - @objectstack/runtime@15.2.0 + - @objectstack/client@15.2.0 + - @objectstack/mcp@15.2.0 + - @objectstack/driver-sqlite-wasm@15.2.0 + - @objectstack/knowledge-memory@15.2.0 + - @objectstack/service-knowledge@15.2.0 + ## 4.0.89 ### Patch Changes diff --git a/examples/app-todo/package.json b/examples/app-todo/package.json index ad1d85fdb..79fcb7fba 100644 --- a/examples/app-todo/package.json +++ b/examples/app-todo/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/example-todo", - "version": "4.0.89", + "version": "4.0.90", "description": "Example Todo App using ObjectStack Protocol", "license": "Apache-2.0", "private": true, diff --git a/examples/embed-objectql/CHANGELOG.md b/examples/embed-objectql/CHANGELOG.md index 7d49610a7..e90a4c61c 100644 --- a/examples/embed-objectql/CHANGELOG.md +++ b/examples/embed-objectql/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/example-embed-objectql +## 0.0.30 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/objectql@15.2.0 + - @objectstack/driver-memory@15.2.0 + ## 0.0.29 ### Patch Changes diff --git a/examples/embed-objectql/package.json b/examples/embed-objectql/package.json index 28450981d..c5bb38846 100644 --- a/examples/embed-objectql/package.json +++ b/examples/embed-objectql/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/example-embed-objectql", - "version": "0.0.29", + "version": "0.0.30", "private": true, "description": "Embed the ObjectQL engine as a plain library via @objectstack/objectql/core — no kernel, no plugins, no metadata protocol (ADR-0076).", "type": "module", diff --git a/packages/adapters/hono/CHANGELOG.md b/packages/adapters/hono/CHANGELOG.md index eb51cc9ba..0e276de07 100644 --- a/packages/adapters/hono/CHANGELOG.md +++ b/packages/adapters/hono/CHANGELOG.md @@ -1,5 +1,18 @@ # @objectstack/hono +## 15.2.0 + +### Patch Changes + +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [2049b6a] +- Updated dependencies [515f11a] +- Updated dependencies [ce468c8] + - @objectstack/runtime@15.2.0 + - @objectstack/plugin-hono-server@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/adapters/hono/package.json b/packages/adapters/hono/package.json index 018b9b206..e61591fab 100644 --- a/packages/adapters/hono/package.json +++ b/packages/adapters/hono/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/hono", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/apps/account/CHANGELOG.md b/packages/apps/account/CHANGELOG.md index c50c05a17..60c6bdded 100644 --- a/packages/apps/account/CHANGELOG.md +++ b/packages/apps/account/CHANGELOG.md @@ -1,5 +1,22 @@ # @objectstack/account +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/apps/account/package.json b/packages/apps/account/package.json index d1dee90ea..b39ee3254 100644 --- a/packages/apps/account/package.json +++ b/packages/apps/account/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/account", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "ObjectStack Account — the end-user account/self-service console app, packaged as its own ObjectStack app package (ADR-0048: one app per package).", "main": "dist/index.js", diff --git a/packages/apps/setup/CHANGELOG.md b/packages/apps/setup/CHANGELOG.md index af8a82e5f..3b54f0901 100644 --- a/packages/apps/setup/CHANGELOG.md +++ b/packages/apps/setup/CHANGELOG.md @@ -1,5 +1,22 @@ # @objectstack/setup +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/apps/setup/package.json b/packages/apps/setup/package.json index ed69a4d47..56ca292f3 100644 --- a/packages/apps/setup/package.json +++ b/packages/apps/setup/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/setup", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "ObjectStack Setup — the platform administration app, packaged as its own ObjectStack app package (ADR-0048: one app per package).", "main": "dist/index.js", diff --git a/packages/apps/studio/CHANGELOG.md b/packages/apps/studio/CHANGELOG.md index 835885226..3d9c9274b 100644 --- a/packages/apps/studio/CHANGELOG.md +++ b/packages/apps/studio/CHANGELOG.md @@ -1,5 +1,22 @@ # @objectstack/studio +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/apps/studio/package.json b/packages/apps/studio/package.json index a68667a64..001aa6e45 100644 --- a/packages/apps/studio/package.json +++ b/packages/apps/studio/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/studio", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "ObjectStack Studio — the metadata builder app, packaged as its own ObjectStack app package (ADR-0048: one app per package).", "main": "dist/index.js", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 8736b9517..cc0d3e5cf 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,170 @@ # @objectstack/cli +## 15.2.0 + +### Minor Changes + +- 2ea08ee: Flow trigger observability — kill the four-layer silence around record-change flows that never fire (2026-07-17 third-party eval). + + A misauthored auto-launched flow (wrong `objectName`, missing `requires: ['automation','triggers']`, failing start condition) produced ZERO output at every layer: the engine's own registration/binding logs land inside the CLI's boot-quiet stdout window (which swallows debug/info/warn — only error/fatal reach stderr), and each "didn't happen" path was itself silent. Fixes: + + - **Startup banner `Flows:` section** (`os serve`/`os dev`/`os start`): flow count, bound-to-trigger count, registered trigger types, draft count — plus loud `⚠` lines for flows declared with no automation engine enabled (`requires` missing), flows whose trigger type has no registered trigger, and bound record-change flows targeting an unknown object (dead binding). Printed after stdout is restored, so it is immune to the boot-quiet window. + - **Trigger-fired run failures now log at ERROR** (stderr — always visible): the automation engine no longer drops the AutomationResult of a trigger-fired execution; condition-evaluation faults and node failures surface with the flow name. Condition-not-met skips stay at debug (high-frequency, intentional). + - **`RecordChangeTrigger` probes object existence at bind time** and warns when a flow's `objectName` matches no registered object (exact-name matching), instead of silently arming a hook that can never fire. + - **`kernel:bootstrapped` binding audit** in the automation plugin: warns per enabled-but-unbound triggered flow with the reason, and reports registered/bound/draft counts (`AutomationEngine.getTriggerBindingAudit()`, extended `getFlowRuntimeStates()` with `status`/`triggerType`/`object`). + - **`os validate` flow-wiring advisories** (`@objectstack/lint` `validateFlowTriggerReadiness`): warns when a record-triggered flow targets an object the stack does not define, and when an auto-triggered flow's status is `draft` (authored or defaulted — draft flows still fire; declare `active` or `obsolete`). + - Removed leftover boot-debug writes (`registerApp`/`AppPlugin`/`StandaloneStack`/`AuditPlugin` stderr noise) that previous debugging of this same silence had left behind. + +### Patch Changes + +- fb107b8: fix(cli): tolerate the `--` separator pnpm injects when forwarding script args (#3114) + + The AGENTS.md-documented backend-debug flow `pnpm dev -- --fresh -p ` failed at + the repo root with an opaque `Unexpected arguments: -p, 44637` (exit 2 + a help dump). + + pnpm appends forwarded args to a script **verbatim, including the `--`**, and each + nested `pnpm --filter` hop preserves it, so the showcase's `objectstack dev +--seed-admin` ran as `objectstack dev --seed-admin -- --fresh -p 44637`. oclif reads + `--` as POSIX end-of-flags, so everything after it became positional: `--fresh` was + silently swallowed as the `package` arg and `-p 44637` overflowed the arg list. Every + flag the user asked for was dropped — the failure was opaque precisely because the + `--` looks inert. + + A `preparse` hook now drops `--` separators before oclif parses argv, so the + npm-style `-- ` form and the bare form behave identically, for every command + and both bins (`run.js`, `run-dev.js`). No `os` command takes passthrough args (none + sets `strict = false`, none reads raw argv), so a `--` carries no meaning here and is + always a package-manager artifact. + + Note this is not fixable via oclif's `'--': false` parser option: that keeps + flag-parsing on past the separator but re-appends the `--` into argv, so strict + commands fail with `Unexpected argument: --` instead. + + Tradeoff: a `-`-prefixed token can no longer be forced to parse as a positional + value. Every `os` positional is a config path, a metadata / datasource / package + name, or an id — none start with `-`. + +- fdc244e: Dev-loop DX fixes from the 15.1 third-party evaluation (P2 batch): + + - **Hot-added objects are now queryable without a restart.** Adding a `*.object.ts` under `os dev` used to recompile "green" while every query answered `no such table` (or `not registered`) until a manual restart: the artifact reload never notified the ObjectQL registry, tables were only created at boot, and seeds only loaded from the boot-time bundle. The `metadata:reloaded` payload now carries the parsed artifact; ObjectQL ingests the object definitions and re-runs the idempotent schema sync (same `skipSchemaSync` opt-out as boot), and the runtime loads seeds for first-seen objects (dev, single-tenant). `os dev` also prints `✚ new object(s): …` on recompile. + - **Dev admin credentials stay visible.** The `os dev` startup banner only showed `admin@objectos.ai / admin123` on the boot that actually seeded it; with the persistent default DB every later boot hid it, and the Console login page never knew it existed. The hint now re-arms on every dev boot for as long as the account still verifies against the default password, and `GET /api/v1/auth/config` exposes a dev-gated `devSeedAdmin` field (never present outside `NODE_ENV=development`) so the login page can show it. + - **`os doctor` reference analysis understands current metadata shapes.** Objects bound through `defineView` containers (`list`/`listViews`/`form`/`formViews` → `data.object`, subform `childObject`, lookup form fields) and app navigation (`objectName`, nested `children`, `areas`) were reported as "defined but not referenced". The collector now walks the canonical shapes (plus flow node `config.object`/`objectName`) and the orphan-view check descends into containers. + +- f58db35: fix(cli): treat an inline `label:` as the default-locale source in i18n coverage + + A fresh `npm create objectstack` scaffold reported 4 `i18n/missing-object` / + `i18n/missing-field` errors for its own `_note` object, even though the + template authors `label: 'Note'`, `pluralLabel: 'Notes'`, `label: 'Title'` and + `label: 'Body'` inline. The only way to silence them was to commit an `en` + bundle restating strings the metadata already carries. + + The inline `label:` _is_ the default-locale text: the runtime resolver falls + back to it when a bundle has no entry (`translateObject`), and `os i18n +extract` seeds bundles from it. Coverage now honours that contract — an inline + label satisfies the default locale, and a bundle is what _other_ locales need. + Keys with no source string anywhere are no longer reported as i18n gaps; a + missing label is already `required/label`'s finding. + + Non-default locales are unaffected: they still warn for every untranslated key + (`os lint` on `examples/app-todo` reports the same 79 warnings as before, with + its 39 default-locale errors gone). `os lint --include-platform` drops the + platform baseline's default-locale errors for the same reason — the platform + ships English labels inline — while keeping its non-default-locale warnings. + +- 878c1ed: `os lint` no longer buries the user's own signal under the platform i18n baseline. A fresh scaffold reported 800+ `i18n/missing-metadataForm` errors — translation keys for platform built-in metadata forms (email_template, …) that the platform packages already ship at runtime. Those are now hidden by default and folded into one summary line (`platform built-ins: N i18n issue(s) hidden`); pass `--include-platform` to audit them, and read `hiddenPlatform` in `--json` output. User-authored metadata coverage is reported unchanged. +- fefcd54: fix(spec): declare `ownership` as a first-class ObjectSchema field (#3175) + + The object-level record-ownership model — `ownership: 'user' | 'org' | 'none'`, + which drives the registry's `owner_id` auto-provisioning (`applySystemFields`) — + was read by the engine via `(schema as any).ownership` while `ObjectSchema.create()` + **rejected** it as an unknown top-level key (ADR-0032 / #1535). So a tested engine + opt-out (`ownership: 'org' | 'none'` on catalog / junction tables) could not be + set through the sanctioned authoring path, and the same `ownership` word was read + elsewhere as the unrelated package-contribution kind (`own` / `extend`). + + - **spec**: `ObjectSchema` now declares `ownership: z.enum(['user','org','none']).optional()`. + Authoring the record-ownership opt-out validates cleanly; the registry reads it + off the typed schema (no `as any`). A retired `ownership: 'own'` / `'extend'` + value fails with guidance pointing at the record-ownership model and noting that + `own`/`extend` is the contribution kind (`registerObject`), not an object-schema value. + - **cli**: the `object` scaffold no longer emits the now-invalid `ownership: 'own'` + (owner injection is the default), and `objectstack info` labels the record model + with the correct `user` default. + + No runtime behavior change: `applySystemFields` and its `owner_id` injection logic + are unchanged — this makes the property the engine already honors legally authorable + and consistently typed. + +- 8923843: Reject view containers that define no views. A flat list-view object (`{ name, label, type, columns, ... }`) parses to an empty `ViewSchema` container because Zod strips unknown keys — zero views register and the Console silently renders nothing. `defineView()` now throws on a zero-view container, and `os validate` gains a `view-container-shape` check (`validateViewContainers` in `@objectstack/lint`) that reports flat or empty `views: []` entries pre-parse with a wrap-it fix hint. +- Updated dependencies [3a18b60] +- Updated dependencies [deb7e7e] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [fdc244e] +- Updated dependencies [780b4b5] +- Updated dependencies [2ea08ee] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [515f11a] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/plugin-approvals@15.2.0 + - @objectstack/lint@15.2.0 + - @objectstack/plugin-auth@15.2.0 + - @objectstack/objectql@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/rest@15.2.0 + - @objectstack/metadata@15.2.0 + - @objectstack/runtime@15.2.0 + - @objectstack/service-automation@15.2.0 + - @objectstack/trigger-record-change@15.2.0 + - @objectstack/plugin-audit@15.2.0 + - @objectstack/observability@15.2.0 + - @objectstack/plugin-hono-server@15.2.0 + - @objectstack/driver-sql@15.2.0 + - @objectstack/formula@15.2.0 + - @objectstack/account@15.2.0 + - @objectstack/setup@15.2.0 + - @objectstack/client@15.2.0 + - @objectstack/cloud-connection@15.2.0 + - @objectstack/mcp@15.2.0 + - @objectstack/platform-objects@15.2.0 + - @objectstack/driver-memory@15.2.0 + - @objectstack/driver-mongodb@15.2.0 + - @objectstack/driver-sqlite-wasm@15.2.0 + - @objectstack/plugin-email@15.2.0 + - @objectstack/plugin-reports@15.2.0 + - @objectstack/plugin-security@15.2.0 + - @objectstack/plugin-sharing@15.2.0 + - @objectstack/plugin-webhooks@15.2.0 + - @objectstack/service-analytics@15.2.0 + - @objectstack/service-cache@15.2.0 + - @objectstack/service-datasource@15.2.0 + - @objectstack/service-job@15.2.0 + - @objectstack/service-messaging@15.2.0 + - @objectstack/service-package@15.2.0 + - @objectstack/service-queue@15.2.0 + - @objectstack/service-realtime@15.2.0 + - @objectstack/service-settings@15.2.0 + - @objectstack/service-sms@15.2.0 + - @objectstack/service-storage@15.2.0 + - @objectstack/trigger-api@15.2.0 + - @objectstack/trigger-schedule@15.2.0 + - @objectstack/types@15.2.0 + - @objectstack/verify@15.2.0 + - @objectstack/plugin-pinyin-search@15.2.0 + - @objectstack/console@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index f4bd244f7..78377407c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/cli", - "version": "15.1.1", + "version": "15.2.0", "description": "Command Line Interface for ObjectStack Protocol", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/client-react/CHANGELOG.md b/packages/client-react/CHANGELOG.md index 5cea754e1..42c2001c2 100644 --- a/packages/client-react/CHANGELOG.md +++ b/packages/client-react/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/client-react +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/client@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/client-react/package.json b/packages/client-react/package.json index 5bdfdcd8f..cf94e3c13 100644 --- a/packages/client-react/package.json +++ b/packages/client-react/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/client-react", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "React hooks for ObjectStack Client SDK", "main": "dist/index.js", diff --git a/packages/client/CHANGELOG.md b/packages/client/CHANGELOG.md index b8ae9fb62..4bf061e4f 100644 --- a/packages/client/CHANGELOG.md +++ b/packages/client/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/client +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/client/package.json b/packages/client/package.json index 611b21129..30e807fc4 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/client", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Official Client SDK for ObjectStack Protocol", "main": "dist/index.js", diff --git a/packages/cloud-connection/CHANGELOG.md b/packages/cloud-connection/CHANGELOG.md index 424a21552..148e90784 100644 --- a/packages/cloud-connection/CHANGELOG.md +++ b/packages/cloud-connection/CHANGELOG.md @@ -1,5 +1,32 @@ # @objectstack/cloud-connection +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [515f11a] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/runtime@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/cloud-connection/package.json b/packages/cloud-connection/package.json index 936ff7d66..9152b1624 100644 --- a/packages/cloud-connection/package.json +++ b/packages/cloud-connection/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/cloud-connection", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Runtime-side client for an ObjectStack cloud control plane — marketplace browse proxy, install-local, device-code binding, org catalog and installed views, and the /api/v1/runtime/config discovery endpoint. Open mechanism (ADR-0008): the hub service, plan policy, and entitlements stay server-side.", "type": "module", diff --git a/packages/connectors/connector-mcp/CHANGELOG.md b/packages/connectors/connector-mcp/CHANGELOG.md index 681bd9531..a4a6e308b 100644 --- a/packages/connectors/connector-mcp/CHANGELOG.md +++ b/packages/connectors/connector-mcp/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/connector-mcp +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/connectors/connector-mcp/package.json b/packages/connectors/connector-mcp/package.json index 3c8209e74..d01351773 100644 --- a/packages/connectors/connector-mcp/package.json +++ b/packages/connectors/connector-mcp/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/connector-mcp", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Model Context Protocol (MCP) connector for ObjectStack — a generic adapter that turns any MCP server's tools into a connector's actions on the automation engine's connector registry (ADR-0024).", "main": "dist/index.js", diff --git a/packages/connectors/connector-openapi/CHANGELOG.md b/packages/connectors/connector-openapi/CHANGELOG.md index cc13b5afa..2b49f9cf3 100644 --- a/packages/connectors/connector-openapi/CHANGELOG.md +++ b/packages/connectors/connector-openapi/CHANGELOG.md @@ -1,5 +1,44 @@ # @objectstack/connector-openapi +## 15.2.0 + +### Minor Changes + +- 41e703b: feat(connector-openapi): degrade + retry on an unreachable remote spec URL (#3049 follow-up) + + The `openapi` provider fetches `providerConfig.spec` when it is an http(s) URL. + That fetch previously threw plain on any failure, so a momentarily-unreachable + spec endpoint aborted the whole app boot. It now classifies the fault the same + way `connector-mcp` classifies its connect path (ADR-0097): + + - **Network error** (DNS / connection refused / timeout) or a **transient HTTP + status** (`408` / `429` / `5xx`, mirroring the `retryableStatusCodes` + convention) throws `ConnectorUpstreamUnavailableError` — the materializer + degrades the instance (`state: 'degraded'` on `GET /connectors`, dispatch + fails clearly) and retries with backoff plus on every `metadata:reloaded`. + - A **wrong URL** (non-retryable `4xx`) or an **unparseable document** stays a + plain, fatal configuration fault. + + Inline and file-path (`#3016`) specs do no boot I/O and are unaffected. + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/connectors/connector-openapi/package.json b/packages/connectors/connector-openapi/package.json index 81a8e829e..fc6641b21 100644 --- a/packages/connectors/connector-openapi/package.json +++ b/packages/connectors/connector-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/connector-openapi", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "OpenAPI 3.x connector generator for ObjectStack — turns a declarative OpenAPI document into connector actions on the automation engine's registry, with a self-contained static-auth HTTP transport (ADR-0023).", "main": "dist/index.js", diff --git a/packages/connectors/connector-rest/CHANGELOG.md b/packages/connectors/connector-rest/CHANGELOG.md index 76363d279..03a1f05d9 100644 --- a/packages/connectors/connector-rest/CHANGELOG.md +++ b/packages/connectors/connector-rest/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/connector-rest +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/connectors/connector-rest/package.json b/packages/connectors/connector-rest/package.json index 5b6f21ac1..04793164f 100644 --- a/packages/connectors/connector-rest/package.json +++ b/packages/connectors/connector-rest/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/connector-rest", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Generic REST connector for ObjectStack — the reference concrete connector that registers a `request` action on the automation engine's connector registry (ADR-0018 §Addendum).", "main": "dist/index.js", diff --git a/packages/connectors/connector-slack/CHANGELOG.md b/packages/connectors/connector-slack/CHANGELOG.md index 697666be0..b3130bf38 100644 --- a/packages/connectors/connector-slack/CHANGELOG.md +++ b/packages/connectors/connector-slack/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/connector-slack +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/connectors/connector-slack/package.json b/packages/connectors/connector-slack/package.json index a96f269a7..67a7b0122 100644 --- a/packages/connectors/connector-slack/package.json +++ b/packages/connectors/connector-slack/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/connector-slack", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Slack Web API connector for ObjectStack — registers `chat.postMessage` / `chat.update` / `call` actions on the automation engine's connector registry (ADR-0018 §Addendum, ADR-0022).", "main": "dist/index.js", diff --git a/packages/console/CHANGELOG.md b/packages/console/CHANGELOG.md index 2de3314c5..65f704771 100644 --- a/packages/console/CHANGELOG.md +++ b/packages/console/CHANGELOG.md @@ -1,5 +1,7 @@ # @objectstack/console +## 15.2.0 + ## 15.1.1 ## 15.1.0 diff --git a/packages/console/package.json b/packages/console/package.json index 7b7b05599..ef102b9a6 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/console", - "version": "15.1.1", + "version": "15.2.0", "description": "Prebuilt Console SPA pinned to this @objectstack/framework release. Source of truth: @object-ui/console (https://github.com/objectstack-ai/objectui).", "license": "Apache-2.0", "homepage": "https://github.com/objectstack-ai/framework/tree/main/packages/console", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 919fecedc..2698f0f33 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,62 @@ # @objectstack/core +## 15.2.0 + +### Patch Changes + +- e057f42: fix: harden the bulk-write path — retries, idempotency, contracts, and summary visibility (#3147–#3152) + + Six reliability fixes to the batched seed/import + `engine.insert(array)` path + introduced by the #2678 bulk-write rework: + + - **#3151** `bulkWrite` validates that `writeBatch` returns one record per input + row (a short/long/non-array return is degraded per-row, not backfilled as + phantom success); `engine.insert(array)` likewise rejects a short driver + `bulkCreate` return instead of padding afterInsert with `undefined`. + - **#3150** wraps the two remaining un-retried write points (seed + `writeRecord`/`resolveDeferredUpdates`, import's no-`createManyData` + fallback) in `withTransientRetry`; `defaultIsTransientError` short-circuits + definitive logical errors to non-transient. + - **#3148** import `resolveRef` flushes pending creates on a same-object miss so + a later row can reference an earlier same-file CREATE, and no longer + negatively caches a miss. + - **#3149** threads an `attempt` counter through `bulkWrite`; seed rechecks by + `externalId` and import by `matchFields` before re-writing, so a + commit-then-lost-response retry cannot duplicate a batch. + - **#3147** `recomputeSummaries` retries transient failures and, on exhaustion, + surfaces `SummaryRecomputeError` (`ERR_SUMMARY_RECOMPUTE`) instead of a + silent warn; seed/import recover it to a warning without re-writing. + - **#3152** autonumbers are assigned after validation, so a batch that dies in + validation consumes no sequence value (no number-range gaps). + +- 5f05de2: **`createLogger({ file })` now actually writes the file under ESM.** `openFileStream` loaded `fs` with a lazy `require()` to keep the browser-safe logger entry out of the `fs` bundle graph; esbuild rewrites that to its `__require` shim in the ESM output, which throws `Dynamic require of "fs" is not supported`, and a bare `catch {}` swallowed it. Since the workspace is `type: module`, every Node ESM consumer — `os serve`, `os dev` — silently got no file logging at all, while the CJS build kept working. The builtin now loads via `process.getBuiltinModule` (opaque to bundlers, works in both module systems, with a `require` fallback for Node < 20.16), and a `file` destination that cannot be opened reports itself on stderr instead of disappearing. + + Turning the destination back on also fixed three faults that were unreachable while it never opened: `child()` opened a second stream per child and orphaned it, destroying a child logger closed the stream its parent and siblings were still writing to, and an async open failure (e.g. an unwritable path) hit an `'error'` event with no listener and took the process down. + +- 021ba4c: fix(core): ObjectLogger honors NO_COLOR and TTY detection before emitting ANSI colors + + The kernel/plugin logger (`ctx.logger`, wired by `os serve` / `os dev`) colorized its + `pretty`-format level tags unconditionally, so `NO_COLOR=1` runs and piped/CI output + still carried ANSI escapes (e.g. `\x1b[31m…ERROR\x1b[0m`), breaking plain-text log + scanners (see scripts/publish-smoke.sh, which had to strip ANSI before grepping). + + Per the no-color.org convention, color is now emitted only when the destination stream + (stdout, or stderr for error/fatal) is an interactive TTY **and** `NO_COLOR` is unset or + empty — any non-empty `NO_COLOR` value disables color. Interactive terminals keep the + existing colorized output. The optional file destination now always receives plain text. + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index 090c37b0a..3fbdd5ae6 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/core", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Microkernel Core for ObjectStack", "type": "module", diff --git a/packages/create-objectstack/CHANGELOG.md b/packages/create-objectstack/CHANGELOG.md index f2f630bf9..1b6ba426e 100644 --- a/packages/create-objectstack/CHANGELOG.md +++ b/packages/create-objectstack/CHANGELOG.md @@ -1,5 +1,80 @@ # create-objectstack +## 15.2.0 + +### Minor Changes + +- 3f218e4: feat(create-objectstack): the blank scaffold ships the three generic connector executors by default + + `npm create objectstack` now generates an `objectstack.config.ts` that wires the + `rest`, `openapi`, and `mcp` connector executor plugins (ADR-0022/0023/0024 + + ADR-0097) into `plugins:`, alongside `requires: ['automation']`. This closes the + last authoring gap in the ADR-0097 promise that integrations are expressible + **and executable** as pure metadata: an author (human or AI) can now add a + declarative `connectors:` entry naming `provider: 'rest' | 'openapi' | 'mcp'` + and have it materialize into a live, dispatchable connector at boot — with no + host-code edit. + + - `plugins:` — `new ConnectorRestPlugin()`, `new ConnectorOpenApiPlugin()`, + `new ConnectorMcpPlugin()` (zero-arg = contribute the provider factory only). + - `requires: ['automation']` — the automation service performs the + materialization and owns the registry the executors register into. It is also + a hard dependency of the connector plugins, so a scaffold that lists them in + `plugins:` without it fails boot; automation ships transitively via + `@objectstack/cli`. + - deps — `@objectstack/connector-rest`, `@objectstack/connector-openapi`, + `@objectstack/connector-mcp`. + - Security (#3055): declarative `mcp` stdio transports stay denied by default — + opt in per host with `new ConnectorMcpPlugin({ declarativeStdio: ['node'] })`. + + Brand connectors (Slack, …) remain marketplace/opt-in. + +### Patch Changes + +- 3b6ef8a: Scaffolded projects ship with a `.gitignore` again — `npx create-objectstack` produced none, leaving `node_modules/` and `.env` un-ignored for every new user. + + `npm pack` / `pnpm pack` strip `.gitignore` from a tarball unconditionally, at every depth. The blank template committed one at `src/templates/blank/.gitignore` and the build faithfully copied it to `dist/templates/blank/.gitignore`, but `files: ["dist"]` publishing dropped it on the way to the registry — so the file was present in the repo, present in every local build, and absent from all 11 files of a real scaffold. Verified against the published 15.1.1 tarball, which ships `dist/templates/blank/.dockerignore` and no `.gitignore`. + + The template is now committed as `_gitignore` (a name npm does not strip) and restored to `.gitignore` when the template is copied, via a `TEMPLATE_FILE_ALIASES` map in the new `template-copy.ts`. Only `.gitignore` is aliased: the strip list is `.gitignore` and `.npmrc`, not "every dotfile" — `.dockerignore` packs fine and stays literal. + + The restored ignore rules also cover `.env` / `.env.*`, which they never did. The template README has users write `OS_AUTH_SECRET` and `OS_SECRET_KEY` into a `.env`, and `docker-compose.yml` calls that file "never committed" — but only the prose said so, and `.dockerignore` was the only file that listed it. + + A packing ratchet in `template-consistency.test.ts` guards both halves: it packs the real package, scaffolds from the extracted tarball with the real copy logic, and asserts every template file lands under its intended name. Source-level assertions cannot see this class of bug — the file only vanishes at publish. + +- 3a8ce9d: fix(create-objectstack): the blank scaffold declares pnpm build approvals, so a fresh `pnpm install` no longer exits 1 on pnpm 11 + + pnpm 11 turned an unapproved dependency build script from a warning into a hard + error. The blank template declared no build approvals, so the very first command + a new user runs failed on any current pnpm: + + ``` + npx create-objectstack myapp && cd myapp && pnpm install + # [ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: better-sqlite3@12.11.1, esbuild@0.28.1 + # exit 1 + ``` + + The scaffold now ships a `pnpm-workspace.yaml` approving the two packages it + actually depends on building — `better-sqlite3` (the native sqlite driver behind + `@objectstack/driver-sql`) and `esbuild` (compiles `objectstack.config.ts`). + + Both approval keys are present because pnpm reads them by version, and neither + alone covers the supported range: + + - `allowBuilds` (a package → boolean map) — the only key pnpm 11 honors, and + understood back to pnpm 10.31. `onlyBuiltDependencies` alone still errors. + - `onlyBuiltDependencies` (a list) — pnpm 10.0–10.30, which ignore `allowBuilds`. + + npm and yarn ignore the file, so the npm install path is unaffected. Both + packages ship prebuilt binaries, so this was an install-time hard stop rather + than a runtime defect — the project ran fine once installed. + + This is the #3091 failure class (in-repo settings masking what users resolve) + and was caught by the publish smoke gate added in #3100, which installs the + release candidate the way a user does — on whatever pnpm corepack hands a fresh + machine. + +- 809214f: Stop leaking repo-internal skills into scaffolded projects. The scaffolder (and the docs) advertised `npx skills add objectstack-ai/framework --all`, and the skills CLI's `--all` implies `--skill '*'` — which includes even `metadata.internal` skills — so repo-internal tooling like `.claude/skills/dogfood-verification` landed in every new project's `.agents/skills/`. All install commands are now scoped to the published catalog via the `/skills` subpath (`npx skills add objectstack-ai/framework/skills --all`), the internal skill is additionally marked `metadata.internal: true` to hide it from interactive discovery, and a template-consistency ratchet plus a scaffold-e2e assertion keep the boundary from regressing. + ## 15.1.1 ## 15.1.0 diff --git a/packages/create-objectstack/package.json b/packages/create-objectstack/package.json index 795a1f5c0..245fd0722 100644 --- a/packages/create-objectstack/package.json +++ b/packages/create-objectstack/package.json @@ -1,6 +1,6 @@ { "name": "create-objectstack", - "version": "15.1.1", + "version": "15.2.0", "description": "Create a new ObjectStack project — npx create-objectstack", "bin": { "create-objectstack": "./bin/create-objectstack.js" diff --git a/packages/formula/CHANGELOG.md b/packages/formula/CHANGELOG.md index 4d43af207..13c80f9d7 100644 --- a/packages/formula/CHANGELOG.md +++ b/packages/formula/CHANGELOG.md @@ -1,5 +1,55 @@ # @objectstack/formula +## 15.2.0 + +### Minor Changes + +- ea32ec7: feat(formula,lint): advisory type-soundness warnings for formula/predicate expressions (#1928 tier 4) + + Closes the last open guardrail from #1928. A `Field.formula` or record-scoped + predicate that uses a **text or boolean field with an arithmetic (`+ - * / %`) + or ordering (`< > <= >=`) operator against a number** faults the runtime + overload and silently evaluates to `null` (e.g. `record.title * 2`, + `record.is_active + 1`). The build now surfaces this as a **non-blocking + warning** with the offending field and a corrective message. + + Honours the ADR-0032 design law — the checker only flags what the runtime + would also fail: + + - Number / currency / percent / date / datetime fields are declared `dyn`, so + the cases the runtime rescues never warn — `record.amount / 100` (the #1930 + `registerOperator` fix), `record.due == today()` and numeric-string / ISO-date + values (the string-hydration retry), and numeric-coded `select` option values. + - Equality (`==` / `!=`) is excluded: a heterogeneous equality is runtime-safe + (evaluates to `false`), never a fault. + + New `firstTypeMismatch(source, fieldCelTypes, scope)` export in + `@objectstack/formula` (and an optional `fieldTypes` hint on + `validateExpression`); `@objectstack/lint`'s `validateStackExpressions` threads + each object's field types into every checked site: + + - **record-scoped** sites (`record.`) — formula fields, validation rules, + action / hook / sharing predicates; + - **flattened** flow / automation conditions (bare `field`) — where flow + variables stay `dyn` and are never flagged, and equality stays runtime-safe. + + Warnings are advisory in `objectstack build` / `validate` (fatal only under + `--strict`), matching the tier-3 channel. + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/formula/package.json b/packages/formula/package.json index 2a3ea8e69..e7236a2e4 100644 --- a/packages/formula/package.json +++ b/packages/formula/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/formula", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "ObjectStack canonical expression engine — CEL (cel-js) + ObjectStack stdlib + dialect registry", "main": "dist/index.js", diff --git a/packages/lint/CHANGELOG.md b/packages/lint/CHANGELOG.md index a38c1d0be..314557b8b 100644 --- a/packages/lint/CHANGELOG.md +++ b/packages/lint/CHANGELOG.md @@ -1,5 +1,109 @@ # @objectstack/lint +## 15.2.0 + +### Minor Changes + +- 3a18b60: feat(approvals): rename the `role` approver type to `org_membership_level` (#3133) + + `ApproverType.role` was the last platform surface projecting the reserved word + "role" (ADR-0090 D3). It is not covered by D3's better-auth exception: that + exception protects better-auth's own `sys_member.role` **column**, which we do + not own — `ApproverType` is our own enum, an authoring surface, and D3 mandates + that the projection of that concept is spelled `org_membership_level` and + labelled "organization membership", **never "role"**. + + The sentence licensing the leak was also false: ADR-0090 D3 claims + `sys_member.role` is "already relabelled `org_membership_level` in the platform + projection", but `org_membership_level` existed nowhere in the codebase and + ADR-0057 D7 lists that relabel under "Deferred (evidence-gated, P4)". The + projection never landed, so the word reached authors. + + The name manufactured a real, silent failure — "hotcrm class": every other + surface renamed to `position` (`sys_role`, `ShareRecipientType.role`, + `ctx.roles[]`), so `{ type: 'role', value: 'sales_manager' }` reads as the + legacy spelling of a position. It resolves against the membership tier, finds + no member row, falls back to an inert `role:sales_manager` literal, and the + request waits forever on an approver that cannot exist. + + - **spec**: `ApproverType` gains `org_membership_level`; `role` stays as a + deprecated alias for one window (a published 15.x flow keeps loading) with + `DEPRECATED_APPROVER_TYPES` + `canonicalApproverType()` as the single source + for the mapping. Removed in the next major. + - **plugin-approvals**: resolves on the canonical type and warns on the + deprecated spelling. The `type:value` fallback literal keeps the **authored** + spelling — stored `sys_approval_approver` rows and `pending_approvers` slots + from 15.x carry `role:`, and rewriting it would orphan them. + - **lint**: `approval-role-not-membership-tier` → `approval-approver-not-membership-tier` + (the rule id carried the reserved word too), plus a new + `approval-approver-type-deprecated`. The two are mutually exclusive: a bad + _value_ wins, because prescribing `org_membership_level` for a position name + would be wrong advice — the fix there is `position`. + + Authoring `type: 'role'` keeps working and now says so out loud. Rewrite it as + `org_membership_level`; if the value is an org position, the fix is `position`. + +- 2ea08ee: Flow trigger observability — kill the four-layer silence around record-change flows that never fire (2026-07-17 third-party eval). + + A misauthored auto-launched flow (wrong `objectName`, missing `requires: ['automation','triggers']`, failing start condition) produced ZERO output at every layer: the engine's own registration/binding logs land inside the CLI's boot-quiet stdout window (which swallows debug/info/warn — only error/fatal reach stderr), and each "didn't happen" path was itself silent. Fixes: + + - **Startup banner `Flows:` section** (`os serve`/`os dev`/`os start`): flow count, bound-to-trigger count, registered trigger types, draft count — plus loud `⚠` lines for flows declared with no automation engine enabled (`requires` missing), flows whose trigger type has no registered trigger, and bound record-change flows targeting an unknown object (dead binding). Printed after stdout is restored, so it is immune to the boot-quiet window. + - **Trigger-fired run failures now log at ERROR** (stderr — always visible): the automation engine no longer drops the AutomationResult of a trigger-fired execution; condition-evaluation faults and node failures surface with the flow name. Condition-not-met skips stay at debug (high-frequency, intentional). + - **`RecordChangeTrigger` probes object existence at bind time** and warns when a flow's `objectName` matches no registered object (exact-name matching), instead of silently arming a hook that can never fire. + - **`kernel:bootstrapped` binding audit** in the automation plugin: warns per enabled-but-unbound triggered flow with the reason, and reports registered/bound/draft counts (`AutomationEngine.getTriggerBindingAudit()`, extended `getFlowRuntimeStates()` with `status`/`triggerType`/`object`). + - **`os validate` flow-wiring advisories** (`@objectstack/lint` `validateFlowTriggerReadiness`): warns when a record-triggered flow targets an object the stack does not define, and when an auto-triggered flow's status is `draft` (authored or defaulted — draft flows still fire; declare `active` or `obsolete`). + - Removed leftover boot-debug writes (`registerApp`/`AppPlugin`/`StandaloneStack`/`AuditPlugin` stderr noise) that previous debugging of this same silence had left behind. + +- ea32ec7: feat(formula,lint): advisory type-soundness warnings for formula/predicate expressions (#1928 tier 4) + + Closes the last open guardrail from #1928. A `Field.formula` or record-scoped + predicate that uses a **text or boolean field with an arithmetic (`+ - * / %`) + or ordering (`< > <= >=`) operator against a number** faults the runtime + overload and silently evaluates to `null` (e.g. `record.title * 2`, + `record.is_active + 1`). The build now surfaces this as a **non-blocking + warning** with the offending field and a corrective message. + + Honours the ADR-0032 design law — the checker only flags what the runtime + would also fail: + + - Number / currency / percent / date / datetime fields are declared `dyn`, so + the cases the runtime rescues never warn — `record.amount / 100` (the #1930 + `registerOperator` fix), `record.due == today()` and numeric-string / ISO-date + values (the string-hydration retry), and numeric-coded `select` option values. + - Equality (`==` / `!=`) is excluded: a heterogeneous equality is runtime-safe + (evaluates to `false`), never a fault. + + New `firstTypeMismatch(source, fieldCelTypes, scope)` export in + `@objectstack/formula` (and an optional `fieldTypes` hint on + `validateExpression`); `@objectstack/lint`'s `validateStackExpressions` threads + each object's field types into every checked site: + + - **record-scoped** sites (`record.`) — formula fields, validation rules, + action / hook / sharing predicates; + - **flattened** flow / automation conditions (bare `field`) — where flow + variables stay `dyn` and are never flagged, and equality stays runtime-safe. + + Warnings are advisory in `objectstack build` / `validate` (fatal only under + `--strict`), matching the tier-3 channel. + +### Patch Changes + +- 8923843: Reject view containers that define no views. A flat list-view object (`{ name, label, type, columns, ... }`) parses to an empty `ViewSchema` container because Zod strips unknown keys — zero views register and the Console silently renders nothing. `defineView()` now throws on a zero-view container, and `os validate` gains a `view-container-shape` check (`validateViewContainers` in `@objectstack/lint`) that reports flat or empty `views: []` entries pre-parse with a wrap-it fix hint. +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/formula@15.2.0 + - @objectstack/sdui-parser@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/lint/package.json b/packages/lint/package.json index e266bd98a..4fed17f55 100644 --- a/packages/lint/package.json +++ b/packages/lint/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/lint", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Static, build-time validation for an ObjectStack metadata graph — dashboard widget bindings, CEL/predicate expressions, and more. Pure (stack) => Issue[] functions shared by the CLI's `os validate` and any other consumer (e.g. AI authoring). Depends on @objectstack/spec; never on a runtime.", "type": "module", diff --git a/packages/mcp/CHANGELOG.md b/packages/mcp/CHANGELOG.md index 40fcf8f0c..430d26e6f 100644 --- a/packages/mcp/CHANGELOG.md +++ b/packages/mcp/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/plugin-mcp-server +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/mcp/package.json b/packages/mcp/package.json index 6cdf7dbca..634a3f135 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/mcp", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "ObjectStack as an MCP server — exposes your app's objects (and AI tools) over the Model Context Protocol (stdio + Streamable HTTP)", "type": "module", diff --git a/packages/metadata-core/CHANGELOG.md b/packages/metadata-core/CHANGELOG.md index 3a0868d9e..2c46a8a19 100644 --- a/packages/metadata-core/CHANGELOG.md +++ b/packages/metadata-core/CHANGELOG.md @@ -1,5 +1,21 @@ # @objectstack/metadata-core +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/metadata-core/package.json b/packages/metadata-core/package.json index 6032264e8..7f7c74609 100644 --- a/packages/metadata-core/package.json +++ b/packages/metadata-core/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/metadata-core", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Metadata Repository contracts: types, canonicalization, errors, interface (ADR-0008).", "type": "module", diff --git a/packages/metadata-fs/CHANGELOG.md b/packages/metadata-fs/CHANGELOG.md index 4125d795b..2a05a704d 100644 --- a/packages/metadata-fs/CHANGELOG.md +++ b/packages/metadata-fs/CHANGELOG.md @@ -1,5 +1,11 @@ # @objectstack/metadata-fs +## 15.2.0 + +### Patch Changes + +- @objectstack/metadata-core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/metadata-fs/package.json b/packages/metadata-fs/package.json index 4d2e86734..3cbec0d3e 100644 --- a/packages/metadata-fs/package.json +++ b/packages/metadata-fs/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/metadata-fs", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "FileSystemRepository: Node-only Repository implementation backed by JSON files and a JSONL change log (ADR-0008).", "type": "module", diff --git a/packages/metadata-protocol/CHANGELOG.md b/packages/metadata-protocol/CHANGELOG.md index e0c0353b4..fbb5f1990 100644 --- a/packages/metadata-protocol/CHANGELOG.md +++ b/packages/metadata-protocol/CHANGELOG.md @@ -1,5 +1,125 @@ # @objectstack/metadata-protocol +## 15.2.0 + +### Patch Changes + +- e057f42: fix: harden the bulk-write path — retries, idempotency, contracts, and summary visibility (#3147–#3152) + + Six reliability fixes to the batched seed/import + `engine.insert(array)` path + introduced by the #2678 bulk-write rework: + + - **#3151** `bulkWrite` validates that `writeBatch` returns one record per input + row (a short/long/non-array return is degraded per-row, not backfilled as + phantom success); `engine.insert(array)` likewise rejects a short driver + `bulkCreate` return instead of padding afterInsert with `undefined`. + - **#3150** wraps the two remaining un-retried write points (seed + `writeRecord`/`resolveDeferredUpdates`, import's no-`createManyData` + fallback) in `withTransientRetry`; `defaultIsTransientError` short-circuits + definitive logical errors to non-transient. + - **#3148** import `resolveRef` flushes pending creates on a same-object miss so + a later row can reference an earlier same-file CREATE, and no longer + negatively caches a miss. + - **#3149** threads an `attempt` counter through `bulkWrite`; seed rechecks by + `externalId` and import by `matchFields` before re-writing, so a + commit-then-lost-response retry cannot duplicate a batch. + - **#3147** `recomputeSummaries` retries transient failures and, on exhaustion, + surfaces `SummaryRecomputeError` (`ERR_SUMMARY_RECOMPUTE`) instead of a + silent warn; seed/import recover it to a warning without re-writing. + - **#3152** autonumbers are assigned after validation, so a batch that dies in + validation consumes no sequence value (no number-range gaps). + +- b8a21ad: Publish/discard package drafts in the draft's own org scope, fixing `no_draft` after saving a draft via Studio. + + Studio "Save Draft" (`PUT /meta/:type/:name?mode=draft`) never threads the session's `activeOrganizationId`, so the draft row is written env-wide (`organization_id = NULL`). "Publish" (`POST /packages/:id/publish-drafts`) resolves the active org and passed it to `promoteDraft`, which looked the draft up with a strict `organization_id = ` equality — so it 404'd (`[no_draft] No pending draft exists …`) on the env-wide row it could never match, even though `listDrafts` had already surfaced that draft to the publish CTA (PR #1852's `$or`). `discardPackageDrafts` had the same latent gap. + + `listDrafts` now projects each draft's own `organizationId`, and `publishPackageDrafts` / `discardPackageDrafts` promote / delete each draft in that scope (env-wide stays env-wide, per-org stays per-org). Seed-body capture and the ADR-0067 revert-plan pre-state read are scoped the same way. + + Fixes #3115. + +- beaf2de: fix(metadata-protocol): strip static `readonly` on INSERT at the data-write ingress (#3043) + + #2948/#3003 made static `readonly: true` fields server-enforced on UPDATE (a + non-system PATCH forging `approval_status: 'approved'` is silently stripped in + the engine), but INSERT was exempt. For approval/status/verdict columns that + exemption was the _shorter_ attack: instead of the #3003 draft-then-PATCH move, a + non-system caller could `POST` a record already `approval_status: 'approved'` in + one step — and the UPDATE-only strip never reached it. + + The strip now also runs on INSERT, but at the **external data-write ingress** + (`DataProtocol.createData` / `createManyData` / `batchData` / `cloneData`) rather + than in the engine. That seam is the single point every external programmatic + create funnels through — the REST CRUD route, the GraphQL/MCP dispatcher + (`bridge.create` → `callData` → `createData`), and bulk import — while **trusted + internal writers** (better-auth's adapter, the metadata repository, the seed + loader) call `engine.insert` directly and bypass it. Enforcing at the ingress + protects every caller/agent path at once without stripping the internal writers + that legitimately seed read-only columns on create (identity provisioning, + provenance stamps, event-log cursors) — the blast radius an engine-level insert + strip would have. + + - **Caller-forged only, at the ingress.** The payload here is raw caller input + (the security middleware stamps `owner_id` / `organization_id` later, inside + `engine.insert`), so only keys the caller actually sent are dropped; server + stamps are added afterwards and are unaffected. + - **Re-derives the default.** A stripped field falls back to its declared + `defaultValue` in the engine (a forged `approval_status` becomes `draft`, not + NULL). + - **System-context exempt.** `isSystem` writes still seed read-only columns. + - **Silent** (HTTP 2xx), per-row on batch/import. `readonlyWhen` stays + INSERT-exempt (a conditional lock needs a prior record). + - **Author-defined business objects only.** Platform objects (`managedBy` set, + or the `sys_` namespace) carry their own field-write governance that a silent + strip must not pre-empt — e.g. ADR-0086 REJECTS (403) a forged + `managed_by:'package'` on `sys_permission_set`, and #3004 rejects a forged + `owner_id`; several of those columns are `readonly`, so stripping them here + would swallow the payload the guard is meant to reject. The #3043 threat is app + approval/status fields, never `sys_` — the same boundary `applySystemFields` + uses for ownership. + + Behavior change: a non-system create through the data API (REST / GraphQL / MCP / + import) can no longer seed a `readonly` column from the payload. Flows that + legitimately write read-only columns at creation must run with a system context + (`isSystem`), the same requirement the UPDATE strip already imposes. + +- 515f11a: fix(seed): replaying seeds no longer corrupts lookup natural keys on the upsert update path + + Every dev-server restart replayed package seeds in upsert mode, and any record whose + lookup/master_detail was authored as a natural key could have that reference overwritten + with NULL on the update path (`NOT NULL constraint failed` on required columns; silent + link loss on nullable ones). Four fixes: + + - An unresolved reference now leaves the column untouched (deferred to pass 2) or drops + the record loudly — it is never written as NULL over an existing row. + - DB-side reference resolution probes the target dataset's declared `externalId` (e.g. + `email`) before falling back to `name` and `id`, matching how in-memory resolution + already keyed records. + - A rejected update (e.g. a `state_machine` rule vetoing the replay) no longer severs + natural-key resolution for downstream child datasets. + - Replays are idempotent: an upsert/update whose declared fields already match the + existing row is skipped instead of rewritten (no more `updated_at` churn or lifecycle + re-validation on every boot). + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/formula@15.2.0 + - @objectstack/metadata-core@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/metadata-protocol/package.json b/packages/metadata-protocol/package.json index 793e85268..5260df211 100644 --- a/packages/metadata-protocol/package.json +++ b/packages/metadata-protocol/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/metadata-protocol", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "ObjectStack metadata management protocol: sys_metadata CRUD, draft/publish, locks, package ownership, diagnostics (ADR-0076).", "type": "module", diff --git a/packages/metadata/CHANGELOG.md b/packages/metadata/CHANGELOG.md index eea85fe56..fabe76d81 100644 --- a/packages/metadata/CHANGELOG.md +++ b/packages/metadata/CHANGELOG.md @@ -1,5 +1,45 @@ # @objectstack/metadata +## 15.2.0 + +### Patch Changes + +- fdc244e: Dev-loop DX fixes from the 15.1 third-party evaluation (P2 batch): + + - **Hot-added objects are now queryable without a restart.** Adding a `*.object.ts` under `os dev` used to recompile "green" while every query answered `no such table` (or `not registered`) until a manual restart: the artifact reload never notified the ObjectQL registry, tables were only created at boot, and seeds only loaded from the boot-time bundle. The `metadata:reloaded` payload now carries the parsed artifact; ObjectQL ingests the object definitions and re-runs the idempotent schema sync (same `skipSchemaSync` opt-out as boot), and the runtime loads seeds for first-seen objects (dev, single-tenant). `os dev` also prints `✚ new object(s): …` on recompile. + - **Dev admin credentials stay visible.** The `os dev` startup banner only showed `admin@objectos.ai / admin123` on the boot that actually seeded it; with the persistent default DB every later boot hid it, and the Console login page never knew it existed. The hint now re-arms on every dev boot for as long as the account still verifies against the default password, and `GET /api/v1/auth/config` exposes a dev-gated `devSeedAdmin` field (never present outside `NODE_ENV=development`) so the login page can show it. + - **`os doctor` reference analysis understands current metadata shapes.** Objects bound through `defineView` containers (`list`/`listViews`/`form`/`formViews` → `data.object`, subform `childObject`, lookup form fields) and app navigation (`objectName`, nested `children`, `areas`) were reported as "defined but not referenced". The collector now walks the canonical shapes (plus flow node `config.object`/`objectName`) and the orphan-view check descends into containers. + +- d2723e2: **`MetadataManager.register()` / `unregister()` now announce to `subscribe()` watchers.** Both updated the registry, persisted to writable loaders and published to realtime, but never fired the watch callbacks — so `subscribe()` looked like it covered every write while silently missing all of them. Only the `saveMetaItem` path (via the repository watch stream) and the filesystem watcher ever reached a subscriber. Runtime consumers that cache metadata — notably ObjectQL's SchemaRegistry bridge, the component that decides what is queryable — went stale on every other write until the process restarted. + + Announcing is now the **default**, so a new call site is correct without knowing this contract exists. This is a contract fix rather than a bug fix: the one live behavior change is that runtime datasource writes (`datasource-admin`) now reach the HMR SSE stream, which subscribes to every registered type. `unregisterPackage()` / `bulkUnregister()` also announce their deletes now — correct, but latent, since neither has a production caller today. + + Bulk ingest opts out explicitly with the new `MetadataWriteOptions` (`{ notify: false }`) — boot-time filesystem priming, artifact ingest, and ObjectQL's registry bridge, each of which either runs before consumers cache anything or announces the whole batch once (as the artifact reload path does via `metadata:reloaded`). The bridge in particular MUST stay silent: it copies objects out of the SchemaRegistry, and announcing would feed them back through a handler that re-registers under `_packageId ?? 'metadata-service'`, overwriting the true package provenance of every object whose body carries no `_packageId`. + + Additive only — `register(type, name, data)` and `unregister(type, name)` keep working unchanged. + + Fixes #3112. + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/metadata-core@15.2.0 + - @objectstack/platform-objects@15.2.0 + - @objectstack/types@15.2.0 + - @objectstack/metadata-fs@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/metadata/package.json b/packages/metadata/package.json index bbc4b5cca..767b18380 100644 --- a/packages/metadata/package.json +++ b/packages/metadata/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/metadata", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Metadata loading, saving, and persistence for ObjectStack", "type": "module", diff --git a/packages/objectql/CHANGELOG.md b/packages/objectql/CHANGELOG.md index e37de8c58..091b490c8 100644 --- a/packages/objectql/CHANGELOG.md +++ b/packages/objectql/CHANGELOG.md @@ -1,5 +1,103 @@ # @objectstack/objectql +## 15.2.0 + +### Minor Changes + +- 04ecd4e: feat(validation): `state_machine.initialStates` enforces the FSM entry point on INSERT (#3165) + + A `state_machine` rule's `transitions` only governs UPDATE — on INSERT the rule + was a no-op, and a `select` field permits ANY declared option as the initial + value. So a record could be born mid-flow (created already `approved`), skipping + the whole state machine. This was the gap #3043's mitigation idea assumed didn't + exist (declared ≠ enforced, ADR-0049). + + `state_machine` rules gain an optional `initialStates: string[]` — the states a + record may be CREATED in. When set, an insert whose (defaulted) state-field value + is outside the list is rejected server-side with `code: 'invalid_initial_state'`. + Omit it to keep the legacy behavior (no initial-state check on insert). A missing + / empty value is left to required-validation; `transitions` (UPDATE) is + unaffected. Enforced at the same `evaluateValidationRules(..., 'insert')` seam the + engine already runs after field defaults. + +### Patch Changes + +- a8aa34c: Enforce validation rules, `requiredWhen`, and per-option `visibleWhen` on multi-row updates (#3106). The bulk branch of `engine.update` (`options.multi` → `driver.updateMany`) previously never called `evaluateValidationRules`, so every object-level rule (`script`, `state_machine`, `format`, `cross_field`, `json_schema`, `conditional`), field-level `requiredWhen`, and per-option `visibleWhen` check was a silent no-op there. The engine now reads the row-scoped match set (the same AST the write binds, one query shared with the `readonlyWhen` bulk strip) and evaluates the payload against each matched row's prior state; any error-severity violation rejects the whole batch with `ValidationError` (annotated with the failing record id) before anything is written. Schemas needing no prior state (`format`/`json_schema`-only) are evaluated once against the payload with no fetch, and rule-free schemas are unaffected. Behavior change: bulk writes that previously slipped past declared rules now throw. Doc comments in `rule-validator.ts` and `validation.zod.ts` no longer overstate coverage and name the remaining `events: ['delete']` gap (tracked separately). +- e057f42: fix: harden the bulk-write path — retries, idempotency, contracts, and summary visibility (#3147–#3152) + + Six reliability fixes to the batched seed/import + `engine.insert(array)` path + introduced by the #2678 bulk-write rework: + + - **#3151** `bulkWrite` validates that `writeBatch` returns one record per input + row (a short/long/non-array return is degraded per-row, not backfilled as + phantom success); `engine.insert(array)` likewise rejects a short driver + `bulkCreate` return instead of padding afterInsert with `undefined`. + - **#3150** wraps the two remaining un-retried write points (seed + `writeRecord`/`resolveDeferredUpdates`, import's no-`createManyData` + fallback) in `withTransientRetry`; `defaultIsTransientError` short-circuits + definitive logical errors to non-transient. + - **#3148** import `resolveRef` flushes pending creates on a same-object miss so + a later row can reference an earlier same-file CREATE, and no longer + negatively caches a miss. + - **#3149** threads an `attempt` counter through `bulkWrite`; seed rechecks by + `externalId` and import by `matchFields` before re-writing, so a + commit-then-lost-response retry cannot duplicate a batch. + - **#3147** `recomputeSummaries` retries transient failures and, on exhaustion, + surfaces `SummaryRecomputeError` (`ERR_SUMMARY_RECOMPUTE`) instead of a + silent warn; seed/import recover it to a warning without re-writing. + - **#3152** autonumbers are assigned after validation, so a batch that dies in + validation consumes no sequence value (no number-range gaps). + +- fdc244e: Dev-loop DX fixes from the 15.1 third-party evaluation (P2 batch): + + - **Hot-added objects are now queryable without a restart.** Adding a `*.object.ts` under `os dev` used to recompile "green" while every query answered `no such table` (or `not registered`) until a manual restart: the artifact reload never notified the ObjectQL registry, tables were only created at boot, and seeds only loaded from the boot-time bundle. The `metadata:reloaded` payload now carries the parsed artifact; ObjectQL ingests the object definitions and re-runs the idempotent schema sync (same `skipSchemaSync` opt-out as boot), and the runtime loads seeds for first-seen objects (dev, single-tenant). `os dev` also prints `✚ new object(s): …` on recompile. + - **Dev admin credentials stay visible.** The `os dev` startup banner only showed `admin@objectos.ai / admin123` on the boot that actually seeded it; with the persistent default DB every later boot hid it, and the Console login page never knew it existed. The hint now re-arms on every dev boot for as long as the account still verifies against the default password, and `GET /api/v1/auth/config` exposes a dev-gated `devSeedAdmin` field (never present outside `NODE_ENV=development`) so the login page can show it. + - **`os doctor` reference analysis understands current metadata shapes.** Objects bound through `defineView` containers (`list`/`listViews`/`form`/`formViews` → `data.object`, subform `childObject`, lookup form fields) and app navigation (`objectName`, nested `children`, `areas`) were reported as "defined but not referenced". The collector now walks the canonical shapes (plus flow node `config.object`/`objectName`) and the orphan-view check descends into containers. + +- 2ea08ee: Flow trigger observability — kill the four-layer silence around record-change flows that never fire (2026-07-17 third-party eval). + + A misauthored auto-launched flow (wrong `objectName`, missing `requires: ['automation','triggers']`, failing start condition) produced ZERO output at every layer: the engine's own registration/binding logs land inside the CLI's boot-quiet stdout window (which swallows debug/info/warn — only error/fatal reach stderr), and each "didn't happen" path was itself silent. Fixes: + + - **Startup banner `Flows:` section** (`os serve`/`os dev`/`os start`): flow count, bound-to-trigger count, registered trigger types, draft count — plus loud `⚠` lines for flows declared with no automation engine enabled (`requires` missing), flows whose trigger type has no registered trigger, and bound record-change flows targeting an unknown object (dead binding). Printed after stdout is restored, so it is immune to the boot-quiet window. + - **Trigger-fired run failures now log at ERROR** (stderr — always visible): the automation engine no longer drops the AutomationResult of a trigger-fired execution; condition-evaluation faults and node failures surface with the flow name. Condition-not-met skips stay at debug (high-frequency, intentional). + - **`RecordChangeTrigger` probes object existence at bind time** and warns when a flow's `objectName` matches no registered object (exact-name matching), instead of silently arming a hook that can never fire. + - **`kernel:bootstrapped` binding audit** in the automation plugin: warns per enabled-but-unbound triggered flow with the reason, and reports registered/bound/draft counts (`AutomationEngine.getTriggerBindingAudit()`, extended `getFlowRuntimeStates()` with `status`/`triggerType`/`object`). + - **`os validate` flow-wiring advisories** (`@objectstack/lint` `validateFlowTriggerReadiness`): warns when a record-triggered flow targets an object the stack does not define, and when an auto-triggered flow's status is `draft` (authored or defaulted — draft flows still fire; declare `active` or `obsolete`). + - Removed leftover boot-debug writes (`registerApp`/`AppPlugin`/`StandaloneStack`/`AuditPlugin` stderr noise) that previous debugging of this same silence had left behind. + +- d2723e2: **`MetadataManager.register()` / `unregister()` now announce to `subscribe()` watchers.** Both updated the registry, persisted to writable loaders and published to realtime, but never fired the watch callbacks — so `subscribe()` looked like it covered every write while silently missing all of them. Only the `saveMetaItem` path (via the repository watch stream) and the filesystem watcher ever reached a subscriber. Runtime consumers that cache metadata — notably ObjectQL's SchemaRegistry bridge, the component that decides what is queryable — went stale on every other write until the process restarted. + + Announcing is now the **default**, so a new call site is correct without knowing this contract exists. This is a contract fix rather than a bug fix: the one live behavior change is that runtime datasource writes (`datasource-admin`) now reach the HMR SSE stream, which subscribes to every registered type. `unregisterPackage()` / `bulkUnregister()` also announce their deletes now — correct, but latent, since neither has a production caller today. + + Bulk ingest opts out explicitly with the new `MetadataWriteOptions` (`{ notify: false }`) — boot-time filesystem priming, artifact ingest, and ObjectQL's registry bridge, each of which either runs before consumers cache anything or announces the whole batch once (as the artifact reload path does via `metadata:reloaded`). The bridge in particular MUST stay silent: it copies objects out of the SchemaRegistry, and announcing would feed them back through a handler that re-registers under `_packageId ?? 'metadata-service'`, overwriting the true package provenance of every object whose body carries no `_packageId`. + + Additive only — `register(type, name, data)` and `unregister(type, name)` keep working unchanged. + + Fixes #3112. + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [b8a21ad] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [515f11a] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/metadata-protocol@15.2.0 + - @objectstack/formula@15.2.0 + - @objectstack/metadata-core@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/objectql/package.json b/packages/objectql/package.json index a97abd272..38fe56cb4 100644 --- a/packages/objectql/package.json +++ b/packages/objectql/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/objectql", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Isomorphic ObjectQL Engine for ObjectStack", "main": "dist/index.js", diff --git a/packages/observability/CHANGELOG.md b/packages/observability/CHANGELOG.md index 6e199e617..e5b42cd95 100644 --- a/packages/observability/CHANGELOG.md +++ b/packages/observability/CHANGELOG.md @@ -1,5 +1,60 @@ # @objectstack/observability +## 15.2.0 + +### Minor Changes + +- 2049b6a: feat(observability): admin-gated per-request `Server-Timing` via `X-OS-Debug-Timing` (#2408) + + Perf-tuning mode was previously global-only (`serverTiming` option / + `OS_SERVER_TIMING`), which discloses internal phase durations — a mild + backend-fingerprinting surface — to every caller. This adds the per-request + gating path from the design so an operator can pull a single request's + `Server-Timing` breakdown on a live environment without turning the header on + for everyone. + + - **observability**: a request-scoped disclosure gate (`runWithPerfDisclosure`, + `allowPerfDisclosure`, `isPerfDisclosureAllowed`, `PerfDisclosureGate`) kept + separate from the pure `PerfTiming` collector and pinned to its own + `Symbol.for` store so the middleware and dispatcher share it across module + copies. + - **plugin-hono-server**: the Server-Timing middleware is registered by default + (unless `serverTiming: false`). It runs the collector when timing is global + **or** the request sends `X-OS-Debug-Timing: 1`, and emits the header only + when the gate is open. `OS_PERF_TIMING=1` now also enables global mode. + - **runtime**: after resolving the execution context, the dispatcher opens the + gate for admin/service/system principals, so ordinary callers never receive + the header even if they send the debug header. + + Existing global-mode behavior is unchanged. + +### Patch Changes + +- ce468c8: feat(observability): decompose `Server-Timing` into auth / db / hooks / serialize spans (perf-tuning mode) + + The opt-in `Server-Timing` header now breaks a request's server time into the phases that actually explain it, so an operator can open DevTools → Network → Timing and see where the time went without standing up an external tracing backend: + + - **`db`** — total SQL time with a **query count**. The SQL driver wires knex's `query` / `query-response` events (keyed by `__knexQueryUid`) and folds each query into one aggregate member (`db;dur=210;desc="6 queries"`) — the query count is the number most useful for spotting N sequential round-trips. Timing is attributed to the originating request via `AsyncLocalStorage`, so it is correct under concurrency and never cross-attributes. SQL text is never emitted, only durations and a count. + - **`auth`** — identity / session resolution in the dispatcher, the prime suspect for unexplained data-API overhead. + - **`hooks`** — total business-hook execution time with a hook count, fed through the engine's existing `HookMetricsRecorder` seam (wired from the runtime, so `@objectstack/objectql`'s lean `core` tier stays observability-free). + - **`serialize`** — response JSON encoding in the HTTP adapter. + + Adds `countServerTiming(name, dur, unit)` (and `PerfTiming.count`) to fold high-frequency phases into a single aggregate member instead of flooding the header. Every phase is a no-op when perf-tuning is off (`serverTiming: true` / `OS_SERVER_TIMING=true`), so there is zero measurable overhead on the normal path. + + Closes #2408. + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/observability/package.json b/packages/observability/package.json index 587be9089..bee00878f 100644 --- a/packages/observability/package.json +++ b/packages/observability/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/observability", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Observability contracts and exporters for ObjectStack — MetricsRegistry, ErrorReporter, Logger plus noop/console/OTLP-HTTP exporters. Deployment-target neutral; runtime and services depend on this so the same instrumentation works on Cloudflare Workers, Node, and self-hosted Kubernetes.", "type": "module", diff --git a/packages/platform-objects/CHANGELOG.md b/packages/platform-objects/CHANGELOG.md index d0b9b61f7..92d545c62 100644 --- a/packages/platform-objects/CHANGELOG.md +++ b/packages/platform-objects/CHANGELOG.md @@ -1,5 +1,22 @@ # @objectstack/platform-objects +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/metadata-core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/platform-objects/package.json b/packages/platform-objects/package.json index 4fa32a183..72c5ab4c6 100644 --- a/packages/platform-objects/package.json +++ b/packages/platform-objects/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/platform-objects", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Core platform object schemas for ObjectStack — identity, security, audit, tenant, and metadata objects", "main": "dist/index.js", diff --git a/packages/plugins/driver-memory/CHANGELOG.md b/packages/plugins/driver-memory/CHANGELOG.md index 08a0f24ba..aa1d8e806 100644 --- a/packages/plugins/driver-memory/CHANGELOG.md +++ b/packages/plugins/driver-memory/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/driver-memory +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/driver-memory/package.json b/packages/plugins/driver-memory/package.json index 0bea70672..b36b5a41f 100644 --- a/packages/plugins/driver-memory/package.json +++ b/packages/plugins/driver-memory/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/driver-memory", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "In-Memory Driver for ObjectStack (Reference Implementation)", "main": "dist/index.js", diff --git a/packages/plugins/driver-mongodb/CHANGELOG.md b/packages/plugins/driver-mongodb/CHANGELOG.md index 09e68aef7..44df3978d 100644 --- a/packages/plugins/driver-mongodb/CHANGELOG.md +++ b/packages/plugins/driver-mongodb/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/driver-mongodb +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/driver-mongodb/package.json b/packages/plugins/driver-mongodb/package.json index 08cc44981..a7c790fa1 100644 --- a/packages/plugins/driver-mongodb/package.json +++ b/packages/plugins/driver-mongodb/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/driver-mongodb", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "MongoDB Driver for ObjectStack - Native document database driver via official mongodb client", "main": "dist/index.js", diff --git a/packages/plugins/driver-sql/CHANGELOG.md b/packages/plugins/driver-sql/CHANGELOG.md index 5dd597ed2..0adf54355 100644 --- a/packages/plugins/driver-sql/CHANGELOG.md +++ b/packages/plugins/driver-sql/CHANGELOG.md @@ -1,5 +1,42 @@ # @objectstack/driver-sql +## 15.2.0 + +### Patch Changes + +- ce468c8: feat(observability): decompose `Server-Timing` into auth / db / hooks / serialize spans (perf-tuning mode) + + The opt-in `Server-Timing` header now breaks a request's server time into the phases that actually explain it, so an operator can open DevTools → Network → Timing and see where the time went without standing up an external tracing backend: + + - **`db`** — total SQL time with a **query count**. The SQL driver wires knex's `query` / `query-response` events (keyed by `__knexQueryUid`) and folds each query into one aggregate member (`db;dur=210;desc="6 queries"`) — the query count is the number most useful for spotting N sequential round-trips. Timing is attributed to the originating request via `AsyncLocalStorage`, so it is correct under concurrency and never cross-attributes. SQL text is never emitted, only durations and a count. + - **`auth`** — identity / session resolution in the dispatcher, the prime suspect for unexplained data-API overhead. + - **`hooks`** — total business-hook execution time with a hook count, fed through the engine's existing `HookMetricsRecorder` seam (wired from the runtime, so `@objectstack/objectql`'s lean `core` tier stays observability-free). + - **`serialize`** — response JSON encoding in the HTTP adapter. + + Adds `countServerTiming(name, dur, unit)` (and `PerfTiming.count`) to fold high-frequency phases into a single aggregate member instead of flooding the header. Every phase is a no-op when perf-tuning is off (`serverTiming: true` / `OS_SERVER_TIMING=true`), so there is zero measurable overhead on the normal path. + + Closes #2408. + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/observability@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/driver-sql/package.json b/packages/plugins/driver-sql/package.json index 1c9a603a8..65dbd023a 100644 --- a/packages/plugins/driver-sql/package.json +++ b/packages/plugins/driver-sql/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/driver-sql", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "SQL Driver for ObjectStack - Supports PostgreSQL, MySQL, SQLite via Knex", "main": "dist/index.js", diff --git a/packages/plugins/driver-sqlite-wasm/CHANGELOG.md b/packages/plugins/driver-sqlite-wasm/CHANGELOG.md index 595c54803..c90487926 100644 --- a/packages/plugins/driver-sqlite-wasm/CHANGELOG.md +++ b/packages/plugins/driver-sqlite-wasm/CHANGELOG.md @@ -1,5 +1,27 @@ # @objectstack/driver-sqlite-wasm +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/driver-sql@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/driver-sqlite-wasm/package.json b/packages/plugins/driver-sqlite-wasm/package.json index 3f9114624..6a1194533 100644 --- a/packages/plugins/driver-sqlite-wasm/package.json +++ b/packages/plugins/driver-sqlite-wasm/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/driver-sqlite-wasm", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "WASM SQLite Driver for ObjectStack — runs in browser/WebContainer (StackBlitz) without native bindings", "keywords": [ diff --git a/packages/plugins/embedder-openai/CHANGELOG.md b/packages/plugins/embedder-openai/CHANGELOG.md index cdc103da1..92162c573 100644 --- a/packages/plugins/embedder-openai/CHANGELOG.md +++ b/packages/plugins/embedder-openai/CHANGELOG.md @@ -1,5 +1,21 @@ # @objectstack/embedder-openai +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/embedder-openai/package.json b/packages/plugins/embedder-openai/package.json index 4a0f52779..f5f502db3 100644 --- a/packages/plugins/embedder-openai/package.json +++ b/packages/plugins/embedder-openai/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/embedder-openai", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "OpenAI-compatible embedder for ObjectStack — works against OpenAI, 阿里通义 DashScope, 智谱 BigModel, 硅基流动 SiliconFlow, 火山引擎 Doubao, MiniMax, Ollama, and any drop-in OpenAI-shape endpoint.", "main": "dist/index.js", diff --git a/packages/plugins/knowledge-memory/CHANGELOG.md b/packages/plugins/knowledge-memory/CHANGELOG.md index 43d9940c9..03838a83c 100644 --- a/packages/plugins/knowledge-memory/CHANGELOG.md +++ b/packages/plugins/knowledge-memory/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/knowledge-memory +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/service-knowledge@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/knowledge-memory/package.json b/packages/plugins/knowledge-memory/package.json index 7bae9b8f3..10613b3e0 100644 --- a/packages/plugins/knowledge-memory/package.json +++ b/packages/plugins/knowledge-memory/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/knowledge-memory", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "In-memory knowledge adapter for ObjectStack (dev / test reference implementation).", "main": "dist/index.js", diff --git a/packages/plugins/knowledge-ragflow/CHANGELOG.md b/packages/plugins/knowledge-ragflow/CHANGELOG.md index 5b0849064..00cfb0feb 100644 --- a/packages/plugins/knowledge-ragflow/CHANGELOG.md +++ b/packages/plugins/knowledge-ragflow/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/knowledge-ragflow +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/service-knowledge@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/knowledge-ragflow/package.json b/packages/plugins/knowledge-ragflow/package.json index 8c48e3a31..1d4b692b2 100644 --- a/packages/plugins/knowledge-ragflow/package.json +++ b/packages/plugins/knowledge-ragflow/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/knowledge-ragflow", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "RAGFlow knowledge adapter for ObjectStack — production-grade RAG via the Apache 2.0 RAGFlow REST API.", "main": "dist/index.js", diff --git a/packages/plugins/plugin-approvals/CHANGELOG.md b/packages/plugins/plugin-approvals/CHANGELOG.md index 175d0f87b..823793072 100644 --- a/packages/plugins/plugin-approvals/CHANGELOG.md +++ b/packages/plugins/plugin-approvals/CHANGELOG.md @@ -1,5 +1,70 @@ # @objectstack/plugin-approvals +## 15.2.0 + +### Minor Changes + +- 3a18b60: feat(approvals): rename the `role` approver type to `org_membership_level` (#3133) + + `ApproverType.role` was the last platform surface projecting the reserved word + "role" (ADR-0090 D3). It is not covered by D3's better-auth exception: that + exception protects better-auth's own `sys_member.role` **column**, which we do + not own — `ApproverType` is our own enum, an authoring surface, and D3 mandates + that the projection of that concept is spelled `org_membership_level` and + labelled "organization membership", **never "role"**. + + The sentence licensing the leak was also false: ADR-0090 D3 claims + `sys_member.role` is "already relabelled `org_membership_level` in the platform + projection", but `org_membership_level` existed nowhere in the codebase and + ADR-0057 D7 lists that relabel under "Deferred (evidence-gated, P4)". The + projection never landed, so the word reached authors. + + The name manufactured a real, silent failure — "hotcrm class": every other + surface renamed to `position` (`sys_role`, `ShareRecipientType.role`, + `ctx.roles[]`), so `{ type: 'role', value: 'sales_manager' }` reads as the + legacy spelling of a position. It resolves against the membership tier, finds + no member row, falls back to an inert `role:sales_manager` literal, and the + request waits forever on an approver that cannot exist. + + - **spec**: `ApproverType` gains `org_membership_level`; `role` stays as a + deprecated alias for one window (a published 15.x flow keeps loading) with + `DEPRECATED_APPROVER_TYPES` + `canonicalApproverType()` as the single source + for the mapping. Removed in the next major. + - **plugin-approvals**: resolves on the canonical type and warns on the + deprecated spelling. The `type:value` fallback literal keeps the **authored** + spelling — stored `sys_approval_approver` rows and `pending_approvers` slots + from 15.x carry `role:`, and rewriting it would orphan them. + - **lint**: `approval-role-not-membership-tier` → `approval-approver-not-membership-tier` + (the rule id carried the reserved word too), plus a new + `approval-approver-type-deprecated`. The two are mutually exclusive: a bad + _value_ wins, because prescribing `org_membership_level` for a position name + would be wrong advice — the fix there is `position`. + + Authoring `type: 'role'` keeps working and now says so out loud. Rewrite it as + `org_membership_level`; if the value is an org position, the fix is `position`. + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/formula@15.2.0 + - @objectstack/metadata-core@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-approvals/package.json b/packages/plugins/plugin-approvals/package.json index a16b0fb73..44a99f8ef 100644 --- a/packages/plugins/plugin-approvals/package.json +++ b/packages/plugins/plugin-approvals/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-approvals", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Multi-step approval engine for ObjectStack — sys_approval_process + sys_approval_request + sys_approval_action + IApprovalService.", "main": "dist/index.js", diff --git a/packages/plugins/plugin-audit/CHANGELOG.md b/packages/plugins/plugin-audit/CHANGELOG.md index d81cd2cca..a03b457fd 100644 --- a/packages/plugins/plugin-audit/CHANGELOG.md +++ b/packages/plugins/plugin-audit/CHANGELOG.md @@ -1,5 +1,37 @@ # @objectstack/plugin-audit +## 15.2.0 + +### Patch Changes + +- 2ea08ee: Flow trigger observability — kill the four-layer silence around record-change flows that never fire (2026-07-17 third-party eval). + + A misauthored auto-launched flow (wrong `objectName`, missing `requires: ['automation','triggers']`, failing start condition) produced ZERO output at every layer: the engine's own registration/binding logs land inside the CLI's boot-quiet stdout window (which swallows debug/info/warn — only error/fatal reach stderr), and each "didn't happen" path was itself silent. Fixes: + + - **Startup banner `Flows:` section** (`os serve`/`os dev`/`os start`): flow count, bound-to-trigger count, registered trigger types, draft count — plus loud `⚠` lines for flows declared with no automation engine enabled (`requires` missing), flows whose trigger type has no registered trigger, and bound record-change flows targeting an unknown object (dead binding). Printed after stdout is restored, so it is immune to the boot-quiet window. + - **Trigger-fired run failures now log at ERROR** (stderr — always visible): the automation engine no longer drops the AutomationResult of a trigger-fired execution; condition-evaluation faults and node failures surface with the flow name. Condition-not-met skips stay at debug (high-frequency, intentional). + - **`RecordChangeTrigger` probes object existence at bind time** and warns when a flow's `objectName` matches no registered object (exact-name matching), instead of silently arming a hook that can never fire. + - **`kernel:bootstrapped` binding audit** in the automation plugin: warns per enabled-but-unbound triggered flow with the reason, and reports registered/bound/draft counts (`AutomationEngine.getTriggerBindingAudit()`, extended `getFlowRuntimeStates()` with `status`/`triggerType`/`object`). + - **`os validate` flow-wiring advisories** (`@objectstack/lint` `validateFlowTriggerReadiness`): warns when a record-triggered flow targets an object the stack does not define, and when an auto-triggered flow's status is `draft` (authored or defaulted — draft flows still fire; declare `active` or `obsolete`). + - Removed leftover boot-debug writes (`registerApp`/`AppPlugin`/`StandaloneStack`/`AuditPlugin` stderr noise) that previous debugging of this same silence had left behind. + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-audit/package.json b/packages/plugins/plugin-audit/package.json index 8fd3467b9..ffc293652 100644 --- a/packages/plugins/plugin-audit/package.json +++ b/packages/plugins/plugin-audit/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-audit", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Audit Plugin for ObjectStack — System audit log object and audit trail", "main": "dist/index.js", diff --git a/packages/plugins/plugin-auth/CHANGELOG.md b/packages/plugins/plugin-auth/CHANGELOG.md index 512310c0e..1be74a645 100644 --- a/packages/plugins/plugin-auth/CHANGELOG.md +++ b/packages/plugins/plugin-auth/CHANGELOG.md @@ -1,5 +1,58 @@ # Changelog +## 15.2.0 + +### Patch Changes + +- deb7e7e: fix(plugin-auth): run better-auth adapter WRITES as system context so #2948 doesn't strip readonly identity columns (#3164) + + The better-auth ObjectQL adapter wrapped the engine so its READS carried + `isSystem` (to bypass the control-plane org-scope read hook), but its WRITES + passed through with no context. The static-`readonly` UPDATE strip (#2948) runs + on any non-system update — and since the adapter carries no caller context, + `!ctx?.isSystem` was `true`, so the strip silently DROPPED better-auth's own + writes to readonly `sys_user` columns: `email` (change-email), `banned` / + `ban_reason` / `ban_expires` (admin ban). Those operations returned success but + never persisted. + + `withSystemReadContext` is renamed to `withSystemContext` (a deprecated alias is + kept for one release) and now injects `isSystem` on `insert` / `update` / + `delete` as well as reads. This is correct because these are the identity + authority's own writes — user-context writes to `managedBy: 'better-auth'` tables + are already rejected upstream by the ADR-0092 identity write guard, so the + adapter path only ever carries better-auth's internal writes. + + Found while implementing #3043 (the INSERT-side readonly strip). This is its + UPDATE-side dual: #3043 relocated the insert strip to the external ingress + precisely because internal writers (this adapter included) don't declare + `isSystem`; the pre-existing engine-level UPDATE strip has no such relocation, so + the adapter had to declare its writes system. + +- fdc244e: Dev-loop DX fixes from the 15.1 third-party evaluation (P2 batch): + + - **Hot-added objects are now queryable without a restart.** Adding a `*.object.ts` under `os dev` used to recompile "green" while every query answered `no such table` (or `not registered`) until a manual restart: the artifact reload never notified the ObjectQL registry, tables were only created at boot, and seeds only loaded from the boot-time bundle. The `metadata:reloaded` payload now carries the parsed artifact; ObjectQL ingests the object definitions and re-runs the idempotent schema sync (same `skipSchemaSync` opt-out as boot), and the runtime loads seeds for first-seen objects (dev, single-tenant). `os dev` also prints `✚ new object(s): …` on recompile. + - **Dev admin credentials stay visible.** The `os dev` startup banner only showed `admin@objectos.ai / admin123` on the boot that actually seeded it; with the persistent default DB every later boot hid it, and the Console login page never knew it existed. The hint now re-arms on every dev boot for as long as the account still verifies against the default password, and `GET /api/v1/auth/config` exposes a dev-gated `devSeedAdmin` field (never present outside `NODE_ENV=development`) so the login page can show it. + - **`os doctor` reference analysis understands current metadata shapes.** Objects bound through `defineView` containers (`list`/`listViews`/`form`/`formViews` → `data.object`, subform `childObject`, lookup form fields) and app navigation (`objectName`, nested `children`, `areas`) were reported as "defined but not referenced". The collector now walks the canonical shapes (plus flow node `config.object`/`objectName`) and the orphan-view check descends into containers. + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/rest@15.2.0 + - @objectstack/platform-objects@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-auth/package.json b/packages/plugins/plugin-auth/package.json index 0b5f5e41e..75b74c4ef 100644 --- a/packages/plugins/plugin-auth/package.json +++ b/packages/plugins/plugin-auth/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-auth", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Authentication & Identity Plugin for ObjectStack", "main": "dist/index.js", diff --git a/packages/plugins/plugin-dev/CHANGELOG.md b/packages/plugins/plugin-dev/CHANGELOG.md index 7518e766d..6641945fe 100644 --- a/packages/plugins/plugin-dev/CHANGELOG.md +++ b/packages/plugins/plugin-dev/CHANGELOG.md @@ -1,5 +1,42 @@ # @objectstack/plugin-dev +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [deb7e7e] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [515f11a] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/plugin-auth@15.2.0 + - @objectstack/objectql@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/rest@15.2.0 + - @objectstack/runtime@15.2.0 + - @objectstack/plugin-hono-server@15.2.0 + - @objectstack/account@15.2.0 + - @objectstack/setup@15.2.0 + - @objectstack/driver-memory@15.2.0 + - @objectstack/plugin-security@15.2.0 + - @objectstack/service-i18n@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-dev/package.json b/packages/plugins/plugin-dev/package.json index f2e8de407..353d5c412 100644 --- a/packages/plugins/plugin-dev/package.json +++ b/packages/plugins/plugin-dev/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-dev", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Development Mode Plugin for ObjectStack — auto-enables all services with in-memory implementations", "main": "dist/index.js", diff --git a/packages/plugins/plugin-email/CHANGELOG.md b/packages/plugins/plugin-email/CHANGELOG.md index 870b32c09..c52dd6cc5 100644 --- a/packages/plugins/plugin-email/CHANGELOG.md +++ b/packages/plugins/plugin-email/CHANGELOG.md @@ -1,5 +1,28 @@ # @objectstack/plugin-email +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/formula@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-email/package.json b/packages/plugins/plugin-email/package.json index 7b390bc8e..a95525bd5 100644 --- a/packages/plugins/plugin-email/package.json +++ b/packages/plugins/plugin-email/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-email", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Email service plugin for ObjectStack — IEmailService + transport-pluggable outbound delivery with sys_email persistence.", "main": "dist/index.js", diff --git a/packages/plugins/plugin-hono-server/CHANGELOG.md b/packages/plugins/plugin-hono-server/CHANGELOG.md index bf5b9adec..db05fb3c8 100644 --- a/packages/plugins/plugin-hono-server/CHANGELOG.md +++ b/packages/plugins/plugin-hono-server/CHANGELOG.md @@ -1,5 +1,68 @@ # @objectstack/plugin-hono-server +## 15.2.0 + +### Minor Changes + +- 2049b6a: feat(observability): admin-gated per-request `Server-Timing` via `X-OS-Debug-Timing` (#2408) + + Perf-tuning mode was previously global-only (`serverTiming` option / + `OS_SERVER_TIMING`), which discloses internal phase durations — a mild + backend-fingerprinting surface — to every caller. This adds the per-request + gating path from the design so an operator can pull a single request's + `Server-Timing` breakdown on a live environment without turning the header on + for everyone. + + - **observability**: a request-scoped disclosure gate (`runWithPerfDisclosure`, + `allowPerfDisclosure`, `isPerfDisclosureAllowed`, `PerfDisclosureGate`) kept + separate from the pure `PerfTiming` collector and pinned to its own + `Symbol.for` store so the middleware and dispatcher share it across module + copies. + - **plugin-hono-server**: the Server-Timing middleware is registered by default + (unless `serverTiming: false`). It runs the collector when timing is global + **or** the request sends `X-OS-Debug-Timing: 1`, and emits the header only + when the gate is open. `OS_PERF_TIMING=1` now also enables global mode. + - **runtime**: after resolving the execution context, the dispatcher opens the + gate for admin/service/system principals, so ordinary callers never receive + the header even if they send the debug header. + + Existing global-mode behavior is unchanged. + +### Patch Changes + +- ce468c8: feat(observability): decompose `Server-Timing` into auth / db / hooks / serialize spans (perf-tuning mode) + + The opt-in `Server-Timing` header now breaks a request's server time into the phases that actually explain it, so an operator can open DevTools → Network → Timing and see where the time went without standing up an external tracing backend: + + - **`db`** — total SQL time with a **query count**. The SQL driver wires knex's `query` / `query-response` events (keyed by `__knexQueryUid`) and folds each query into one aggregate member (`db;dur=210;desc="6 queries"`) — the query count is the number most useful for spotting N sequential round-trips. Timing is attributed to the originating request via `AsyncLocalStorage`, so it is correct under concurrency and never cross-attributes. SQL text is never emitted, only durations and a count. + - **`auth`** — identity / session resolution in the dispatcher, the prime suspect for unexplained data-API overhead. + - **`hooks`** — total business-hook execution time with a hook count, fed through the engine's existing `HookMetricsRecorder` seam (wired from the runtime, so `@objectstack/objectql`'s lean `core` tier stays observability-free). + - **`serialize`** — response JSON encoding in the HTTP adapter. + + Adds `countServerTiming(name, dur, unit)` (and `PerfTiming.count`) to fold high-frequency phases into a single aggregate member instead of flooding the header. Every phase is a no-op when perf-tuning is off (`serverTiming: true` / `OS_SERVER_TIMING=true`), so there is zero measurable overhead on the normal path. + + Closes #2408. + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/observability@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-hono-server/package.json b/packages/plugins/plugin-hono-server/package.json index f00dbcbb8..7406e3f69 100644 --- a/packages/plugins/plugin-hono-server/package.json +++ b/packages/plugins/plugin-hono-server/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-hono-server", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Standard Hono Server Adapter for ObjectStack Runtime", "main": "dist/index.js", diff --git a/packages/plugins/plugin-pinyin-search/CHANGELOG.md b/packages/plugins/plugin-pinyin-search/CHANGELOG.md index ceb7d22fa..ef4deadb8 100644 --- a/packages/plugins/plugin-pinyin-search/CHANGELOG.md +++ b/packages/plugins/plugin-pinyin-search/CHANGELOG.md @@ -1,5 +1,21 @@ # @objectstack/plugin-pinyin-search +## 15.2.0 + +### Patch Changes + +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [04ecd4e] + - @objectstack/objectql@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-pinyin-search/package.json b/packages/plugins/plugin-pinyin-search/package.json index abcc26ce4..418f491bc 100644 --- a/packages/plugins/plugin-pinyin-search/package.json +++ b/packages/plugins/plugin-pinyin-search/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-pinyin-search", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Pinyin search recall for ObjectStack — populates the hidden `__search` companion column (full pinyin + initials of the display/name field) so `$search` hits CJK names typed as pinyin. Locale-gated via OS_SEARCH_PINYIN_ENABLED (#2486).", "main": "dist/index.js", diff --git a/packages/plugins/plugin-reports/CHANGELOG.md b/packages/plugins/plugin-reports/CHANGELOG.md index d6294a3b9..950d79297 100644 --- a/packages/plugins/plugin-reports/CHANGELOG.md +++ b/packages/plugins/plugin-reports/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/plugin-reports +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-reports/package.json b/packages/plugins/plugin-reports/package.json index 33c99eeec..1d6d5a383 100644 --- a/packages/plugins/plugin-reports/package.json +++ b/packages/plugins/plugin-reports/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-reports", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Saved reports + scheduled email digests for ObjectStack — sys_saved_report + sys_report_schedule + IReportService.", "main": "dist/index.js", diff --git a/packages/plugins/plugin-security/CHANGELOG.md b/packages/plugins/plugin-security/CHANGELOG.md index 962f20507..dd4457985 100644 --- a/packages/plugins/plugin-security/CHANGELOG.md +++ b/packages/plugins/plugin-security/CHANGELOG.md @@ -1,5 +1,28 @@ # @objectstack/plugin-security +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/formula@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-security/package.json b/packages/plugins/plugin-security/package.json index fe02c5091..5296f6fb5 100644 --- a/packages/plugins/plugin-security/package.json +++ b/packages/plugins/plugin-security/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-security", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Security Plugin for ObjectStack — RBAC, RLS, and Field-Level Security Runtime", "main": "dist/index.js", diff --git a/packages/plugins/plugin-sharing/CHANGELOG.md b/packages/plugins/plugin-sharing/CHANGELOG.md index 73ffc162d..8bd297710 100644 --- a/packages/plugins/plugin-sharing/CHANGELOG.md +++ b/packages/plugins/plugin-sharing/CHANGELOG.md @@ -1,5 +1,31 @@ # @objectstack/plugin-sharing +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/objectql@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/formula@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-sharing/package.json b/packages/plugins/plugin-sharing/package.json index 18db7193c..27d5faf31 100644 --- a/packages/plugins/plugin-sharing/package.json +++ b/packages/plugins/plugin-sharing/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-sharing", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Record-level sharing for ObjectStack — sys_record_share + middleware that enforces sharingModel + ISharingService.", "main": "dist/index.js", diff --git a/packages/plugins/plugin-webhooks/CHANGELOG.md b/packages/plugins/plugin-webhooks/CHANGELOG.md index 9d6857b33..7ff2d5b18 100644 --- a/packages/plugins/plugin-webhooks/CHANGELOG.md +++ b/packages/plugins/plugin-webhooks/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/plugin-webhooks +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/service-messaging@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-webhooks/package.json b/packages/plugins/plugin-webhooks/package.json index 50ca71add..3c368d8ea 100644 --- a/packages/plugins/plugin-webhooks/package.json +++ b/packages/plugins/plugin-webhooks/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-webhooks", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Persistent, cluster-aware webhook dispatcher. Durable outbox + per-partition cluster.lock for exactly-once-ish delivery across nodes. See content/docs/concepts/webhook-delivery.mdx.", "type": "module", diff --git a/packages/qa/dogfood/CHANGELOG.md b/packages/qa/dogfood/CHANGELOG.md index 0fc120659..8d4c043ff 100644 --- a/packages/qa/dogfood/CHANGELOG.md +++ b/packages/qa/dogfood/CHANGELOG.md @@ -1,5 +1,37 @@ # @objectstack/dogfood +## 0.0.38 + +### Patch Changes + +- Updated dependencies [41e703b] +- Updated dependencies [3a18b60] +- Updated dependencies [deb7e7e] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/connector-openapi@15.2.0 + - @objectstack/spec@15.2.0 + - @objectstack/plugin-auth@15.2.0 + - @objectstack/objectql@15.2.0 + - @objectstack/plugin-audit@15.2.0 + - @objectstack/example-showcase@0.3.12 + - @objectstack/example-crm@4.0.90 + - @objectstack/connector-mcp@15.2.0 + - @objectstack/connector-rest@15.2.0 + - @objectstack/plugin-security@15.2.0 + - @objectstack/service-storage@15.2.0 + - @objectstack/verify@15.2.0 + ## 0.0.37 ### Patch Changes diff --git a/packages/qa/dogfood/package.json b/packages/qa/dogfood/package.json index 3a565cdc8..d5baaf232 100644 --- a/packages/qa/dogfood/package.json +++ b/packages/qa/dogfood/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/dogfood", - "version": "0.0.37", + "version": "0.0.38", "private": true, "license": "Apache-2.0", "description": "Dogfood regression gate — hand-written golden tests that boot real example apps through @objectstack/verify's in-process HTTP stack, pinning historical runtime regressions (#2018 timezone bucketing, #1994 cross-owner RLS, #2004 field fidelity) that static checks miss.", diff --git a/packages/qa/downstream-contract/CHANGELOG.md b/packages/qa/downstream-contract/CHANGELOG.md index 4131a65d9..17f78f28d 100644 --- a/packages/qa/downstream-contract/CHANGELOG.md +++ b/packages/qa/downstream-contract/CHANGELOG.md @@ -1,5 +1,21 @@ # @objectstack/downstream-contract +## 0.0.36 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + ## 0.0.35 ### Patch Changes diff --git a/packages/qa/downstream-contract/package.json b/packages/qa/downstream-contract/package.json index 369735b93..5ec4d1404 100644 --- a/packages/qa/downstream-contract/package.json +++ b/packages/qa/downstream-contract/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/downstream-contract", - "version": "0.0.35", + "version": "0.0.36", "description": "Frozen third-party consumer fixture — a backward-compatibility gate for @objectstack/spec. Authored the way an external project on a published release authors metadata; if a spec change breaks it, that change is breaking (#2035).", "license": "Apache-2.0", "private": true, diff --git a/packages/qa/http-conformance/CHANGELOG.md b/packages/qa/http-conformance/CHANGELOG.md index 87f20efdf..865ae32ba 100644 --- a/packages/qa/http-conformance/CHANGELOG.md +++ b/packages/qa/http-conformance/CHANGELOG.md @@ -1,5 +1,14 @@ # @objectstack/http-conformance +## 0.0.4 + +### Patch Changes + +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] + - @objectstack/core@15.2.0 + ## 0.0.3 ### Patch Changes diff --git a/packages/qa/http-conformance/package.json b/packages/qa/http-conformance/package.json index 8b38ebfa6..4bec23a72 100644 --- a/packages/qa/http-conformance/package.json +++ b/packages/qa/http-conformance/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/http-conformance", - "version": "0.0.3", + "version": "0.0.4", "private": true, "license": "Apache-2.0", "description": "HTTP transport-port conformance gate (ADR-0076 D11/OQ#10, #2462) — a zero-dependency node:http reference implementation of IHttpServer plus a cross-adapter suite that boots the dispatcher bridge and REST generator on it AND on plugin-hono-server, pinning that the port stays free of framework-isms. Not published; validation instrument, not a product server.", diff --git a/packages/rest/CHANGELOG.md b/packages/rest/CHANGELOG.md index 5f6f62083..02b76a399 100644 --- a/packages/rest/CHANGELOG.md +++ b/packages/rest/CHANGELOG.md @@ -1,5 +1,53 @@ # @objectstack/rest +## 15.2.0 + +### Patch Changes + +- e057f42: fix: harden the bulk-write path — retries, idempotency, contracts, and summary visibility (#3147–#3152) + + Six reliability fixes to the batched seed/import + `engine.insert(array)` path + introduced by the #2678 bulk-write rework: + + - **#3151** `bulkWrite` validates that `writeBatch` returns one record per input + row (a short/long/non-array return is degraded per-row, not backfilled as + phantom success); `engine.insert(array)` likewise rejects a short driver + `bulkCreate` return instead of padding afterInsert with `undefined`. + - **#3150** wraps the two remaining un-retried write points (seed + `writeRecord`/`resolveDeferredUpdates`, import's no-`createManyData` + fallback) in `withTransientRetry`; `defaultIsTransientError` short-circuits + definitive logical errors to non-transient. + - **#3148** import `resolveRef` flushes pending creates on a same-object miss so + a later row can reference an earlier same-file CREATE, and no longer + negatively caches a miss. + - **#3149** threads an `attempt` counter through `bulkWrite`; seed rechecks by + `externalId` and import by `matchFields` before re-writing, so a + commit-then-lost-response retry cannot duplicate a batch. + - **#3147** `recomputeSummaries` retries transient failures and, on exhaustion, + surfaces `SummaryRecomputeError` (`ERR_SUMMARY_RECOMPUTE`) instead of a + silent warn; seed/import recover it to a warning without re-writing. + - **#3152** autonumbers are assigned after validation, so a batch that dies in + validation consumes no sequence value (no number-range gaps). + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/platform-objects@15.2.0 + - @objectstack/service-package@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/rest/package.json b/packages/rest/package.json index 198d14a67..878ccaa7d 100644 --- a/packages/rest/package.json +++ b/packages/rest/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/rest", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "ObjectStack REST API Server - automatic REST endpoint generation from protocol", "type": "module", diff --git a/packages/runtime/CHANGELOG.md b/packages/runtime/CHANGELOG.md index b8758efa5..9cb09d206 100644 --- a/packages/runtime/CHANGELOG.md +++ b/packages/runtime/CHANGELOG.md @@ -1,5 +1,120 @@ # @objectstack/runtime +## 15.2.0 + +### Minor Changes + +- 2049b6a: feat(observability): admin-gated per-request `Server-Timing` via `X-OS-Debug-Timing` (#2408) + + Perf-tuning mode was previously global-only (`serverTiming` option / + `OS_SERVER_TIMING`), which discloses internal phase durations — a mild + backend-fingerprinting surface — to every caller. This adds the per-request + gating path from the design so an operator can pull a single request's + `Server-Timing` breakdown on a live environment without turning the header on + for everyone. + + - **observability**: a request-scoped disclosure gate (`runWithPerfDisclosure`, + `allowPerfDisclosure`, `isPerfDisclosureAllowed`, `PerfDisclosureGate`) kept + separate from the pure `PerfTiming` collector and pinned to its own + `Symbol.for` store so the middleware and dispatcher share it across module + copies. + - **plugin-hono-server**: the Server-Timing middleware is registered by default + (unless `serverTiming: false`). It runs the collector when timing is global + **or** the request sends `X-OS-Debug-Timing: 1`, and emits the header only + when the gate is open. `OS_PERF_TIMING=1` now also enables global mode. + - **runtime**: after resolving the execution context, the dispatcher opens the + gate for admin/service/system principals, so ordinary callers never receive + the header even if they send the debug header. + + Existing global-mode behavior is unchanged. + +### Patch Changes + +- fdc244e: Dev-loop DX fixes from the 15.1 third-party evaluation (P2 batch): + + - **Hot-added objects are now queryable without a restart.** Adding a `*.object.ts` under `os dev` used to recompile "green" while every query answered `no such table` (or `not registered`) until a manual restart: the artifact reload never notified the ObjectQL registry, tables were only created at boot, and seeds only loaded from the boot-time bundle. The `metadata:reloaded` payload now carries the parsed artifact; ObjectQL ingests the object definitions and re-runs the idempotent schema sync (same `skipSchemaSync` opt-out as boot), and the runtime loads seeds for first-seen objects (dev, single-tenant). `os dev` also prints `✚ new object(s): …` on recompile. + - **Dev admin credentials stay visible.** The `os dev` startup banner only showed `admin@objectos.ai / admin123` on the boot that actually seeded it; with the persistent default DB every later boot hid it, and the Console login page never knew it existed. The hint now re-arms on every dev boot for as long as the account still verifies against the default password, and `GET /api/v1/auth/config` exposes a dev-gated `devSeedAdmin` field (never present outside `NODE_ENV=development`) so the login page can show it. + - **`os doctor` reference analysis understands current metadata shapes.** Objects bound through `defineView` containers (`list`/`listViews`/`form`/`formViews` → `data.object`, subform `childObject`, lookup form fields) and app navigation (`objectName`, nested `children`, `areas`) were reported as "defined but not referenced". The collector now walks the canonical shapes (plus flow node `config.object`/`objectName`) and the orphan-view check descends into containers. + +- 2ea08ee: Flow trigger observability — kill the four-layer silence around record-change flows that never fire (2026-07-17 third-party eval). + + A misauthored auto-launched flow (wrong `objectName`, missing `requires: ['automation','triggers']`, failing start condition) produced ZERO output at every layer: the engine's own registration/binding logs land inside the CLI's boot-quiet stdout window (which swallows debug/info/warn — only error/fatal reach stderr), and each "didn't happen" path was itself silent. Fixes: + + - **Startup banner `Flows:` section** (`os serve`/`os dev`/`os start`): flow count, bound-to-trigger count, registered trigger types, draft count — plus loud `⚠` lines for flows declared with no automation engine enabled (`requires` missing), flows whose trigger type has no registered trigger, and bound record-change flows targeting an unknown object (dead binding). Printed after stdout is restored, so it is immune to the boot-quiet window. + - **Trigger-fired run failures now log at ERROR** (stderr — always visible): the automation engine no longer drops the AutomationResult of a trigger-fired execution; condition-evaluation faults and node failures surface with the flow name. Condition-not-met skips stay at debug (high-frequency, intentional). + - **`RecordChangeTrigger` probes object existence at bind time** and warns when a flow's `objectName` matches no registered object (exact-name matching), instead of silently arming a hook that can never fire. + - **`kernel:bootstrapped` binding audit** in the automation plugin: warns per enabled-but-unbound triggered flow with the reason, and reports registered/bound/draft counts (`AutomationEngine.getTriggerBindingAudit()`, extended `getFlowRuntimeStates()` with `status`/`triggerType`/`object`). + - **`os validate` flow-wiring advisories** (`@objectstack/lint` `validateFlowTriggerReadiness`): warns when a record-triggered flow targets an object the stack does not define, and when an auto-triggered flow's status is `draft` (authored or defaulted — draft flows still fire; declare `active` or `obsolete`). + - Removed leftover boot-debug writes (`registerApp`/`AppPlugin`/`StandaloneStack`/`AuditPlugin` stderr noise) that previous debugging of this same silence had left behind. + +- 515f11a: fix(seed): replaying seeds no longer corrupts lookup natural keys on the upsert update path + + Every dev-server restart replayed package seeds in upsert mode, and any record whose + lookup/master_detail was authored as a natural key could have that reference overwritten + with NULL on the update path (`NOT NULL constraint failed` on required columns; silent + link loss on nullable ones). Four fixes: + + - An unresolved reference now leaves the column untouched (deferred to pass 2) or drops + the record loudly — it is never written as NULL over an existing row. + - DB-side reference resolution probes the target dataset's declared `externalId` (e.g. + `email`) before falling back to `name` and `id`, matching how in-memory resolution + already keyed records. + - A rejected update (e.g. a `state_machine` rule vetoing the replay) no longer severs + natural-key resolution for downstream child datasets. + - Replays are idempotent: an upsert/update whose declared fields already match the + existing row is skipped instead of rewritten (no more `updated_at` churn or lifecycle + re-validation on every boot). + +- ce468c8: feat(observability): decompose `Server-Timing` into auth / db / hooks / serialize spans (perf-tuning mode) + + The opt-in `Server-Timing` header now breaks a request's server time into the phases that actually explain it, so an operator can open DevTools → Network → Timing and see where the time went without standing up an external tracing backend: + + - **`db`** — total SQL time with a **query count**. The SQL driver wires knex's `query` / `query-response` events (keyed by `__knexQueryUid`) and folds each query into one aggregate member (`db;dur=210;desc="6 queries"`) — the query count is the number most useful for spotting N sequential round-trips. Timing is attributed to the originating request via `AsyncLocalStorage`, so it is correct under concurrency and never cross-attributes. SQL text is never emitted, only durations and a count. + - **`auth`** — identity / session resolution in the dispatcher, the prime suspect for unexplained data-API overhead. + - **`hooks`** — total business-hook execution time with a hook count, fed through the engine's existing `HookMetricsRecorder` seam (wired from the runtime, so `@objectstack/objectql`'s lean `core` tier stays observability-free). + - **`serialize`** — response JSON encoding in the HTTP adapter. + + Adds `countServerTiming(name, dur, unit)` (and `PerfTiming.count`) to fold high-frequency phases into a single aggregate member instead of flooding the header. Every phase is a no-op when perf-tuning is off (`serverTiming: true` / `OS_SERVER_TIMING=true`), so there is zero measurable overhead on the normal path. + + Closes #2408. + +- Updated dependencies [3a18b60] +- Updated dependencies [deb7e7e] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/plugin-auth@15.2.0 + - @objectstack/objectql@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/rest@15.2.0 + - @objectstack/metadata@15.2.0 + - @objectstack/observability@15.2.0 + - @objectstack/driver-sql@15.2.0 + - @objectstack/formula@15.2.0 + - @objectstack/metadata-core@15.2.0 + - @objectstack/driver-memory@15.2.0 + - @objectstack/driver-sqlite-wasm@15.2.0 + - @objectstack/plugin-security@15.2.0 + - @objectstack/service-cluster@15.2.0 + - @objectstack/service-datasource@15.2.0 + - @objectstack/service-i18n@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 5db5da222..30af48936 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/runtime", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "ObjectStack Core Runtime & Query Engine", "type": "module", diff --git a/packages/sdui-parser/CHANGELOG.md b/packages/sdui-parser/CHANGELOG.md index 2910f03c2..cf4194bae 100644 --- a/packages/sdui-parser/CHANGELOG.md +++ b/packages/sdui-parser/CHANGELOG.md @@ -1,5 +1,7 @@ # @objectstack/sdui-parser +## 15.2.0 + ## 15.1.1 ## 15.1.0 diff --git a/packages/sdui-parser/package.json b/packages/sdui-parser/package.json index 9a09d7ea9..eb9e3b6ae 100644 --- a/packages/sdui-parser/package.json +++ b/packages/sdui-parser/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/sdui-parser", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "ObjectStack constrained JSX-source → SDUI SchemaNode tree compiler (parse, never execute). Isomorphic, zero React. ADR-0080.", "main": "dist/index.js", diff --git a/packages/services/service-analytics/CHANGELOG.md b/packages/services/service-analytics/CHANGELOG.md index 63f87fc1f..847a73bb0 100644 --- a/packages/services/service-analytics/CHANGELOG.md +++ b/packages/services/service-analytics/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog — @objectstack/service-analytics +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-analytics/package.json b/packages/services/service-analytics/package.json index 829ad7ed8..47d3d4d6d 100644 --- a/packages/services/service-analytics/package.json +++ b/packages/services/service-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-analytics", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Analytics Service for ObjectStack — implements IAnalyticsService with multi-driver strategy pattern (NativeSQL, ObjectQL, InMemory)", "type": "module", diff --git a/packages/services/service-automation/CHANGELOG.md b/packages/services/service-automation/CHANGELOG.md index 1f628944d..d0a464a28 100644 --- a/packages/services/service-automation/CHANGELOG.md +++ b/packages/services/service-automation/CHANGELOG.md @@ -1,5 +1,63 @@ # @objectstack/service-automation +## 15.2.0 + +### Minor Changes + +- 780b4b5: feat(automation): schema-aware flow-condition validation at registration (#1928) + + `registerFlow` now runs the same schema-aware condition checks as + `objectstack build` — so a flow registered dynamically (via the API / Studio, + bypassing the build lint) still gets the guardrail. When the host wires an + object-schema resolver, a flow condition that references an unknown field, + likely-typos a field name, or does arithmetic/ordering on a text/boolean field + against a number is surfaced as an **advisory warning** (logged), pointing at + the object's real schema. + + - New `AutomationEngine.setObjectSchemaResolver(resolver)` bridge (mirrors + `setFunctionResolver`); `AutomationServicePlugin` wires it to + `objectql.registry.getObject` in `start()`, before the flow pull, so + registry-sourced flows are covered too. + - **Strictly additive / zero regression**: the fatal set is unchanged (syntax, + brace-in-CEL, unknown-function still throw); everything the schema pass adds is + logged, never thrown, and the whole thing is a no-op when no resolver is wired. + Flow conditions bind fields flat, so the check runs in `flattened` scope + (flow variables stay `dyn` and are never flagged; equality is runtime-safe). + + Builds on the tier-4 type-soundness check in `@objectstack/formula` / + `@objectstack/lint` (#1928). + +- 2ea08ee: Flow trigger observability — kill the four-layer silence around record-change flows that never fire (2026-07-17 third-party eval). + + A misauthored auto-launched flow (wrong `objectName`, missing `requires: ['automation','triggers']`, failing start condition) produced ZERO output at every layer: the engine's own registration/binding logs land inside the CLI's boot-quiet stdout window (which swallows debug/info/warn — only error/fatal reach stderr), and each "didn't happen" path was itself silent. Fixes: + + - **Startup banner `Flows:` section** (`os serve`/`os dev`/`os start`): flow count, bound-to-trigger count, registered trigger types, draft count — plus loud `⚠` lines for flows declared with no automation engine enabled (`requires` missing), flows whose trigger type has no registered trigger, and bound record-change flows targeting an unknown object (dead binding). Printed after stdout is restored, so it is immune to the boot-quiet window. + - **Trigger-fired run failures now log at ERROR** (stderr — always visible): the automation engine no longer drops the AutomationResult of a trigger-fired execution; condition-evaluation faults and node failures surface with the flow name. Condition-not-met skips stay at debug (high-frequency, intentional). + - **`RecordChangeTrigger` probes object existence at bind time** and warns when a flow's `objectName` matches no registered object (exact-name matching), instead of silently arming a hook that can never fire. + - **`kernel:bootstrapped` binding audit** in the automation plugin: warns per enabled-but-unbound triggered flow with the reason, and reports registered/bound/draft counts (`AutomationEngine.getTriggerBindingAudit()`, extended `getFlowRuntimeStates()` with `status`/`triggerType`/`object`). + - **`os validate` flow-wiring advisories** (`@objectstack/lint` `validateFlowTriggerReadiness`): warns when a record-triggered flow targets an object the stack does not define, and when an auto-triggered flow's status is `draft` (authored or defaulted — draft flows still fire; declare `active` or `obsolete`). + - Removed leftover boot-debug writes (`registerApp`/`AppPlugin`/`StandaloneStack`/`AuditPlugin` stderr noise) that previous debugging of this same silence had left behind. + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/formula@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-automation/package.json b/packages/services/service-automation/package.json index b3137144f..3aa5646a1 100644 --- a/packages/services/service-automation/package.json +++ b/packages/services/service-automation/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-automation", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Automation Service for ObjectStack — implements IAutomationService with plugin-based DAG flow execution engine", "type": "module", diff --git a/packages/services/service-cache/CHANGELOG.md b/packages/services/service-cache/CHANGELOG.md index 61baaf03e..668e8e553 100644 --- a/packages/services/service-cache/CHANGELOG.md +++ b/packages/services/service-cache/CHANGELOG.md @@ -1,5 +1,28 @@ # @objectstack/service-cache +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/observability@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-cache/package.json b/packages/services/service-cache/package.json index 7500aa04e..d18e305f0 100644 --- a/packages/services/service-cache/package.json +++ b/packages/services/service-cache/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-cache", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Cache Service for ObjectStack — implements ICacheService with in-memory and Redis adapters", "type": "module", diff --git a/packages/services/service-cluster-redis/CHANGELOG.md b/packages/services/service-cluster-redis/CHANGELOG.md index 8065a4063..97d2adddc 100644 --- a/packages/services/service-cluster-redis/CHANGELOG.md +++ b/packages/services/service-cluster-redis/CHANGELOG.md @@ -1,5 +1,22 @@ # @objectstack/service-cluster-redis +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/service-cluster@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-cluster-redis/package.json b/packages/services/service-cluster-redis/package.json index 45551ff9a..809017afa 100644 --- a/packages/services/service-cluster-redis/package.json +++ b/packages/services/service-cluster-redis/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-cluster-redis", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Redis cluster driver for ObjectStack — implements IPubSub/ILock/IKV/ICounter against Redis using ioredis.", "type": "module", diff --git a/packages/services/service-cluster/CHANGELOG.md b/packages/services/service-cluster/CHANGELOG.md index bf1465ec2..bbbea07d1 100644 --- a/packages/services/service-cluster/CHANGELOG.md +++ b/packages/services/service-cluster/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/service-cluster +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-cluster/package.json b/packages/services/service-cluster/package.json index 338d6adef..6b8dd1764 100644 --- a/packages/services/service-cluster/package.json +++ b/packages/services/service-cluster/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-cluster", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Cluster Service for ObjectStack — pluggable PubSub/Lock/KV/Counter primitives. Memory driver included; postgres/redis drivers ship separately.", "type": "module", diff --git a/packages/services/service-datasource/CHANGELOG.md b/packages/services/service-datasource/CHANGELOG.md index e6ec90008..1910b0b88 100644 --- a/packages/services/service-datasource/CHANGELOG.md +++ b/packages/services/service-datasource/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/service-external-datasource +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-datasource/package.json b/packages/services/service-datasource/package.json index 2ba847fc2..2f79cdbc4 100644 --- a/packages/services/service-datasource/package.json +++ b/packages/services/service-datasource/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-datasource", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "The datasource service (ADR-0015): external-table federation (introspect/draft/import/validate) + runtime UI datasource lifecycle (list/test/create/update/remove + REST routes). Open-source mechanism; the tier line falls on which ICryptoProvider / driver factory a host injects.", "type": "module", diff --git a/packages/services/service-i18n/CHANGELOG.md b/packages/services/service-i18n/CHANGELOG.md index 49133dc21..7134c90d6 100644 --- a/packages/services/service-i18n/CHANGELOG.md +++ b/packages/services/service-i18n/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/service-i18n +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-i18n/package.json b/packages/services/service-i18n/package.json index 00a44cf1f..989ac9bed 100644 --- a/packages/services/service-i18n/package.json +++ b/packages/services/service-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-i18n", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "I18n Service for ObjectStack — implements II18nService with file-based locale loading", "type": "module", diff --git a/packages/services/service-job/CHANGELOG.md b/packages/services/service-job/CHANGELOG.md index d9b2004e6..c14ccc61c 100644 --- a/packages/services/service-job/CHANGELOG.md +++ b/packages/services/service-job/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/service-job +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-job/package.json b/packages/services/service-job/package.json index 0e0e855e2..f83281917 100644 --- a/packages/services/service-job/package.json +++ b/packages/services/service-job/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-job", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Job Service for ObjectStack — implements IJobService with setInterval and cron scheduling", "type": "module", diff --git a/packages/services/service-knowledge/CHANGELOG.md b/packages/services/service-knowledge/CHANGELOG.md index fc378329e..595d035f5 100644 --- a/packages/services/service-knowledge/CHANGELOG.md +++ b/packages/services/service-knowledge/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/service-knowledge +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-knowledge/package.json b/packages/services/service-knowledge/package.json index 76d448edc..cae35a535 100644 --- a/packages/services/service-knowledge/package.json +++ b/packages/services/service-knowledge/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-knowledge", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Knowledge Service for ObjectStack — orchestrator implementing IKnowledgeService over pluggable IKnowledgeAdapter backends (RAGFlow, LlamaIndex, Dify, in-memory).", "type": "module", diff --git a/packages/services/service-messaging/CHANGELOG.md b/packages/services/service-messaging/CHANGELOG.md index ffcf31e25..7bb77ea04 100644 --- a/packages/services/service-messaging/CHANGELOG.md +++ b/packages/services/service-messaging/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/service-messaging +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-messaging/package.json b/packages/services/service-messaging/package.json index c3a26e354..4e1e32619 100644 --- a/packages/services/service-messaging/package.json +++ b/packages/services/service-messaging/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-messaging", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Messaging Service for ObjectStack — outbound notification dispatch (ADR-0012). Ships the MessagingChannel registry, emit() fan-out, and the always-on inbox channel; other channels (email/webhook/push/IM) plug in.", "type": "module", diff --git a/packages/services/service-package/CHANGELOG.md b/packages/services/service-package/CHANGELOG.md index afc7937a0..4ce2fd9f2 100644 --- a/packages/services/service-package/CHANGELOG.md +++ b/packages/services/service-package/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/service-package +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/metadata-core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-package/package.json b/packages/services/service-package/package.json index fdcf76d8f..3bffa1750 100644 --- a/packages/services/service-package/package.json +++ b/packages/services/service-package/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-package", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Package management service for ObjectStack — publish, install, and manage packages", "type": "module", diff --git a/packages/services/service-queue/CHANGELOG.md b/packages/services/service-queue/CHANGELOG.md index 20a3f123b..321d84df6 100644 --- a/packages/services/service-queue/CHANGELOG.md +++ b/packages/services/service-queue/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/service-queue +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-queue/package.json b/packages/services/service-queue/package.json index c4c55aa29..042102c64 100644 --- a/packages/services/service-queue/package.json +++ b/packages/services/service-queue/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-queue", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Queue Service for ObjectStack — implements IQueueService with in-memory and durable DB-backed (sys_job_queue) adapters", "type": "module", diff --git a/packages/services/service-realtime/CHANGELOG.md b/packages/services/service-realtime/CHANGELOG.md index 7b716f1a4..bf5f5af3c 100644 --- a/packages/services/service-realtime/CHANGELOG.md +++ b/packages/services/service-realtime/CHANGELOG.md @@ -1,5 +1,26 @@ # @objectstack/service-realtime +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-realtime/package.json b/packages/services/service-realtime/package.json index fe91c3f43..4b320a720 100644 --- a/packages/services/service-realtime/package.json +++ b/packages/services/service-realtime/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-realtime", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Realtime Service for ObjectStack — implements IRealtimeService with WebSocket and in-memory pub/sub", "type": "module", diff --git a/packages/services/service-settings/CHANGELOG.md b/packages/services/service-settings/CHANGELOG.md index f5d5f92a7..0aa660674 100644 --- a/packages/services/service-settings/CHANGELOG.md +++ b/packages/services/service-settings/CHANGELOG.md @@ -1,5 +1,27 @@ # @objectstack/service-settings +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/platform-objects@15.2.0 + - @objectstack/types@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-settings/package.json b/packages/services/service-settings/package.json index fe84bf072..e8d3cde37 100644 --- a/packages/services/service-settings/package.json +++ b/packages/services/service-settings/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-settings", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Settings service for ObjectStack — manifest registry + K/V resolver (OS_* env > Tenant > User > Default) + REST routes. See ADR-0007.", "type": "module", diff --git a/packages/services/service-sms/CHANGELOG.md b/packages/services/service-sms/CHANGELOG.md index 7778a464a..6da297d6c 100644 --- a/packages/services/service-sms/CHANGELOG.md +++ b/packages/services/service-sms/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/service-sms +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-sms/package.json b/packages/services/service-sms/package.json index ed0c5e306..ae2afc067 100644 --- a/packages/services/service-sms/package.json +++ b/packages/services/service-sms/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-sms", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "SMS service for ObjectStack — ISmsService + transport-pluggable outbound delivery (Aliyun / Twilio / log).", "main": "dist/index.js", diff --git a/packages/services/service-storage/CHANGELOG.md b/packages/services/service-storage/CHANGELOG.md index 612cac3f2..54a33bae8 100644 --- a/packages/services/service-storage/CHANGELOG.md +++ b/packages/services/service-storage/CHANGELOG.md @@ -1,5 +1,29 @@ # @objectstack/service-storage +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/observability@15.2.0 + - @objectstack/platform-objects@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-storage/package.json b/packages/services/service-storage/package.json index 0de39a619..12027b66c 100644 --- a/packages/services/service-storage/package.json +++ b/packages/services/service-storage/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-storage", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Storage Service for ObjectStack — implements IStorageService with local filesystem and S3 adapter skeleton", "type": "module", diff --git a/packages/spec/CHANGELOG.md b/packages/spec/CHANGELOG.md index 5a61b6ec4..cc144ff05 100644 --- a/packages/spec/CHANGELOG.md +++ b/packages/spec/CHANGELOG.md @@ -1,5 +1,211 @@ # @objectstack/spec +## 15.2.0 + +### Minor Changes + +- 3a18b60: feat(approvals): rename the `role` approver type to `org_membership_level` (#3133) + + `ApproverType.role` was the last platform surface projecting the reserved word + "role" (ADR-0090 D3). It is not covered by D3's better-auth exception: that + exception protects better-auth's own `sys_member.role` **column**, which we do + not own — `ApproverType` is our own enum, an authoring surface, and D3 mandates + that the projection of that concept is spelled `org_membership_level` and + labelled "organization membership", **never "role"**. + + The sentence licensing the leak was also false: ADR-0090 D3 claims + `sys_member.role` is "already relabelled `org_membership_level` in the platform + projection", but `org_membership_level` existed nowhere in the codebase and + ADR-0057 D7 lists that relabel under "Deferred (evidence-gated, P4)". The + projection never landed, so the word reached authors. + + The name manufactured a real, silent failure — "hotcrm class": every other + surface renamed to `position` (`sys_role`, `ShareRecipientType.role`, + `ctx.roles[]`), so `{ type: 'role', value: 'sales_manager' }` reads as the + legacy spelling of a position. It resolves against the membership tier, finds + no member row, falls back to an inert `role:sales_manager` literal, and the + request waits forever on an approver that cannot exist. + + - **spec**: `ApproverType` gains `org_membership_level`; `role` stays as a + deprecated alias for one window (a published 15.x flow keeps loading) with + `DEPRECATED_APPROVER_TYPES` + `canonicalApproverType()` as the single source + for the mapping. Removed in the next major. + - **plugin-approvals**: resolves on the canonical type and warns on the + deprecated spelling. The `type:value` fallback literal keeps the **authored** + spelling — stored `sys_approval_approver` rows and `pending_approvers` slots + from 15.x carry `role:`, and rewriting it would orphan them. + - **lint**: `approval-role-not-membership-tier` → `approval-approver-not-membership-tier` + (the rule id carried the reserved word too), plus a new + `approval-approver-type-deprecated`. The two are mutually exclusive: a bad + _value_ wins, because prescribing `org_membership_level` for a position name + would be wrong advice — the fix there is `position`. + + Authoring `type: 'role'` keeps working and now says so out loud. Rewrite it as + `org_membership_level`; if the value is an org position, the fix is `position`. + +- fefcd54: fix(spec): declare `ownership` as a first-class ObjectSchema field (#3175) + + The object-level record-ownership model — `ownership: 'user' | 'org' | 'none'`, + which drives the registry's `owner_id` auto-provisioning (`applySystemFields`) — + was read by the engine via `(schema as any).ownership` while `ObjectSchema.create()` + **rejected** it as an unknown top-level key (ADR-0032 / #1535). So a tested engine + opt-out (`ownership: 'org' | 'none'` on catalog / junction tables) could not be + set through the sanctioned authoring path, and the same `ownership` word was read + elsewhere as the unrelated package-contribution kind (`own` / `extend`). + + - **spec**: `ObjectSchema` now declares `ownership: z.enum(['user','org','none']).optional()`. + Authoring the record-ownership opt-out validates cleanly; the registry reads it + off the typed schema (no `as any`). A retired `ownership: 'own'` / `'extend'` + value fails with guidance pointing at the record-ownership model and noting that + `own`/`extend` is the contribution kind (`registerObject`), not an object-schema value. + - **cli**: the `object` scaffold no longer emits the now-invalid `ownership: 'own'` + (owner injection is the default), and `objectstack info` labels the record model + with the correct `user` default. + + No runtime behavior change: `applySystemFields` and its `owner_id` injection logic + are unchanged — this makes the property the engine already honors legally authorable + and consistently typed. + +- b659111: feat(spec)!: remove dead author-facing metadata properties (#2377, ADR-0049 enforce-or-remove) + + Breaking spec-surface removal, versioned as `minor` per the launch-window changeset + policy (a `major` would promote the whole fixed-group monorepo; breaking cleanups ride + the minor line, as with #2402 → 11.1.0). + + Removes a batch of spec properties that parsed but had **no runtime consumer** — + authoring them was a false affordance (especially dangerous for AI-authored + metadata). Verified dead against the liveness ledger (`packages/spec/liveness/*.json`) + and a repo-wide grep of readers. This is the follow-up slice to #2402. + + ## Removed (each was `dead` + no reader anywhere) + + - **field** (`field.zod.ts`): `vectorConfig` (+ `VectorConfigSchema` + types), + `fileAttachmentConfig` (+ `FileAttachmentConfigSchema` + types), `dependencies`. + Vector fields keep the live flat `dimensions` prop; file/image fields keep the + live flat `multiple`/`accept`/`maxSize` siblings. + - **object** (`object.zod.ts`): `versioning` (+ `VersioningConfigSchema`), + `softDelete` (+ `SoftDeleteConfigSchema`), `search` (+ `SearchConfigSchema`), + `recordName`, `keyPrefix`. Each is now a **rejecting tombstone** in + `UNKNOWN_KEY_GUIDANCE` carrying the upgrade prescription. + - **action** (`action.zod.ts`): `timeout` (server uses `body.timeoutMs`; no + action-level timeout is enforced). + - **agent** (`agent.zod.ts`): `planning.strategy`, `planning.allowReplan` + (only `planning.maxIterations` is read by the runtime). + - **dataset** (`dataset.zod.ts`): `measures.certified` (declared-but-unenforced + governance flag — never compiled into the Cube). + + Liveness ledgers, the ledger README table, and `api-surface.json` are updated; + the removed sub-schema keys are dropped from `json-schema.manifest.json`. + + ## Migration + + - **field/agent/dataset/action props**: authoring them is now silently stripped + (they never did anything). Remove them. Vector → set flat `dimensions`; + file/image → set flat `multiple`/`accept`/`maxSize`. + - **object props**: `ObjectSchema.create()` now throws a located error naming the + replacement — `versioning`/`softDelete` → hard deletes + `Field.trackHistory` / + `lifecycle`; `search` → `searchableFields`; `recordName` → an `autonumber` + `Field` designated as `nameField`; `keyPrefix` → remove (never had an effect). + + ## Deliberately NOT removed (dead, but entangled — a scoped follow-up) + + `field.index`/`columnName`/`referenceFilters` and object + `tags`/`active`/`isSystem`/`abstract`/`enable.searchable`/`enable.trash`/`enable.mru` + and `agent.tenantId` are surfaced in the Studio metadata-authoring forms + (`*.form.ts`) — removing them cascades into i18n bundle regeneration, so they are + deferred. `action.type:'form'` has a dedicated build-time lint (`lint-view-refs.ts`) + and a first-party showcase usage, so it needs a UX decision. `field.columnName` + additionally has an ADR-0062 D7 lint. These stay `dead` + `authorWarn` in the + ledgers. + +- 04ecd4e: feat(validation): `state_machine.initialStates` enforces the FSM entry point on INSERT (#3165) + + A `state_machine` rule's `transitions` only governs UPDATE — on INSERT the rule + was a no-op, and a `select` field permits ANY declared option as the initial + value. So a record could be born mid-flow (created already `approved`), skipping + the whole state machine. This was the gap #3043's mitigation idea assumed didn't + exist (declared ≠ enforced, ADR-0049). + + `state_machine` rules gain an optional `initialStates: string[]` — the states a + record may be CREATED in. When set, an insert whose (defaulted) state-field value + is outside the list is rejected server-side with `code: 'invalid_initial_state'`. + Omit it to keep the legacy behavior (no initial-state check on insert). A missing + / empty value is left to required-validation; `transitions` (UPDATE) is + unaffected. Enforced at the same `evaluateValidationRules(..., 'insert')` seam the + engine already runs after field defaults. + +### Patch Changes + +- a8aa34c: Enforce validation rules, `requiredWhen`, and per-option `visibleWhen` on multi-row updates (#3106). The bulk branch of `engine.update` (`options.multi` → `driver.updateMany`) previously never called `evaluateValidationRules`, so every object-level rule (`script`, `state_machine`, `format`, `cross_field`, `json_schema`, `conditional`), field-level `requiredWhen`, and per-option `visibleWhen` check was a silent no-op there. The engine now reads the row-scoped match set (the same AST the write binds, one query shared with the `readonlyWhen` bulk strip) and evaluates the payload against each matched row's prior state; any error-severity violation rejects the whole batch with `ValidationError` (annotated with the failing record id) before anything is written. Schemas needing no prior state (`format`/`json_schema`-only) are evaluated once against the payload with no fetch, and rule-free schemas are unaffected. Behavior change: bulk writes that previously slipped past declared rules now throw. Doc comments in `rule-validator.ts` and `validation.zod.ts` no longer overstate coverage and name the remaining `events: ['delete']` gap (tracked separately). +- d2723e2: **`MetadataManager.register()` / `unregister()` now announce to `subscribe()` watchers.** Both updated the registry, persisted to writable loaders and published to realtime, but never fired the watch callbacks — so `subscribe()` looked like it covered every write while silently missing all of them. Only the `saveMetaItem` path (via the repository watch stream) and the filesystem watcher ever reached a subscriber. Runtime consumers that cache metadata — notably ObjectQL's SchemaRegistry bridge, the component that decides what is queryable — went stale on every other write until the process restarted. + + Announcing is now the **default**, so a new call site is correct without knowing this contract exists. This is a contract fix rather than a bug fix: the one live behavior change is that runtime datasource writes (`datasource-admin`) now reach the HMR SSE stream, which subscribes to every registered type. `unregisterPackage()` / `bulkUnregister()` also announce their deletes now — correct, but latent, since neither has a production caller today. + + Bulk ingest opts out explicitly with the new `MetadataWriteOptions` (`{ notify: false }`) — boot-time filesystem priming, artifact ingest, and ObjectQL's registry bridge, each of which either runs before consumers cache anything or announces the whole batch once (as the artifact reload path does via `metadata:reloaded`). The bridge in particular MUST stay silent: it copies objects out of the SchemaRegistry, and announcing would feed them back through a handler that re-registers under `_packageId ?? 'metadata-service'`, overwriting the true package provenance of every object whose body carries no `_packageId`. + + Additive only — `register(type, name, data)` and `unregister(type, name)` keep working unchanged. + + Fixes #3112. + +- beaf2de: fix(metadata-protocol): strip static `readonly` on INSERT at the data-write ingress (#3043) + + #2948/#3003 made static `readonly: true` fields server-enforced on UPDATE (a + non-system PATCH forging `approval_status: 'approved'` is silently stripped in + the engine), but INSERT was exempt. For approval/status/verdict columns that + exemption was the _shorter_ attack: instead of the #3003 draft-then-PATCH move, a + non-system caller could `POST` a record already `approval_status: 'approved'` in + one step — and the UPDATE-only strip never reached it. + + The strip now also runs on INSERT, but at the **external data-write ingress** + (`DataProtocol.createData` / `createManyData` / `batchData` / `cloneData`) rather + than in the engine. That seam is the single point every external programmatic + create funnels through — the REST CRUD route, the GraphQL/MCP dispatcher + (`bridge.create` → `callData` → `createData`), and bulk import — while **trusted + internal writers** (better-auth's adapter, the metadata repository, the seed + loader) call `engine.insert` directly and bypass it. Enforcing at the ingress + protects every caller/agent path at once without stripping the internal writers + that legitimately seed read-only columns on create (identity provisioning, + provenance stamps, event-log cursors) — the blast radius an engine-level insert + strip would have. + + - **Caller-forged only, at the ingress.** The payload here is raw caller input + (the security middleware stamps `owner_id` / `organization_id` later, inside + `engine.insert`), so only keys the caller actually sent are dropped; server + stamps are added afterwards and are unaffected. + - **Re-derives the default.** A stripped field falls back to its declared + `defaultValue` in the engine (a forged `approval_status` becomes `draft`, not + NULL). + - **System-context exempt.** `isSystem` writes still seed read-only columns. + - **Silent** (HTTP 2xx), per-row on batch/import. `readonlyWhen` stays + INSERT-exempt (a conditional lock needs a prior record). + - **Author-defined business objects only.** Platform objects (`managedBy` set, + or the `sys_` namespace) carry their own field-write governance that a silent + strip must not pre-empt — e.g. ADR-0086 REJECTS (403) a forged + `managed_by:'package'` on `sys_permission_set`, and #3004 rejects a forged + `owner_id`; several of those columns are `readonly`, so stripping them here + would swallow the payload the guard is meant to reject. The #3043 threat is app + approval/status fields, never `sys_` — the same boundary `applySystemFields` + uses for ownership. + + Behavior change: a non-system create through the data API (REST / GraphQL / MCP / + import) can no longer seed a `readonly` column from the payload. Flows that + legitimately write read-only columns at creation must run with a system context + (`isSystem`), the same requirement the UPDATE strip already imposes. + +- 8923843: Reject view containers that define no views. A flat list-view object (`{ name, label, type, columns, ... }`) parses to an empty `ViewSchema` container because Zod strips unknown keys — zero views register and the Console silently renders nothing. `defineView()` now throws on a zero-view container, and `os validate` gains a `view-container-shape` check (`validateViewContainers` in `@objectstack/lint`) that reports flat or empty `views: []` entries pre-parse with a wrap-it fix hint. +- f16b492: Remove the dead `'delete'` member from the validation-rule `events` enum (#3184). The rule evaluator only runs on the insert/update write path — `engine.delete` never invokes it — so a rule declaring `events: ['delete']` was a silent no-op (flagged in #3106 and `docs/audits/2026-06-validationschema-property-liveness.md`). The enum now admits only `insert`/`update`; guard deletions with a `beforeDelete` lifecycle hook instead. No shipped metadata declares `events: ['delete']`; any off-spec metadata that did now fails loudly at `os validate` / registration rather than parsing and doing nothing. Also narrows the two hand-written mirrors (`rule-validator.ts` `BaseRule`, `metadata-protocol` JSON-schema form helper — whose stale `type` enum listing removed `unique`/`async`/`custom` variants is corrected in the same pass), updates the doc comments, the published data skill, and the hand-written validation doc. +- fc5a3a2: **The `view` metadata type-schema now validates all three runtime `view` shapes instead of stripping two of them to `{}`.** `metadata-type-schemas.ts` mapped `view` to the aggregate container `ViewSchema` (`{ list, form, listViews, formViews }`, every slot optional). Zod strips unknown keys, so the two non-container shapes a `view` body actually carries at runtime — a standalone **ViewItem record** (`{ name, object, viewKind, config }`) and a **console personalization overlay** (raw view config + identity inherited by `normalizeViewMetadata`, #2555) — both strip-parsed to `{}`. That made the `422` check in `saveMetaItem` and read-time `computeMetadataDiagnostics` a **no-op** for those shapes: a broken `config` (e.g. a kanban missing `groupByField`) saved with a false `200` and badged valid, and the view create-seed test validated against nothing. + + `view` now maps to a new `ViewMetadataSchema` — a union over the three shapes, each validated genuinely: + + 1. **defineView container** — non-empty (`ViewSchema` refined to require at least one of `list`/`form`/`listViews`/`formViews`; an empty container is rejected, mirroring `defineView`). + 2. **ViewItem record** — `ViewItemSchema`; the nested `config` is validated against ListView/FormView. + 3. **Flattened personalization overlay** — inline ListView/FormView config plus optional identity fields. Structural guards pin `config`/`list`/`form`/`listViews`/`formViews` to `undefined` so a malformed record or container can never be rescued through this lenient branch with its real payload silently stripped. + + All members strip-parse (no `.strict()`), so auxiliary Studio round-trip keys (`isPinned`, `sortOrder`, …) still ride along without a false `422`, and `saveMetaItem` keeps persisting the body verbatim. `z.toJSONSchema()` emits the schema as an `anyOf` of the four members, which `/api/v1/meta/types/view` serves to Studio's SchemaForm. + + Fixes #3095. + ## 15.1.1 ## 15.1.0 diff --git a/packages/spec/package.json b/packages/spec/package.json index a6c5ed2ba..85a434a77 100644 --- a/packages/spec/package.json +++ b/packages/spec/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/spec", - "version": "15.1.1", + "version": "15.2.0", "description": "ObjectStack Protocol & Specification - TypeScript Interfaces, JSON Schemas, and Convention Configurations", "license": "Apache-2.0", "main": "dist/index.js", diff --git a/packages/triggers/trigger-api/CHANGELOG.md b/packages/triggers/trigger-api/CHANGELOG.md index 7e9464a04..9db25eca6 100644 --- a/packages/triggers/trigger-api/CHANGELOG.md +++ b/packages/triggers/trigger-api/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/trigger-api +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/triggers/trigger-api/package.json b/packages/triggers/trigger-api/package.json index 8b96960e2..91d22d1ab 100644 --- a/packages/triggers/trigger-api/package.json +++ b/packages/triggers/trigger-api/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/trigger-api", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Inbound HTTP/webhook flow trigger for ObjectStack — per-flow HMAC-verified endpoints with queue-backed ingestion (ADR-0041)", "main": "dist/index.js", diff --git a/packages/triggers/trigger-record-change/CHANGELOG.md b/packages/triggers/trigger-record-change/CHANGELOG.md index 334362680..257c1f372 100644 --- a/packages/triggers/trigger-record-change/CHANGELOG.md +++ b/packages/triggers/trigger-record-change/CHANGELOG.md @@ -1,5 +1,38 @@ # @objectstack/plugin-trigger-record-change +## 15.2.0 + +### Minor Changes + +- 2ea08ee: Flow trigger observability — kill the four-layer silence around record-change flows that never fire (2026-07-17 third-party eval). + + A misauthored auto-launched flow (wrong `objectName`, missing `requires: ['automation','triggers']`, failing start condition) produced ZERO output at every layer: the engine's own registration/binding logs land inside the CLI's boot-quiet stdout window (which swallows debug/info/warn — only error/fatal reach stderr), and each "didn't happen" path was itself silent. Fixes: + + - **Startup banner `Flows:` section** (`os serve`/`os dev`/`os start`): flow count, bound-to-trigger count, registered trigger types, draft count — plus loud `⚠` lines for flows declared with no automation engine enabled (`requires` missing), flows whose trigger type has no registered trigger, and bound record-change flows targeting an unknown object (dead binding). Printed after stdout is restored, so it is immune to the boot-quiet window. + - **Trigger-fired run failures now log at ERROR** (stderr — always visible): the automation engine no longer drops the AutomationResult of a trigger-fired execution; condition-evaluation faults and node failures surface with the flow name. Condition-not-met skips stay at debug (high-frequency, intentional). + - **`RecordChangeTrigger` probes object existence at bind time** and warns when a flow's `objectName` matches no registered object (exact-name matching), instead of silently arming a hook that can never fire. + - **`kernel:bootstrapped` binding audit** in the automation plugin: warns per enabled-but-unbound triggered flow with the reason, and reports registered/bound/draft counts (`AutomationEngine.getTriggerBindingAudit()`, extended `getFlowRuntimeStates()` with `status`/`triggerType`/`object`). + - **`os validate` flow-wiring advisories** (`@objectstack/lint` `validateFlowTriggerReadiness`): warns when a record-triggered flow targets an object the stack does not define, and when an auto-triggered flow's status is `draft` (authored or defaulted — draft flows still fire; declare `active` or `obsolete`). + - Removed leftover boot-debug writes (`registerApp`/`AppPlugin`/`StandaloneStack`/`AuditPlugin` stderr noise) that previous debugging of this same silence had left behind. + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/triggers/trigger-record-change/package.json b/packages/triggers/trigger-record-change/package.json index ec9433abf..28a2a4b42 100644 --- a/packages/triggers/trigger-record-change/package.json +++ b/packages/triggers/trigger-record-change/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/trigger-record-change", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Record-change flow trigger for ObjectStack — auto-launches flows on object insert/update/delete via ObjectQL lifecycle hooks (ADR-0018)", "main": "dist/index.js", diff --git a/packages/triggers/trigger-schedule/CHANGELOG.md b/packages/triggers/trigger-schedule/CHANGELOG.md index a67ef158b..f9786d4ff 100644 --- a/packages/triggers/trigger-schedule/CHANGELOG.md +++ b/packages/triggers/trigger-schedule/CHANGELOG.md @@ -1,5 +1,25 @@ # @objectstack/plugin-trigger-schedule +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/core@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/triggers/trigger-schedule/package.json b/packages/triggers/trigger-schedule/package.json index af50e2571..34d900c2a 100644 --- a/packages/triggers/trigger-schedule/package.json +++ b/packages/triggers/trigger-schedule/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/trigger-schedule", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Schedule flow trigger for ObjectStack — auto-launches flows on a cron/interval/once schedule via the IJobService (ADR-0018)", "main": "dist/index.js", diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index 138da4918..2745a8498 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -1,5 +1,21 @@ # @objectstack/types +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/types/package.json b/packages/types/package.json index 64610e365..e8429668f 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/types", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Shared interfaces describing the ObjectStack Runtime environment", "main": "dist/index.js", diff --git a/packages/verify/CHANGELOG.md b/packages/verify/CHANGELOG.md index 640468b20..cd66dce0a 100644 --- a/packages/verify/CHANGELOG.md +++ b/packages/verify/CHANGELOG.md @@ -1,5 +1,44 @@ # @objectstack/verify +## 15.2.0 + +### Patch Changes + +- Updated dependencies [3a18b60] +- Updated dependencies [deb7e7e] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [fdc244e] +- Updated dependencies [780b4b5] +- Updated dependencies [2ea08ee] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [b659111] +- Updated dependencies [515f11a] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [8923843] +- Updated dependencies [f16b492] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@15.2.0 + - @objectstack/plugin-auth@15.2.0 + - @objectstack/objectql@15.2.0 + - @objectstack/core@15.2.0 + - @objectstack/rest@15.2.0 + - @objectstack/runtime@15.2.0 + - @objectstack/service-automation@15.2.0 + - @objectstack/plugin-hono-server@15.2.0 + - @objectstack/driver-sqlite-wasm@15.2.0 + - @objectstack/plugin-security@15.2.0 + - @objectstack/plugin-sharing@15.2.0 + - @objectstack/service-analytics@15.2.0 + - @objectstack/service-datasource@15.2.0 + - @objectstack/service-settings@15.2.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/verify/package.json b/packages/verify/package.json index 1fd963301..47408ec3c 100644 --- a/packages/verify/package.json +++ b/packages/verify/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/verify", - "version": "15.1.1", + "version": "15.2.0", "license": "Apache-2.0", "description": "Boot any ObjectStack app in-process and verify it through the real HTTP stack — auto-derived CRUD round-trip fidelity plus the cross-owner RLS invariant. Catches runtime regressions that static checks miss.", "type": "module", diff --git a/packages/vscode-objectstack/CHANGELOG.md b/packages/vscode-objectstack/CHANGELOG.md index 99ab416cc..4c04b2773 100644 --- a/packages/vscode-objectstack/CHANGELOG.md +++ b/packages/vscode-objectstack/CHANGELOG.md @@ -1,5 +1,7 @@ # objectstack-vscode +## 15.2.0 + ## 15.1.1 ## 15.1.0 diff --git a/packages/vscode-objectstack/package.json b/packages/vscode-objectstack/package.json index 7e8795200..88cb55923 100644 --- a/packages/vscode-objectstack/package.json +++ b/packages/vscode-objectstack/package.json @@ -2,7 +2,7 @@ "name": "objectstack-vscode", "displayName": "ObjectStack", "description": "ObjectStack Protocol — Autocomplete, validation, and inline diagnostics for .object.ts, .view.ts, and objectstack.config.ts files", - "version": "15.1.1", + "version": "15.2.0", "publisher": "objectstack", "license": "Apache-2.0", "repository": {