From d4e12d0ecab939b5ee4623f8a10201dd14a4e4ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 19 Jul 2026 18:23:36 +0000 Subject: [PATCH] chore: version packages (rc) --- .changeset/pre.json | 90 ++- examples/app-crm/CHANGELOG.md | 50 ++ examples/app-crm/package.json | 2 +- examples/app-showcase/CHANGELOG.md | 60 ++ examples/app-showcase/package.json | 2 +- examples/app-todo/CHANGELOG.md | 62 ++ examples/app-todo/package.json | 2 +- examples/embed-objectql/CHANGELOG.md | 42 ++ examples/embed-objectql/package.json | 2 +- packages/adapters/hono/CHANGELOG.md | 24 + packages/adapters/hono/package.json | 2 +- packages/apps/account/CHANGELOG.md | 39 + packages/apps/account/package.json | 2 +- packages/apps/setup/CHANGELOG.md | 39 + packages/apps/setup/package.json | 2 +- packages/apps/studio/CHANGELOG.md | 39 + packages/apps/studio/package.json | 2 +- packages/cli/CHANGELOG.md | 340 +++++++++ packages/cli/package.json | 2 +- packages/client-react/CHANGELOG.md | 45 ++ packages/client-react/package.json | 2 +- packages/client/CHANGELOG.md | 128 ++++ packages/client/package.json | 2 +- packages/cloud-connection/CHANGELOG.md | 58 ++ packages/cloud-connection/package.json | 2 +- .../connectors/connector-mcp/CHANGELOG.md | 43 ++ .../connectors/connector-mcp/package.json | 2 +- .../connectors/connector-openapi/CHANGELOG.md | 62 ++ .../connectors/connector-openapi/package.json | 2 +- .../connectors/connector-rest/CHANGELOG.md | 43 ++ .../connectors/connector-rest/package.json | 2 +- .../connectors/connector-slack/CHANGELOG.md | 43 ++ .../connectors/connector-slack/package.json | 2 +- packages/console/CHANGELOG.md | 74 ++ packages/console/package.json | 2 +- packages/core/CHANGELOG.md | 123 ++++ packages/core/package.json | 2 +- packages/create-objectstack/CHANGELOG.md | 98 +++ packages/create-objectstack/package.json | 2 +- .../src/templates/blank/objectstack.config.ts | 2 +- .../src/templates/blank/package.json | 16 +- packages/formula/CHANGELOG.md | 169 +++++ packages/formula/package.json | 2 +- packages/lint/CHANGELOG.md | 201 ++++++ packages/lint/package.json | 2 +- packages/mcp/CHANGELOG.md | 124 ++++ packages/mcp/package.json | 2 +- packages/metadata-core/CHANGELOG.md | 66 ++ packages/metadata-core/package.json | 2 +- packages/metadata-fs/CHANGELOG.md | 7 + packages/metadata-fs/package.json | 2 +- packages/metadata-protocol/CHANGELOG.md | 234 ++++++ packages/metadata-protocol/package.json | 2 +- packages/metadata/CHANGELOG.md | 68 ++ packages/metadata/package.json | 2 +- packages/objectql/CHANGELOG.md | 281 ++++++++ packages/objectql/package.json | 2 +- packages/observability/CHANGELOG.md | 100 +++ packages/observability/package.json | 2 +- packages/platform-objects/CHANGELOG.md | 63 ++ packages/platform-objects/package.json | 2 +- packages/plugins/driver-memory/CHANGELOG.md | 43 ++ packages/plugins/driver-memory/package.json | 2 +- packages/plugins/driver-mongodb/CHANGELOG.md | 43 ++ packages/plugins/driver-mongodb/package.json | 2 +- packages/plugins/driver-sql/CHANGELOG.md | 130 ++++ packages/plugins/driver-sql/package.json | 2 +- .../plugins/driver-sqlite-wasm/CHANGELOG.md | 47 ++ .../plugins/driver-sqlite-wasm/package.json | 2 +- packages/plugins/embedder-openai/CHANGELOG.md | 37 + packages/plugins/embedder-openai/package.json | 2 +- .../plugins/knowledge-memory/CHANGELOG.md | 44 ++ .../plugins/knowledge-memory/package.json | 2 +- .../plugins/knowledge-ragflow/CHANGELOG.md | 44 ++ .../plugins/knowledge-ragflow/package.json | 2 +- .../plugins/plugin-approvals/CHANGELOG.md | 105 +++ .../plugins/plugin-approvals/package.json | 2 +- packages/plugins/plugin-audit/CHANGELOG.md | 56 ++ packages/plugins/plugin-audit/package.json | 2 +- packages/plugins/plugin-auth/CHANGELOG.md | 99 +++ packages/plugins/plugin-auth/package.json | 2 +- packages/plugins/plugin-dev/CHANGELOG.md | 73 ++ packages/plugins/plugin-dev/package.json | 2 +- packages/plugins/plugin-email/CHANGELOG.md | 49 ++ packages/plugins/plugin-email/package.json | 2 +- .../plugins/plugin-hono-server/CHANGELOG.md | 127 ++++ .../plugins/plugin-hono-server/package.json | 2 +- .../plugins/plugin-pinyin-search/CHANGELOG.md | 28 + .../plugins/plugin-pinyin-search/package.json | 2 +- packages/plugins/plugin-reports/CHANGELOG.md | 45 ++ packages/plugins/plugin-reports/package.json | 2 +- packages/plugins/plugin-security/CHANGELOG.md | 72 ++ packages/plugins/plugin-security/package.json | 2 +- packages/plugins/plugin-sharing/CHANGELOG.md | 65 ++ packages/plugins/plugin-sharing/package.json | 2 +- packages/plugins/plugin-webhooks/CHANGELOG.md | 51 ++ packages/plugins/plugin-webhooks/package.json | 2 +- packages/qa/dogfood/CHANGELOG.md | 61 ++ packages/qa/dogfood/package.json | 2 +- packages/qa/downstream-contract/CHANGELOG.md | 37 + packages/qa/downstream-contract/package.json | 2 +- packages/qa/http-conformance/CHANGELOG.md | 11 + packages/qa/http-conformance/package.json | 2 +- packages/rest/CHANGELOG.md | 119 ++++ packages/rest/package.json | 2 +- packages/runtime/CHANGELOG.md | 328 +++++++++ packages/runtime/package.json | 2 +- packages/sdui-parser/CHANGELOG.md | 2 + packages/sdui-parser/package.json | 2 +- .../services/service-analytics/CHANGELOG.md | 92 +++ .../services/service-analytics/package.json | 2 +- .../services/service-automation/CHANGELOG.md | 189 +++++ .../services/service-automation/package.json | 2 +- packages/services/service-cache/CHANGELOG.md | 47 ++ packages/services/service-cache/package.json | 2 +- .../service-cluster-redis/CHANGELOG.md | 38 + .../service-cluster-redis/package.json | 2 +- .../services/service-cluster/CHANGELOG.md | 43 ++ .../services/service-cluster/package.json | 2 +- .../services/service-datasource/CHANGELOG.md | 43 ++ .../services/service-datasource/package.json | 2 +- packages/services/service-i18n/CHANGELOG.md | 43 ++ packages/services/service-i18n/package.json | 2 +- packages/services/service-job/CHANGELOG.md | 45 ++ packages/services/service-job/package.json | 2 +- .../services/service-knowledge/CHANGELOG.md | 43 ++ .../services/service-knowledge/package.json | 2 +- .../services/service-messaging/CHANGELOG.md | 56 ++ .../services/service-messaging/package.json | 2 +- .../services/service-package/CHANGELOG.md | 45 ++ .../services/service-package/package.json | 2 +- packages/services/service-queue/CHANGELOG.md | 45 ++ packages/services/service-queue/package.json | 2 +- .../services/service-realtime/CHANGELOG.md | 74 ++ .../services/service-realtime/package.json | 2 +- .../services/service-settings/CHANGELOG.md | 49 ++ .../services/service-settings/package.json | 2 +- packages/services/service-sms/CHANGELOG.md | 43 ++ packages/services/service-sms/package.json | 2 +- .../services/service-storage/CHANGELOG.md | 49 ++ .../services/service-storage/package.json | 2 +- packages/spec/CHANGELOG.md | 666 ++++++++++++++++++ packages/spec/package.json | 2 +- packages/spec/src/kernel/protocol-version.ts | 2 +- packages/triggers/trigger-api/CHANGELOG.md | 43 ++ packages/triggers/trigger-api/package.json | 2 +- .../trigger-record-change/CHANGELOG.md | 81 +++ .../trigger-record-change/package.json | 2 +- .../triggers/trigger-schedule/CHANGELOG.md | 87 +++ .../triggers/trigger-schedule/package.json | 2 +- packages/types/CHANGELOG.md | 126 ++++ packages/types/package.json | 2 +- packages/verify/CHANGELOG.md | 77 ++ packages/verify/package.json | 2 +- packages/vscode-objectstack/CHANGELOG.md | 2 + packages/vscode-objectstack/package.json | 2 +- 156 files changed, 6642 insertions(+), 87 deletions(-) diff --git a/.changeset/pre.json b/.changeset/pre.json index 71e7f96fed..4276dfca13 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -80,5 +80,93 @@ "@objectstack/verify": "15.1.1", "objectstack-vscode": "15.1.1" }, - "changesets": [] + "changesets": [ + "action-body-org-identifier", + "action-param-widget-config", + "adr-0097-openapi-upstream-classify", + "adr-0099-p0-equivalence-gate", + "adr-0099-p1-layer0-reads-rung", + "adr-0099-p2prime-two-axis-cells", + "adr-0103-managedby-write-policy", + "analytics-drill-raw-totals", + "annotate-schema-only-enums", + "approver-type-org-membership-level", + "automation-schema-resolver-e2e", + "betterauth-adapter-system-writes", + "bulk-update-validation-rules", + "bulk-write-hardening", + "cli-memory-driver-dispatch", + "cli-strip-arg-separator", + "cli-turso-loud-error", + "client-batch-transaction-sdk", + "collapse-hook-event-taxonomy", + "console-2e7d7f0f7ee7", + "console-94d4876df090", + "console-e164196801bd", + "console-fd45313b4d00", + "create-user-result-dialog-phone", + "cross-object-batch-authz-hardening", + "dashboard-widget-strict-3251", + "date-equality-runtime-fix", + "date-field-equality-guardrail", + "dev-loop-dx-p2", + "document-validation-governance-crossfield", + "drill-range-datetime-tz", + "driver-sql-sqlite3-peer", + "field-form-summary-subfields", + "fix-explain-ownership-values", + "flow-registration-schema-aware-validation", + "flow-trigger-observability", + "hook-nested-write-timeout", + "i18n-inline-label-default-locale", + "import-users-auto-policy", + "lint-hide-platform-baseline", + "logger-esm-file-destination", + "logger-honors-no-color", + "loop-collection-xexpression", + "mcp-dev-connect-hint", + "mcp-stdio-principal-admission", + "mcp-stdio-switch-split-and-dev-connect-hint", + "mcp-validate-expression-tool", + "metadata-list-package-aware-dedup", + "metadata-register-notifies-watchers", + "ownership-record-model-field", + "perf-timing-admin-detail", + "perf-timing-per-request-gating", + "publish-drafts-org-scope", + "readonly-static-insert-strip", + "reconcile-system-append-only-api-methods", + "region-aware-history-compaction", + "remove-agent-visibility", + "remove-dead-metadata-props-2377", + "remove-form-surfaced-dead-props-2377", + "remove-session-tenantid-alias", + "report-drill-down-range-filter", + "retire-feed-contracts", + "retire-feed-discovery-surface", + "retire-js-expression-dialect", + "sandbox-cpu-budget", + "sandbox-drop-asyncify", + "sandbox-pump-idle-backoff", + "sandbox-timeout-env-override", + "scaffold-default-connector-executors", + "scaffold-gitignore-survives-publish", + "scaffold-pnpm11-build-approvals", + "scaffold-skill-catalog-boundary", + "seed-replay-lookup-corruption", + "seed-replayer-skipped", + "server-timing-perf-spans-2408", + "service-automation-test-hardening", + "state-machine-initial-states", + "summary-rollup-filter", + "systemfields-drop-owner-key", + "tenant-scope-platform-global-3249", + "tidy-views-guard", + "tier4-type-soundness-warnings", + "time-relative-trigger", + "trim-validation-delete-event", + "trim-webhook-dead-triggers", + "unify-org-identifier-hook-session", + "view-metadata-type-schema-runtime-shapes" + ] } diff --git a/examples/app-crm/CHANGELOG.md b/examples/app-crm/CHANGELOG.md index a4abb372a7..01612fa52a 100644 --- a/examples/app-crm/CHANGELOG.md +++ b/examples/app-crm/CHANGELOG.md @@ -1,5 +1,55 @@ # @objectstack/example-crm +## 4.0.90-rc.0 + +### Patch Changes + +- Updated dependencies [b39c65d] +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [2ea08ee] +- Updated dependencies [d1d1c40] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [a2d6555] +- Updated dependencies [3a6310c] +- Updated dependencies [32899e6] +- Updated dependencies [515f11a] +- Updated dependencies [4174a07] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/runtime@16.0.0-rc.0 + - @objectstack/spec@16.0.0-rc.0 + ## 4.0.89 ### Patch Changes diff --git a/examples/app-crm/package.json b/examples/app-crm/package.json index 9097ec6a02..47857d5169 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-rc.0", "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 291fc0a6c9..80cbaa93a6 100644 --- a/examples/app-showcase/CHANGELOG.md +++ b/examples/app-showcase/CHANGELOG.md @@ -1,5 +1,65 @@ # @objectstack/example-showcase +## 0.3.12-rc.0 + +### Patch Changes + +- Updated dependencies [b39c65d] +- Updated dependencies [f972574] +- Updated dependencies [41e703b] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [47d923c] +- Updated dependencies [46e876c] +- Updated dependencies [2ea08ee] +- Updated dependencies [d1d1c40] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [efbcfe1] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [a2d6555] +- Updated dependencies [3a6310c] +- Updated dependencies [32899e6] +- Updated dependencies [515f11a] +- Updated dependencies [4174a07] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/runtime@16.0.0-rc.0 + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/connector-openapi@16.0.0-rc.0 + - @objectstack/driver-sql@16.0.0-rc.0 + - @objectstack/cloud-connection@16.0.0-rc.0 + - @objectstack/connector-mcp@16.0.0-rc.0 + - @objectstack/connector-rest@16.0.0-rc.0 + - @objectstack/connector-slack@16.0.0-rc.0 + - @objectstack/service-datasource@16.0.0-rc.0 + ## 0.3.11 ### Patch Changes diff --git a/examples/app-showcase/package.json b/examples/app-showcase/package.json index fba1e6e6bf..81eb3fbcf8 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-rc.0", "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 5cb1024d7a..432feb28cd 100644 --- a/examples/app-todo/CHANGELOG.md +++ b/examples/app-todo/CHANGELOG.md @@ -1,5 +1,67 @@ # @objectstack/example-todo +## 4.0.90-rc.0 + +### Patch Changes + +- Updated dependencies [b39c65d] +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [9ccd1e9] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [2ea08ee] +- Updated dependencies [d1d1c40] +- Updated dependencies [158aa14] +- Updated dependencies [15dbe18] +- Updated dependencies [83e8f7d] +- Updated dependencies [230358c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [a2d6555] +- Updated dependencies [3a6310c] +- Updated dependencies [32899e6] +- Updated dependencies [515f11a] +- Updated dependencies [4174a07] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/runtime@16.0.0-rc.0 + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/objectql@16.0.0-rc.0 + - @objectstack/client@16.0.0-rc.0 + - @objectstack/metadata@16.0.0-rc.0 + - @objectstack/mcp@16.0.0-rc.0 + - @objectstack/driver-sqlite-wasm@16.0.0-rc.0 + - @objectstack/knowledge-memory@16.0.0-rc.0 + - @objectstack/service-knowledge@16.0.0-rc.0 + ## 4.0.89 ### Patch Changes diff --git a/examples/app-todo/package.json b/examples/app-todo/package.json index ad1d85fdbf..3b4d2f473a 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-rc.0", "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 7d49610a75..4002928588 100644 --- a/examples/embed-objectql/CHANGELOG.md +++ b/examples/embed-objectql/CHANGELOG.md @@ -1,5 +1,47 @@ # @objectstack/example-embed-objectql +## 0.0.30-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [2ea08ee] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/objectql@16.0.0-rc.0 + - @objectstack/driver-memory@16.0.0-rc.0 + ## 0.0.29 ### Patch Changes diff --git a/examples/embed-objectql/package.json b/examples/embed-objectql/package.json index 28450981d7..b29e003efd 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-rc.0", "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 eb51cc9ba7..32d5845e68 100644 --- a/packages/adapters/hono/CHANGELOG.md +++ b/packages/adapters/hono/CHANGELOG.md @@ -1,5 +1,29 @@ # @objectstack/hono +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [b39c65d] +- Updated dependencies [22013aa] +- Updated dependencies [fdc244e] +- Updated dependencies [2ea08ee] +- Updated dependencies [d1d1c40] +- Updated dependencies [83e8f7d] +- Updated dependencies [efbcfe1] +- Updated dependencies [2049b6a] +- Updated dependencies [6c270a6] +- Updated dependencies [92f5f19] +- Updated dependencies [a2d6555] +- Updated dependencies [3a6310c] +- Updated dependencies [32899e6] +- Updated dependencies [515f11a] +- Updated dependencies [4174a07] +- Updated dependencies [ce468c8] + - @objectstack/runtime@16.0.0-rc.0 + - @objectstack/plugin-hono-server@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/adapters/hono/package.json b/packages/adapters/hono/package.json index 018b9b2060..9b05bb31ea 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": "16.0.0-rc.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 c50c05a176..996349352c 100644 --- a/packages/apps/account/CHANGELOG.md +++ b/packages/apps/account/CHANGELOG.md @@ -1,5 +1,44 @@ # @objectstack/account +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/apps/account/package.json b/packages/apps/account/package.json index d1dee90eaf..373e8362fb 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": "16.0.0-rc.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 af8a82e5f2..323f9b6621 100644 --- a/packages/apps/setup/CHANGELOG.md +++ b/packages/apps/setup/CHANGELOG.md @@ -1,5 +1,44 @@ # @objectstack/setup +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/apps/setup/package.json b/packages/apps/setup/package.json index ed69a4d472..37e4c3bc59 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": "16.0.0-rc.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 8358852268..343ccdd079 100644 --- a/packages/apps/studio/CHANGELOG.md +++ b/packages/apps/studio/CHANGELOG.md @@ -1,5 +1,44 @@ # @objectstack/studio +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/apps/studio/package.json b/packages/apps/studio/package.json index a68667a64d..98c235ce67 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": "16.0.0-rc.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 8736b95171..806ffb7aef 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,345 @@ # @objectstack/cli +## 16.0.0-rc.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. + +- 83e8f7d: feat(mcp): decouple the stdio auto-start switch from the HTTP surface + surface the MCP endpoint on `os dev` boot (#3167) + + The MCP HTTP surface (`/api/v1/mcp`) and the long-lived stdio transport used to + share one env var: `OS_MCP_SERVER_ENABLED=true` turned the HTTP surface on **and** + silently auto-started the stdio transport — which bridges the raw metadata service + + - data engine with no per-request principal (unscoped). An operator setting it to + "make sure MCP is on" got an unscoped transport as a side effect. + + * **`@objectstack/types`** — new `resolveMcpStdioAutoStart()`. Stdio auto-start is + now its own switch, `OS_MCP_STDIO_ENABLED` (default off); `OS_MCP_SERVER_ENABLED` + governs only the HTTP surface. The legacy `OS_MCP_SERVER_ENABLED=true` trigger + still starts stdio for one release, flagged as deprecated. `=false` is unchanged + (it only ever gated HTTP). + * **`@objectstack/mcp`** — `MCPServerPlugin.start()` gates stdio on the new switch + and logs a one-time deprecation warning when started via the legacy alias. + * **`@objectstack/cli`** — `os dev` now prints the MCP endpoint, the agent-skill + URL, and a ready-to-paste `claude mcp add` command on boot (gated on the HTTP + surface being on), so the "an agent operates the app it's building" loop is + discoverable at dev time. + * **`create-objectstack`** — the blank scaffold README documents that the app is + itself an MCP server (the serve side), distinct from the consume-side connector. + +### Patch Changes + +- da58467: fix(cli): honor `OS_DATABASE_DRIVER=memory` (mingo InMemoryDriver) (#3276) + + `os dev` / `os start` / `os serve` advertised a `memory` database driver + (`--database-driver memory`, `OS_DATABASE_DRIVER=memory`, and a `memory://` + URL scheme), but `serve.ts`'s driver dispatch had no `memory` branch — so it + silently fell through to the dev SQLite `:memory:` default (SQLite-in-memory, + a _different_ engine) or, in production, registered no driver at all. + + The driver kind-resolution + construction is now extracted into + `utils/storage-driver.ts` (unit-testable in isolation) with the missing + `memory` branch: selecting it yields the mingo `InMemoryDriver` in dev AND + production. The `memory://` / `mingo://` URL scheme is now recognized too, + kept distinct from sqlite's `:memory:` pseudo-file. Telemetry-datasource + provisioning behavior is unchanged. + +- 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 `-`. + +- 216c2db: fix(cli): fail loudly when `turso`/libSQL is selected in the open-core CLI (#3276 follow-up) + + Same "declared ≠ enforced" class as the `memory` fix: the CLI advertised `turso` + (`--database-driver turso`, `OS_DATABASE_DRIVER=turso`, `libsql://` URLs) but the + driver dispatch had no `turso` branch, so it silently fell through to the SQLite + default and ignored the requested engine. + + `turso`/libSQL ships in the cloud / enterprise distribution + (`@objectstack/driver-turso`, composed by the cloud runtime's own kernel factory — + open-core's standalone stack deliberately does not consume it). Rather than pull an + EE driver into open-core, `createStorageDriver` now throws a typed + `UnsupportedDriverError` for `turso`/`libsql`, and `serve.ts` surfaces it as a + fatal, actionable boot error (naming the cloud/EE package and the open-core + alternatives) instead of silently degrading to SQLite. `libsql://` / `*.turso.*` + URLs stay classified as `turso` so they hit the same loud failure. + +- 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. + +- 546a0d6: fix(cli): `os explain object` documented `ownership` with the wrong allowed values (#3244) + + The schema catalog described the object `ownership` field as the package + _contribution_ kind (`"own" | "extend"`, the `ObjectOwnershipEnum` set via + `registerObject`). But `ObjectSchema.ownership` is the **record-ownership + model** — `z.enum(['user', 'org', 'none'])` — a distinct concept the spec + explicitly warns not to conflate despite the shared word. + + `os explain object` now prints: + + ownership 'user' | 'org' | 'none' Record-ownership model: user (default, + injects a reassignable owner_id) | org | none (no per-record owner). + Distinct from the package own/extend contribution kind. + + A regression test (`packages/cli/test/commands.test.ts`) pins the documented + values to the record-ownership enum so the two concepts can't drift back + together. Found during the #1880 docs implementation-accuracy audit. + +- 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. +- 9760844: feat(cli): surface the MCP endpoint in the server-ready banner (#3167) + + The MCP server (`/api/v1/mcp`) is a default-on core capability, but nothing in + the `os dev` / `os serve` boot output pointed to it — a developer had to already + know it was there to connect an AI client. The server-ready banner now prints + the MCP URL and the `SKILL.md` pointer whenever the surface is enabled + (`isMcpServerEnabled()`, the same switch that auto-loads the plugin and gates + the route), so an agent can operate the running app straight from the dev loop. + Hidden when `OS_MCP_SERVER_ENABLED=false`. + +- 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. +- a2795f6: feat(triggers): declarative time-relative trigger — daily sweep instead of fragile date-equality (#1874) + + Time-relative business rules ("alert 60 days before a contract's `end_date`") + could only be expressed as a `record_change` flow gated on a date-equality + condition like `end_date == daysFromNow(60)`. That predicate is only evaluated + when the record _happens to change_, so it fires only if a record is edited on + exactly the threshold day — i.e. almost never, unattended. The robust + alternative was a hand-written cron + range query that every author + re-implemented (contracts `renewal_alert`, hr `document_expiring_soon`, + procurement `po_overdue`, …). + + A flow's start node can now declare a `timeRelative` descriptor instead: + + ```ts + config: { + timeRelative: { + object: 'contracts', + dateField: 'end_date', + offsetDays: [60, 30, 7], // T-minus reminders — fires on each threshold day + // — or — withinDays: 30 // "expiring soon" range; negative = overdue lookback + filter: { status: 'active' }, // optional, ANDed with the date window + }, + schedule: { type: 'cron', expression: '0 8 * * *' }, // optional; defaults to daily 08:00 UTC + } + ``` + + The new `time_relative` trigger (shipped in `@objectstack/trigger-schedule` as + `TimeRelativeTriggerPlugin`) sweeps the object on that schedule and launches the + flow **once per matching record**, with the record on the automation context — + so the start-node `condition` gate and `{record.}` interpolation work + exactly as for a record-change flow. Because the window is evaluated every day, + a threshold is never missed regardless of when the record last changed. The + discovery query runs as a system operation (RLS-bypassing) and is capped + (`maxRecords`, default 1000) so a mis-scoped window can't fan out unboundedly; + per-record failures are isolated so one bad row never aborts the sweep. + + The automation engine routes a start node carrying `config.timeRelative` to the + `time_relative` trigger (ahead of the plain `schedule` trigger, whose behavior is + unchanged), and `os validate` gains readiness checks for the new descriptor + (unknown swept object, ambiguous draft status). New authorable spec key: + `TimeRelativeTriggerSchema` (`@objectstack/spec/automation`). + +- Updated dependencies [b39c65d] +- Updated dependencies [f972574] +- Updated dependencies [2f3c641] +- Updated dependencies [e38da5b] +- Updated dependencies [f9b118d] +- Updated dependencies [22013aa] +- Updated dependencies [a9459e6] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [02eafa5] +- Updated dependencies [deb7e7e] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [9ccd1e9] +- Updated dependencies [a3823b2] +- Updated dependencies [47d923c] +- Updated dependencies [39b56d0] +- Updated dependencies [447465a] +- Updated dependencies [a140ff0] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [47d923c] +- Updated dependencies [46e876c] +- Updated dependencies [780b4b5] +- Updated dependencies [2ea08ee] +- Updated dependencies [d1d1c40] +- Updated dependencies [616e839] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [15dbe18] +- Updated dependencies [83e8f7d] +- Updated dependencies [230358c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [efbcfe1] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [06cb319] +- Updated dependencies [1e145eb] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [a2d6555] +- Updated dependencies [3a6310c] +- Updated dependencies [32899e6] +- Updated dependencies [515f11a] +- Updated dependencies [4174a07] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/runtime@16.0.0-rc.0 + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/plugin-security@16.0.0-rc.0 + - @objectstack/objectql@16.0.0-rc.0 + - @objectstack/plugin-hono-server@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/plugin-approvals@16.0.0-rc.0 + - @objectstack/service-automation@16.0.0-rc.0 + - @objectstack/service-messaging@16.0.0-rc.0 + - @objectstack/plugin-sharing@16.0.0-rc.0 + - @objectstack/rest@16.0.0-rc.0 + - @objectstack/service-analytics@16.0.0-rc.0 + - @objectstack/lint@16.0.0-rc.0 + - @objectstack/plugin-auth@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/client@16.0.0-rc.0 + - @objectstack/console@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + - @objectstack/metadata@16.0.0-rc.0 + - @objectstack/driver-sql@16.0.0-rc.0 + - @objectstack/trigger-record-change@16.0.0-rc.0 + - @objectstack/plugin-audit@16.0.0-rc.0 + - @objectstack/mcp@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + - @objectstack/observability@16.0.0-rc.0 + - @objectstack/service-realtime@16.0.0-rc.0 + - @objectstack/trigger-schedule@16.0.0-rc.0 + - @objectstack/plugin-webhooks@16.0.0-rc.0 + - @objectstack/cloud-connection@16.0.0-rc.0 + - @objectstack/verify@16.0.0-rc.0 + - @objectstack/account@16.0.0-rc.0 + - @objectstack/setup@16.0.0-rc.0 + - @objectstack/driver-memory@16.0.0-rc.0 + - @objectstack/driver-mongodb@16.0.0-rc.0 + - @objectstack/driver-sqlite-wasm@16.0.0-rc.0 + - @objectstack/plugin-email@16.0.0-rc.0 + - @objectstack/plugin-reports@16.0.0-rc.0 + - @objectstack/service-cache@16.0.0-rc.0 + - @objectstack/service-datasource@16.0.0-rc.0 + - @objectstack/service-job@16.0.0-rc.0 + - @objectstack/service-package@16.0.0-rc.0 + - @objectstack/service-queue@16.0.0-rc.0 + - @objectstack/service-settings@16.0.0-rc.0 + - @objectstack/service-sms@16.0.0-rc.0 + - @objectstack/service-storage@16.0.0-rc.0 + - @objectstack/trigger-api@16.0.0-rc.0 + - @objectstack/plugin-pinyin-search@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index f4bd244f72..faf832c5f7 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/cli", - "version": "15.1.1", + "version": "16.0.0-rc.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 5cea754e1a..1391803453 100644 --- a/packages/client-react/CHANGELOG.md +++ b/packages/client-react/CHANGELOG.md @@ -1,5 +1,50 @@ # @objectstack/client-react +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [9ccd1e9] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/client@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/client-react/package.json b/packages/client-react/package.json index 5bdfdcd8fb..0c6fce6a8d 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": "16.0.0-rc.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 b8ae9fb62e..659a28bb76 100644 --- a/packages/client/CHANGELOG.md +++ b/packages/client/CHANGELOG.md @@ -1,5 +1,133 @@ # @objectstack/client +## 16.0.0-rc.0 + +### Minor Changes + +- 9ccd1e9: feat(client): typed `data.batchTransaction()` for the atomic cross-object batch (#1604 / ADR-0034 item 4) + + Adds `client.data.batchTransaction(operations)` (and the environment-scoped + `client.project(id).data.batchTransaction`) — a typed SDK surface for + `POST {basePath}/batch`, the all-or-nothing cross-object transactional batch + that master-detail saves go through. Reuses `CrossObjectBatchOperation` / + `CrossObjectBatchRequest` / `CrossObjectBatchResponse` from + `@objectstack/spec/api` (also re-exported from the client for convenience); + supports `{ $ref: }` intra-batch parent references. + + The method is always atomic and deliberately exposes no `atomic` flag — the + endpoint rejects `atomic: false` with `400 BATCH_NOT_ATOMIC`. Non-atomic + per-object bulk writes stay on `data.batch()` / `createMany` / `updateMany`, + so any best-effort fallback is isolated in the caller's adapter (the ObjectUI + `masterDetailTx` adapter), not in the SDK. + +- 668dd17: **Breaking (npm type surface): retire the vestigial feed contracts + protocol surface (ADR-0052 §5 follow-up, #1959).** + + The `service-feed` runtime was deleted in #1955; `sys_comment` / `sys_activity` + are the canonical record-collaboration/timeline backend. This removes the dead + type surface that still pointed at the deleted runtime — every removed method was + already unreachable (the feed REST route was never mounted → 404; the protocol + implementation was never wired with a feed service, so `requireFeedService()` + could only throw). No behavior changes. + + No authorable metadata key is removed (the `feeds:` object capability flag and + the `RecordActivity` UI component config are unchanged), so `PROTOCOL_MAJOR` + stays 15 and this ships as `minor` rather than a protocol major. + + FROM → TO migration for every removed export: + + - `@objectstack/spec/contracts` — `IFeedService`, `CreateFeedItemInput`, + `UpdateFeedItemInput`, `ListFeedOptions`, `FeedListResult` → **removed, no + replacement**. Comments/activity are plain records: write `sys_comment` / read + `sys_activity` via the data engine or the REST data API. + - `@objectstack/spec/api` — `FeedApiContracts`, `FeedApiErrorCode`, + `FeedProtocol`, and all feed request/response schemas + types (`GetFeed*`, + `CreateFeedItem*`, `UpdateFeedItem*`, `DeleteFeedItem*`, `AddReaction*`, + `RemoveReaction*`, `PinFeedItem*`, `UnpinFeedItem*`, `StarFeedItem*`, + `UnstarFeedItem*`, `SearchFeed*`, `GetChangelog*`, `ChangelogEntry`, + `SubscribeRequest/Response`, `FeedUnsubscribeRequest`, `UnsubscribeResponse`, + `FeedPathParams`, `FeedItemPathParams`, `FeedListFilterType`) → **removed**. Use + the data API against `sys_comment` / `sys_activity` (`/api/v1/data/sys_comment/…`); + reactions and threaded replies are fields on `sys_comment`. + - `@objectstack/spec/data` — `FeedItemSchema`/`FeedItem`, `FeedActorSchema`/`FeedActor`, + `MentionSchema`/`Mention`, `ReactionSchema`/`Reaction`, + `FieldChangeEntrySchema`/`FieldChangeEntry`, `FeedVisibility`, + `RecordSubscriptionSchema`/`RecordSubscription`, `SubscriptionEventType`, and the + `data`-namespace `NotificationChannel` → **removed**. `FeedItemType` and + `FeedFilterMode` are **kept** (live UI activity-timeline config). For notification + channels use `NotificationChannelSchema` from `@objectstack/spec/system`. + - `@objectstack/client` — `client.feed.*` (`list` / `create` / `update` / `delete` / + `addReaction` / `removeReaction` / `pin` / `unpin` / `star` / `unstar` / `search` / + `getChangelog` / `subscribe` / `unsubscribe`) and the re-exported feed response + types → **removed**. One-line fix: use `client.data.*` on `sys_comment` / + `sys_activity`, e.g. `client.data.create('sys_comment', { object, record_id, body })` + and `client.data.find('sys_activity', { filters: [['record_id', '=', id]] })`. + - `@objectstack/metadata-protocol` — `ObjectStackProtocolImplementation` no longer + implements the 14 feed methods; its constructor + `(engine, getServicesRegistry?, getFeedService?, environmentId?)` becomes + `(engine, getServicesRegistry?, environmentId?)`. One-line fix: delete the third + argument. + +### Patch Changes + +- 8abf133: **Breaking (discovery response shape): retire the residual feed capability surface (#3180, follow-up to #1959 / ADR-0052 §5).** + + The feed backend was retired long ago; #1959 removed the feed contracts + SDK. This + removes the last discovery/dispatcher references to it, and fixes a real bug where the + `comments` capability was permanently `false`. + + - `@objectstack/spec` — `WellKnownCapabilitiesSchema.feed` and `ApiRoutesSchema.feed` + (`routes.feed`) are **removed**, and the `/api/v1/feed` entry is dropped from + `DEFAULT_DISPATCHER_ROUTES`. FROM → TO: clients reading `discovery.capabilities.feed` + or `discovery.routes.feed` → use `discovery.capabilities.comments`; comments/activity + are served by the generic data API on `sys_comment` / `sys_activity` + (`/api/v1/data/sys_comment/…`). + - `@objectstack/metadata-protocol` — `getDiscovery()` no longer emits the always-`false` + `feed` service/capability. **Bug fix:** the `comments` capability previously keyed off + the deleted `'feed'` service (so it was permanently `false` after #1955); it now tracks + the presence of the `sys_comment` object (provided by the always-on audit slate), so + `declared === enforced`. + - `@objectstack/client` — the internal `feed: '/api/v1/feed'` route constant is removed + (it only existed to satisfy the now-removed `ApiRoutes.feed` type; no client code used it). + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/client/package.json b/packages/client/package.json index 611b211290..4df9788382 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/client", - "version": "15.1.1", + "version": "16.0.0-rc.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 424a215526..e6f25fc817 100644 --- a/packages/cloud-connection/CHANGELOG.md +++ b/packages/cloud-connection/CHANGELOG.md @@ -1,5 +1,63 @@ # @objectstack/cloud-connection +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [b39c65d] +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [2ea08ee] +- Updated dependencies [d1d1c40] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [a2d6555] +- Updated dependencies [3a6310c] +- Updated dependencies [32899e6] +- Updated dependencies [515f11a] +- Updated dependencies [4174a07] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/runtime@16.0.0-rc.0 + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/cloud-connection/package.json b/packages/cloud-connection/package.json index 936ff7d668..33c9948679 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": "16.0.0-rc.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 681bd95315..6e4b6df48d 100644 --- a/packages/connectors/connector-mcp/CHANGELOG.md +++ b/packages/connectors/connector-mcp/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/connector-mcp +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/connectors/connector-mcp/package.json b/packages/connectors/connector-mcp/package.json index 3c8209e74b..7bc943ce9f 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": "16.0.0-rc.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 cc13b5afa1..99c546cd4a 100644 --- a/packages/connectors/connector-openapi/CHANGELOG.md +++ b/packages/connectors/connector-openapi/CHANGELOG.md @@ -1,5 +1,67 @@ # @objectstack/connector-openapi +## 16.0.0-rc.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 [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/connectors/connector-openapi/package.json b/packages/connectors/connector-openapi/package.json index 81a8e829e3..46f7909ba3 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": "16.0.0-rc.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 76363d2791..ed69eadc6a 100644 --- a/packages/connectors/connector-rest/CHANGELOG.md +++ b/packages/connectors/connector-rest/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/connector-rest +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/connectors/connector-rest/package.json b/packages/connectors/connector-rest/package.json index 5b6f21ac1a..431a22580a 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": "16.0.0-rc.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 697666be08..5162c5c601 100644 --- a/packages/connectors/connector-slack/CHANGELOG.md +++ b/packages/connectors/connector-slack/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/connector-slack +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/connectors/connector-slack/package.json b/packages/connectors/connector-slack/package.json index a96f269a73..8ce228ce30 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": "16.0.0-rc.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 2de3314c57..ca8b679344 100644 --- a/packages/console/CHANGELOG.md +++ b/packages/console/CHANGELOG.md @@ -1,5 +1,79 @@ # @objectstack/console +## 16.0.0-rc.0 + +### Major Changes + +- 39b56d0: Console (objectui) refreshed to `94d4876df090`. Frontend changes in this range: + + - feat(dashboard): Studio authors the ADR-0021 dataset shape only (framework#3251) (#2703) + - feat(app-shell): render ActionParamDialog params through the shared form field-widget renderer (#2700, ADR-0059) (#2704) + - feat(app-shell): distinguish writable system objects from engine-owned in badge + empty-state (ADR-0103 / #3220) (#2705) + - fix(list): keep injected owner_id out of leading auto-derived list columns (#2702) + - feat(flow-designer): #2670 Phase 3 — nested container node selection + schema-driven editing (#2699) + - feat(approvals-inbox): retire hardcoded secondary buttons for server-declared actions (#2697) + + objectui range: `fd45313b4d00...94d4876df090` + +### Minor Changes + +- 447465a: Console (objectui) refreshed to `e164196801bd`. Frontend changes in this range: + + - fix(app-shell,plugin-detail): record History tab renders display values, not raw audit payloads (#2691) + - fix(plugin-gantt): mirror the row 「→」 slot in the task-list header (#2690) + - fix(plugin-detail): #2688 header Record-#id floor + raw audit user id in meta footer (#2689) + - feat(plugin-gantt)!: remove the mobile QR share (移动端二维码) context-menu feature (#2687) + - feat(plugin-gantt): dependencyTypes switch — hide the type switcher for id-only dependency stores (#2686) + - feat(approvals): decision attachments + progress display + deep link + designer sync (#2681) + - feat(studio): inline push-down expansion of loop/parallel/try_catch regions on the flow canvas (#2680) + - feat(plugin-gantt): ownership-aware reschedule + confirm-first auto-schedule, export fixes, business time zone (#2683) + - fix(app-shell): skip resultDialog fields whose path does not resolve (#2674) + - feat(studio): visualize loop/parallel/try_catch nested regions on the flow canvas (#2670) (#2675) + - feat(plugin-gantt): manual-scheduling summary bars, interaction switches, beforeTaskUpdate veto + tooltip/scrollbar/cursor fixes (#2677) + - fix(flow-designer): author the canonical config.schedule the runtime reads (#2671) + - feat(report): drill a date-bucket cell into its time range, not a superset (#1752) (#2672) + - feat(studio): filter editor for roll-up summary fields (framework#1868) (#2669) + - feat(flow-designer): first-class panel for the time-relative trigger (#1874) (#2668) + - feat(studio): nest per-iteration / per-region step logs in the flow Runs panel (#2667) + - fix(metadata-admin): dashboard label fallback + skill activation editors (#1878) (#2666) + + objectui range: `2e7d7f0f7ee7...e164196801bd` + +- a140ff0: Console (objectui) refreshed to `fd45313b4d00`. Frontend changes in this range: + + - feat(app-shell): DeclaredActionsBar — render server-declared object actions on bespoke pages (#2678 P2-4) (#2692) + - feat(data): unify master-detail saves behind DataSource.batchTransaction; isolate non-atomic fallback in the adapter (#2679) (#2684) + + objectui range: `e164196801bd...fd45313b4d00` + +### Patch Changes + +- 47d923c: Console (objectui) refreshed to `2e7d7f0f7ee7`. Frontend changes in this range: + + - feat(evaluator): route CEL-dialect component/action predicates to the canonical engine (#2664) + - fix(grid): explain the import wizard's disabled Next and silent downgrade (#2640, #2639) (#2646) + - fix(form+detail): single-file children stay inline grids; drop non-spec `attachment` (#2654, #2655) (#2656) + - feat(access): localize curated capability labels client-side (#2600 B5 follow-up) (#2657) + - feat(access): localize capability picker group headers (#2600 B5, objectui side) (#2653) + - fix(access): Studio permission matrix — stop clipping the Bulk column at narrow widths (#2600 B3) (#2652) + - feat(access): Studio permission matrix — field-level bulk + filter for wide objects (#2600 B4) (#2651) + - feat(access): Studio Explain panel — package-scoped object dropdown instead of free-text api-name (#2600 B2) (#2650) + - feat(access): Studio permission matrix — collapse identity + zero-grant capabilities so the matrix hits the first screen (#2600 B1) (#2649) + - feat(plugin-list): 列表工具栏增加手动刷新按钮 (#2634) (#2645) + - fix(studio): approver Type dropdown drops deprecated `role`, membership-tier picker (#2643) + - fix(components): route internal html-page links through the SPA navigation handler (#2642) + - feat(discovery): trust only handlerReady/available services (ADR-0076 D12) (#2637) + - feat(types)!: adopt @objectstack/spec 15.1.1; drop value-erased spec/ui `…Schema` re-exports (#2589) + - feat(console): dev-seeded admin credentials hint on the login page (#2635) + - fix(auth): 注册页去掉重复的「or」分隔线(与 #2629 登录页修复对齐) (#2633) + - feat(app-shell/react): adapt to framework 15.1 — atomic publish rendering + honest discovery (#2630) + - fix(chatbot): plan approval flips the card to a Building… badge immediately (#2632) + - fix(app-shell,components): welcome CTA deep-links into the environment create dialog (#2631) + - fix(auth): login-page config race + sign-in watchdog — never strand SSO-only users on a password wall (#2629) + - feat(types): derive ListViewSchema from @objectstack/spec/ui (#2231) (#2622) + + objectui range: `077e45b4bc55...2e7d7f0f7ee7` + ## 15.1.1 ## 15.1.0 diff --git a/packages/console/package.json b/packages/console/package.json index 7b7b05599d..af987e94d0 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/console", - "version": "15.1.1", + "version": "16.0.0-rc.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 919fecedcb..7157581de4 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,128 @@ # @objectstack/core +## 16.0.0-rc.0 + +### Minor Changes + +- dd9f223: feat(analytics): scope a datetime date-bucket drill to the reference-tz midnight instants (#1752 follow-up) + + Closes the one gap left by the initial #1752 change: a `datetime` date dimension + bucketed under a **non-UTC reference timezone** previously fell back to a superset + drill (its bucket boundary is that tz's midnight _instant_, which `YYYY-MM-DD` + calendar bounds can't express). + + - **`@objectstack/core`** adds `zonedDateStartToUtcMs(ymd, tz)` — the UTC instant + at which a calendar day begins in a reference timezone (the inverse of + `calendarPartsInTz`). DST-safe: the offset is read from the platform tz + database via `Intl`, with a two-pass resolution for the rare offset-boundary + case; an unset/`'UTC'`/invalid zone returns plain UTC midnight. + - **`@objectstack/service-analytics`** now emits `drillRanges` bounds per the + field's temporal type (ADR-0053): a `datetime` field → ISO **instant** bounds + at the reference tz's midnight (works under any tz, incl. DST); a `date` field + → `YYYY-MM-DD` calendar bounds (tz-naive, exact under any tz). An unknown field + type is still emitted only under UTC and omitted (superset) under a non-UTC tz. + + No objectui change is needed — the client already forwards whatever bound values + the server sends into the drill filter and the `filter[field][gte|lt]` URL. + +- 290e2f0: feat(analytics): emit a half-open date-range drill scope for granularity-bucketed date dimensions (#1752) + + A report/dashboard cell grouped by a `dateGranularity` date dimension ("2026-Q2") + covers a SPAN of records, so drilling it needs a range (`>= start AND < nextStart`), + which the equality drill contract (`drillRawRows`) can't express — date dims were + therefore excluded from drill metadata and a drill landed on an unscoped superset. + + - **`@objectstack/core`** adds `bucketKeyToCalendarRange(key, granularity)`, the + inverse of `bucketDateValue`: it turns a canonical bucket key into its half-open + `[start, end)` calendar span (`YYYY-MM-DD`, `end` exclusive). Pure, timezone-naive + calendar arithmetic; returns `null` for unbucketable / out-of-range keys so the + caller falls back to an unscoped (superset) drill rather than emit a wrong bound. + - **`@objectstack/service-analytics`** emits a `drillRanges` sidecar (aligned to + `rows` by index — the range companion to `drillRawRows`) for `date` + + `dateGranularity` dimensions, computed from the canonical bucket key in the + pre-label-resolution snapshot pass. A `datetime` field under a non-UTC reference + timezone is omitted (host drills a superset) until instant-boundary support + lands; a tz-naive `date` field is exact under any timezone (ADR-0053). + + Consumed by objectui's report drill-through to scope the drilled record list to the + clicked time bucket. + +### 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 [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index 090c37b0aa..80ee165ff9 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/core", - "version": "15.1.1", + "version": "16.0.0-rc.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 f2f630bf96..0336762f70 100644 --- a/packages/create-objectstack/CHANGELOG.md +++ b/packages/create-objectstack/CHANGELOG.md @@ -1,5 +1,103 @@ # create-objectstack +## 16.0.0-rc.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 + +- 83e8f7d: feat(mcp): decouple the stdio auto-start switch from the HTTP surface + surface the MCP endpoint on `os dev` boot (#3167) + + The MCP HTTP surface (`/api/v1/mcp`) and the long-lived stdio transport used to + share one env var: `OS_MCP_SERVER_ENABLED=true` turned the HTTP surface on **and** + silently auto-started the stdio transport — which bridges the raw metadata service + + - data engine with no per-request principal (unscoped). An operator setting it to + "make sure MCP is on" got an unscoped transport as a side effect. + + * **`@objectstack/types`** — new `resolveMcpStdioAutoStart()`. Stdio auto-start is + now its own switch, `OS_MCP_STDIO_ENABLED` (default off); `OS_MCP_SERVER_ENABLED` + governs only the HTTP surface. The legacy `OS_MCP_SERVER_ENABLED=true` trigger + still starts stdio for one release, flagged as deprecated. `=false` is unchanged + (it only ever gated HTTP). + * **`@objectstack/mcp`** — `MCPServerPlugin.start()` gates stdio on the new switch + and logs a one-time deprecation warning when started via the legacy alias. + * **`@objectstack/cli`** — `os dev` now prints the MCP endpoint, the agent-skill + URL, and a ready-to-paste `claude mcp add` command on boot (gated on the HTTP + surface being on), so the "an agent operates the app it's building" loop is + discoverable at dev time. + * **`create-objectstack`** — the blank scaffold README documents that the app is + itself an MCP server (the serve side), distinct from the consume-side connector. + +- 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 795a1f5c00..90c142f3de 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": "16.0.0-rc.0", "description": "Create a new ObjectStack project — npx create-objectstack", "bin": { "create-objectstack": "./bin/create-objectstack.js" diff --git a/packages/create-objectstack/src/templates/blank/objectstack.config.ts b/packages/create-objectstack/src/templates/blank/objectstack.config.ts index 9576fea072..67c7699d64 100644 --- a/packages/create-objectstack/src/templates/blank/objectstack.config.ts +++ b/packages/create-objectstack/src/templates/blank/objectstack.config.ts @@ -16,7 +16,7 @@ export default defineStack({ // refuse this package at the boundary with the exact migration command, // instead of crashing later. Kept in lockstep with releases by // scripts/sync-template-versions.mjs. - engines: { protocol: '^15' }, + engines: { protocol: '^16' }, }, // `automation` backs flow execution and, per ADR-0097, materializes any diff --git a/packages/create-objectstack/src/templates/blank/package.json b/packages/create-objectstack/src/templates/blank/package.json index 5a1faddbd3..5b627698d1 100644 --- a/packages/create-objectstack/src/templates/blank/package.json +++ b/packages/create-objectstack/src/templates/blank/package.json @@ -11,16 +11,16 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@objectstack/spec": "^15.0.0", - "@objectstack/runtime": "^15.0.0", - "@objectstack/driver-memory": "^15.0.0", - "@objectstack/plugin-hono-server": "^15.0.0", - "@objectstack/connector-rest": "^15.0.0", - "@objectstack/connector-openapi": "^15.0.0", - "@objectstack/connector-mcp": "^15.0.0" + "@objectstack/spec": "^16.0.0", + "@objectstack/runtime": "^16.0.0", + "@objectstack/driver-memory": "^16.0.0", + "@objectstack/plugin-hono-server": "^16.0.0", + "@objectstack/connector-rest": "^16.0.0", + "@objectstack/connector-openapi": "^16.0.0", + "@objectstack/connector-mcp": "^16.0.0" }, "devDependencies": { - "@objectstack/cli": "^15.0.0", + "@objectstack/cli": "^16.0.0", "typescript": "^6.0.0" } } diff --git a/packages/formula/CHANGELOG.md b/packages/formula/CHANGELOG.md index 4d43af2070..f82d4483e7 100644 --- a/packages/formula/CHANGELOG.md +++ b/packages/formula/CHANGELOG.md @@ -1,5 +1,174 @@ # @objectstack/formula +## 16.0.0-rc.0 + +### Minor Changes + +- 6b51346: feat(formula): `dateField == today()` now matches — AST temporal-comparison rewrite (#3183) + + **Behavior change (the fix):** a `Field.date` compared with `==`/`!=` against a + temporal function now matches on the calendar day. Previously it **silently + returned the wrong answer** — `record.due_date == today()` was always `false` + (and `!= today()` always `true`) even for a same-day record, because a + `Field.date` reads back as a `YYYY-MM-DD` **string** (ADR-0053 Phase 1) and + cel-js's equality (`overloads.js` `isEqual`) treats a string and a timestamp as + unequal without consulting any overload. + + `celEngine.evaluate` now rewrites the parsed AST: for each `==`/`!=` whose one + operand is `today()`/`daysFromNow()`/`daysAgo()`/`now()`, the **field operand** + is wrapped in `date(...)` (the stdlib coercion), then the expression is + serialized and evaluated. So `record.due_date == today()` runs as + `date(record.due_date) == today()`. + + - **Per-occurrence**, not per-field: `record.d == "2026-06-20" || record.d == today()` + keeps the string-literal comparison intact while fixing the temporal one. + - **Type-blind-safe**: `date()` degrades gracefully — an already-`Date` + (`Field.datetime`) operand passes through; a non-date string or null → + `Invalid Date` → the comparison stays `false`, exactly as before. No + field-type information is needed, and no currently-correct result is worsened. + - **Cheap**: the rewrite only reserializes when such a comparison is present + (a plain-`includes` gate skips the rest), and is memoized per source string. + + Applies to every interpreter site — read-time `Field.formula`, default values, + validation rules, hook conditions, and flow conditions — since all route through + `celEngine.evaluate`. RLS/sharing conditions are unaffected: they compile via + `cel-to-filter`, which already rejects function calls as a loud authoring error. + + **Supersedes the #3192 advisory lint.** That build-time warning + (`checkTemporalDateEquality`) flagged `dateField == today()` as a silent-miss; + with the runtime fixed it would be a false alarm, so it (and the + `temporalEqualityFields` helper it used) is removed. Authors can now write the + natural `record.due_date == today()` directly; the `date(...)` / + `daysBetween(...) == 0` / range idioms all keep working. + +- 80273c8: feat(formula): warn when a `date` field is compared to a temporal function with `==`/`!=` (#3183) + + A `Field.date` deserializes as a `YYYY-MM-DD` **string** (ADR-0053 Phase 1), and + cel-js's equality hard-codes `string == ` to `false` — it returns + `false` for a string left operand without ever consulting a registered overload, + and refuses cross-type object equality (`@marcbachmann/cel-js` `overloads.js` + `isEqual`). So the most natural "is it due today" predicate — + + ```cel + record.due_date == today() // silently false, even when due_date IS today + record.due_date != today() // silently true for a same-day record + ``` + + — compiles clean, throws nothing, and silently never matches. Same silent-miss + family as #1928; **timezone-independent** (fails identically at UTC) and + cross-cutting (formulas, validation, RLS, flow/action/sharing/hook predicates). + + cel-js gives no operator-layer hook to fix the comparison, so this adds a + **build-time advisory warning** (the established ADR-0032 guardrail strategy) + rather than a runtime behavior change. `validateExpression` reuses the shared + `ExprSchemaHint.fieldTypes` (the same per-field type map the #1928 tier-4 + soundness check already threads through `@objectstack/lint`) to flag a `==`/`!=` + between a `date` field (`record.`/`previous.`/bare) and + `today()`/`daysFromNow()`/`daysAgo()`/`now()`, with a self-correcting message + pointing at the working idioms: `date(record.d) == today()`, a range + (`>= … && <= …`), or `daysBetween(today(), record.d) == 0`. + + Warning severity — never fails the build (the write/validation path may carry a + real `Date`). Restricted to `type: 'date'` (unambiguously a string); `datetime` + is excluded to avoid false positives. Ordering operators (`>=`/`<=`/`<`/`>`) + already work — cel-js _throws_ for them, tripping the engine's existing + string-hydration retry — so they are not flagged. + + A runtime fix (normalizing the peer of a temporal operand in the data layer) + remains tracked in #3183; a naive "hydrate date fields to `Date`" version would + trade this silent-miss for another (breaking `dateField == "2026-06-20"`), so it + needs its own design. + +- 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 + +- e0859b1: fix(formula): retire the `js` expression dialect and fix the `hasDialect` false-positive (#3278) + + The `js` **expression** dialect was declared in `ExpressionDialect` but never + shipped — it existed only as a registry stub with no engine and no author helper + (`cel`/`F`/`P` → CEL, `tmpl` → template, `cron` → cron; nothing ever emitted + `js`). Per ADR-0049 (enforce-or-remove) it is removed from the enum; the set is + now `{cel, cron, template}`. + + Procedural JavaScript is unaffected: it remains the **L2** authoring surface — + the sandboxed, capability-gated `ScriptBody { language: 'js' }` in hook/action + bodies — which is a separate enum (`hook-body.zod.ts`), not an expression + dialect. + + Also fixes a latent bug in `hasDialect`: it detected stubs via + `dialect.startsWith('stub:')`, but stubs were registered under their real name, + so the check was dead code and `hasDialect('js')` returned a false-positive + `true`. With the stub removed, `hasDialect` reports only registered real + engines, and the registry test now asserts the negative case (`hasDialect('js') +=== false`) so the gate can actually go red. + + No runtime behavior changes for any valid persisted artifact — no producer ever + emitted `dialect: 'js'`. See the ADR-0058 addendum. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/formula/package.json b/packages/formula/package.json index 2a3ea8e694..a1964b4ff2 100644 --- a/packages/formula/package.json +++ b/packages/formula/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/formula", - "version": "15.1.1", + "version": "16.0.0-rc.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 a38c1d0bec..fc42dc5cd6 100644 --- a/packages/lint/CHANGELOG.md +++ b/packages/lint/CHANGELOG.md @@ -1,5 +1,206 @@ # @objectstack/lint +## 16.0.0-rc.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. + +- a2795f6: feat(triggers): declarative time-relative trigger — daily sweep instead of fragile date-equality (#1874) + + Time-relative business rules ("alert 60 days before a contract's `end_date`") + could only be expressed as a `record_change` flow gated on a date-equality + condition like `end_date == daysFromNow(60)`. That predicate is only evaluated + when the record _happens to change_, so it fires only if a record is edited on + exactly the threshold day — i.e. almost never, unattended. The robust + alternative was a hand-written cron + range query that every author + re-implemented (contracts `renewal_alert`, hr `document_expiring_soon`, + procurement `po_overdue`, …). + + A flow's start node can now declare a `timeRelative` descriptor instead: + + ```ts + config: { + timeRelative: { + object: 'contracts', + dateField: 'end_date', + offsetDays: [60, 30, 7], // T-minus reminders — fires on each threshold day + // — or — withinDays: 30 // "expiring soon" range; negative = overdue lookback + filter: { status: 'active' }, // optional, ANDed with the date window + }, + schedule: { type: 'cron', expression: '0 8 * * *' }, // optional; defaults to daily 08:00 UTC + } + ``` + + The new `time_relative` trigger (shipped in `@objectstack/trigger-schedule` as + `TimeRelativeTriggerPlugin`) sweeps the object on that schedule and launches the + flow **once per matching record**, with the record on the automation context — + so the start-node `condition` gate and `{record.}` interpolation work + exactly as for a record-change flow. Because the window is evaluated every day, + a threshold is never missed regardless of when the record last changed. The + discovery query runs as a system operation (RLS-bypassing) and is capped + (`maxRecords`, default 1000) so a mis-scoped window can't fan out unboundedly; + per-record failures are isolated so one bad row never aborts the sweep. + + The automation engine routes a start node carrying `config.timeRelative` to the + `time_relative` trigger (ahead of the plain `schedule` trigger, whose behavior is + unchanged), and `os validate` gains readiness checks for the new descriptor + (unknown swept object, ambiguous draft status). New authorable spec key: + `TimeRelativeTriggerSchema` (`@objectstack/spec/automation`). + +### Patch Changes + +- 524696a: feat(spec)!: `DashboardWidgetSchema.strict()` — reject undeclared widget keys (framework#3251) + + The ADR-0021 analytics endpoint. `DashboardWidgetSchema` now rejects any + undeclared top-level key instead of silently stripping it, moving a whole class + of author error (a hallucinated or legacy key that renders as a silent no-op) + from fallible human review to deterministic CI. `options: z.unknown()` remains + the escape hatch for renderer-specific extras. + + A custom error map names the offending key(s) and, when a key is a removed + pre-ADR-0021 inline-analytics key (`object` / `categoryField` / `valueField` / + `aggregate`, pivot `rowField` / `columnField`) or an objectui-internal prop + (`component`, inline `data`), points the author at the dataset shape + (`dataset` + `dimensions` + `values`). + + Recorded as protocol-16 migration `step16` + (`dashboard-widget-strict-unknown-keys`), mirroring protocol-15's `step15` + strict flip on the form/page schemas (ADR-0089 D3a). The inline-analytics shape + itself was already removed at protocol 9 (single-form cutover), so there is no + mechanical rewrite — the residue is the strictness, delegated to the author. + + **Breaking:** shipped as `minor` per the launch-window policy (a breaking change + does not burn a major while the stack is in lockstep), riding the already-pending + 16.0.0 train. The release train's Version-Packages PR must set + `PROTOCOL_VERSION = '16.0.0'`; until then `step16` is inert + (`composeMigrationChain` caps at `PROTOCOL_MAJOR`). + + `@objectstack/lint` — the `widget-legacy-analytics-shape` / + `widget-legacy-analytics-unrenderable` rules are retained as the friendly, + suppressible bridge on the raw-config lint/doctor paths (strict preempts them on + the schema-parsed compile/validate paths); doc comment updated to explain the + interplay. + +- 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 [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + - @objectstack/sdui-parser@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/lint/package.json b/packages/lint/package.json index e266bd98a8..40e6ee3c0f 100644 --- a/packages/lint/package.json +++ b/packages/lint/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/lint", - "version": "15.1.1", + "version": "16.0.0-rc.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 40fcf8f0cb..0863be6675 100644 --- a/packages/mcp/CHANGELOG.md +++ b/packages/mcp/CHANGELOG.md @@ -1,5 +1,129 @@ # @objectstack/plugin-mcp-server +## 16.0.0-rc.0 + +### Minor Changes + +- 15dbe18: feat(mcp)!: stdio transport requires an API-key principal — fail-closed, no unscoped bridge (ADR-0101, #3246) + + The long-lived MCP **stdio** transport no longer reads data unscoped. It now runs + under an env-supplied identity, closing the platform's last identity-less + execution surface (the `mcp-stdio-authority` conformance row graduates + `experimental` → `enforced`). + + - `OS_MCP_STDIO_API_KEY=osk_...` supplies the stdio identity, resolved through + the SAME `@objectstack/core` verify + authorization chain as the HTTP/REST + surfaces; the `record_by_id` resource reads via `ql.find(obj, { where:{id}, +context })`, so RLS/FLS/tenant apply exactly as on REST `/data`. Re-resolved + per read, so a revoked/expired key stops working on a live session. + - **Fail-closed** — enabling stdio auto-start (`OS_MCP_STDIO_ENABLED=true` / + `autoStart`) without a resolvable key throws and refuses to start. There is no + unscoped fallback and deliberately no `system` bypass; full authority is a key + minted on a platform-admin or dedicated service identity. + + **BREAKING (stdio auto-start only):** previously `OS_MCP_STDIO_ENABLED=true` + (or the plugin `autoStart` option) started stdio with full, unscoped authority + and no credential. It now requires `OS_MCP_STDIO_API_KEY`; without it, boot + fails closed. The default-on HTTP surface and any deployment that never enables + stdio auto-start are unaffected. + +- 83e8f7d: feat(mcp): decouple the stdio auto-start switch from the HTTP surface + surface the MCP endpoint on `os dev` boot (#3167) + + The MCP HTTP surface (`/api/v1/mcp`) and the long-lived stdio transport used to + share one env var: `OS_MCP_SERVER_ENABLED=true` turned the HTTP surface on **and** + silently auto-started the stdio transport — which bridges the raw metadata service + + - data engine with no per-request principal (unscoped). An operator setting it to + "make sure MCP is on" got an unscoped transport as a side effect. + + * **`@objectstack/types`** — new `resolveMcpStdioAutoStart()`. Stdio auto-start is + now its own switch, `OS_MCP_STDIO_ENABLED` (default off); `OS_MCP_SERVER_ENABLED` + governs only the HTTP surface. The legacy `OS_MCP_SERVER_ENABLED=true` trigger + still starts stdio for one release, flagged as deprecated. `=false` is unchanged + (it only ever gated HTTP). + * **`@objectstack/mcp`** — `MCPServerPlugin.start()` gates stdio on the new switch + and logs a one-time deprecation warning when started via the legacy alias. + * **`@objectstack/cli`** — `os dev` now prints the MCP endpoint, the agent-skill + URL, and a ready-to-paste `claude mcp add` command on boot (gated on the HTTP + surface being on), so the "an agent operates the app it's building" loop is + discoverable at dev time. + * **`create-objectstack`** — the blank scaffold README documents that the app is + itself an MCP server (the serve side), distinct from the consume-side connector. + +- 230358c: feat(mcp): `validate_expression` tool — validate a CEL expression against a schema before authoring (#1928) + + Adds an agent-callable MCP tool that runs the same build-time expression checks + as `objectstack build`, so an AI can validate a formula / predicate / flow + condition **while authoring** instead of shipping one that silently evaluates to + `null`. Given `{ objectName, expression, site? }` it resolves the object's real + schema (field names + types, via the principal-bound `describeObject` bridge) + and returns: + + - **errors** — bare field refs (`amount` → `record.amount`), unknown fields + (with a did-you-mean), unknown functions; + - **warnings** — text/boolean fields misused in arithmetic, date-equality + pitfalls; + - **inScope** — the fields, stdlib functions, and namespace roots available, so + the model can self-correct; + - **inferredType** for a `formula` site. + + `site` (`formula` | `validation` | `flow_condition` | `template`, default + `formula`) maps to the validator's role + scope — `flow_condition` binds fields + bare, the rest bind `record.`. Read-only, gated by the `data:read` OAuth + scope, and fail-closed on `sys_*` objects like the other schema tools. This is + the authoring-time surface the guardrail series (#1928) always pointed at; + `@objectstack/mcp` gains a `@objectstack/formula` dependency (acyclic; formula is + a leaf). + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/mcp/package.json b/packages/mcp/package.json index 287f82337f..4bc49ad6b8 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/mcp", - "version": "15.1.1", + "version": "16.0.0-rc.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 3a0868d9e3..324db558da 100644 --- a/packages/metadata-core/CHANGELOG.md +++ b/packages/metadata-core/CHANGELOG.md @@ -1,5 +1,71 @@ # @objectstack/metadata-core +## 16.0.0-rc.0 + +### Patch Changes + +- 06cb319: fix(identity): close the generic-write apiMethods hole on sys_presence and sys_metadata (#3220) + + Follow-through on #1591/#3213 (better-auth apiMethods reconciliation) for two + non-better-auth managed objects that shipped the same contradiction: their + `enable.apiMethods` advertised generic `create`/`update`/`delete` while their + `managedBy` bucket forbids user-context writes, leaving the generic `/data` + route open to a write the bucket does not permit. + + - `sys_presence` (`managedBy: 'append-only'`) advertised `create`/`update`/`delete` + (update/delete on an append-only object at that) but is written only over the + realtime websocket/in-memory path, never through ObjectQL. Narrowed to + `['get', 'list']`. + - `sys_metadata` (`managedBy: 'system'`) advertised full CRUD but customization + overlays are authored only through the metadata-protocol RPC (engine writes + carry a transaction context, not a user session); neither the framework nor + the Console (objectui) POSTs `/data/sys_metadata`. Narrowed to `['get', 'list']`. + + Reads stay open. The metadata-protocol / realtime write paths are engine-level + and bypass the HTTP exposure gate, so they are unaffected — verified by the + metadata-authoring dogfood and the objectql overlay tests. + + A blast-radius audit confirmed the broader `system`/`append-only` buckets are NOT + safe to guard wholesale: several `system` objects (`sys_user_position`, + `sys_user_permission_set`, `sys_position_permission_set`, `sys_user_preference`, + `sys_import_job`) are legitimately user-writable by design (delegated + administration, user preferences, imports). Generalizing the engine write guard + to those buckets is intentionally NOT done here — see #3220 for the bucket-taxonomy + root cause. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/metadata-core/package.json b/packages/metadata-core/package.json index 6032264e83..030fff4747 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": "16.0.0-rc.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 4125d795b2..62c803c844 100644 --- a/packages/metadata-fs/CHANGELOG.md +++ b/packages/metadata-fs/CHANGELOG.md @@ -1,5 +1,12 @@ # @objectstack/metadata-fs +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [06cb319] + - @objectstack/metadata-core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/metadata-fs/package.json b/packages/metadata-fs/package.json index 4d2e867341..42bf1f46b4 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": "16.0.0-rc.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 e0c0353b48..d0c8a3af0a 100644 --- a/packages/metadata-protocol/CHANGELOG.md +++ b/packages/metadata-protocol/CHANGELOG.md @@ -1,5 +1,239 @@ # @objectstack/metadata-protocol +## 16.0.0-rc.0 + +### Minor Changes + +- 668dd17: **Breaking (npm type surface): retire the vestigial feed contracts + protocol surface (ADR-0052 §5 follow-up, #1959).** + + The `service-feed` runtime was deleted in #1955; `sys_comment` / `sys_activity` + are the canonical record-collaboration/timeline backend. This removes the dead + type surface that still pointed at the deleted runtime — every removed method was + already unreachable (the feed REST route was never mounted → 404; the protocol + implementation was never wired with a feed service, so `requireFeedService()` + could only throw). No behavior changes. + + No authorable metadata key is removed (the `feeds:` object capability flag and + the `RecordActivity` UI component config are unchanged), so `PROTOCOL_MAJOR` + stays 15 and this ships as `minor` rather than a protocol major. + + FROM → TO migration for every removed export: + + - `@objectstack/spec/contracts` — `IFeedService`, `CreateFeedItemInput`, + `UpdateFeedItemInput`, `ListFeedOptions`, `FeedListResult` → **removed, no + replacement**. Comments/activity are plain records: write `sys_comment` / read + `sys_activity` via the data engine or the REST data API. + - `@objectstack/spec/api` — `FeedApiContracts`, `FeedApiErrorCode`, + `FeedProtocol`, and all feed request/response schemas + types (`GetFeed*`, + `CreateFeedItem*`, `UpdateFeedItem*`, `DeleteFeedItem*`, `AddReaction*`, + `RemoveReaction*`, `PinFeedItem*`, `UnpinFeedItem*`, `StarFeedItem*`, + `UnstarFeedItem*`, `SearchFeed*`, `GetChangelog*`, `ChangelogEntry`, + `SubscribeRequest/Response`, `FeedUnsubscribeRequest`, `UnsubscribeResponse`, + `FeedPathParams`, `FeedItemPathParams`, `FeedListFilterType`) → **removed**. Use + the data API against `sys_comment` / `sys_activity` (`/api/v1/data/sys_comment/…`); + reactions and threaded replies are fields on `sys_comment`. + - `@objectstack/spec/data` — `FeedItemSchema`/`FeedItem`, `FeedActorSchema`/`FeedActor`, + `MentionSchema`/`Mention`, `ReactionSchema`/`Reaction`, + `FieldChangeEntrySchema`/`FieldChangeEntry`, `FeedVisibility`, + `RecordSubscriptionSchema`/`RecordSubscription`, `SubscriptionEventType`, and the + `data`-namespace `NotificationChannel` → **removed**. `FeedItemType` and + `FeedFilterMode` are **kept** (live UI activity-timeline config). For notification + channels use `NotificationChannelSchema` from `@objectstack/spec/system`. + - `@objectstack/client` — `client.feed.*` (`list` / `create` / `update` / `delete` / + `addReaction` / `removeReaction` / `pin` / `unpin` / `star` / `unstar` / `search` / + `getChangelog` / `subscribe` / `unsubscribe`) and the re-exported feed response + types → **removed**. One-line fix: use `client.data.*` on `sys_comment` / + `sys_activity`, e.g. `client.data.create('sys_comment', { object, record_id, body })` + and `client.data.find('sys_activity', { filters: [['record_id', '=', id]] })`. + - `@objectstack/metadata-protocol` — `ObjectStackProtocolImplementation` no longer + implements the 14 feed methods; its constructor + `(engine, getServicesRegistry?, getFeedService?, environmentId?)` becomes + `(engine, getServicesRegistry?, environmentId?)`. One-line fix: delete the third + argument. + +### 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). + +- 0e41302: fix(metadata-protocol): unscoped metadata list dedupes package-aware, not by bare name (ADR-0048 #1828) + + `getMetaItems` merged registry items, `sys_metadata` overlay rows, draft-preview + rows, and MetadataService items into `Map`s keyed by bare `name`, so two installed + packages shipping the same `type/name` (e.g. `page/home`) collapsed to one row + (last-write-wins) on an unscoped `GET /meta/:type` whenever either package had an + overlay — and the frontend prefer-local resolution, which reads that list, could + no longer tell the two packages' rows apart. + + The three merge sites (plus the env/org pre-merge) now key by `(package, name)`, + mirroring `getMetaItem`'s scoped-then-global-fallback resolution: colliding rows + stay distinct each with its own `_packageId`, a package-less (env-wide) overlay + still wins over the single artifact it customizes (ADR-0005 precedence and + single-package behaviour unchanged), and the registry-hydration artifact graft is + scoped to each row's own `package_id` so a collision no longer mislabels provenance. + +- 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. + +- 8abf133: **Breaking (discovery response shape): retire the residual feed capability surface (#3180, follow-up to #1959 / ADR-0052 §5).** + + The feed backend was retired long ago; #1959 removed the feed contracts + SDK. This + removes the last discovery/dispatcher references to it, and fixes a real bug where the + `comments` capability was permanently `false`. + + - `@objectstack/spec` — `WellKnownCapabilitiesSchema.feed` and `ApiRoutesSchema.feed` + (`routes.feed`) are **removed**, and the `/api/v1/feed` entry is dropped from + `DEFAULT_DISPATCHER_ROUTES`. FROM → TO: clients reading `discovery.capabilities.feed` + or `discovery.routes.feed` → use `discovery.capabilities.comments`; comments/activity + are served by the generic data API on `sys_comment` / `sys_activity` + (`/api/v1/data/sys_comment/…`). + - `@objectstack/metadata-protocol` — `getDiscovery()` no longer emits the always-`false` + `feed` service/capability. **Bug fix:** the `comments` capability previously keyed off + the deleted `'feed'` service (so it was permanently `false` after #1955); it now tracks + the presence of the `sys_comment` object (provided by the always-on audit slate), so + `declared === enforced`. + - `@objectstack/client` — the internal `feed: '/api/v1/feed'` route constant is removed + (it only existed to satisfy the now-removed `ApiRoutes.feed` type; no client code used it). + +- 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 [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [06cb319] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + - @objectstack/metadata-core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/metadata-protocol/package.json b/packages/metadata-protocol/package.json index 793e852681..0abe2e0ede 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": "16.0.0-rc.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 eea85fe566..cacfc66140 100644 --- a/packages/metadata/CHANGELOG.md +++ b/packages/metadata/CHANGELOG.md @@ -1,5 +1,73 @@ # @objectstack/metadata +## 16.0.0-rc.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 [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [06cb319] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + - @objectstack/metadata-core@16.0.0-rc.0 + - @objectstack/metadata-fs@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/metadata/package.json b/packages/metadata/package.json index bbc4b5cca2..5ecb306259 100644 --- a/packages/metadata/package.json +++ b/packages/metadata/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/metadata", - "version": "15.1.1", + "version": "16.0.0-rc.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 e37de8c58a..7f44738ae9 100644 --- a/packages/objectql/CHANGELOG.md +++ b/packages/objectql/CHANGELOG.md @@ -1,5 +1,286 @@ # @objectstack/objectql +## 16.0.0-rc.0 + +### Major Changes + +- 6c270a6: **BREAKING: remove the deprecated `ctx.session.tenantId` / `ctx.user.tenantId` alias from the hook & action authoring surface — converge on `organizationId` (#3290).** + + #3280 made `organizationId` the blessed developer-facing name for the caller's active org across the JS authoring surface and kept `tenantId` as a `@deprecated` alias carrying the identical value. That alias is now **removed** from the hook `ctx.session`, the action-body `ctx.session`, and the action-body `ctx.user`. Read the caller's active org under the single blessed name: + + ```diff + - const org = ctx.session.tenantId; // hook or action body + + const org = ctx.user?.organizationId ?? ctx.session?.organizationId; + ``` + + **FROM → TO migration** (in any `*.hook.ts` / `*.action.ts` body): + + - `ctx.session.tenantId` → `ctx.session.organizationId` + - `ctx.user.tenantId` (action body) → `ctx.user.organizationId` + + The value is unchanged — `organizationId` is the same active-org id, matching the `organization_id` column and `current_user.organizationId` in RLS/sharing. `ctx.user` is `undefined` for system / unauthenticated writes, so read `ctx.session?.organizationId` when a hook or action must work regardless of a resolved user. + + What changed internally: + + - **`@objectstack/spec`** — `HookContextSchema.session` drops the `tenantId` field (only `organizationId` remains). A stray `tenantId` on a constructed session is now stripped by the schema. + - **`@objectstack/objectql`** — the engine's `buildSession()` no longer emits `session.tenantId`; the audit-stamp plugin sources the `tenant_id` column from `session.organizationId`. + - **`@objectstack/runtime`** — `buildActionSession()` and the REST action `ctx.user` no longer emit `tenantId`. + - **`@objectstack/trigger-record-change`** — reads `session.organizationId` (was `session.tenantId`) when forwarding the writer's org to a `runAs:'user'` flow; behavior is identical. + + **Explicit non-goal (unchanged):** the generic **driver-layer** tenancy abstraction is _not_ touched — `ExecutionContext.tenantId`, `DriverOptions.tenantId`, `SqlDriver.applyTenantScope` / `TenancyConfig.tenantField`, and `ExecutionLog.tenantId`. That isolation column is configurable and legitimately carries an _environment_ id in database-per-tenant kernels; it is a distinct axis from the developer-facing org. The build-time `check:org-identifier` guard now also covers `packages/**` to keep reference bodies off the removed name. + +### Minor Changes + +- 22013aa: **Split the overloaded `managedBy: 'system'` bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220).** The `system` bucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row as `better-auth`/`append-only` but, unlike `better-auth`, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap). + + Rather than add a new `managedBy` enum value (which would fall through to fully-editable `platform` defaults on already-deployed Console clients), the write policy is now the **resolved affordance** (`resolveCrudAffordances` = bucket default + `userActions`), and _engine-owned_ is defined as a `system`/`append-only` object that grants no write: + + - **Writable set declares `userActions`** — the RBAC link tables (`sys_user_position`, `sys_user_permission_set`, `sys_position_permission_set`), `sys_user_preference`, `sys_approval_delegation`, and the messaging config grids (`sys_notification_preference` / `…_subscription` / `…_template`) now declare `userActions: { create, edit, delete: true }`. The affordance is a declaration only — the `DelegatedAdminGate` / RLS / permission sets remain the authz. + - **Engine-owned objects locked to reads** — `apiMethods: ['get','list']` added where absent (jobs, notifications, approval request/approver/token/action, `sys_record_share`, `sys_automation_run`, mail/settings/secret audit, the messaging delivery pipeline). `sys_secret` is explicitly read-locked (an empty `apiMethods` array fails open). + - **`sys_import_job`** stays engine-owned: the REST import route now writes its job rows `isSystem`-elevated (attribution preserved via the explicit `created_by` stamp) and the object is locked to `['get','list']`. + - **New engine write guard** (`assertEngineOwnedWriteAllowed`, plugin-security) fail-closed rejects user-context generic writes to engine-owned `system`/`append-only` objects, keyed off the resolved affordance; `isSystem` and context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. + - **`reconcileManagedApiMethods`** (objectql registry) now runs for **every** managed bucket, not just `better-auth`: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049). + - **`/me/permissions` clamp** (plugin-hono-server) now clamps `system`/`append-only` as well as `better-auth`, so the client hint reflects `permission ∩ guard`. + + **Potentially breaking:** a downstream/third-party `system` object that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. Declare `userActions` opening the verbs the object legitimately takes from a user context. `better-auth` keeps plugin-auth's identity write guard unchanged; the row-level `managed_by` provenance vocabulary (ADR-0066) is a different axis and is untouched. + +- 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. + +- 4d5a892: feat(objectql): roll-up `summary` fields can filter which child rows they aggregate (#1868) + + `summaryOperations` gains an optional `filter` — a query `where` FilterCondition + evaluated against each child row, so a summary aggregates only the matching + children instead of the whole collection. This is what lets a single child object + feed several distinct parent totals, which the cross-object rollup templates need: + + ```typescript + // One `engagement` child → distinct filtered totals. + total_signups: { + type: 'summary', + summaryOperations: { object: 'engagement', field: 'id', function: 'count', filter: { type: 'signup' } }, + } + // Sum only received receipt lines (3-way match). + received_amount: { + type: 'summary', + summaryOperations: { object: 'procurement_receipt', field: 'amount', function: 'sum', filter: { status: 'received' } }, + } + ``` + + The engine ANDs the predicate with the parent-FK match when it recomputes, and + because the whole filtered aggregate is re-run on every child write, a child that + moves in or out of the predicate (e.g. a status change) keeps the parent current + with no extra wiring. Operator and compound forms work too + (`filter: { type: { $in: ['signup', 'trial'] }, amount: { $gte: 100 } }`). + + Purely additive: omitting `filter` aggregates every child exactly as before. + +### 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). + +- a3823b2: Collapse the hook event taxonomy from 18 declared events to the 8 the engine actually dispatches (#3195). The removed 10 (`beforeFindOne`/`afterFindOne`, `beforeCount`/`afterCount`, `beforeAggregate`/`afterAggregate`, `beforeUpdateMany`/`afterUpdateMany`, `beforeDeleteMany`/`afterDeleteMany`) were declared in `HookEvent` but never fired — the enum mirrored the engine method table instead of domain events, so a hook subscribing to them registered fine and then silently no-op'd. + + - `findOne` now fires the same `beforeFind`/`afterFind` hooks as `find` — the read event attaches to record materialization, not the engine method, so one subscription covers every read shape (no separate `beforeFindOne`/`afterFindOne`). + - Bulk (`multi: true`) updates/deletes already fire the singular `beforeUpdate`/`beforeDelete`/`afterUpdate`/`afterDelete` events with the row-scoping predicate in `ctx.input.ast`; this is now documented, and there is no `*Many` event. + - Read authorization / row filtering is the RLS/permission-rule layer's job and field masking is field-level metadata — neither is a hook every author must re-attach. + - `engine.registerHook` now warns when a hook subscribes to an event the engine never dispatches, so enum-vs-dispatch drift can't recur silently. + + No shipped hook or authored metadata used any of the removed events; authoring one now fails loudly at parse/validate time instead of registering a dead hook. Skills and docs updated to teach the 8 events and the declarative alternatives. + +- 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. + +- 668dd17: **Breaking (npm type surface): retire the vestigial feed contracts + protocol surface (ADR-0052 §5 follow-up, #1959).** + + The `service-feed` runtime was deleted in #1955; `sys_comment` / `sys_activity` + are the canonical record-collaboration/timeline backend. This removes the dead + type surface that still pointed at the deleted runtime — every removed method was + already unreachable (the feed REST route was never mounted → 404; the protocol + implementation was never wired with a feed service, so `requireFeedService()` + could only throw). No behavior changes. + + No authorable metadata key is removed (the `feeds:` object capability flag and + the `RecordActivity` UI component config are unchanged), so `PROTOCOL_MAJOR` + stays 15 and this ships as `minor` rather than a protocol major. + + FROM → TO migration for every removed export: + + - `@objectstack/spec/contracts` — `IFeedService`, `CreateFeedItemInput`, + `UpdateFeedItemInput`, `ListFeedOptions`, `FeedListResult` → **removed, no + replacement**. Comments/activity are plain records: write `sys_comment` / read + `sys_activity` via the data engine or the REST data API. + - `@objectstack/spec/api` — `FeedApiContracts`, `FeedApiErrorCode`, + `FeedProtocol`, and all feed request/response schemas + types (`GetFeed*`, + `CreateFeedItem*`, `UpdateFeedItem*`, `DeleteFeedItem*`, `AddReaction*`, + `RemoveReaction*`, `PinFeedItem*`, `UnpinFeedItem*`, `StarFeedItem*`, + `UnstarFeedItem*`, `SearchFeed*`, `GetChangelog*`, `ChangelogEntry`, + `SubscribeRequest/Response`, `FeedUnsubscribeRequest`, `UnsubscribeResponse`, + `FeedPathParams`, `FeedItemPathParams`, `FeedListFilterType`) → **removed**. Use + the data API against `sys_comment` / `sys_activity` (`/api/v1/data/sys_comment/…`); + reactions and threaded replies are fields on `sys_comment`. + - `@objectstack/spec/data` — `FeedItemSchema`/`FeedItem`, `FeedActorSchema`/`FeedActor`, + `MentionSchema`/`Mention`, `ReactionSchema`/`Reaction`, + `FieldChangeEntrySchema`/`FieldChangeEntry`, `FeedVisibility`, + `RecordSubscriptionSchema`/`RecordSubscription`, `SubscriptionEventType`, and the + `data`-namespace `NotificationChannel` → **removed**. `FeedItemType` and + `FeedFilterMode` are **kept** (live UI activity-timeline config). For notification + channels use `NotificationChannelSchema` from `@objectstack/spec/system`. + - `@objectstack/client` — `client.feed.*` (`list` / `create` / `update` / `delete` / + `addReaction` / `removeReaction` / `pin` / `unpin` / `star` / `unstar` / `search` / + `getChangelog` / `subscribe` / `unsubscribe`) and the re-exported feed response + types → **removed**. One-line fix: use `client.data.*` on `sys_comment` / + `sys_activity`, e.g. `client.data.create('sys_comment', { object, record_id, body })` + and `client.data.find('sys_activity', { filters: [['record_id', '=', id]] })`. + - `@objectstack/metadata-protocol` — `ObjectStackProtocolImplementation` no longer + implements the 14 feed methods; its constructor + `(engine, getServicesRegistry?, getFeedService?, environmentId?)` becomes + `(engine, getServicesRegistry?, environmentId?)`. One-line fix: delete the third + argument. + +- 86d30af: fix(tenancy): platform-global (`tenancy.enabled:false`) objects are never driver-org-scoped (#3249) + + An org-context read of a platform-global object (e.g. `sys_license`, ADR-0066) + could return 0 rows for an authenticated caller while an anonymous read saw the + data: the engine stamped `execCtx.tenantId` into driver options unconditionally, + and the SQL driver's tenant-field cache could be re-corrupted to + `organization_id` by a partial re-registration (lifecycle archive `syncSchema`, + schema-drift re-sync) whose schema omitted the `tenancy` block. + + - New `isTenancyDisabled(schema)` export from `@objectstack/spec/data` — the + single source of truth for the ADR-0066 platform-global posture, now shared by + the registry (tenant-column injection), the ObjectQL engine, and the SQL + driver. + - `ObjectQL.buildDriverOptions` no longer stamps `tenantId` for objects whose + registered schema declares `tenancy.enabled: false` (an explicitly-passed + options `tenantId` still wins — deliberate caller intent). + - `SqlDriver` (and `SqliteWasmDriver`) now keep a sticky record of an explicit + `tenancy.enabled:false` declaration: a later registration without a `tenancy` + block preserves the opt-out instead of re-scoping via the implicit + `organization_id` heuristic; a registration that carries a `tenancy` + declaration stays authoritative. + +- 2018df9: **Unify the developer-facing org identifier in JS hooks — `organizationId` is now the blessed name; `session.tenantId` becomes a deprecated alias (#3280).** The caller's active organization was surfaced to hook authors as `ctx.session.tenantId`, while everything else on the developer surface — the `organization_id` column, `current_user.organizationId` in RLS/sharing, and seed rows — already said `organization`. A hook author had to internalize the hidden equation `tenantId === organizationId` to move between surfaces. This is additive and non-breaking: + + - **`ctx.session.organizationId`** is added as the blessed name; **`ctx.session.tenantId`** still carries the identical value but is marked `@deprecated` in its TSDoc. Both come from the same resolved `ExecutionContext.tenantId` (which the kernel derives from `session.activeOrganizationId`). + - **`ctx.user.organizationId`** is added to the ergonomic `user` shortcut, so a hook that needs "the current org to filter by" writes `ctx.user.organizationId` with zero relearning — matching `current_user.organizationId` (RLS) and the `organization_id` column. The engine now populates `ctx.user` (`{ id, email?, organizationId? }`) at every hook event that already carries a `session`; it stays `undefined` for system / unauthenticated writes. + + **No behavior change and no breaking rename.** The generic driver-layer tenancy abstraction (`ExecutionContext.tenantId`, `DriverOptions.tenantId`, `SqlDriver.applyTenantScope`, `TenancyConfig.tenantField`) is deliberately untouched — that layer's isolation column is configurable and legitimately carries an _environment_ id in per-environment (database-per-tenant) kernels. Hook-authoring docs now teach `organizationId` and distinguish the two isolation axes: **org row-scoping** (`organization_id`, shared DB) vs **environment / database-per-tenant** (`service-tenant`, `driver-turso`). Community edition never populates an org, so `organizationId` is `undefined` there. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [0e41302] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [b8a21ad] +- Updated dependencies [beaf2de] +- Updated dependencies [06cb319] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [515f11a] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/metadata-protocol@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + - @objectstack/metadata-core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/objectql/package.json b/packages/objectql/package.json index a97abd272f..36c8367543 100644 --- a/packages/objectql/package.json +++ b/packages/objectql/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/objectql", - "version": "15.1.1", + "version": "16.0.0-rc.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 6e199e617c..68206eb534 100644 --- a/packages/observability/CHANGELOG.md +++ b/packages/observability/CHANGELOG.md @@ -1,5 +1,105 @@ # @objectstack/observability +## 16.0.0-rc.0 + +### Minor Changes + +- efbcfe1: feat(observability): admin-only richer per-request timing detail via `X-OS-Debug-Timing: json` (#2408) + + Completes the optional "richer JSON" diagnostic from #2408. In addition to the + basic `Server-Timing` header, an admin/service caller can now request a + per-query breakdown — the slowest SQL statements and a query count — by sending + `X-OS-Debug-Timing: json`. The detail is returned in a separate + `X-OS-Debug-Timing-Detail` response header (compact JSON) and is **admin-only, + even under global mode**: an ordinary caller never sees SQL shapes. + + - **observability**: `PerfTiming` gains opt-in per-event detail capture + (`enableDetail` / `recordDetail` / `details`) plus the ambient + `recordServerTimingDetail`. The disclosure gate gains a `privileged` level + (set by `allowPerfDisclosure`, read via `isPerfDisclosurePrivileged`) so the + richer detail can be gated independently of the basic header. + - **driver-sql**: when detail capture is on, the query listener additionally + records each query's **parametrized** statement (knex's `q.sql`, `?` + placeholders) — never the bindings, so no literal row value ever enters the + collector. Zero overhead when detail is off. + - **plugin-hono-server**: `X-OS-Debug-Timing: json` enables detail capture; the + middleware emits `X-OS-Debug-Timing-Detail` (slowest queries, capped and + sanitized to header-safe ASCII) only when the principal is a proven admin. + + Basic and global behavior are unchanged; `json` is purely additive. + +- 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 [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/observability/package.json b/packages/observability/package.json index 587be9089c..62104e864c 100644 --- a/packages/observability/package.json +++ b/packages/observability/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/observability", - "version": "15.1.1", + "version": "16.0.0-rc.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 d0b9b61f74..c70e2540e8 100644 --- a/packages/platform-objects/CHANGELOG.md +++ b/packages/platform-objects/CHANGELOG.md @@ -1,5 +1,68 @@ # @objectstack/platform-objects +## 16.0.0-rc.0 + +### Minor Changes + +- bc65105: feat(platform-objects): surface phone number in the create_user result dialog + + `sys_user`'s `create_user` action now declares `user.phoneNumber` in its + `resultDialog.fields`, so admins creating phone-based accounts see the + sign-in phone number alongside the email and temporary password. The + create-user response carries `phoneNumber` only for phone-based users; + objectui's ActionResultDialog skips declared fields whose path is absent + from the payload, so email-only users see no extra row. + +### Patch Changes + +- 22013aa: **Split the overloaded `managedBy: 'system'` bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220).** The `system` bucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row as `better-auth`/`append-only` but, unlike `better-auth`, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap). + + Rather than add a new `managedBy` enum value (which would fall through to fully-editable `platform` defaults on already-deployed Console clients), the write policy is now the **resolved affordance** (`resolveCrudAffordances` = bucket default + `userActions`), and _engine-owned_ is defined as a `system`/`append-only` object that grants no write: + + - **Writable set declares `userActions`** — the RBAC link tables (`sys_user_position`, `sys_user_permission_set`, `sys_position_permission_set`), `sys_user_preference`, `sys_approval_delegation`, and the messaging config grids (`sys_notification_preference` / `…_subscription` / `…_template`) now declare `userActions: { create, edit, delete: true }`. The affordance is a declaration only — the `DelegatedAdminGate` / RLS / permission sets remain the authz. + - **Engine-owned objects locked to reads** — `apiMethods: ['get','list']` added where absent (jobs, notifications, approval request/approver/token/action, `sys_record_share`, `sys_automation_run`, mail/settings/secret audit, the messaging delivery pipeline). `sys_secret` is explicitly read-locked (an empty `apiMethods` array fails open). + - **`sys_import_job`** stays engine-owned: the REST import route now writes its job rows `isSystem`-elevated (attribution preserved via the explicit `created_by` stamp) and the object is locked to `['get','list']`. + - **New engine write guard** (`assertEngineOwnedWriteAllowed`, plugin-security) fail-closed rejects user-context generic writes to engine-owned `system`/`append-only` objects, keyed off the resolved affordance; `isSystem` and context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. + - **`reconcileManagedApiMethods`** (objectql registry) now runs for **every** managed bucket, not just `better-auth`: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049). + - **`/me/permissions` clamp** (plugin-hono-server) now clamps `system`/`append-only` as well as `better-auth`, so the client hint reflects `permission ∩ guard`. + + **Potentially breaking:** a downstream/third-party `system` object that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. Declare `userActions` opening the verbs the object legitimately takes from a user context. `better-auth` keeps plugin-auth's identity write guard unchanged; the row-level `managed_by` provenance vocabulary (ADR-0066) is a different axis and is untouched. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [06cb319] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/metadata-core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/platform-objects/package.json b/packages/platform-objects/package.json index 4fa32a1831..0e36760c26 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": "16.0.0-rc.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 08a0f24ba8..f5ea567003 100644 --- a/packages/plugins/driver-memory/CHANGELOG.md +++ b/packages/plugins/driver-memory/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/driver-memory +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/driver-memory/package.json b/packages/plugins/driver-memory/package.json index 0bea706724..9b4c4650a0 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": "16.0.0-rc.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 09e68aef70..4c67cc1abc 100644 --- a/packages/plugins/driver-mongodb/CHANGELOG.md +++ b/packages/plugins/driver-mongodb/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/driver-mongodb +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/driver-mongodb/package.json b/packages/plugins/driver-mongodb/package.json index 08cc44981e..365825406d 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": "16.0.0-rc.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 5dd597ed26..ea9af1628b 100644 --- a/packages/plugins/driver-sql/CHANGELOG.md +++ b/packages/plugins/driver-sql/CHANGELOG.md @@ -1,5 +1,135 @@ # @objectstack/driver-sql +## 16.0.0-rc.0 + +### Minor Changes + +- efbcfe1: feat(observability): admin-only richer per-request timing detail via `X-OS-Debug-Timing: json` (#2408) + + Completes the optional "richer JSON" diagnostic from #2408. In addition to the + basic `Server-Timing` header, an admin/service caller can now request a + per-query breakdown — the slowest SQL statements and a query count — by sending + `X-OS-Debug-Timing: json`. The detail is returned in a separate + `X-OS-Debug-Timing-Detail` response header (compact JSON) and is **admin-only, + even under global mode**: an ordinary caller never sees SQL shapes. + + - **observability**: `PerfTiming` gains opt-in per-event detail capture + (`enableDetail` / `recordDetail` / `details`) plus the ambient + `recordServerTimingDetail`. The disclosure gate gains a `privileged` level + (set by `allowPerfDisclosure`, read via `isPerfDisclosurePrivileged`) so the + richer detail can be gated independently of the basic header. + - **driver-sql**: when detail capture is on, the query listener additionally + records each query's **parametrized** statement (knex's `q.sql`, `?` + placeholders) — never the bindings, so no literal row value ever enters the + collector. Zero overhead when detail is off. + - **plugin-hono-server**: `X-OS-Debug-Timing: json` enables detail capture; the + middleware emits `X-OS-Debug-Timing-Detail` (slowest queries, capped and + sanitized to header-safe ASCII) only when the principal is a proven admin. + + Basic and global behavior are unchanged; `json` is purely additive. + +### Patch Changes + +- 47d923c: fix(driver-sql): drop the vestigial `sqlite3` peerDependency — the SQLite path uses `better-sqlite3` (#3277) + + `package.json` advertised `peerDependencies.sqlite3: "^5.0.0"`, but the driver never + loads `sqlite3` at runtime. Every first-party SQLite construction site builds a + `client: 'better-sqlite3'` Knex driver (`resolveSqliteDriver` in + `@objectstack/service-datasource`, the datasource driver factory, and the whole + driver test suite), and the README already tells consumers to `pnpm add better-sqlite3`. + `better-sqlite3` is auto-provided as an `optionalDependency` (with the native → wasm → + memory step-down of #2229 covering a failed native build), so the SQLite requirement is + already satisfied without the consumer installing anything. + + The stale `sqlite3` peer only misled: a consumer resolving peer deps could `pnpm add +sqlite3` (never used) while believing they'd satisfied the SQLite requirement. Removing + it aligns the declared contract with the code and the docs. The `sqlite3` string alias + still maps to `better-sqlite3` in the driver factory and dialect detection, so + `driver: 'sqlite3'` config keeps working — it just resolves to `better-sqlite3` like + everything else. + +- 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. + +- 86d30af: fix(tenancy): platform-global (`tenancy.enabled:false`) objects are never driver-org-scoped (#3249) + + An org-context read of a platform-global object (e.g. `sys_license`, ADR-0066) + could return 0 rows for an authenticated caller while an anonymous read saw the + data: the engine stamped `execCtx.tenantId` into driver options unconditionally, + and the SQL driver's tenant-field cache could be re-corrupted to + `organization_id` by a partial re-registration (lifecycle archive `syncSchema`, + schema-drift re-sync) whose schema omitted the `tenancy` block. + + - New `isTenancyDisabled(schema)` export from `@objectstack/spec/data` — the + single source of truth for the ADR-0066 platform-global posture, now shared by + the registry (tenant-column injection), the ObjectQL engine, and the SQL + driver. + - `ObjectQL.buildDriverOptions` no longer stamps `tenantId` for objects whose + registered schema declares `tenancy.enabled: false` (an explicitly-passed + options `tenantId` still wins — deliberate caller intent). + - `SqlDriver` (and `SqliteWasmDriver`) now keep a sticky record of an explicit + `tenancy.enabled:false` declaration: a later registration without a `tenancy` + block preserves the opt-out instead of re-scoping via the implicit + `organization_id` heuristic; a registration that carries a `tenancy` + declaration stays authoritative. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [efbcfe1] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + - @objectstack/observability@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/driver-sql/package.json b/packages/plugins/driver-sql/package.json index bc8d256ee0..6b1cc31e8f 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": "16.0.0-rc.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 595c548039..2c718cfadd 100644 --- a/packages/plugins/driver-sqlite-wasm/CHANGELOG.md +++ b/packages/plugins/driver-sqlite-wasm/CHANGELOG.md @@ -1,5 +1,52 @@ # @objectstack/driver-sqlite-wasm +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [47d923c] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [efbcfe1] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/driver-sql@16.0.0-rc.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 3f9114624d..67aebb9aca 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": "16.0.0-rc.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 cdc103da14..b8b42f8b5c 100644 --- a/packages/plugins/embedder-openai/CHANGELOG.md +++ b/packages/plugins/embedder-openai/CHANGELOG.md @@ -1,5 +1,42 @@ # @objectstack/embedder-openai +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/embedder-openai/package.json b/packages/plugins/embedder-openai/package.json index 4a0f527798..2b303ff027 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": "16.0.0-rc.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 43d9940c92..6734946a42 100644 --- a/packages/plugins/knowledge-memory/CHANGELOG.md +++ b/packages/plugins/knowledge-memory/CHANGELOG.md @@ -1,5 +1,49 @@ # @objectstack/knowledge-memory +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/service-knowledge@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/knowledge-memory/package.json b/packages/plugins/knowledge-memory/package.json index 7bae9b8f33..b4891c6ebd 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": "16.0.0-rc.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 5b08490640..904a548d24 100644 --- a/packages/plugins/knowledge-ragflow/CHANGELOG.md +++ b/packages/plugins/knowledge-ragflow/CHANGELOG.md @@ -1,5 +1,49 @@ # @objectstack/knowledge-ragflow +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/service-knowledge@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/knowledge-ragflow/package.json b/packages/plugins/knowledge-ragflow/package.json index 8c48e3a319..91294bd3e4 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": "16.0.0-rc.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 175d0f87b9..b91c738e9f 100644 --- a/packages/plugins/plugin-approvals/CHANGELOG.md +++ b/packages/plugins/plugin-approvals/CHANGELOG.md @@ -1,5 +1,110 @@ # @objectstack/plugin-approvals +## 16.0.0-rc.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 + +- 22013aa: **Split the overloaded `managedBy: 'system'` bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220).** The `system` bucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row as `better-auth`/`append-only` but, unlike `better-auth`, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap). + + Rather than add a new `managedBy` enum value (which would fall through to fully-editable `platform` defaults on already-deployed Console clients), the write policy is now the **resolved affordance** (`resolveCrudAffordances` = bucket default + `userActions`), and _engine-owned_ is defined as a `system`/`append-only` object that grants no write: + + - **Writable set declares `userActions`** — the RBAC link tables (`sys_user_position`, `sys_user_permission_set`, `sys_position_permission_set`), `sys_user_preference`, `sys_approval_delegation`, and the messaging config grids (`sys_notification_preference` / `…_subscription` / `…_template`) now declare `userActions: { create, edit, delete: true }`. The affordance is a declaration only — the `DelegatedAdminGate` / RLS / permission sets remain the authz. + - **Engine-owned objects locked to reads** — `apiMethods: ['get','list']` added where absent (jobs, notifications, approval request/approver/token/action, `sys_record_share`, `sys_automation_run`, mail/settings/secret audit, the messaging delivery pipeline). `sys_secret` is explicitly read-locked (an empty `apiMethods` array fails open). + - **`sys_import_job`** stays engine-owned: the REST import route now writes its job rows `isSystem`-elevated (attribution preserved via the explicit `created_by` stamp) and the object is locked to `['get','list']`. + - **New engine write guard** (`assertEngineOwnedWriteAllowed`, plugin-security) fail-closed rejects user-context generic writes to engine-owned `system`/`append-only` objects, keyed off the resolved affordance; `isSystem` and context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. + - **`reconcileManagedApiMethods`** (objectql registry) now runs for **every** managed bucket, not just `better-auth`: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049). + - **`/me/permissions` clamp** (plugin-hono-server) now clamps `system`/`append-only` as well as `better-auth`, so the client hint reflects `permission ∩ guard`. + + **Potentially breaking:** a downstream/third-party `system` object that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. Declare `userActions` opening the verbs the object legitimately takes from a user context. `better-auth` keeps plugin-auth's identity write guard unchanged; the row-level `managed_by` provenance vocabulary (ADR-0066) is a different axis and is untouched. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [06cb319] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + - @objectstack/metadata-core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-approvals/package.json b/packages/plugins/plugin-approvals/package.json index a16b0fb734..a78c86a793 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": "16.0.0-rc.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 d81cd2cca9..7dedd6acc1 100644 --- a/packages/plugins/plugin-audit/CHANGELOG.md +++ b/packages/plugins/plugin-audit/CHANGELOG.md @@ -1,5 +1,61 @@ # @objectstack/plugin-audit +## 16.0.0-rc.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 [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-audit/package.json b/packages/plugins/plugin-audit/package.json index 8fd3467b90..0660e75489 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": "16.0.0-rc.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 512310c0e4..9dc60fde36 100644 --- a/packages/plugins/plugin-auth/CHANGELOG.md +++ b/packages/plugins/plugin-auth/CHANGELOG.md @@ -1,5 +1,104 @@ # Changelog +## 16.0.0-rc.0 + +### Minor Changes + +- 616e839: **Bulk user import defaults to `auto` — prefer invite per row, temporary only for undeliverable rows (#3236).** The identity import endpoint (`POST /api/v1/auth/admin/import-users`) gains a fourth `passwordPolicy`, **`auto`**, and it is now the **default** (was `none`). + + `auto` decides **per row** instead of forcing one policy on the whole batch: + + - a row with a deliverable channel — a **real email + a wired email service**, or a **phone + a wired SMS-invite path** — is **invited** (a set-your-password email, or an invitation SMS for phone-only rows), so no shared secret ever leaves the server; + - a row with **no** deliverable channel (placeholder email, phone-only without SMS, or an email row when no email service is wired) falls back to a **temporary password**, returned once in the response with `must_change_password` stamped. + + This shrinks the temporary-password blast radius from "the whole batch" to "only the rows that genuinely can't be reached", and — unlike `invite` — `auto` **never rejects the request for missing infrastructure**: with nothing wired, every row simply degrades to temporary. The per-row outcome is surfaced on `rows[].delivery` (`email` / `sms` / `temporary`) with a batch breakdown on `summary.delivery` (also recorded in the run audit). + + The three existing policies are unchanged and still selectable explicitly: + + - `invite` — force the invite path for every row; unreachable rows are **failed** per-row (never downgraded). Pick this when a temporary-password fallback is unacceptable. + - `temporary` — force a generated temporary password for every row. + - `none` — identity only, no password and no invitation. + + **Behavior change to note:** callers that **omit** `passwordPolicy` previously got `none` (no credential, no outbound message); they now get `auto`, which proactively sends invitations to deliverable rows (and returns temporary passwords for the rest). Callers that want the old identity-only behavior must pass `passwordPolicy: 'none'` explicitly. Every call that already passes an explicit policy is unaffected, and the response is a strict superset (adds the `delivery` fields). + +### 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 [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/rest@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-auth/package.json b/packages/plugins/plugin-auth/package.json index 0b5f5e41ee..a13d00403d 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": "16.0.0-rc.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 7518e766d0..3d1b858179 100644 --- a/packages/plugins/plugin-dev/CHANGELOG.md +++ b/packages/plugins/plugin-dev/CHANGELOG.md @@ -1,5 +1,78 @@ # @objectstack/plugin-dev +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [b39c65d] +- Updated dependencies [f972574] +- Updated dependencies [2f3c641] +- Updated dependencies [e38da5b] +- Updated dependencies [f9b118d] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [deb7e7e] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [2ea08ee] +- Updated dependencies [d1d1c40] +- Updated dependencies [616e839] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [efbcfe1] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [a2d6555] +- Updated dependencies [3a6310c] +- Updated dependencies [32899e6] +- Updated dependencies [515f11a] +- Updated dependencies [4174a07] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/runtime@16.0.0-rc.0 + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/plugin-security@16.0.0-rc.0 + - @objectstack/objectql@16.0.0-rc.0 + - @objectstack/plugin-hono-server@16.0.0-rc.0 + - @objectstack/rest@16.0.0-rc.0 + - @objectstack/plugin-auth@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + - @objectstack/account@16.0.0-rc.0 + - @objectstack/setup@16.0.0-rc.0 + - @objectstack/driver-memory@16.0.0-rc.0 + - @objectstack/service-i18n@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-dev/package.json b/packages/plugins/plugin-dev/package.json index f2e8de407b..4783a35938 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": "16.0.0-rc.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 870b32c090..ad6778d852 100644 --- a/packages/plugins/plugin-email/CHANGELOG.md +++ b/packages/plugins/plugin-email/CHANGELOG.md @@ -1,5 +1,54 @@ # @objectstack/plugin-email +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-email/package.json b/packages/plugins/plugin-email/package.json index 7b390bc8e3..96fe7f9ebb 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": "16.0.0-rc.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 bf5b9adeca..2f35acd15e 100644 --- a/packages/plugins/plugin-hono-server/CHANGELOG.md +++ b/packages/plugins/plugin-hono-server/CHANGELOG.md @@ -1,5 +1,132 @@ # @objectstack/plugin-hono-server +## 16.0.0-rc.0 + +### Minor Changes + +- 22013aa: **Split the overloaded `managedBy: 'system'` bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220).** The `system` bucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row as `better-auth`/`append-only` but, unlike `better-auth`, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap). + + Rather than add a new `managedBy` enum value (which would fall through to fully-editable `platform` defaults on already-deployed Console clients), the write policy is now the **resolved affordance** (`resolveCrudAffordances` = bucket default + `userActions`), and _engine-owned_ is defined as a `system`/`append-only` object that grants no write: + + - **Writable set declares `userActions`** — the RBAC link tables (`sys_user_position`, `sys_user_permission_set`, `sys_position_permission_set`), `sys_user_preference`, `sys_approval_delegation`, and the messaging config grids (`sys_notification_preference` / `…_subscription` / `…_template`) now declare `userActions: { create, edit, delete: true }`. The affordance is a declaration only — the `DelegatedAdminGate` / RLS / permission sets remain the authz. + - **Engine-owned objects locked to reads** — `apiMethods: ['get','list']` added where absent (jobs, notifications, approval request/approver/token/action, `sys_record_share`, `sys_automation_run`, mail/settings/secret audit, the messaging delivery pipeline). `sys_secret` is explicitly read-locked (an empty `apiMethods` array fails open). + - **`sys_import_job`** stays engine-owned: the REST import route now writes its job rows `isSystem`-elevated (attribution preserved via the explicit `created_by` stamp) and the object is locked to `['get','list']`. + - **New engine write guard** (`assertEngineOwnedWriteAllowed`, plugin-security) fail-closed rejects user-context generic writes to engine-owned `system`/`append-only` objects, keyed off the resolved affordance; `isSystem` and context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. + - **`reconcileManagedApiMethods`** (objectql registry) now runs for **every** managed bucket, not just `better-auth`: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049). + - **`/me/permissions` clamp** (plugin-hono-server) now clamps `system`/`append-only` as well as `better-auth`, so the client hint reflects `permission ∩ guard`. + + **Potentially breaking:** a downstream/third-party `system` object that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. Declare `userActions` opening the verbs the object legitimately takes from a user context. `better-auth` keeps plugin-auth's identity write guard unchanged; the row-level `managed_by` provenance vocabulary (ADR-0066) is a different axis and is untouched. + +- efbcfe1: feat(observability): admin-only richer per-request timing detail via `X-OS-Debug-Timing: json` (#2408) + + Completes the optional "richer JSON" diagnostic from #2408. In addition to the + basic `Server-Timing` header, an admin/service caller can now request a + per-query breakdown — the slowest SQL statements and a query count — by sending + `X-OS-Debug-Timing: json`. The detail is returned in a separate + `X-OS-Debug-Timing-Detail` response header (compact JSON) and is **admin-only, + even under global mode**: an ordinary caller never sees SQL shapes. + + - **observability**: `PerfTiming` gains opt-in per-event detail capture + (`enableDetail` / `recordDetail` / `details`) plus the ambient + `recordServerTimingDetail`. The disclosure gate gains a `privileged` level + (set by `allowPerfDisclosure`, read via `isPerfDisclosurePrivileged`) so the + richer detail can be gated independently of the basic header. + - **driver-sql**: when detail capture is on, the query listener additionally + records each query's **parametrized** statement (knex's `q.sql`, `?` + placeholders) — never the bindings, so no literal row value ever enters the + collector. Zero overhead when detail is off. + - **plugin-hono-server**: `X-OS-Debug-Timing: json` enables detail capture; the + middleware emits `X-OS-Debug-Timing-Detail` (slowest queries, capped and + sanitized to header-safe ASCII) only when the principal is a proven admin. + + Basic and global behavior are unchanged; `json` is purely additive. + +- 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 [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [efbcfe1] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + - @objectstack/observability@16.0.0-rc.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 f00dbcbb87..281aff6486 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": "16.0.0-rc.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 ceb7d22fa1..91eb03791b 100644 --- a/packages/plugins/plugin-pinyin-search/CHANGELOG.md +++ b/packages/plugins/plugin-pinyin-search/CHANGELOG.md @@ -1,5 +1,33 @@ # @objectstack/plugin-pinyin-search +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [22013aa] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [fdc244e] +- Updated dependencies [dd9f223] +- Updated dependencies [2ea08ee] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [86d30af] +- Updated dependencies [2018df9] + - @objectstack/objectql@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.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 abcc26ce43..695f05fefd 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": "16.0.0-rc.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 d6294a3b99..f95fc92dad 100644 --- a/packages/plugins/plugin-reports/CHANGELOG.md +++ b/packages/plugins/plugin-reports/CHANGELOG.md @@ -1,5 +1,50 @@ # @objectstack/plugin-reports +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-reports/package.json b/packages/plugins/plugin-reports/package.json index 33c99eeecf..05d4096474 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": "16.0.0-rc.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 962f205071..f8adf6d85e 100644 --- a/packages/plugins/plugin-security/CHANGELOG.md +++ b/packages/plugins/plugin-security/CHANGELOG.md @@ -1,5 +1,77 @@ # @objectstack/plugin-security +## 16.0.0-rc.0 + +### Minor Changes + +- 22013aa: **Split the overloaded `managedBy: 'system'` bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220).** The `system` bucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row as `better-auth`/`append-only` but, unlike `better-auth`, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap). + + Rather than add a new `managedBy` enum value (which would fall through to fully-editable `platform` defaults on already-deployed Console clients), the write policy is now the **resolved affordance** (`resolveCrudAffordances` = bucket default + `userActions`), and _engine-owned_ is defined as a `system`/`append-only` object that grants no write: + + - **Writable set declares `userActions`** — the RBAC link tables (`sys_user_position`, `sys_user_permission_set`, `sys_position_permission_set`), `sys_user_preference`, `sys_approval_delegation`, and the messaging config grids (`sys_notification_preference` / `…_subscription` / `…_template`) now declare `userActions: { create, edit, delete: true }`. The affordance is a declaration only — the `DelegatedAdminGate` / RLS / permission sets remain the authz. + - **Engine-owned objects locked to reads** — `apiMethods: ['get','list']` added where absent (jobs, notifications, approval request/approver/token/action, `sys_record_share`, `sys_automation_run`, mail/settings/secret audit, the messaging delivery pipeline). `sys_secret` is explicitly read-locked (an empty `apiMethods` array fails open). + - **`sys_import_job`** stays engine-owned: the REST import route now writes its job rows `isSystem`-elevated (attribution preserved via the explicit `created_by` stamp) and the object is locked to `['get','list']`. + - **New engine write guard** (`assertEngineOwnedWriteAllowed`, plugin-security) fail-closed rejects user-context generic writes to engine-owned `system`/`append-only` objects, keyed off the resolved affordance; `isSystem` and context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. + - **`reconcileManagedApiMethods`** (objectql registry) now runs for **every** managed bucket, not just `better-auth`: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049). + - **`/me/permissions` clamp** (plugin-hono-server) now clamps `system`/`append-only` as well as `better-auth`, so the client hint reflects `permission ∩ guard`. + + **Potentially breaking:** a downstream/third-party `system` object that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. Declare `userActions` opening the verbs the object legitimately takes from a user context. `better-auth` keeps plugin-auth's identity write guard unchanged; the row-level `managed_by` provenance vocabulary (ADR-0066) is a different axis and is untouched. + +### Patch Changes + +- 2f3c641: ADR-0099 P0: land the probe-vs-carried-rung equivalence gate in the authz matrix (`authz-matrix-gate.test.ts`) — seeded-shape equivalence cells, two adversarial `KNOWN DIVERGENCE` pins (scoped `admin_full_access` grant; piecemeal platform-exclusive capability), the I2 nesting and I3 narrowing invariant cells, posture-blindness staging pins for the P1 flip, and the EXTERNAL dead-branch cell. Extracts the platform-admin capability probe as the exported pure `hasPlatformAdminCapability` (mechanical, behavior unchanged). Test-only gate; the ADR-0099 P1 flip lands behind it (#3211). +- e38da5b: ADR-0099 P1 (#3211 M2): the Layer 0 cross-tenant exemption gate now reads the carried `ctx.posture` rung (#2956) as authoritative, with the platform-admin capability probe demoted to a fallback for resolver-less contexts (delegated-admin bridge, sharing service, `getReadFilter`). The read and write (insert/update post-image) tenant checks share one decision (`computeLayeredRlsFilter`), so they cannot drift. A probe↔rung disagreement logs a defect breadcrumb and enforces the narrower rung verdict. + + **Behavior change (security narrowing, multi-org / `@objectstack/organizations` only):** a principal whose carried rung is not `PLATFORM_ADMIN` no longer crosses the tenant wall on private / platform-global / better-auth-managed objects, even when its resolved permission sets carry a platform-exclusive capability. Two shapes are affected: (a) a **scoped** `admin_full_access` grant (`sys_user_permission_set.organization_id` non-null), and (b) a custom set granting a platform capability (e.g. `studio.access`) piecemeal alongside a superuser bit. Both are now walled to their own org — the fail-safe direction (the carried rung is a strict subset of the probe). Single-org / env-per-database deployments are unaffected (Layer 0 is inert). + + **Upgrade check:** before upgrading, scan `sys_user_permission_set` for `admin_full_access` rows with a non-null `organization_id`, and custom permission sets whose `systemPermissions` intersect `{manage_metadata, manage_platform_settings, studio.access, manage_users}`. To restore cross-tenant operator access for such a principal, grant the **unscoped** `admin_full_access` instead. The `[authz/ADR-0099]` warn log names any principal hitting the divergence at runtime. + +- f9b118d: ADR-0099 P2′ (#3211 M3′): pin the two-axis Amendment in the authz matrix. The original P2 (collapse the Layer 1 tier onto posture) was rejected — Layer 1's tier input is the per-object super-bit, a per-principal × per-object delegation primitive posture cannot represent. New cells pin: seeded-face agreement (seeded super-bit holders are already ≥ TENANT_ADMIN), the load-bearing delegation cell (a MEMBER with a delegated per-object `viewAllRecords`/`modifyAllRecords` short-circuits Layer 1 yet stays walled by Layer 0 — the auditor pattern), invariant I7 (the scope axis never crosses a boundary posture has not opened), and the contrast that the bit is a real grantable capability, not conditionally inert. Test-only; zero behavior change. +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-security/package.json b/packages/plugins/plugin-security/package.json index fe02c5091b..5edd94b60d 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": "16.0.0-rc.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 73ffc162db..4a0100055b 100644 --- a/packages/plugins/plugin-sharing/CHANGELOG.md +++ b/packages/plugins/plugin-sharing/CHANGELOG.md @@ -1,5 +1,70 @@ # @objectstack/plugin-sharing +## 16.0.0-rc.0 + +### Patch Changes + +- 22013aa: **Split the overloaded `managedBy: 'system'` bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220).** The `system` bucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row as `better-auth`/`append-only` but, unlike `better-auth`, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap). + + Rather than add a new `managedBy` enum value (which would fall through to fully-editable `platform` defaults on already-deployed Console clients), the write policy is now the **resolved affordance** (`resolveCrudAffordances` = bucket default + `userActions`), and _engine-owned_ is defined as a `system`/`append-only` object that grants no write: + + - **Writable set declares `userActions`** — the RBAC link tables (`sys_user_position`, `sys_user_permission_set`, `sys_position_permission_set`), `sys_user_preference`, `sys_approval_delegation`, and the messaging config grids (`sys_notification_preference` / `…_subscription` / `…_template`) now declare `userActions: { create, edit, delete: true }`. The affordance is a declaration only — the `DelegatedAdminGate` / RLS / permission sets remain the authz. + - **Engine-owned objects locked to reads** — `apiMethods: ['get','list']` added where absent (jobs, notifications, approval request/approver/token/action, `sys_record_share`, `sys_automation_run`, mail/settings/secret audit, the messaging delivery pipeline). `sys_secret` is explicitly read-locked (an empty `apiMethods` array fails open). + - **`sys_import_job`** stays engine-owned: the REST import route now writes its job rows `isSystem`-elevated (attribution preserved via the explicit `created_by` stamp) and the object is locked to `['get','list']`. + - **New engine write guard** (`assertEngineOwnedWriteAllowed`, plugin-security) fail-closed rejects user-context generic writes to engine-owned `system`/`append-only` objects, keyed off the resolved affordance; `isSystem` and context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. + - **`reconcileManagedApiMethods`** (objectql registry) now runs for **every** managed bucket, not just `better-auth`: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049). + - **`/me/permissions` clamp** (plugin-hono-server) now clamps `system`/`append-only` as well as `better-auth`, so the client hint reflects `permission ∩ guard`. + + **Potentially breaking:** a downstream/third-party `system` object that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. Declare `userActions` opening the verbs the object legitimately takes from a user context. `better-auth` keeps plugin-auth's identity write guard unchanged; the row-level `managed_by` provenance vocabulary (ADR-0066) is a different axis and is untouched. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [2ea08ee] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/objectql@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-sharing/package.json b/packages/plugins/plugin-sharing/package.json index 18db7193c2..010368616b 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": "16.0.0-rc.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 9d6857b330..1ef1e611f7 100644 --- a/packages/plugins/plugin-webhooks/CHANGELOG.md +++ b/packages/plugins/plugin-webhooks/CHANGELOG.md @@ -1,5 +1,56 @@ # @objectstack/plugin-webhooks +## 16.0.0-rc.0 + +### Patch Changes + +- 4b6fde8: Trim the dead `undelete` and `api` webhook triggers (#3196). `WebhookTriggerType` declared five triggers but only three ever fired: + + - `undelete` had no event source — the engine has no soft-delete/restore capability (`delete` is a hard delete; no `deleted_at` convention, no restore operation, and `data.record.undeleted` is never emitted). The `undeleted` case in the auto-enqueuer's action mapper was dead code awaiting a producer that doesn't exist. + - `api` ("manually triggered") had no fire path — the only webhook HTTP surface re-queues already-failed deliveries; nothing originates a manual fire. + + Both are removed from the enum (contract-first, matching #3184/#3195): authoring a webhook on a removed trigger now fails loudly at `os validate` / registration instead of registering a webhook that silently never fires. No shipped webhook metadata used either. The auto-enqueuer now also warns when a persisted `sys_webhook` row carries a trigger it can't map to an emitted record event (a drift-guard, so a dead trigger can't silently no-op again). Reintroduce `undelete` only alongside a real restore subsystem, and `api` only alongside a real manual-fire endpoint. Updated the `sys_webhook` trigger options, field help (all locales), docs, and reference; added rejection tests. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/service-messaging@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/plugins/plugin-webhooks/package.json b/packages/plugins/plugin-webhooks/package.json index 50ca71adda..33b01ba2c7 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": "16.0.0-rc.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 0fc1206592..d61208b6a2 100644 --- a/packages/qa/dogfood/CHANGELOG.md +++ b/packages/qa/dogfood/CHANGELOG.md @@ -1,5 +1,66 @@ # @objectstack/dogfood +## 0.0.38-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [41e703b] +- Updated dependencies [2f3c641] +- Updated dependencies [e38da5b] +- Updated dependencies [f9b118d] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [deb7e7e] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [2ea08ee] +- Updated dependencies [616e839] +- Updated dependencies [158aa14] +- Updated dependencies [15dbe18] +- Updated dependencies [83e8f7d] +- Updated dependencies [230358c] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/connector-openapi@16.0.0-rc.0 + - @objectstack/plugin-security@16.0.0-rc.0 + - @objectstack/objectql@16.0.0-rc.0 + - @objectstack/plugin-auth@16.0.0-rc.0 + - @objectstack/plugin-audit@16.0.0-rc.0 + - @objectstack/mcp@16.0.0-rc.0 + - @objectstack/example-crm@4.0.90-rc.0 + - @objectstack/example-showcase@0.3.12-rc.0 + - @objectstack/verify@16.0.0-rc.0 + - @objectstack/connector-mcp@16.0.0-rc.0 + - @objectstack/connector-rest@16.0.0-rc.0 + - @objectstack/service-storage@16.0.0-rc.0 + ## 0.0.37 ### Patch Changes diff --git a/packages/qa/dogfood/package.json b/packages/qa/dogfood/package.json index bc9ccdd6a8..f4f1cd7d2a 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-rc.0", "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 4131a65d93..a9c9f1db94 100644 --- a/packages/qa/downstream-contract/CHANGELOG.md +++ b/packages/qa/downstream-contract/CHANGELOG.md @@ -1,5 +1,42 @@ # @objectstack/downstream-contract +## 0.0.36-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + ## 0.0.35 ### Patch Changes diff --git a/packages/qa/downstream-contract/package.json b/packages/qa/downstream-contract/package.json index 369735b932..9b269ac477 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-rc.0", "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 87f20efdf8..d98e18f9be 100644 --- a/packages/qa/http-conformance/CHANGELOG.md +++ b/packages/qa/http-conformance/CHANGELOG.md @@ -1,5 +1,16 @@ # @objectstack/http-conformance +## 0.0.4-rc.0 + +### Patch Changes + +- Updated dependencies [e057f42] +- Updated dependencies [dd9f223] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [290e2f0] + - @objectstack/core@16.0.0-rc.0 + ## 0.0.3 ### Patch Changes diff --git a/packages/qa/http-conformance/package.json b/packages/qa/http-conformance/package.json index 8b38ebfa6c..566c15c436 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-rc.0", "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 5f6f620837..0994f3cfab 100644 --- a/packages/rest/CHANGELOG.md +++ b/packages/rest/CHANGELOG.md @@ -1,5 +1,124 @@ # @objectstack/rest +## 16.0.0-rc.0 + +### Patch Changes + +- 22013aa: **Split the overloaded `managedBy: 'system'` bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220).** The `system` bucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row as `better-auth`/`append-only` but, unlike `better-auth`, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap). + + Rather than add a new `managedBy` enum value (which would fall through to fully-editable `platform` defaults on already-deployed Console clients), the write policy is now the **resolved affordance** (`resolveCrudAffordances` = bucket default + `userActions`), and _engine-owned_ is defined as a `system`/`append-only` object that grants no write: + + - **Writable set declares `userActions`** — the RBAC link tables (`sys_user_position`, `sys_user_permission_set`, `sys_position_permission_set`), `sys_user_preference`, `sys_approval_delegation`, and the messaging config grids (`sys_notification_preference` / `…_subscription` / `…_template`) now declare `userActions: { create, edit, delete: true }`. The affordance is a declaration only — the `DelegatedAdminGate` / RLS / permission sets remain the authz. + - **Engine-owned objects locked to reads** — `apiMethods: ['get','list']` added where absent (jobs, notifications, approval request/approver/token/action, `sys_record_share`, `sys_automation_run`, mail/settings/secret audit, the messaging delivery pipeline). `sys_secret` is explicitly read-locked (an empty `apiMethods` array fails open). + - **`sys_import_job`** stays engine-owned: the REST import route now writes its job rows `isSystem`-elevated (attribution preserved via the explicit `created_by` stamp) and the object is locked to `['get','list']`. + - **New engine write guard** (`assertEngineOwnedWriteAllowed`, plugin-security) fail-closed rejects user-context generic writes to engine-owned `system`/`append-only` objects, keyed off the resolved affordance; `isSystem` and context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. + - **`reconcileManagedApiMethods`** (objectql registry) now runs for **every** managed bucket, not just `better-auth`: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049). + - **`/me/permissions` clamp** (plugin-hono-server) now clamps `system`/`append-only` as well as `better-auth`, so the client hint reflects `permission ∩ guard`. + + **Potentially breaking:** a downstream/third-party `system` object that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. Declare `userActions` opening the verbs the object legitimately takes from a user context. `better-auth` keeps plugin-auth's identity write guard unchanged; the row-level `managed_by` provenance vocabulary (ADR-0066) is a different axis and is untouched. + +- 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). + +- 43a3efb: fix(rest): gate the cross-object transactional batch by the same per-object API rules as single-record writes (#1604) + + The `POST {basePath}/batch` route (issue #1604 / ADR-0034) wraps N cross-object + create/update/delete ops in one engine transaction, but it skipped the + per-object API-exposure gate every single-record route applies — an + authenticated caller could write to an `apiEnabled: false` object, or run an + operation outside an object's `apiMethods` whitelist, straight through the batch + surface (ADR-0049 / #1889 — the same "declared ≠ enforced" hole closed for the + generic write path in #3220 / #3213). + + The route now: + + - validates the body against a new `CrossObjectBatchRequestSchema` + (`@objectstack/spec/api`, Zod-First) — a malformed op, an unknown action, or a + missing `object` is a `400` instead of a `500`; + - enforces `enable.apiEnabled` / `enable.apiMethods` for **every** op (metadata + fetched once, each distinct `(object, action)` checked) BEFORE opening the + transaction — `404 OBJECT_API_DISABLED` / `405 OBJECT_API_METHOD_NOT_ALLOWED`; + - requires an `id` for `update` / `delete` (`400`); + - rejects an unresolvable `{ $ref }` with `400 BATCH_UNRESOLVED_REF` instead of + silently writing a `null` FK; + - rejects an explicit `atomic: false` (`400 BATCH_NOT_ATOMIC`) rather than + silently applying atomically — non-atomic per-object batches stay on + `POST /data/:object/batch`. + + `enforceApiAccess` is refactored to share the pure `apiAccessDenialFromEnable` + check + a `loadObjectItems` helper with the batch route (single-record behavior + unchanged). Adds `rest-batch-endpoint.test.ts` — the REST-boundary coverage + ADR-0034 flagged as missing (commit, `$ref`, rollback surfacing, API-access + denial, request validation). + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + - @objectstack/service-package@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/rest/package.json b/packages/rest/package.json index 198d14a67a..ad8c117aa5 100644 --- a/packages/rest/package.json +++ b/packages/rest/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/rest", - "version": "15.1.1", + "version": "16.0.0-rc.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 b8758efa59..f594a6f39c 100644 --- a/packages/runtime/CHANGELOG.md +++ b/packages/runtime/CHANGELOG.md @@ -1,5 +1,333 @@ # @objectstack/runtime +## 16.0.0-rc.0 + +### Major Changes + +- 6c270a6: **BREAKING: remove the deprecated `ctx.session.tenantId` / `ctx.user.tenantId` alias from the hook & action authoring surface — converge on `organizationId` (#3290).** + + #3280 made `organizationId` the blessed developer-facing name for the caller's active org across the JS authoring surface and kept `tenantId` as a `@deprecated` alias carrying the identical value. That alias is now **removed** from the hook `ctx.session`, the action-body `ctx.session`, and the action-body `ctx.user`. Read the caller's active org under the single blessed name: + + ```diff + - const org = ctx.session.tenantId; // hook or action body + + const org = ctx.user?.organizationId ?? ctx.session?.organizationId; + ``` + + **FROM → TO migration** (in any `*.hook.ts` / `*.action.ts` body): + + - `ctx.session.tenantId` → `ctx.session.organizationId` + - `ctx.user.tenantId` (action body) → `ctx.user.organizationId` + + The value is unchanged — `organizationId` is the same active-org id, matching the `organization_id` column and `current_user.organizationId` in RLS/sharing. `ctx.user` is `undefined` for system / unauthenticated writes, so read `ctx.session?.organizationId` when a hook or action must work regardless of a resolved user. + + What changed internally: + + - **`@objectstack/spec`** — `HookContextSchema.session` drops the `tenantId` field (only `organizationId` remains). A stray `tenantId` on a constructed session is now stripped by the schema. + - **`@objectstack/objectql`** — the engine's `buildSession()` no longer emits `session.tenantId`; the audit-stamp plugin sources the `tenant_id` column from `session.organizationId`. + - **`@objectstack/runtime`** — `buildActionSession()` and the REST action `ctx.user` no longer emit `tenantId`. + - **`@objectstack/trigger-record-change`** — reads `session.organizationId` (was `session.tenantId`) when forwarding the writer's org to a `runAs:'user'` flow; behavior is identical. + + **Explicit non-goal (unchanged):** the generic **driver-layer** tenancy abstraction is _not_ touched — `ExecutionContext.tenantId`, `DriverOptions.tenantId`, `SqlDriver.applyTenantScope` / `TenancyConfig.tenantField`, and `ExecutionLog.tenantId`. That isolation column is configurable and legitimately carries an _environment_ id in database-per-tenant kernels; it is a distinct axis from the developer-facing org. The build-time `check:org-identifier` guard now also covers `packages/**` to keep reference bodies off the removed name. + +### 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. + +- 92f5f19: feat(runtime): sandbox budget is script CPU-time, not wall clock (ADR-0102 D1, #3295) + + The QuickJS sandbox now meters each hook/action invocation against how much + **VM-active (CPU) time** the body burns, not wall clock. Idle host-await time and + a nested hook's own execution (which runs host-side while the caller's VM is + parked) are no longer charged to the caller — so a slow/loaded host or a deep + nested-write chain can't trip the budget while a script is merely waiting (the + root cause of the #3259 CI flake). A separate, generous **wall-clock ceiling** + (default 30s, `max(ceiling, cpuBudget)`) remains as the backstop for a body stuck + on a host call that never settles. + + What changes for consumers (behaviour, not API signatures): + + - **Meaning of the timeout knobs.** `body.timeoutMs`, the `hookTimeoutMs` / + `actionTimeoutMs` runner options, and `OS_SANDBOX_HOOK_TIMEOUT_MS` / + `OS_SANDBOX_ACTION_TIMEOUT_MS` keep their **names, defaults (250ms / 5000ms), + and precedence** — but now bound CPU-time instead of wall-clock. In practice + this only _loosens_ legitimate slow/nested work; a runaway synchronous script + is still cut at the same budget. + - **Error messages.** `exceeded timeout of Nms` → either `exceeded CPU budget of +Nms` (script burned its CPU budget) or `exceeded wall-clock ceiling of Nms +while awaiting host calls` (stuck on a never-settling host call). Update any + code/tests matching the old string. + + New knobs (additive): + + - `QuickJSScriptRunner` option `wallCeilingMs` and env `OS_SANDBOX_WALL_CEILING_MS` + — tune the wall ceiling (explicit option › env › 30s). + - `resolveSandboxTimeoutMs` (`@objectstack/types`) gains a `'wallCeiling'` kind. + + Also fixes a latent init bug in the new accounting where the interrupt handler + could fire during `installCtx` and corrupt ctx marshalling. The nested-write + integration suites now run at the stock 250ms budget (previously forced to 10s), + which is itself the regression guard for the nested-charging fix. + +- 32899e6: feat(runtime): env-overridable sandbox hook/action timeout default (#3259) + + The QuickJS sandbox enforces a wall-clock deadline on every hook/action + invocation (250ms hooks / 5000ms actions). Each invocation compiles a fresh + WASM module, and a nested hook compiles ANOTHER one inside the parent's budget, + so on a heavily loaded or slow host — an oversubscribed CI runner, constrained + production hardware — that fixed VM-creation cost alone can trip the hook + default even while the VM is still making progress. On CI this surfaced as an + intermittent `hook '…' exceeded timeout of 250ms` flake on PRs that never + touched the sandbox path. + + The per-invocation timeout DEFAULT is now resolvable from the environment via + `resolveSandboxTimeoutMs` (`@objectstack/types`), which `QuickJSScriptRunner` + consults, so an operator can raise the floor once, deployment-wide, instead of + re-tuning every call site: + + - `OS_SANDBOX_HOOK_TIMEOUT_MS` — default hook budget (ms) + - `OS_SANDBOX_ACTION_TIMEOUT_MS` — default action budget (ms) + + Precedence is unchanged: an explicit `hookTimeoutMs` / `actionTimeoutMs` passed + to the runner still wins over the env var, and a body's own declared `timeoutMs` + still wins over the resolved default (the smaller of the explicit values). Only + a positive integer is honored; unset / empty / non-numeric / non-positive keeps + the built-in 250ms / 5000ms defaults, so behaviour is byte-for-byte unchanged + when the vars are absent — production is unaffected unless it opts in. + + CI's Test Core now sets `OS_SANDBOX_HOOK_TIMEOUT_MS=10000` so the shared-runner + load flake can't recur; genuine hangs stay bounded by each test's own timeout. + +### Patch Changes + +- b39c65d: **Extend the blessed `organizationId` org name to the action-body surface (follow-up to #3280).** Hooks now teach `ctx.user.organizationId` / `ctx.session.organizationId` as the blessed name for the caller's active org; action bodies — the sibling authoring surface that shares the same sandbox runner — were left behind: the REST dispatch path exposed only `ctx.user.tenantId` (the deprecated name) and no `ctx.session` at all, and the MCP `run_action` path exposed neither. + + Both action-dispatch sites (`handleActions`, MCP `runAction`) now populate: + + - **`ctx.user.organizationId`** — the blessed name (matches the `organization_id` column and `current_user.organizationId` in RLS); `ctx.user.tenantId` is kept as a deprecated alias with the identical value on the REST path. + - **`ctx.session`** (`{ userId, organizationId, tenantId, roles? }`) — mirrors the hook `ctx.session` shape, `undefined` for a context-less / self-invoked call. + + Action bodies execute trusted (the `ctx.engine` / `ctx.api` facade bypasses RLS/FLS), so a body that must scope by org has to read it from `ctx` — now under the same name a hook author uses. Additive and behavior-preserving; the objectstack-ui skill documents the action-body `ctx` and the `organizationId` read. + +- 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. + +- d1d1c40: fix(runtime): honor a hook body's declared `timeoutMs` so nested cross-object writes aren't clamped to 250ms (#1867) + + Hook bodies run in the QuickJS sandbox with a default 250ms timeout. The runner + folded that engine default straight into `Math.min(...)` when resolving the + effective timeout, so it _always_ dominated for hooks: a body that declared a + larger `timeoutMs` (the spec permits up to 30_000ms — `ScriptBody.timeoutMs`) to + give a legitimate nested write — "when a child changes, update the parent" — + room to settle was silently clamped back to 250ms and killed mid-flight. The + declared knob was never enforced. + + The engine default is now a FALLBACK used only when no explicit timeout is + supplied, not a hard ceiling. An explicit `body.timeoutMs` (and/or an enclosing + hook/action timeout) is honored; when both are present the smaller wins. Bodies + that declare nothing still get the 250ms hook / 5000ms action default, and a + body may still LOWER its own timeout below the default. + + This clears the last reliability blocker for nested cross-object writes from + hooks — the sandbox crash itself (`memory access out of bounds`) was already + fixed by the deferred-promise host-call model — so header/rollup fields no + longer need denormalized, hand-maintained workarounds. + +- a2d6555: perf(runtime): drop asyncify — sandbox runs on the sync QuickJS variant (ADR-0102 D2, #3296) + + Phase 2 of #3275. The QuickJS sandbox switches from the asyncify build + (`newAsyncContext`) to the already-installed sync release variant + (`newQuickJSWASMModule().newContext()`), keeping one physically isolated WASM + module per invocation (ADR-0102 D2/D4). Asyncify's only justification — suspending + the WASM stack across a host call — disappeared with the #1867 deferred-promise + + pump redesign, so nothing depended on it. Wins: smaller binary, faster + compile/instantiate, faster per-instruction, and removal of an entire class of + suspended-stack failure modes. + + Also fixes a latent resource leak surfaced by the stricter sync teardown: host + `ctx.api` calls hand the VM a `vm.newPromise()` deferred that was never + `dispose()`d (the newPromise contract requires it). The asyncify build tolerated + the leak; the sync build's `JS_FreeRuntime` aborted (`Assertion failed: +list_empty`) when a context was torn down with a pending, never-settled host call + (the timeout path). Deferreds are now tracked and disposed before context + teardown. + + Memory: the sync `QuickJSWASMModule` has no `dispose()`; its WebAssembly instance + + - linear memory are GC-reclaimed when the reference is dropped. A new RSS soak + test guards that per-invocation modules don't ratchet RSS. + +- 3a6310c: perf(runtime): stop the sandbox pump loop from idle-spinning while awaiting a host call (#3233) + + The QuickJS hook/action runner drives a script's async continuations with a + pump loop that, on every iteration, yielded via `setImmediate` and then drained + the VM job queue. While the body was only _waiting_ on an in-flight host promise + (a slow `ctx.api` read/write, or one call that settles after many event-loop + turns), that queue was empty every iteration, so the loop woke ~200k times/sec + doing nothing — a ~50,000-iteration burn for a 250ms wait. + + The yield is now adaptive: it stays on `setImmediate` (near-zero latency) while + the script is making progress, and once a pump executes zero VM jobs it ramps up + to a small capped `setTimeout` (≤8ms). Any executed job — a settled host call, a + resumed continuation — resets it to the fast path, so sequential host calls and + multi-turn work keep their low latency; only a genuinely idle wait backs off. + Deadline enforcement and every existing pump-budget/timeout/transaction + guarantee are unchanged. + +- 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). + +- 4174a07: feat(runtime): seed-replayer reports `skipped` so hosts can stamp seed-once on progress + + The `seed-replayer` kernel service returned `{ inserted, updated, errors }` but + not `skipped`. A cloud host therefore could not tell an **all-skip replay** + (the env's seed data is already present — a no-op) apart from the + zero-summary early-returns that never ran the loader (no organization, no + metadata service, no datasets). Both looked like `inserted = updated = 0`, so + the host could not safely stamp its seed-once record for the all-skip case and + re-ran the full remote replay on every cold boot. + + Add `skipped: result.summary.totalSkipped` to the replayer's return; the + early-returns report `skipped: 0`. This lets a host (cloud#853's + `decideSeedStamp`) stamp on progress — including an all-skip replay — while + still declining to stamp a genuine no-loader zero-summary. Additive and + backward compatible; existing consumers ignore the new field. + +- 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 [f972574] +- Updated dependencies [2f3c641] +- Updated dependencies [e38da5b] +- Updated dependencies [f9b118d] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [deb7e7e] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [47d923c] +- Updated dependencies [46e876c] +- Updated dependencies [2ea08ee] +- Updated dependencies [616e839] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [efbcfe1] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [06cb319] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/plugin-security@16.0.0-rc.0 + - @objectstack/objectql@16.0.0-rc.0 + - @objectstack/rest@16.0.0-rc.0 + - @objectstack/plugin-auth@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + - @objectstack/metadata@16.0.0-rc.0 + - @objectstack/driver-sql@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + - @objectstack/observability@16.0.0-rc.0 + - @objectstack/metadata-core@16.0.0-rc.0 + - @objectstack/driver-memory@16.0.0-rc.0 + - @objectstack/driver-sqlite-wasm@16.0.0-rc.0 + - @objectstack/service-cluster@16.0.0-rc.0 + - @objectstack/service-datasource@16.0.0-rc.0 + - @objectstack/service-i18n@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 5db5da222f..b717b3ef25 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/runtime", - "version": "15.1.1", + "version": "16.0.0-rc.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 2910f03c25..24b7615fd1 100644 --- a/packages/sdui-parser/CHANGELOG.md +++ b/packages/sdui-parser/CHANGELOG.md @@ -1,5 +1,7 @@ # @objectstack/sdui-parser +## 16.0.0-rc.0 + ## 15.1.1 ## 15.1.0 diff --git a/packages/sdui-parser/package.json b/packages/sdui-parser/package.json index 9a09d7ea9f..bbd2d4871d 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": "16.0.0-rc.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 63f87fc1f7..5d9cc28a1c 100644 --- a/packages/services/service-analytics/CHANGELOG.md +++ b/packages/services/service-analytics/CHANGELOG.md @@ -1,5 +1,97 @@ # Changelog — @objectstack/service-analytics +## 16.0.0-rc.0 + +### Minor Changes + +- a9459e6: Analytics drill metadata now snapshots raw grouped values for totals/subtotal rows too (#3214). The ADR-0021 D2 drill sidecar (`drillRawRows`, #2080) only covered `result.rows`, but the totals rows added in #1753 carry dimension values and go through the same label resolution — which overwrote their stored value (select option value, lookup/master_detail FK id) with the display label, leaving a subtotal drill nothing to exact-match on. + + `queryDataset` now also emits `drillRawTotals`, aligned to `result.totals` by index (`drillRawTotals[i][j]` ↔ `result.totals[i].rows[j]`), captured in the same pre-label-resolution pass. Each map is restricted to the drillable dimensions the grouping actually groups by, so the grand-total grouping (`[]`) contributes an empty map per row. Purely additive result props (same as #2080) — no spec-contract change. + +- dd9f223: feat(analytics): scope a datetime date-bucket drill to the reference-tz midnight instants (#1752 follow-up) + + Closes the one gap left by the initial #1752 change: a `datetime` date dimension + bucketed under a **non-UTC reference timezone** previously fell back to a superset + drill (its bucket boundary is that tz's midnight _instant_, which `YYYY-MM-DD` + calendar bounds can't express). + + - **`@objectstack/core`** adds `zonedDateStartToUtcMs(ymd, tz)` — the UTC instant + at which a calendar day begins in a reference timezone (the inverse of + `calendarPartsInTz`). DST-safe: the offset is read from the platform tz + database via `Intl`, with a two-pass resolution for the rare offset-boundary + case; an unset/`'UTC'`/invalid zone returns plain UTC midnight. + - **`@objectstack/service-analytics`** now emits `drillRanges` bounds per the + field's temporal type (ADR-0053): a `datetime` field → ISO **instant** bounds + at the reference tz's midnight (works under any tz, incl. DST); a `date` field + → `YYYY-MM-DD` calendar bounds (tz-naive, exact under any tz). An unknown field + type is still emitted only under UTC and omitted (superset) under a non-UTC tz. + + No objectui change is needed — the client already forwards whatever bound values + the server sends into the drill filter and the `filter[field][gte|lt]` URL. + +- 290e2f0: feat(analytics): emit a half-open date-range drill scope for granularity-bucketed date dimensions (#1752) + + A report/dashboard cell grouped by a `dateGranularity` date dimension ("2026-Q2") + covers a SPAN of records, so drilling it needs a range (`>= start AND < nextStart`), + which the equality drill contract (`drillRawRows`) can't express — date dims were + therefore excluded from drill metadata and a drill landed on an unscoped superset. + + - **`@objectstack/core`** adds `bucketKeyToCalendarRange(key, granularity)`, the + inverse of `bucketDateValue`: it turns a canonical bucket key into its half-open + `[start, end)` calendar span (`YYYY-MM-DD`, `end` exclusive). Pure, timezone-naive + calendar arithmetic; returns `null` for unbucketable / out-of-range keys so the + caller falls back to an unscoped (superset) drill rather than emit a wrong bound. + - **`@objectstack/service-analytics`** emits a `drillRanges` sidecar (aligned to + `rows` by index — the range companion to `drillRawRows`) for `date` + + `dateGranularity` dimensions, computed from the canonical bucket key in the + pre-label-resolution snapshot pass. A `datetime` field under a non-UTC reference + timezone is omitted (host drills a superset) until instant-boundary support + lands; a tz-naive `date` field is exact under any timezone (ADR-0053). + + Consumed by objectui's report drill-through to scope the drilled record list to the + clicked time bucket. + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-analytics/package.json b/packages/services/service-analytics/package.json index 829ad7ed8b..aab8ce427e 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": "16.0.0-rc.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 1f628944dd..1c691beaa1 100644 --- a/packages/services/service-automation/CHANGELOG.md +++ b/packages/services/service-automation/CHANGELOG.md @@ -1,5 +1,194 @@ # @objectstack/service-automation +## 16.0.0-rc.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. + +- 1e145eb: fix(automation): region-aware run-history compaction keeps loop containers + early failures (#3234) + + `compactStepsForHistory` bounded a terminal run's persisted step log to the last + `MAX_PERSISTED_HISTORY_STEPS` entries with a plain tail-slice. With the ADR-0031 + structured-region step logs (#1505) a single `loop` can emit + `iterations × body-steps` entries, so the tail-slice dropped the + `loop`/`parallel`/`try_catch` **container** step (it precedes all its body steps) + and every early iteration — leaving `getRun`/`listRuns` (after a process restart + or ring-buffer eviction) with body steps the Runs surface could no longer nest, + and silently hiding an early failure. + + Compaction is now region-aware (new exported `compactStepLogForHistory`): over + budget it keeps the run's structural backbone — every top-level step (including + the region container steps) and every failure, each pulled in with its ancestor + container chain — plus the most recent body steps, order-preserving and + hard-capped at `max` so `steps_json` stays bounded (#2585). Every retained body + step keeps its enclosing container(s), so the compacted log never contains an + orphan and the observability surface's per-iteration / per-region nesting still + reconstructs. + +- a2795f6: feat(triggers): declarative time-relative trigger — daily sweep instead of fragile date-equality (#1874) + + Time-relative business rules ("alert 60 days before a contract's `end_date`") + could only be expressed as a `record_change` flow gated on a date-equality + condition like `end_date == daysFromNow(60)`. That predicate is only evaluated + when the record _happens to change_, so it fires only if a record is edited on + exactly the threshold day — i.e. almost never, unattended. The robust + alternative was a hand-written cron + range query that every author + re-implemented (contracts `renewal_alert`, hr `document_expiring_soon`, + procurement `po_overdue`, …). + + A flow's start node can now declare a `timeRelative` descriptor instead: + + ```ts + config: { + timeRelative: { + object: 'contracts', + dateField: 'end_date', + offsetDays: [60, 30, 7], // T-minus reminders — fires on each threshold day + // — or — withinDays: 30 // "expiring soon" range; negative = overdue lookback + filter: { status: 'active' }, // optional, ANDed with the date window + }, + schedule: { type: 'cron', expression: '0 8 * * *' }, // optional; defaults to daily 08:00 UTC + } + ``` + + The new `time_relative` trigger (shipped in `@objectstack/trigger-schedule` as + `TimeRelativeTriggerPlugin`) sweeps the object on that schedule and launches the + flow **once per matching record**, with the record on the automation context — + so the start-node `condition` gate and `{record.}` interpolation work + exactly as for a record-change flow. Because the window is evaluated every day, + a threshold is never missed regardless of when the record last changed. The + discovery query runs as a system operation (RLS-bypassing) and is capped + (`maxRecords`, default 1000) so a mis-scoped window can't fan out unboundedly; + per-record failures are isolated so one bad row never aborts the sweep. + + The automation engine routes a start node carrying `config.timeRelative` to the + `time_relative` trigger (ahead of the plain `schedule` trigger, whose behavior is + unchanged), and `os validate` gains readiness checks for the new descriptor + (unknown swept object, ambiguous draft status). New authorable spec key: + `TimeRelativeTriggerSchema` (`@objectstack/spec/automation`). + +### Patch Changes + +- 22013aa: **Split the overloaded `managedBy: 'system'` bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220).** The `system` bucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row as `better-auth`/`append-only` but, unlike `better-auth`, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap). + + Rather than add a new `managedBy` enum value (which would fall through to fully-editable `platform` defaults on already-deployed Console clients), the write policy is now the **resolved affordance** (`resolveCrudAffordances` = bucket default + `userActions`), and _engine-owned_ is defined as a `system`/`append-only` object that grants no write: + + - **Writable set declares `userActions`** — the RBAC link tables (`sys_user_position`, `sys_user_permission_set`, `sys_position_permission_set`), `sys_user_preference`, `sys_approval_delegation`, and the messaging config grids (`sys_notification_preference` / `…_subscription` / `…_template`) now declare `userActions: { create, edit, delete: true }`. The affordance is a declaration only — the `DelegatedAdminGate` / RLS / permission sets remain the authz. + - **Engine-owned objects locked to reads** — `apiMethods: ['get','list']` added where absent (jobs, notifications, approval request/approver/token/action, `sys_record_share`, `sys_automation_run`, mail/settings/secret audit, the messaging delivery pipeline). `sys_secret` is explicitly read-locked (an empty `apiMethods` array fails open). + - **`sys_import_job`** stays engine-owned: the REST import route now writes its job rows `isSystem`-elevated (attribution preserved via the explicit `created_by` stamp) and the object is locked to `['get','list']`. + - **New engine write guard** (`assertEngineOwnedWriteAllowed`, plugin-security) fail-closed rejects user-context generic writes to engine-owned `system`/`append-only` objects, keyed off the resolved affordance; `isSystem` and context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. + - **`reconcileManagedApiMethods`** (objectql registry) now runs for **every** managed bucket, not just `better-auth`: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049). + - **`/me/permissions` clamp** (plugin-hono-server) now clamps `system`/`append-only` as well as `better-auth`, so the client hint reflects `permission ∩ guard`. + + **Potentially breaking:** a downstream/third-party `system` object that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. Declare `userActions` opening the verbs the object legitimately takes from a user context. `better-auth` keeps plugin-auth's identity write guard unchanged; the row-level `managed_by` provenance vocabulary (ADR-0066) is a different axis and is untouched. + +- 02eafa5: test(automation): end-to-end coverage for the #1928 object-schema resolver wiring + + Adds a kernel-level integration test proving `AutomationServicePlugin` bridges + the engine's object-schema resolver to the live `objectql.registry.getObject` at + `start()` (fields + types resolved from the registry), and that a flow + registered through the running kernel with a text field misused in arithmetic + emits the tier-4 advisory — while a sound condition stays quiet. Locks in the + production integration point that the engine-level unit tests (which set the + resolver by hand) could not exercise. Test-only; no behavior change. + +- 158aa14: feat(automation): mark the loop `collection` config field as an interpolate() template so designer forms render it correctly (#3304) + + The flow designer generates a node's config form from its published + `configSchema` (ADR-0018). A string property can now carry an `xExpression: +'expression' | 'template'` marker — riding the same Zod `.meta()` → JSON-Schema + channel as `xRef` / `xEnumDeprecated` — that declares whether the string is bare + CEL or an `interpolate()` single-brace `{var}` template. + + The `loop` node's `collection` (e.g. `{tasks}`) is a template, so it is now + marked `xExpression: 'template'` on both the canonical `LoopConfigSchema` and the + shipped descriptor's `configSchema` literal (service-automation loop-node). + Without the marker the designer rendered `collection` as plain text online while + the offline hardcoded form rendered it as a mono expression editor, and the CEL + brace-trap false-flagged `{tasks}` as a malformed condition. The marker closes + that divergence — objectui #2670 Phase 3 (#2699) already consumes it. + + Additive and backward-compatible: an unknown `xExpression` value is ignored by + the designer, and runtime behavior is unchanged. Filling the same marker in on + the remaining node types (map/decision/script and the node types that publish no + `configSchema` yet) is tracked as follow-up in #3304. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [6b51346] +- Updated dependencies [80273c8] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [ea32ec7] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/formula@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-automation/package.json b/packages/services/service-automation/package.json index b3137144f9..ea164bab20 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": "16.0.0-rc.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 61baaf03e8..4a5f3319a2 100644 --- a/packages/services/service-cache/CHANGELOG.md +++ b/packages/services/service-cache/CHANGELOG.md @@ -1,5 +1,52 @@ # @objectstack/service-cache +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [efbcfe1] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/observability@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-cache/package.json b/packages/services/service-cache/package.json index 7500aa04eb..e3e7c46dc8 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": "16.0.0-rc.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 8065a40637..b24e98e53e 100644 --- a/packages/services/service-cluster-redis/CHANGELOG.md +++ b/packages/services/service-cluster-redis/CHANGELOG.md @@ -1,5 +1,43 @@ # @objectstack/service-cluster-redis +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/service-cluster@16.0.0-rc.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 45551ff9a2..84eae4a040 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": "16.0.0-rc.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 bf1465ec24..a4f49712d8 100644 --- a/packages/services/service-cluster/CHANGELOG.md +++ b/packages/services/service-cluster/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/service-cluster +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-cluster/package.json b/packages/services/service-cluster/package.json index 338d6adefd..6bdbd78a25 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": "16.0.0-rc.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 e6ec900082..3809e19b29 100644 --- a/packages/services/service-datasource/CHANGELOG.md +++ b/packages/services/service-datasource/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/service-external-datasource +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-datasource/package.json b/packages/services/service-datasource/package.json index 2ba847fc2b..12f85d5c0d 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": "16.0.0-rc.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 49133dc215..6e798a8be8 100644 --- a/packages/services/service-i18n/CHANGELOG.md +++ b/packages/services/service-i18n/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/service-i18n +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-i18n/package.json b/packages/services/service-i18n/package.json index 00a44cf1f3..5864ac8f3f 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": "16.0.0-rc.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 d9b2004e69..c13e35320c 100644 --- a/packages/services/service-job/CHANGELOG.md +++ b/packages/services/service-job/CHANGELOG.md @@ -1,5 +1,50 @@ # @objectstack/service-job +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-job/package.json b/packages/services/service-job/package.json index 0e0e855e24..06899f1e71 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": "16.0.0-rc.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 fc378329e1..439718d689 100644 --- a/packages/services/service-knowledge/CHANGELOG.md +++ b/packages/services/service-knowledge/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/service-knowledge +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-knowledge/package.json b/packages/services/service-knowledge/package.json index 76d448edc3..9883e82507 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": "16.0.0-rc.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 ffcf31e255..99fdd7a9d4 100644 --- a/packages/services/service-messaging/CHANGELOG.md +++ b/packages/services/service-messaging/CHANGELOG.md @@ -1,5 +1,61 @@ # @objectstack/service-messaging +## 16.0.0-rc.0 + +### Patch Changes + +- 22013aa: **Split the overloaded `managedBy: 'system'` bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220).** The `system` bucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row as `better-auth`/`append-only` but, unlike `better-auth`, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap). + + Rather than add a new `managedBy` enum value (which would fall through to fully-editable `platform` defaults on already-deployed Console clients), the write policy is now the **resolved affordance** (`resolveCrudAffordances` = bucket default + `userActions`), and _engine-owned_ is defined as a `system`/`append-only` object that grants no write: + + - **Writable set declares `userActions`** — the RBAC link tables (`sys_user_position`, `sys_user_permission_set`, `sys_position_permission_set`), `sys_user_preference`, `sys_approval_delegation`, and the messaging config grids (`sys_notification_preference` / `…_subscription` / `…_template`) now declare `userActions: { create, edit, delete: true }`. The affordance is a declaration only — the `DelegatedAdminGate` / RLS / permission sets remain the authz. + - **Engine-owned objects locked to reads** — `apiMethods: ['get','list']` added where absent (jobs, notifications, approval request/approver/token/action, `sys_record_share`, `sys_automation_run`, mail/settings/secret audit, the messaging delivery pipeline). `sys_secret` is explicitly read-locked (an empty `apiMethods` array fails open). + - **`sys_import_job`** stays engine-owned: the REST import route now writes its job rows `isSystem`-elevated (attribution preserved via the explicit `created_by` stamp) and the object is locked to `['get','list']`. + - **New engine write guard** (`assertEngineOwnedWriteAllowed`, plugin-security) fail-closed rejects user-context generic writes to engine-owned `system`/`append-only` objects, keyed off the resolved affordance; `isSystem` and context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. + - **`reconcileManagedApiMethods`** (objectql registry) now runs for **every** managed bucket, not just `better-auth`: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049). + - **`/me/permissions` clamp** (plugin-hono-server) now clamps `system`/`append-only` as well as `better-auth`, so the client hint reflects `permission ∩ guard`. + + **Potentially breaking:** a downstream/third-party `system` object that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. Declare `userActions` opening the verbs the object legitimately takes from a user context. `better-auth` keeps plugin-auth's identity write guard unchanged; the row-level `managed_by` provenance vocabulary (ADR-0066) is a different axis and is untouched. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-messaging/package.json b/packages/services/service-messaging/package.json index c3a26e354f..ccb3770dc3 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": "16.0.0-rc.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 afc7937a0c..b1182d814c 100644 --- a/packages/services/service-package/CHANGELOG.md +++ b/packages/services/service-package/CHANGELOG.md @@ -1,5 +1,50 @@ # @objectstack/service-package +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [06cb319] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/metadata-core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-package/package.json b/packages/services/service-package/package.json index fdcf76d8ff..6ab61647da 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": "16.0.0-rc.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 20a3f123bd..ac8e331a34 100644 --- a/packages/services/service-queue/CHANGELOG.md +++ b/packages/services/service-queue/CHANGELOG.md @@ -1,5 +1,50 @@ # @objectstack/service-queue +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-queue/package.json b/packages/services/service-queue/package.json index c4c55aa296..7222031b84 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": "16.0.0-rc.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 7b716f1a4f..b1ca418ab9 100644 --- a/packages/services/service-realtime/CHANGELOG.md +++ b/packages/services/service-realtime/CHANGELOG.md @@ -1,5 +1,79 @@ # @objectstack/service-realtime +## 16.0.0-rc.0 + +### Patch Changes + +- 06cb319: fix(identity): close the generic-write apiMethods hole on sys_presence and sys_metadata (#3220) + + Follow-through on #1591/#3213 (better-auth apiMethods reconciliation) for two + non-better-auth managed objects that shipped the same contradiction: their + `enable.apiMethods` advertised generic `create`/`update`/`delete` while their + `managedBy` bucket forbids user-context writes, leaving the generic `/data` + route open to a write the bucket does not permit. + + - `sys_presence` (`managedBy: 'append-only'`) advertised `create`/`update`/`delete` + (update/delete on an append-only object at that) but is written only over the + realtime websocket/in-memory path, never through ObjectQL. Narrowed to + `['get', 'list']`. + - `sys_metadata` (`managedBy: 'system'`) advertised full CRUD but customization + overlays are authored only through the metadata-protocol RPC (engine writes + carry a transaction context, not a user session); neither the framework nor + the Console (objectui) POSTs `/data/sys_metadata`. Narrowed to `['get', 'list']`. + + Reads stay open. The metadata-protocol / realtime write paths are engine-level + and bypass the HTTP exposure gate, so they are unaffected — verified by the + metadata-authoring dogfood and the objectql overlay tests. + + A blast-radius audit confirmed the broader `system`/`append-only` buckets are NOT + safe to guard wholesale: several `system` objects (`sys_user_position`, + `sys_user_permission_set`, `sys_position_permission_set`, `sys_user_preference`, + `sys_import_job`) are legitimately user-writable by design (delegated + administration, user preferences, imports). Generalizing the engine write guard + to those buckets is intentionally NOT done here — see #3220 for the bucket-taxonomy + root cause. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-realtime/package.json b/packages/services/service-realtime/package.json index fe91c3f439..009ca12a86 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": "16.0.0-rc.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 f5d5f92a79..2c2a1ee7ae 100644 --- a/packages/services/service-settings/CHANGELOG.md +++ b/packages/services/service-settings/CHANGELOG.md @@ -1,5 +1,54 @@ # @objectstack/service-settings +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [83e8f7d] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [32899e6] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/types@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-settings/package.json b/packages/services/service-settings/package.json index fe84bf0724..5aed6194f4 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": "16.0.0-rc.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 7778a464af..8ff498cf0d 100644 --- a/packages/services/service-sms/CHANGELOG.md +++ b/packages/services/service-sms/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/service-sms +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-sms/package.json b/packages/services/service-sms/package.json index ed0c5e3060..3b92aed3e3 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": "16.0.0-rc.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 612cac3f24..3ec8c5b294 100644 --- a/packages/services/service-storage/CHANGELOG.md +++ b/packages/services/service-storage/CHANGELOG.md @@ -1,5 +1,54 @@ # @objectstack/service-storage +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [bc65105] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [efbcfe1] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/platform-objects@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/observability@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/services/service-storage/package.json b/packages/services/service-storage/package.json index 0de39a6192..19ac93f0ca 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": "16.0.0-rc.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 5a61b6ec41..d4bba11e3f 100644 --- a/packages/spec/CHANGELOG.md +++ b/packages/spec/CHANGELOG.md @@ -1,5 +1,671 @@ # @objectstack/spec +## 16.0.0-rc.0 + +### Major Changes + +- 6c270a6: **BREAKING: remove the deprecated `ctx.session.tenantId` / `ctx.user.tenantId` alias from the hook & action authoring surface — converge on `organizationId` (#3290).** + + #3280 made `organizationId` the blessed developer-facing name for the caller's active org across the JS authoring surface and kept `tenantId` as a `@deprecated` alias carrying the identical value. That alias is now **removed** from the hook `ctx.session`, the action-body `ctx.session`, and the action-body `ctx.user`. Read the caller's active org under the single blessed name: + + ```diff + - const org = ctx.session.tenantId; // hook or action body + + const org = ctx.user?.organizationId ?? ctx.session?.organizationId; + ``` + + **FROM → TO migration** (in any `*.hook.ts` / `*.action.ts` body): + + - `ctx.session.tenantId` → `ctx.session.organizationId` + - `ctx.user.tenantId` (action body) → `ctx.user.organizationId` + + The value is unchanged — `organizationId` is the same active-org id, matching the `organization_id` column and `current_user.organizationId` in RLS/sharing. `ctx.user` is `undefined` for system / unauthenticated writes, so read `ctx.session?.organizationId` when a hook or action must work regardless of a resolved user. + + What changed internally: + + - **`@objectstack/spec`** — `HookContextSchema.session` drops the `tenantId` field (only `organizationId` remains). A stray `tenantId` on a constructed session is now stripped by the schema. + - **`@objectstack/objectql`** — the engine's `buildSession()` no longer emits `session.tenantId`; the audit-stamp plugin sources the `tenant_id` column from `session.organizationId`. + - **`@objectstack/runtime`** — `buildActionSession()` and the REST action `ctx.user` no longer emit `tenantId`. + - **`@objectstack/trigger-record-change`** — reads `session.organizationId` (was `session.tenantId`) when forwarding the writer's org to a `runAs:'user'` flow; behavior is identical. + + **Explicit non-goal (unchanged):** the generic **driver-layer** tenancy abstraction is _not_ touched — `ExecutionContext.tenantId`, `DriverOptions.tenantId`, `SqlDriver.applyTenantScope` / `TenancyConfig.tenantField`, and `ExecutionLog.tenantId`. That isolation column is configurable and legitimately carries an _environment_ id in database-per-tenant kernels; it is a distinct axis from the developer-facing org. The build-time `check:org-identifier` guard now also covers `packages/**` to keep reference bodies off the removed name. + +### Minor Changes + +- f972574: feat(spec): `ActionParamSchema` gains optional widget config — `multiple`, `accept`, `maxSize` + + The console now renders action params through the same field-widget renderer + the record form uses (objectui#2700, objectui ADR-0059), so inline params can + declare the widget config the form widgets consume: `multiple` (array value + shape, mirrors `FieldSchema.multiple`), and the upload constraints `accept` + (MIME types / extensions) and `maxSize` (bytes) for `file`/`image` params. + Field-backed params (`{ field }`) keep inheriting these from the referenced + field at runtime; inline values override. Purely additive — no existing + schema changes shape. + +- 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`. + +- 43a3efb: fix(rest): gate the cross-object transactional batch by the same per-object API rules as single-record writes (#1604) + + The `POST {basePath}/batch` route (issue #1604 / ADR-0034) wraps N cross-object + create/update/delete ops in one engine transaction, but it skipped the + per-object API-exposure gate every single-record route applies — an + authenticated caller could write to an `apiEnabled: false` object, or run an + operation outside an object's `apiMethods` whitelist, straight through the batch + surface (ADR-0049 / #1889 — the same "declared ≠ enforced" hole closed for the + generic write path in #3220 / #3213). + + The route now: + + - validates the body against a new `CrossObjectBatchRequestSchema` + (`@objectstack/spec/api`, Zod-First) — a malformed op, an unknown action, or a + missing `object` is a `400` instead of a `500`; + - enforces `enable.apiEnabled` / `enable.apiMethods` for **every** op (metadata + fetched once, each distinct `(object, action)` checked) BEFORE opening the + transaction — `404 OBJECT_API_DISABLED` / `405 OBJECT_API_METHOD_NOT_ALLOWED`; + - requires an `id` for `update` / `delete` (`400`); + - rejects an unresolvable `{ $ref }` with `400 BATCH_UNRESOLVED_REF` instead of + silently writing a `null` FK; + - rejects an explicit `atomic: false` (`400 BATCH_NOT_ATOMIC`) rather than + silently applying atomically — non-atomic per-object batches stay on + `POST /data/:object/batch`. + + `enforceApiAccess` is refactored to share the pure `apiAccessDenialFromEnable` + check + a `loadObjectItems` helper with the batch route (single-record behavior + unchanged). Adds `rest-batch-endpoint.test.ts` — the REST-boundary coverage + ADR-0034 flagged as missing (commit, `$ref`, rollback surfacing, API-access + denial, request validation). + +- 524696a: feat(spec)!: `DashboardWidgetSchema.strict()` — reject undeclared widget keys (framework#3251) + + The ADR-0021 analytics endpoint. `DashboardWidgetSchema` now rejects any + undeclared top-level key instead of silently stripping it, moving a whole class + of author error (a hallucinated or legacy key that renders as a silent no-op) + from fallible human review to deterministic CI. `options: z.unknown()` remains + the escape hatch for renderer-specific extras. + + A custom error map names the offending key(s) and, when a key is a removed + pre-ADR-0021 inline-analytics key (`object` / `categoryField` / `valueField` / + `aggregate`, pivot `rowField` / `columnField`) or an objectui-internal prop + (`component`, inline `data`), points the author at the dataset shape + (`dataset` + `dimensions` + `values`). + + Recorded as protocol-16 migration `step16` + (`dashboard-widget-strict-unknown-keys`), mirroring protocol-15's `step15` + strict flip on the form/page schemas (ADR-0089 D3a). The inline-analytics shape + itself was already removed at protocol 9 (single-form cutover), so there is no + mechanical rewrite — the residue is the strictness, delegated to the author. + + **Breaking:** shipped as `minor` per the launch-window policy (a breaking change + does not burn a major while the stack is in lockstep), riding the already-pending + 16.0.0 train. The release train's Version-Packages PR must set + `PROTOCOL_VERSION = '16.0.0'`; until then `step16` is inert + (`composeMigrationChain` caps at `PROTOCOL_MAJOR`). + + `@objectstack/lint` — the `widget-legacy-analytics-shape` / + `widget-legacy-analytics-unrenderable` rules are retained as the friendly, + suppressible bridge on the raw-config lint/doctor paths (strict preempts them on + the schema-parsed compile/validate paths); doc comment updated to explain the + interplay. + +- 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. + +- 369eb6e: refactor(spec): remove unenforced agent `visibility` field (ADR-0056 D8, #1901) + + The agent `visibility` (`global`/`organization`/`private`) field is **removed** + from `AgentSchema`. It was never enforced: the chat-access evaluator excluded it + and the agent list route did not filter by it, so setting `private` never hid an + agent. Per ADR-0049 / ADR-0056 D8 ("design+enforce or remove"), a security-shaped + field with no runtime consumer is a liability — authors who set `private` believe + they've restricted an agent when they have not. + + Unlike `field-encryption` (kept `[EXPERIMENTAL]` — it has a stable schema shape on + a real roadmap), correct `visibility` enforcement is undesigned: it needs + owner/org anchors that do not exist today. `agent.tenantId` was already removed + (#2377), agents carry no owner field, and the `EXTERNAL` posture rung is defined + but never derived — so `organization` vs `global` is runtime-indistinguishable. + The semantics, not just the plumbing, are unresolved, so the field is dropped + rather than carried marked. + + - `AgentSchema` is not `.strict()`, so existing metadata that still sets + `visibility` parses cleanly — the unknown key is stripped, not rejected. + - Use `access` / `permissions` to restrict who can use an agent — both **enforced** + at the chat route (#1884). + - Re-introduce `visibility` when the agent listing surface gains real owner/org + semantics; tracked in #1901. + + Also updated: authoring form (`agent.form.ts`), liveness ledger + (`liveness/agent.json`), the ADR-0056 D10 authz-conformance matrix (moved from + `experimental` to `removed`), and the generated schema reference docs. + +- 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. + +- 5754a23: feat(spec)!: remove form-surfaced dead metadata props + correct 3 misclassified-live entries (#2377, ADR-0049) + + The next enforce-or-remove slice of #2377. Versioned `minor` per the launch-window + policy (the fixed group makes a `major` promote the whole monorepo). + + ## Removed (dead, no runtime reader — verified in both framework and objectui) + + - **field**: `columnName`, `index`, `referenceFilters`. This empties the field + dead-prop set. `columnName` also removed its now-moot **ADR-0062 D7** lint + (`validate-expressions.ts`), the dead `StorageNameMapping.resolveColumnName` / + `buildColumnMap` / `buildReverseColumnMap` helpers, and closes ADR-0062 R10 — + external physical-column mapping is `external.columnMap` only. + - **object**: `tags`, `active`, `abstract` — now rejecting tombstones in + `UNKNOWN_KEY_GUIDANCE`. + - **agent**: `tenantId`. + + The removed props are dropped from the authoring forms (`field/object/agent.form.ts`) + and the regenerated metadata-forms i18n bundles. + + ## Corrected to `live` (the ledger was wrong — readers existed) + + - **object `isSystem`** — `plugin-sharing` `effectiveSharingModel` defaults a + no-`sharingModel` `isSystem` object to public; also read by the security-posture + lint. KEPT. + - **object `enable.searchable`** — `metadata-protocol` global search (`searchAll`) + uses `enable.searchable === false` as an opt-out. KEPT. + - **action `type:'form'`** — objectui `ActionRunner.executeForm` routes it to the + FormView at `/forms/:target`; a build-time lint validates the target. KEPT. + + ## Deliberately deferred + + `object.enable.trash` / `enable.mru` — dead, but inert `default(true)` flags set by + ~35 `sys-*.object.ts` files; removing them is high-churn / low-value. Left `dead` + (authorWarn-skipped). + + ## Migration + + - field/agent props: authoring them was already a no-op; they now strip silently. + `columnName` → the physical column is always the field key (rename the field, or + use `external.columnMap` for external objects); `index` → declare it in object + `indexes[]`; `referenceFilters` → `lookupFilters`. + - object `tags`/`active`/`abstract`: `ObjectSchema.create()` now throws a located + error naming the removal. None gated anything at runtime — remove them. + +- 668dd17: **Breaking (npm type surface): retire the vestigial feed contracts + protocol surface (ADR-0052 §5 follow-up, #1959).** + + The `service-feed` runtime was deleted in #1955; `sys_comment` / `sys_activity` + are the canonical record-collaboration/timeline backend. This removes the dead + type surface that still pointed at the deleted runtime — every removed method was + already unreachable (the feed REST route was never mounted → 404; the protocol + implementation was never wired with a feed service, so `requireFeedService()` + could only throw). No behavior changes. + + No authorable metadata key is removed (the `feeds:` object capability flag and + the `RecordActivity` UI component config are unchanged), so `PROTOCOL_MAJOR` + stays 15 and this ships as `minor` rather than a protocol major. + + FROM → TO migration for every removed export: + + - `@objectstack/spec/contracts` — `IFeedService`, `CreateFeedItemInput`, + `UpdateFeedItemInput`, `ListFeedOptions`, `FeedListResult` → **removed, no + replacement**. Comments/activity are plain records: write `sys_comment` / read + `sys_activity` via the data engine or the REST data API. + - `@objectstack/spec/api` — `FeedApiContracts`, `FeedApiErrorCode`, + `FeedProtocol`, and all feed request/response schemas + types (`GetFeed*`, + `CreateFeedItem*`, `UpdateFeedItem*`, `DeleteFeedItem*`, `AddReaction*`, + `RemoveReaction*`, `PinFeedItem*`, `UnpinFeedItem*`, `StarFeedItem*`, + `UnstarFeedItem*`, `SearchFeed*`, `GetChangelog*`, `ChangelogEntry`, + `SubscribeRequest/Response`, `FeedUnsubscribeRequest`, `UnsubscribeResponse`, + `FeedPathParams`, `FeedItemPathParams`, `FeedListFilterType`) → **removed**. Use + the data API against `sys_comment` / `sys_activity` (`/api/v1/data/sys_comment/…`); + reactions and threaded replies are fields on `sys_comment`. + - `@objectstack/spec/data` — `FeedItemSchema`/`FeedItem`, `FeedActorSchema`/`FeedActor`, + `MentionSchema`/`Mention`, `ReactionSchema`/`Reaction`, + `FieldChangeEntrySchema`/`FieldChangeEntry`, `FeedVisibility`, + `RecordSubscriptionSchema`/`RecordSubscription`, `SubscriptionEventType`, and the + `data`-namespace `NotificationChannel` → **removed**. `FeedItemType` and + `FeedFilterMode` are **kept** (live UI activity-timeline config). For notification + channels use `NotificationChannelSchema` from `@objectstack/spec/system`. + - `@objectstack/client` — `client.feed.*` (`list` / `create` / `update` / `delete` / + `addReaction` / `removeReaction` / `pin` / `unpin` / `star` / `unstar` / `search` / + `getChangelog` / `subscribe` / `unsubscribe`) and the re-exported feed response + types → **removed**. One-line fix: use `client.data.*` on `sys_comment` / + `sys_activity`, e.g. `client.data.create('sys_comment', { object, record_id, body })` + and `client.data.find('sys_activity', { filters: [['record_id', '=', id]] })`. + - `@objectstack/metadata-protocol` — `ObjectStackProtocolImplementation` no longer + implements the 14 feed methods; its constructor + `(engine, getServicesRegistry?, getFeedService?, environmentId?)` becomes + `(engine, getServicesRegistry?, environmentId?)`. One-line fix: delete the third + argument. + +- 8abf133: **Breaking (discovery response shape): retire the residual feed capability surface (#3180, follow-up to #1959 / ADR-0052 §5).** + + The feed backend was retired long ago; #1959 removed the feed contracts + SDK. This + removes the last discovery/dispatcher references to it, and fixes a real bug where the + `comments` capability was permanently `false`. + + - `@objectstack/spec` — `WellKnownCapabilitiesSchema.feed` and `ApiRoutesSchema.feed` + (`routes.feed`) are **removed**, and the `/api/v1/feed` entry is dropped from + `DEFAULT_DISPATCHER_ROUTES`. FROM → TO: clients reading `discovery.capabilities.feed` + or `discovery.routes.feed` → use `discovery.capabilities.comments`; comments/activity + are served by the generic data API on `sys_comment` / `sys_activity` + (`/api/v1/data/sys_comment/…`). + - `@objectstack/metadata-protocol` — `getDiscovery()` no longer emits the always-`false` + `feed` service/capability. **Bug fix:** the `comments` capability previously keyed off + the deleted `'feed'` service (so it was permanently `false` after #1955); it now tracks + the presence of the `sys_comment` object (provided by the always-on audit slate), so + `declared === enforced`. + - `@objectstack/client` — the internal `feed: '/api/v1/feed'` route constant is removed + (it only existed to satisfy the now-removed `ApiRoutes.feed` type; no client code used it). + +- 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. + +- 4d5a892: feat(objectql): roll-up `summary` fields can filter which child rows they aggregate (#1868) + + `summaryOperations` gains an optional `filter` — a query `where` FilterCondition + evaluated against each child row, so a summary aggregates only the matching + children instead of the whole collection. This is what lets a single child object + feed several distinct parent totals, which the cross-object rollup templates need: + + ```typescript + // One `engagement` child → distinct filtered totals. + total_signups: { + type: 'summary', + summaryOperations: { object: 'engagement', field: 'id', function: 'count', filter: { type: 'signup' } }, + } + // Sum only received receipt lines (3-way match). + received_amount: { + type: 'summary', + summaryOperations: { object: 'procurement_receipt', field: 'amount', function: 'sum', filter: { status: 'received' } }, + } + ``` + + The engine ANDs the predicate with the parent-FK match when it recomputes, and + because the whole filtered aggregate is re-run on every child write, a child that + moves in or out of the predicate (e.g. a status change) keeps the parent current + with no extra wiring. Operator and compound forms work too + (`filter: { type: { $in: ['signup', 'trial'] }, amount: { $gte: 100 } }`). + + Purely additive: omitting `filter` aggregates every child exactly as before. + +- 16cebeb: fix(spec): drop the dead `systemFields.owner` key (#3175 follow-up) + + `ObjectSchema.systemFields` exposed an `owner?: boolean` opt-out key that nothing + read — the registry (`applySystemFields`) only consumes `systemFields.tenant` and + `systemFields.audit`, and `owner_id` provisioning is governed by the object-level + `ownership` property (`'user' | 'org' | 'none'`, made first-class in #3185). The + key was declared but wired to nothing. + + Removed it so the schema only advertises the two opt-outs it actually honors + (`tenant`, `audit`). Backward-compatible at runtime: the key was ignored before and + is stripped now (both no-ops). A TypeScript author who set `systemFields.owner` + will now see an excess-property error — the fix is to delete the key (it never did + anything) or use `ownership: 'org' | 'none'` to skip `owner_id`. Also corrected the + stale `objectql/security` doc that called `audit` "reserved" (it is active). + +- 86d30af: fix(tenancy): platform-global (`tenancy.enabled:false`) objects are never driver-org-scoped (#3249) + + An org-context read of a platform-global object (e.g. `sys_license`, ADR-0066) + could return 0 rows for an authenticated caller while an anonymous read saw the + data: the engine stamped `execCtx.tenantId` into driver options unconditionally, + and the SQL driver's tenant-field cache could be re-corrupted to + `organization_id` by a partial re-registration (lifecycle archive `syncSchema`, + schema-drift re-sync) whose schema omitted the `tenancy` block. + + - New `isTenancyDisabled(schema)` export from `@objectstack/spec/data` — the + single source of truth for the ADR-0066 platform-global posture, now shared by + the registry (tenant-column injection), the ObjectQL engine, and the SQL + driver. + - `ObjectQL.buildDriverOptions` no longer stamps `tenantId` for objects whose + registered schema declares `tenancy.enabled: false` (an explicitly-passed + options `tenantId` still wins — deliberate caller intent). + - `SqlDriver` (and `SqliteWasmDriver`) now keep a sticky record of an explicit + `tenancy.enabled:false` declaration: a later registration without a `tenancy` + block preserves the opt-out instead of re-scoping via the implicit + `organization_id` heuristic; a registration that carries a `tenancy` + declaration stays authoritative. + +- a2795f6: feat(triggers): declarative time-relative trigger — daily sweep instead of fragile date-equality (#1874) + + Time-relative business rules ("alert 60 days before a contract's `end_date`") + could only be expressed as a `record_change` flow gated on a date-equality + condition like `end_date == daysFromNow(60)`. That predicate is only evaluated + when the record _happens to change_, so it fires only if a record is edited on + exactly the threshold day — i.e. almost never, unattended. The robust + alternative was a hand-written cron + range query that every author + re-implemented (contracts `renewal_alert`, hr `document_expiring_soon`, + procurement `po_overdue`, …). + + A flow's start node can now declare a `timeRelative` descriptor instead: + + ```ts + config: { + timeRelative: { + object: 'contracts', + dateField: 'end_date', + offsetDays: [60, 30, 7], // T-minus reminders — fires on each threshold day + // — or — withinDays: 30 // "expiring soon" range; negative = overdue lookback + filter: { status: 'active' }, // optional, ANDed with the date window + }, + schedule: { type: 'cron', expression: '0 8 * * *' }, // optional; defaults to daily 08:00 UTC + } + ``` + + The new `time_relative` trigger (shipped in `@objectstack/trigger-schedule` as + `TimeRelativeTriggerPlugin`) sweeps the object on that schedule and launches the + flow **once per matching record**, with the record on the automation context — + so the start-node `condition` gate and `{record.}` interpolation work + exactly as for a record-change flow. Because the window is evaluated every day, + a threshold is never missed regardless of when the record last changed. The + discovery query runs as a system operation (RLS-bypassing) and is capped + (`maxRecords`, default 1000) so a mis-scoped window can't fan out unboundedly; + per-record failures are isolated so one bad row never aborts the sweep. + + The automation engine routes a start node carrying `config.timeRelative` to the + `time_relative` trigger (ahead of the plain `schedule` trigger, whose behavior is + unchanged), and `os validate` gains readiness checks for the new descriptor + (unknown swept object, ambiguous draft status). New authorable spec key: + `TimeRelativeTriggerSchema` (`@objectstack/spec/automation`). + +### Patch Changes + +- 22013aa: **Split the overloaded `managedBy: 'system'` bucket into engine-owned vs. admin-writable, and enforce engine-owned writes (ADR-0103, #3220).** The `system` bucket conflated two incompatible write policies: rows a platform service owns end to end (never user-written), and platform-defined schema whose rows are legitimately admin/user-writable. It carried the same all-false affordance row as `better-auth`/`append-only` but, unlike `better-auth`, had no engine enforcement — a wildcard admin could raw-write these rows through the generic data API (ADR-0049 gap). + + Rather than add a new `managedBy` enum value (which would fall through to fully-editable `platform` defaults on already-deployed Console clients), the write policy is now the **resolved affordance** (`resolveCrudAffordances` = bucket default + `userActions`), and _engine-owned_ is defined as a `system`/`append-only` object that grants no write: + + - **Writable set declares `userActions`** — the RBAC link tables (`sys_user_position`, `sys_user_permission_set`, `sys_position_permission_set`), `sys_user_preference`, `sys_approval_delegation`, and the messaging config grids (`sys_notification_preference` / `…_subscription` / `…_template`) now declare `userActions: { create, edit, delete: true }`. The affordance is a declaration only — the `DelegatedAdminGate` / RLS / permission sets remain the authz. + - **Engine-owned objects locked to reads** — `apiMethods: ['get','list']` added where absent (jobs, notifications, approval request/approver/token/action, `sys_record_share`, `sys_automation_run`, mail/settings/secret audit, the messaging delivery pipeline). `sys_secret` is explicitly read-locked (an empty `apiMethods` array fails open). + - **`sys_import_job`** stays engine-owned: the REST import route now writes its job rows `isSystem`-elevated (attribution preserved via the explicit `created_by` stamp) and the object is locked to `['get','list']`. + - **New engine write guard** (`assertEngineOwnedWriteAllowed`, plugin-security) fail-closed rejects user-context generic writes to engine-owned `system`/`append-only` objects, keyed off the resolved affordance; `isSystem` and context-less engine/service writes bypass by construction. Wired into the security middleware alongside the other data-layer gates. + - **`reconcileManagedApiMethods`** (objectql registry) now runs for **every** managed bucket, not just `better-auth`: any advertised write verb an object's resolved affordances forbid is stripped at registration with a warning (the drift backstop, ADR-0049). + - **`/me/permissions` clamp** (plugin-hono-server) now clamps `system`/`append-only` as well as `better-auth`, so the client hint reflects `permission ∩ guard`. + + **Potentially breaking:** a downstream/third-party `system` object that advertised generic write verbs relying on today's fail-open behaviour will have those verbs stripped (with a warning) and user-context generic writes to it rejected. Declare `userActions` opening the verbs the object legitimately takes from a user context. `better-auth` keeps plugin-auth's identity write guard unchanged; the row-level `managed_by` provenance vocabulary (ADR-0066) is a different axis and is untouched. + +- 3ad3dd5: Annotate the schema-only event/subscription/connector surfaces flagged by the #3197 audit with explicit "not yet enforced / not yet implemented" notes in their doc comments and `.describe()` texts, so authoring metadata against them is no longer silently swallowed. No runtime behavior or schema shape changes — documentation only. + + Surfaces annotated (each trace re-confirmed against the current tree before annotating): + + - `GraphQLSubscriptionConfigSchema` (`api/graphql.zod.ts`) — no subscription transport exists; the GraphQL HTTP entry serves query/mutation only. + - `WebSocketMessageType` + module header (`api/websocket.zod.ts`) — no WebSocket server is mounted (#2462); the protocol is a future wire contract. + - `RealtimeEventType` (`api/realtime.zod.ts`) — zero runtime importers; the engine emits `data.record.*` names (which don't match this enum's members) and nothing emits `field.changed`. + - Connector `webhooks`/`WebhookConfigSchema`/`WebhookEventSchema` and `triggers`/`ConnectorTriggerSchema` (`integration/connector.zod.ts`) — `AutomationEngine.registerConnector` reads only `actions`; webhook events and trigger definitions parse but are never dispatched or polled. + - Automation `ConnectorTriggerSchema`/`TriggerRegistrySchema` (`automation/trigger-registry.zod.ts`) — no runtime importer; the `stream` trigger mechanism exists only here. + - `NotificationChannelSchema` (`system/notification.zod.ts`) + the mirrored `NotificationChannel` contract type — implemented delivery channels are `inbox`/`email`/`sms`; `push`/`slack`/`teams`/`webhook` dead-letter, and the enum's `in-app` does not match the registered `inbox` channel id. + + The audit's sixth row (`SubscriptionEventType`, formerly `data/subscription.zod.ts`) needed no annotation — it was already removed outright by the feed-contract retirement (#1959). + +- 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). +- a3823b2: Collapse the hook event taxonomy from 18 declared events to the 8 the engine actually dispatches (#3195). The removed 10 (`beforeFindOne`/`afterFindOne`, `beforeCount`/`afterCount`, `beforeAggregate`/`afterAggregate`, `beforeUpdateMany`/`afterUpdateMany`, `beforeDeleteMany`/`afterDeleteMany`) were declared in `HookEvent` but never fired — the enum mirrored the engine method table instead of domain events, so a hook subscribing to them registered fine and then silently no-op'd. + + - `findOne` now fires the same `beforeFind`/`afterFind` hooks as `find` — the read event attaches to record materialization, not the engine method, so one subscription covers every read shape (no separate `beforeFindOne`/`afterFindOne`). + - Bulk (`multi: true`) updates/deletes already fire the singular `beforeUpdate`/`beforeDelete`/`afterUpdate`/`afterDelete` events with the row-scoping predicate in `ctx.input.ast`; this is now documented, and there is no `*Many` event. + - Read authorization / row filtering is the RLS/permission-rule layer's job and field masking is field-level metadata — neither is a hook every author must re-attach. + - `engine.registerHook` now warns when a hook subscribes to an event the engine never dispatches, so enum-vs-dispatch drift can't recur silently. + + No shipped hook or authored metadata used any of the removed events; authoring one now fails loudly at parse/validate time instead of registering a dead hook. Skills and docs updated to teach the 8 events and the declarative alternatives. + +- 5e3301d: Document two validation-rule facts surfaced by the 2026-06 liveness audit (follow-up to #3106 / #3184), and clean up a stale form-schema mirror — no runtime behavior change: + + - `label` / `description` / `tags` on validation rules are governance / editor metadata (surfaced to the Studio rule editor and rule listings), not evaluated on the write path. Documented as such on `BaseValidationSchema` rather than removed — they are set by nearly every example rule and feed the `/meta/types` editor form, so they are declared on purpose, not silent no-ops. + - `cross_field` evaluates identically to `script` (same CEL predicate path); only `fields[0]` is read, to target the violation at a field. Documented the overlap on the schema, its `fields` `.describe()`, and the validation docs so authors can choose between them; the variant is kept for the field-targeting affordance and backward compatibility. + - Removed dead form-field entries (`scope`, `caseSensitive`, `url`, `handler`) and the stale `type=unique` hint from the hand-written `HAND_CRAFTED_SCHEMAS['validation']` fallback in `@objectstack/metadata-protocol` — leftovers from the removed `unique`/`async`/`custom` variants. + - Added the missing `beforeDelete` lifecycle-hook pointer to the validation docs' "not a rule type" callout, so delete-time guards aren't stranded now that validation has no `delete` event (#3184). + +- 46e876c: fix(spec): declare `summaryOperations` sub-fields in the Field metadata form (#3257) + + `fieldForm` (the registered metadata form for editing a Field) previously + declared `summaryOperations` as a bare `composite` with no sub-fields, so a + protocol-driven renderer had to fall back to a raw JSON editor. It now declares + the inner shape explicitly — `object` (`ref:object`), `function` (select), + `field`, `relationshipField`, and `filter` (bound to `widget: 'filter-condition'`) + — mirroring the `summaryOperations` Zod schema and surfacing the roll-up `filter` + added in #1868. Also gates the block to `data.type == 'summary'`. + + Small step toward #3257 (making the Studio field designer metadata-driven rather + than hand-coded); the live objectui inspector already edits these fields. + +- 158aa14: feat(automation): mark the loop `collection` config field as an interpolate() template so designer forms render it correctly (#3304) + + The flow designer generates a node's config form from its published + `configSchema` (ADR-0018). A string property can now carry an `xExpression: +'expression' | 'template'` marker — riding the same Zod `.meta()` → JSON-Schema + channel as `xRef` / `xEnumDeprecated` — that declares whether the string is bare + CEL or an `interpolate()` single-brace `{var}` template. + + The `loop` node's `collection` (e.g. `{tasks}`) is a template, so it is now + marked `xExpression: 'template'` on both the canonical `LoopConfigSchema` and the + shipped descriptor's `configSchema` literal (service-automation loop-node). + Without the marker the designer rendered `collection` as plain text online while + the offline hardcoded form rendered it as a mono expression editor, and the CEL + brace-trap false-flagged `{tasks}` as a malformed condition. The marker closes + that divergence — objectui #2670 Phase 3 (#2699) already consumes it. + + Additive and backward-compatible: an unknown `xExpression` value is ignored by + the designer, and runtime behavior is unchanged. Filling the same marker in on + the remaining node types (map/decision/script and the node types that publish no + `configSchema` yet) is tracked as follow-up in #3304. + +- 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. + +- e0859b1: fix(formula): retire the `js` expression dialect and fix the `hasDialect` false-positive (#3278) + + The `js` **expression** dialect was declared in `ExpressionDialect` but never + shipped — it existed only as a registry stub with no engine and no author helper + (`cel`/`F`/`P` → CEL, `tmpl` → template, `cron` → cron; nothing ever emitted + `js`). Per ADR-0049 (enforce-or-remove) it is removed from the enum; the set is + now `{cel, cron, template}`. + + Procedural JavaScript is unaffected: it remains the **L2** authoring surface — + the sandboxed, capability-gated `ScriptBody { language: 'js' }` in hook/action + bodies — which is a separate enum (`hook-body.zod.ts`), not an expression + dialect. + + Also fixes a latent bug in `hasDialect`: it detected stubs via + `dialect.startsWith('stub:')`, but stubs were registered under their real name, + so the check was dead code and `hasDialect('js')` returned a false-positive + `true`. With the stub removed, `hasDialect` reports only registered real + engines, and the registry test now asserts the negative case (`hasDialect('js') +=== false`) so the gate can actually go red. + + No runtime behavior changes for any valid persisted artifact — no producer ever + emitted `dialect: 'js'`. See the ADR-0058 addendum. + +- 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. +- 4b6fde8: Trim the dead `undelete` and `api` webhook triggers (#3196). `WebhookTriggerType` declared five triggers but only three ever fired: + + - `undelete` had no event source — the engine has no soft-delete/restore capability (`delete` is a hard delete; no `deleted_at` convention, no restore operation, and `data.record.undeleted` is never emitted). The `undeleted` case in the auto-enqueuer's action mapper was dead code awaiting a producer that doesn't exist. + - `api` ("manually triggered") had no fire path — the only webhook HTTP surface re-queues already-failed deliveries; nothing originates a manual fire. + + Both are removed from the enum (contract-first, matching #3184/#3195): authoring a webhook on a removed trigger now fails loudly at `os validate` / registration instead of registering a webhook that silently never fires. No shipped webhook metadata used either. The auto-enqueuer now also warns when a persisted `sys_webhook` row carries a trigger it can't map to an emitted record event (a drift-guard, so a dead trigger can't silently no-op again). Reintroduce `undelete` only alongside a real restore subsystem, and `api` only alongside a real manual-fire endpoint. Updated the `sys_webhook` trigger options, field help (all locales), docs, and reference; added rejection tests. + +- 2018df9: **Unify the developer-facing org identifier in JS hooks — `organizationId` is now the blessed name; `session.tenantId` becomes a deprecated alias (#3280).** The caller's active organization was surfaced to hook authors as `ctx.session.tenantId`, while everything else on the developer surface — the `organization_id` column, `current_user.organizationId` in RLS/sharing, and seed rows — already said `organization`. A hook author had to internalize the hidden equation `tenantId === organizationId` to move between surfaces. This is additive and non-breaking: + + - **`ctx.session.organizationId`** is added as the blessed name; **`ctx.session.tenantId`** still carries the identical value but is marked `@deprecated` in its TSDoc. Both come from the same resolved `ExecutionContext.tenantId` (which the kernel derives from `session.activeOrganizationId`). + - **`ctx.user.organizationId`** is added to the ergonomic `user` shortcut, so a hook that needs "the current org to filter by" writes `ctx.user.organizationId` with zero relearning — matching `current_user.organizationId` (RLS) and the `organization_id` column. The engine now populates `ctx.user` (`{ id, email?, organizationId? }`) at every hook event that already carries a `session`; it stays `undefined` for system / unauthenticated writes. + + **No behavior change and no breaking rename.** The generic driver-layer tenancy abstraction (`ExecutionContext.tenantId`, `DriverOptions.tenantId`, `SqlDriver.applyTenantScope`, `TenancyConfig.tenantField`) is deliberately untouched — that layer's isolation column is configurable and legitimately carries an _environment_ id in per-environment (database-per-tenant) kernels. Hook-authoring docs now teach `organizationId` and distinguish the two isolation axes: **org row-scoping** (`organization_id`, shared DB) vs **environment / database-per-tenant** (`service-tenant`, `driver-turso`). Community edition never populates an org, so `organizationId` is `undefined` there. + +- 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 b764454d40..ce70118c85 100644 --- a/packages/spec/package.json +++ b/packages/spec/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/spec", - "version": "15.1.1", + "version": "16.0.0-rc.0", "description": "ObjectStack Protocol & Specification - TypeScript Interfaces, JSON Schemas, and Convention Configurations", "license": "Apache-2.0", "main": "dist/index.js", diff --git a/packages/spec/src/kernel/protocol-version.ts b/packages/spec/src/kernel/protocol-version.ts index 3fe27d7b8d..e986a83160 100644 --- a/packages/spec/src/kernel/protocol-version.ts +++ b/packages/spec/src/kernel/protocol-version.ts @@ -15,7 +15,7 @@ * Kept in lockstep with the package's own major; `protocol-version.test.ts` * asserts it against `package.json` so the two cannot drift. */ -export const PROTOCOL_VERSION = '15.0.0'; +export const PROTOCOL_VERSION = '16.0.0'; /** The protocol major as an integer — the value the handshake compares. */ export const PROTOCOL_MAJOR: number = Number.parseInt(PROTOCOL_VERSION.split('.')[0]!, 10); diff --git a/packages/triggers/trigger-api/CHANGELOG.md b/packages/triggers/trigger-api/CHANGELOG.md index 7e9464a04e..8bbd0d0e76 100644 --- a/packages/triggers/trigger-api/CHANGELOG.md +++ b/packages/triggers/trigger-api/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/trigger-api +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/triggers/trigger-api/package.json b/packages/triggers/trigger-api/package.json index 8b96960e29..8c86415f1f 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": "16.0.0-rc.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 3343626808..aa9d9ba15b 100644 --- a/packages/triggers/trigger-record-change/CHANGELOG.md +++ b/packages/triggers/trigger-record-change/CHANGELOG.md @@ -1,5 +1,86 @@ # @objectstack/plugin-trigger-record-change +## 16.0.0-rc.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 + +- 6c270a6: **BREAKING: remove the deprecated `ctx.session.tenantId` / `ctx.user.tenantId` alias from the hook & action authoring surface — converge on `organizationId` (#3290).** + + #3280 made `organizationId` the blessed developer-facing name for the caller's active org across the JS authoring surface and kept `tenantId` as a `@deprecated` alias carrying the identical value. That alias is now **removed** from the hook `ctx.session`, the action-body `ctx.session`, and the action-body `ctx.user`. Read the caller's active org under the single blessed name: + + ```diff + - const org = ctx.session.tenantId; // hook or action body + + const org = ctx.user?.organizationId ?? ctx.session?.organizationId; + ``` + + **FROM → TO migration** (in any `*.hook.ts` / `*.action.ts` body): + + - `ctx.session.tenantId` → `ctx.session.organizationId` + - `ctx.user.tenantId` (action body) → `ctx.user.organizationId` + + The value is unchanged — `organizationId` is the same active-org id, matching the `organization_id` column and `current_user.organizationId` in RLS/sharing. `ctx.user` is `undefined` for system / unauthenticated writes, so read `ctx.session?.organizationId` when a hook or action must work regardless of a resolved user. + + What changed internally: + + - **`@objectstack/spec`** — `HookContextSchema.session` drops the `tenantId` field (only `organizationId` remains). A stray `tenantId` on a constructed session is now stripped by the schema. + - **`@objectstack/objectql`** — the engine's `buildSession()` no longer emits `session.tenantId`; the audit-stamp plugin sources the `tenant_id` column from `session.organizationId`. + - **`@objectstack/runtime`** — `buildActionSession()` and the REST action `ctx.user` no longer emit `tenantId`. + - **`@objectstack/trigger-record-change`** — reads `session.organizationId` (was `session.tenantId`) when forwarding the writer's org to a `runAs:'user'` flow; behavior is identical. + + **Explicit non-goal (unchanged):** the generic **driver-layer** tenancy abstraction is _not_ touched — `ExecutionContext.tenantId`, `DriverOptions.tenantId`, `SqlDriver.applyTenantScope` / `TenancyConfig.tenantField`, and `ExecutionLog.tenantId`. That isolation column is configurable and legitimately carries an _environment_ id in database-per-tenant kernels; it is a distinct axis from the developer-facing org. The build-time `check:org-identifier` guard now also covers `packages/**` to keep reference bodies off the removed name. + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.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 ec9433abf2..8d0fe4eb47 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": "16.0.0-rc.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 a67ef158b5..e191354fd9 100644 --- a/packages/triggers/trigger-schedule/CHANGELOG.md +++ b/packages/triggers/trigger-schedule/CHANGELOG.md @@ -1,5 +1,92 @@ # @objectstack/plugin-trigger-schedule +## 16.0.0-rc.0 + +### Minor Changes + +- a2795f6: feat(triggers): declarative time-relative trigger — daily sweep instead of fragile date-equality (#1874) + + Time-relative business rules ("alert 60 days before a contract's `end_date`") + could only be expressed as a `record_change` flow gated on a date-equality + condition like `end_date == daysFromNow(60)`. That predicate is only evaluated + when the record _happens to change_, so it fires only if a record is edited on + exactly the threshold day — i.e. almost never, unattended. The robust + alternative was a hand-written cron + range query that every author + re-implemented (contracts `renewal_alert`, hr `document_expiring_soon`, + procurement `po_overdue`, …). + + A flow's start node can now declare a `timeRelative` descriptor instead: + + ```ts + config: { + timeRelative: { + object: 'contracts', + dateField: 'end_date', + offsetDays: [60, 30, 7], // T-minus reminders — fires on each threshold day + // — or — withinDays: 30 // "expiring soon" range; negative = overdue lookback + filter: { status: 'active' }, // optional, ANDed with the date window + }, + schedule: { type: 'cron', expression: '0 8 * * *' }, // optional; defaults to daily 08:00 UTC + } + ``` + + The new `time_relative` trigger (shipped in `@objectstack/trigger-schedule` as + `TimeRelativeTriggerPlugin`) sweeps the object on that schedule and launches the + flow **once per matching record**, with the record on the automation context — + so the start-node `condition` gate and `{record.}` interpolation work + exactly as for a record-change flow. Because the window is evaluated every day, + a threshold is never missed regardless of when the record last changed. The + discovery query runs as a system operation (RLS-bypassing) and is capped + (`maxRecords`, default 1000) so a mis-scoped window can't fan out unboundedly; + per-record failures are isolated so one bad row never aborts the sweep. + + The automation engine routes a start node carrying `config.timeRelative` to the + `time_relative` trigger (ahead of the plain `schedule` trigger, whose behavior is + unchanged), and `os validate` gains readiness checks for the new descriptor + (unknown swept object, ambiguous draft status). New authorable spec key: + `TimeRelativeTriggerSchema` (`@objectstack/spec/automation`). + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/triggers/trigger-schedule/package.json b/packages/triggers/trigger-schedule/package.json index af50e2571e..efc11a4282 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": "16.0.0-rc.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 138da49189..5f62000865 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -1,5 +1,131 @@ # @objectstack/types +## 16.0.0-rc.0 + +### Minor Changes + +- 83e8f7d: feat(mcp): decouple the stdio auto-start switch from the HTTP surface + surface the MCP endpoint on `os dev` boot (#3167) + + The MCP HTTP surface (`/api/v1/mcp`) and the long-lived stdio transport used to + share one env var: `OS_MCP_SERVER_ENABLED=true` turned the HTTP surface on **and** + silently auto-started the stdio transport — which bridges the raw metadata service + + - data engine with no per-request principal (unscoped). An operator setting it to + "make sure MCP is on" got an unscoped transport as a side effect. + + * **`@objectstack/types`** — new `resolveMcpStdioAutoStart()`. Stdio auto-start is + now its own switch, `OS_MCP_STDIO_ENABLED` (default off); `OS_MCP_SERVER_ENABLED` + governs only the HTTP surface. The legacy `OS_MCP_SERVER_ENABLED=true` trigger + still starts stdio for one release, flagged as deprecated. `=false` is unchanged + (it only ever gated HTTP). + * **`@objectstack/mcp`** — `MCPServerPlugin.start()` gates stdio on the new switch + and logs a one-time deprecation warning when started via the legacy alias. + * **`@objectstack/cli`** — `os dev` now prints the MCP endpoint, the agent-skill + URL, and a ready-to-paste `claude mcp add` command on boot (gated on the HTTP + surface being on), so the "an agent operates the app it's building" loop is + discoverable at dev time. + * **`create-objectstack`** — the blank scaffold README documents that the app is + itself an MCP server (the serve side), distinct from the consume-side connector. + +- 92f5f19: feat(runtime): sandbox budget is script CPU-time, not wall clock (ADR-0102 D1, #3295) + + The QuickJS sandbox now meters each hook/action invocation against how much + **VM-active (CPU) time** the body burns, not wall clock. Idle host-await time and + a nested hook's own execution (which runs host-side while the caller's VM is + parked) are no longer charged to the caller — so a slow/loaded host or a deep + nested-write chain can't trip the budget while a script is merely waiting (the + root cause of the #3259 CI flake). A separate, generous **wall-clock ceiling** + (default 30s, `max(ceiling, cpuBudget)`) remains as the backstop for a body stuck + on a host call that never settles. + + What changes for consumers (behaviour, not API signatures): + + - **Meaning of the timeout knobs.** `body.timeoutMs`, the `hookTimeoutMs` / + `actionTimeoutMs` runner options, and `OS_SANDBOX_HOOK_TIMEOUT_MS` / + `OS_SANDBOX_ACTION_TIMEOUT_MS` keep their **names, defaults (250ms / 5000ms), + and precedence** — but now bound CPU-time instead of wall-clock. In practice + this only _loosens_ legitimate slow/nested work; a runaway synchronous script + is still cut at the same budget. + - **Error messages.** `exceeded timeout of Nms` → either `exceeded CPU budget of +Nms` (script burned its CPU budget) or `exceeded wall-clock ceiling of Nms +while awaiting host calls` (stuck on a never-settling host call). Update any + code/tests matching the old string. + + New knobs (additive): + + - `QuickJSScriptRunner` option `wallCeilingMs` and env `OS_SANDBOX_WALL_CEILING_MS` + — tune the wall ceiling (explicit option › env › 30s). + - `resolveSandboxTimeoutMs` (`@objectstack/types`) gains a `'wallCeiling'` kind. + + Also fixes a latent init bug in the new accounting where the interrupt handler + could fire during `installCtx` and corrupt ctx marshalling. The nested-write + integration suites now run at the stock 250ms budget (previously forced to 10s), + which is itself the regression guard for the nested-charging fix. + +- 32899e6: feat(runtime): env-overridable sandbox hook/action timeout default (#3259) + + The QuickJS sandbox enforces a wall-clock deadline on every hook/action + invocation (250ms hooks / 5000ms actions). Each invocation compiles a fresh + WASM module, and a nested hook compiles ANOTHER one inside the parent's budget, + so on a heavily loaded or slow host — an oversubscribed CI runner, constrained + production hardware — that fixed VM-creation cost alone can trip the hook + default even while the VM is still making progress. On CI this surfaced as an + intermittent `hook '…' exceeded timeout of 250ms` flake on PRs that never + touched the sandbox path. + + The per-invocation timeout DEFAULT is now resolvable from the environment via + `resolveSandboxTimeoutMs` (`@objectstack/types`), which `QuickJSScriptRunner` + consults, so an operator can raise the floor once, deployment-wide, instead of + re-tuning every call site: + + - `OS_SANDBOX_HOOK_TIMEOUT_MS` — default hook budget (ms) + - `OS_SANDBOX_ACTION_TIMEOUT_MS` — default action budget (ms) + + Precedence is unchanged: an explicit `hookTimeoutMs` / `actionTimeoutMs` passed + to the runner still wins over the env var, and a body's own declared `timeoutMs` + still wins over the resolved default (the smaller of the explicit values). Only + a positive integer is honored; unset / empty / non-numeric / non-positive keeps + the built-in 250ms / 5000ms defaults, so behaviour is byte-for-byte unchanged + when the vars are absent — production is unaffected unless it opts in. + + CI's Test Core now sets `OS_SANDBOX_HOOK_TIMEOUT_MS=10000` so the shared-runner + load flake can't recur; genuine hangs stay bounded by each test's own timeout. + +### Patch Changes + +- Updated dependencies [f972574] +- Updated dependencies [22013aa] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [a8aa34c] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [5e3301d] +- Updated dependencies [46e876c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [beaf2de] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/spec@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/types/package.json b/packages/types/package.json index 64610e365e..ac8d3de921 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/types", - "version": "15.1.1", + "version": "16.0.0-rc.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 640468b208..e1236f4b6d 100644 --- a/packages/verify/CHANGELOG.md +++ b/packages/verify/CHANGELOG.md @@ -1,5 +1,82 @@ # @objectstack/verify +## 16.0.0-rc.0 + +### Patch Changes + +- Updated dependencies [b39c65d] +- Updated dependencies [f972574] +- Updated dependencies [2f3c641] +- Updated dependencies [e38da5b] +- Updated dependencies [f9b118d] +- Updated dependencies [22013aa] +- Updated dependencies [a9459e6] +- Updated dependencies [3ad3dd5] +- Updated dependencies [3a18b60] +- Updated dependencies [02eafa5] +- Updated dependencies [deb7e7e] +- Updated dependencies [a8aa34c] +- Updated dependencies [e057f42] +- Updated dependencies [a3823b2] +- Updated dependencies [43a3efb] +- Updated dependencies [524696a] +- Updated dependencies [fdc244e] +- Updated dependencies [5e3301d] +- Updated dependencies [dd9f223] +- Updated dependencies [46e876c] +- Updated dependencies [780b4b5] +- Updated dependencies [2ea08ee] +- Updated dependencies [d1d1c40] +- Updated dependencies [616e839] +- Updated dependencies [5f05de2] +- Updated dependencies [021ba4c] +- Updated dependencies [158aa14] +- Updated dependencies [d2723e2] +- Updated dependencies [fefcd54] +- Updated dependencies [efbcfe1] +- Updated dependencies [2049b6a] +- Updated dependencies [beaf2de] +- Updated dependencies [1e145eb] +- Updated dependencies [369eb6e] +- Updated dependencies [b659111] +- Updated dependencies [5754a23] +- Updated dependencies [6c270a6] +- Updated dependencies [290e2f0] +- Updated dependencies [668dd17] +- Updated dependencies [8abf133] +- Updated dependencies [e0859b1] +- Updated dependencies [92f5f19] +- Updated dependencies [a2d6555] +- Updated dependencies [3a6310c] +- Updated dependencies [32899e6] +- Updated dependencies [515f11a] +- Updated dependencies [4174a07] +- Updated dependencies [ce468c8] +- Updated dependencies [04ecd4e] +- Updated dependencies [4d5a892] +- Updated dependencies [16cebeb] +- Updated dependencies [86d30af] +- Updated dependencies [8923843] +- Updated dependencies [a2795f6] +- Updated dependencies [f16b492] +- Updated dependencies [4b6fde8] +- Updated dependencies [2018df9] +- Updated dependencies [fc5a3a2] + - @objectstack/runtime@16.0.0-rc.0 + - @objectstack/spec@16.0.0-rc.0 + - @objectstack/plugin-security@16.0.0-rc.0 + - @objectstack/objectql@16.0.0-rc.0 + - @objectstack/plugin-hono-server@16.0.0-rc.0 + - @objectstack/service-automation@16.0.0-rc.0 + - @objectstack/plugin-sharing@16.0.0-rc.0 + - @objectstack/rest@16.0.0-rc.0 + - @objectstack/service-analytics@16.0.0-rc.0 + - @objectstack/plugin-auth@16.0.0-rc.0 + - @objectstack/core@16.0.0-rc.0 + - @objectstack/driver-sqlite-wasm@16.0.0-rc.0 + - @objectstack/service-datasource@16.0.0-rc.0 + - @objectstack/service-settings@16.0.0-rc.0 + ## 15.1.1 ### Patch Changes diff --git a/packages/verify/package.json b/packages/verify/package.json index 1fd963301b..b5d6586df7 100644 --- a/packages/verify/package.json +++ b/packages/verify/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/verify", - "version": "15.1.1", + "version": "16.0.0-rc.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 99ab416cc2..7cab9cc19e 100644 --- a/packages/vscode-objectstack/CHANGELOG.md +++ b/packages/vscode-objectstack/CHANGELOG.md @@ -1,5 +1,7 @@ # objectstack-vscode +## 16.0.0-rc.0 + ## 15.1.1 ## 15.1.0 diff --git a/packages/vscode-objectstack/package.json b/packages/vscode-objectstack/package.json index 7e8795200a..802487f4bb 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": "16.0.0-rc.0", "publisher": "objectstack", "license": "Apache-2.0", "repository": {