diff --git a/.changeset/adr-0067-commit-history.md b/.changeset/adr-0067-commit-history.md deleted file mode 100644 index a361ee90c..000000000 --- a/.changeset/adr-0067-commit-history.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'@objectstack/metadata-core': minor -'@objectstack/objectql': minor -'@objectstack/runtime': minor ---- - -Package-scoped commit history & rollback for AI authoring (ADR-0067) - -Each authoring apply now lands as one revertible **commit** on a package timeline, on top of `sys_metadata_history`: - -- New `sys_metadata_commit` object groups a turn's metadata changes (by `event_seq` range). -- `publishPackageDrafts` records each publish as one commit (best-effort) with a per-artifact revert plan and an optional `message` / `aiModel`. -- New protocol methods `listCommits`, `revertCommit`, `rollbackToPackageCommit` (reusing `restoreVersion` + delete; a revert is itself an append-only commit). -- New REST routes: `GET /packages/:id/commits`, `POST /packages/:id/commits/:commitId/revert`, `POST /packages/:id/rollback`. diff --git a/.changeset/adr-0070-d4-duplicate-package.md b/.changeset/adr-0070-d4-duplicate-package.md deleted file mode 100644 index fedba8b17..000000000 --- a/.changeset/adr-0070-d4-duplicate-package.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -"@objectstack/objectql": patch -"@objectstack/runtime": patch ---- - -feat(objectql): duplicate a writable base — ADR-0070 D4 ("duplicate base") - -`protocol.duplicatePackage` clones every ACTIVE item a base owns into a NEW -package, **re-namespacing** object names (the blueprint prefixes a base's object -names with its namespace, e.g. `iojn_repair_ticket`, and `sys_metadata` keys on -`(type,name,org)` so a same-name copy would collide with the source) and -**rewriting every intra-package reference** (lookup `reference`, view `object`, -expressions, …) to the new names via a longest-first, identifier-boundary -replace. Exposed as `POST /packages/:id/duplicate` (body -`{ targetPackageId, targetName?, targetNamespace? }`). - -Completes ADR-0070 D4 (package = lifecycle unit): delete-cascade and export -already shipped; this adds the duplicate gesture. diff --git a/.changeset/adr-0070-d5-orphan-migration.md b/.changeset/adr-0070-d5-orphan-migration.md deleted file mode 100644 index 97223ea59..000000000 --- a/.changeset/adr-0070-d5-orphan-migration.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -"@objectstack/objectql": patch -"@objectstack/runtime": patch ---- - -feat(objectql): adopt orphaned metadata into a base — ADR-0070 D5 migration - -`protocol.reassignOrphanedMetadata` bulk-rebinds every package-less orphan -(`package_id` null / `""` / the `sys_metadata` sentinel left by the pre- -package-first stopgaps) onto a target base, leaving already-owned rows -untouched. Exposed as `POST /packages/:id/adopt-orphans`. This is the migration -affordance behind retiring the "Local / Custom" scope (D5): once an env has no -orphans, that scope can be dropped from the selector. Pairs with the kernel's -`writable_package_required` (D1) so no NEW orphans are created. diff --git a/.changeset/adr-0070-kernel-writable-package.md b/.changeset/adr-0070-kernel-writable-package.md deleted file mode 100644 index c41b02317..000000000 --- a/.changeset/adr-0070-kernel-writable-package.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -"@objectstack/objectql": patch ---- - -feat(objectql): enforce package-first authoring at the kernel (ADR-0070 D1/D2) - -A runtime-only metadata **create** that targets a read-only code/installed -package now throws `writable_package_required` (status 422) instead of silently -coercing `package_id` to `null`. The old coercion (#2252 stopgap) unblocked -editing but scattered orphans into a package-less bucket with no container to -delete (#1946); the rejection instead directs the authoring surface (Studio / -AI) to pick or create a writable base first. - -`isLoadedPackage` is generalized into `isWritablePackage` (D2): a package is -writable unless it is a booted code package (registered in the engine manifest -map) or a `system`/`cloud`-scoped installed package. The old "owns ≥1 registered -object" heuristic is dropped — it was the read-only-after-publish trap (#2252), -since a writable base accrues registered objects once its drafts publish. - -`null` is still accepted as the legacy org-overlay destination; ADR-0070 D5 -retires it after the orphan migration. diff --git a/.changeset/analytics-boolean-filter-groupby.md b/.changeset/analytics-boolean-filter-groupby.md deleted file mode 100644 index bf2a395c7..000000000 --- a/.changeset/analytics-boolean-filter-groupby.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@objectstack/service-analytics": patch ---- - -fix(analytics): compare boolean filters/group-by against the real boolean, not stringified '1' - -The analytics filter normalizer stringified boolean `true` → `'1'`, which the -ObjectQL strategy then coerced back to the number `1` before calling -`engine.aggregate`. Boolean fields hold a real `true`/`false`, so `1 !== true` -never matched: a metric widget filtered on a boolean field (e.g. -`{ is_critical: true }`) always returned 0, and pie/donut/bar charts grouped by -a boolean dimension failed to bucket. `stringifyForCube` now serializes booleans -as the tokens `'true'`/`'false'`, and a new `coerceFilterValueForObjectQL` -recovers a real boolean for the ObjectQL engine while the SQL path keeps binding -`1`/`0` (better-sqlite3 cannot bind a JS boolean). diff --git a/.changeset/auth-config-sso-feature-flag.md b/.changeset/auth-config-sso-feature-flag.md deleted file mode 100644 index 6d9d73984..000000000 --- a/.changeset/auth-config-sso-feature-flag.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -"@objectstack/plugin-auth": patch ---- - -feat(auth): surface `features.sso` in the public `/auth/config` response - -`getPublicConfig()` reported every other auth capability flag (`oidcProvider`, -`twoFactor`, `multiOrgEnabled`, …) but omitted enterprise SSO, even though the -manager already computes whether the domain-routed `@better-auth/sso` plugin is -wired (`OS_SSO_ENABLED` / `plugins.sso`). Without it the login UI had no signal -to gate on, so it rendered a "Sign in with SSO" button unconditionally — and on -a self-hosted / local deployment where SSO isn't wired, clicking it only then -surfaced "No SSO provider is configured for this email domain." - -The config now includes `features.sso`. `getPublicConfig()` returns the coarse -"is the plugin wired" flag — resolved with the EXACT logic that decides whether -the plugin is mounted in `buildPlugins()`, so the advertised capability can never -disagree with the actual `/sign-in/sso` route. The `/auth/config` route then -refines it to "usable" via the new `AuthManager.isSsoUsable()`, which additionally -requires at least one `sys_sso_provider` row to exist — so a freshly-enabled but -unconfigured SSO setup doesn't advertise a button that errors for everyone. -`isSsoUsable()` only queries when wired and fails open to the wired flag on any -introspection error (no data engine, query failure), so config never 500s. The -console login form consumes `features.sso` to hide the button (objectui side). diff --git a/.changeset/ce-ai-opt-in.md b/.changeset/ce-ai-opt-in.md deleted file mode 100644 index d48a0f14d..000000000 --- a/.changeset/ce-ai-opt-in.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -"@objectstack/cli": minor -"@objectstack/spec": minor ---- - -feat(cli): make the AI service opt-in via a declared dependency; honor `config.tiers` - -**AI edition boundary (cli).** The CLI auto-registered the headless `AIServicePlugin` -whenever the `ai` tier was enabled (default) and `@objectstack/service-ai` was -merely *resolvable*. In a workspace/monorepo the package is hoist-resolvable even -when an app does not declare it, so every app got the AI service — discovery -reported `services.ai: available` and the agent runtime served any -metadata-defined agents — including Community-Edition apps that ship no AI. - -Now the *declared* dependency is the boundary: AIService auto-registers only when -the host app declares `@objectstack/service-ai` **or** `@objectstack/service-ai-studio` -(Studio attaches its personas via the base service's `ai:ready` hook, so declaring -Studio implies the base). A CE app that declares neither gets no AI service, no -agents, and `services.ai: { enabled: false, status: 'unavailable' }` in discovery -(so the console hides its AI surface). MCP and every other capability are -unaffected. The `app-showcase`/`app-crm` examples now declare `@objectstack/service-ai`. - -**`config.tiers` now honored (spec).** `ObjectStackDefinitionSchema` gains a `tiers` -field, so `defineStack` no longer strips it. `config.tiers` (e.g. a list WITHOUT -`ai`) now actually overrides the `--preset` default — previously it was silently -dropped by schema validation, making the `--preset` help text inaccurate. This is -a second, in-place way to disable AI for a deployment without touching dependencies. diff --git a/.changeset/chart-config-colors-map.md b/.changeset/chart-config-colors-map.md deleted file mode 100644 index 966ad7cc8..000000000 --- a/.changeset/chart-config-colors-map.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@objectstack/spec": patch ---- - -feat(spec): type ChartConfig `colors` as a palette OR a value→color map - -`ChartConfigSchema.colors` now accepts either a positional palette (`string[]`) -or an explicit value→color map (`Record`, kanban-style). A -value→color map — and a select/lookup dimension's option colors — take -precedence over the positional palette per category, so semantic charts -(health, status) paint their own colors instead of the generic palette. diff --git a/.changeset/client-remove-env-member-methods.md b/.changeset/client-remove-env-member-methods.md deleted file mode 100644 index e6808bc15..000000000 --- a/.changeset/client-remove-env-member-methods.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@objectstack/client": patch ---- - -chore(client): remove dead `projects.*` env-member SDK methods (cloud#533 / ADR-0024 D9) - -Removes `projects.listMembers` / `addMember` / `updateMemberRole` / `removeMember`, -which called `GET/POST/PATCH/DELETE /api/v1/cloud/environments/:id/members`. Those -control-plane endpoints were deleted in cloud#533 (retiring `sys_environment_member`), -so the methods returned 404. Org membership/invites now flow through the better-auth -`organization` plugin (`organization.inviteMember` / `listMembers` / …); objectui -already uses `organization.*` and no in-repo callers remained. - -The `membership` field on the `projects.get()` response is unchanged — cloud#533 still -returns it on the single-env GET (re-sourced to the caller's org `sys_member` role). diff --git a/.changeset/dashboard-widget-layout-optional.md b/.changeset/dashboard-widget-layout-optional.md deleted file mode 100644 index 9f6d1299d..000000000 --- a/.changeset/dashboard-widget-layout-optional.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -"@objectstack/spec": patch ---- - -fix(spec): make dashboard widget `layout` optional (auto-flowed when omitted) - -`DashboardWidgetSchema.layout` was required, but the entire runtime treats it as -optional: the renderer (`DashboardGridLayout`) auto-flows any widget without a -layout (`x: (i % 4) * 3, y: ⌊i/4⌋ * 4, w: 3, h: 4`), and the Studio dashboard -designer adds widgets **without** a layout by design. - -The mismatch meant every dashboard authored in the Studio designer failed spec -validation the moment a widget was added — the draft `PUT /meta/dashboard/...` -returned **422** ("widgets: Invalid type: expected object, received undefined"), -so the draft never saved and **Publish stayed disabled**, even though the widget -rendered correctly in the canvas. Found by dogfooding the dashboard designer in -the browser. - -`layout` is now optional; absence means "auto-place". Authors may still pin an -explicit grid position. Backward-compatible — existing dashboards that specify -`layout` are unaffected. diff --git a/.changeset/dataset-authoring-form.md b/.changeset/dataset-authoring-form.md deleted file mode 100644 index f8bd5ce73..000000000 --- a/.changeset/dataset-authoring-form.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -"@objectstack/spec": minor ---- - -feat(spec): dataset authoring form + derived measures without a dummy aggregate - -`dataset` was the only UI-authorable metadata type without a `defineForm` -layout, so Studio's create surface fell back to the auto-generated flat layout -(free-text `object`, no grouping). Adds `dataset.form.ts` (registered in -`METADATA_FORM_REGISTRY`): sectioned Basics / Source / Dimensions / Measures -with an `object` picker (`ref:object`) and guidance — matching the sibling -`report` editor. - -Also makes `DatasetMeasureSchema.aggregate` optional. A derived measure -(`derived: { op, of }`) combines other measures by name and `aggregate` is -ignored for it at compile time, but the schema still required it — so a derived -measure failed validation unless you added a meaningless aggregate. `aggregate` -is now required only for non-derived measures (enforced in the existing -`superRefine`). Backward compatible: existing measures that carry an aggregate -stay valid. diff --git a/.changeset/dataset-join-ambiguous-column.md b/.changeset/dataset-join-ambiguous-column.md deleted file mode 100644 index e909465af..000000000 --- a/.changeset/dataset-join-ambiguous-column.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@objectstack/service-analytics": patch ---- - -fix(analytics): qualify base-object columns in joined dataset queries - -A dataset that joins a related object (`include` + a `relationship.field` -dimension/measure) emitted BARE base-table columns in SELECT/GROUP BY while the -joined columns were alias-qualified. When the base and joined tables share a -column name (e.g. both have `status`), the query failed at runtime with -"ambiguous column name". `NativeSQLStrategy` now qualifies plain base-column -identifiers with the base table when the cube has joins; single-object cubes -are unchanged (byte-for-byte identical SQL). diff --git a/.changeset/dataset-multihop-joins.md b/.changeset/dataset-multihop-joins.md deleted file mode 100644 index 69e360ffc..000000000 --- a/.changeset/dataset-multihop-joins.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@objectstack/spec': minor -'@objectstack/service-analytics': minor ---- - -feat(analytics): multi-hop relationship joins for datasets (ADR-0071) - -A dataset's `include` and dimension/measure `field` paths may now traverse up to -3 to-one relationship hops (`account.owner.region`), not just one. The compiler -expands each declared path into the ordered join chain (one `cube.join` per path -prefix, aliased dot-free as `account__owner` so it stays a single valid SQL -identifier), and the NativeSQLStrategy emits the chained `LEFT JOIN`s. Per-hop -tenant/RLS read-scope is enforced for EVERY object in the chain — the -alias-driven scope loop already generalizes, so no security path is rewritten. - -Restricted to **to-one** (lookup / master_detail) relationships, which never fan -out — aggregates stay correct with no symmetric-aggregate machinery; to-many -traversal is out of scope. Single-hop datasets are byte-for-byte unchanged (the -dot-free alias is a no-op for a single segment). Undeclared paths are still -rejected (ADR-0021 D-C); paths beyond 3 hops are rejected at both parse and -compile time. diff --git a/.changeset/dev-reload-scheduled-flow-rebind.md b/.changeset/dev-reload-scheduled-flow-rebind.md deleted file mode 100644 index 7912e03cd..000000000 --- a/.changeset/dev-reload-scheduled-flow-rebind.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -"@objectstack/service-automation": patch -"@objectstack/metadata": patch ---- - -fix(automation): re-bind scheduled-flow jobs on `os dev` hot-reload - -Editing a schedule-triggered flow under `objectstack dev` silently kept firing -the OLD definition until a full server restart. The dev watcher recompiles -`dist/objectstack.json` and MetadataPlugin reloads it into the MetadataManager -(so GET /meta reads + UI HMR are fresh), but the AutomationEngine pulls its flow -definitions and trigger/job bindings ONCE at boot — nothing re-registered them -on reload. So the scheduled job bound at boot kept running the pre-edit flow -(old `runAs`, schedule, or logic) on its timer, with no signal that the edit had -no effect. - -Fix: MetadataPlugin now fires a generic `metadata:reloaded` hook after each -artifact reload (the HMR POST handler and the server-side artifact-file watcher; -never on the initial boot load). AutomationServicePlugin subscribes and re-syncs -the engine from the metadata service — re-registering every current flow -(idempotent: `registerFlow` re-binds the trigger, and `ScheduleTrigger.start` -cancels + reschedules the job) and unregistering flows removed from the artifact -so their jobs stop firing. This covers all auto-triggered flow types -(schedule / record-change / api), not just scheduled ones, since record-change -flows were also executing their boot-time definitions after an edit. Production -deployments are unaffected — nothing reloads the artifact there. diff --git a/.changeset/docs-formula-returntype.md b/.changeset/docs-formula-returntype.md deleted file mode 100644 index 42ba7f3a4..000000000 --- a/.changeset/docs-formula-returntype.md +++ /dev/null @@ -1,4 +0,0 @@ ---- ---- - -docs: formula guides declare a formula result type via `returnType` (not the forbidden `type`); CEL source on `expression`. diff --git a/.changeset/flow-assignment-config-shape.md b/.changeset/flow-assignment-config-shape.md deleted file mode 100644 index 5feabee84..000000000 --- a/.changeset/flow-assignment-config-shape.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -"@objectstack/service-automation": patch ---- - -fix(automation): honor the `assignments` wrapper shape on assignment nodes - -The built-in `assignment` node executor set each TOP-LEVEL `config` key as a flow -variable. But the surfaces that author these nodes all emit an `assignments` -wrapper instead: - -- Studio's visual Assignment editor → `config: { assignments: { : } }` -- bundled example flows (app-crm, showcase) → `config: { assignments: [{ variable, value }] }` - -So a node designed in Studio (or any of the shipped examples) silently set a -single variable literally named `assignments` to the whole map/array and never -set the intended variables — it passed build and no-oped at run time, leaving -every downstream reference unresolved. - -The executor now normalizes all three shapes (`assignments` map, `assignments` -array of `{ variable | name | key, value }`, and the legacy flat -`{ : }`) and interpolates `{var}` templates in the values, matching -the CRUD / screen nodes. Adds `logic-nodes.test.ts` covering each shape as a -regression guard. diff --git a/.changeset/flow-builder-back-edge-style.md b/.changeset/flow-builder-back-edge-style.md deleted file mode 100644 index 3cc9a338f..000000000 --- a/.changeset/flow-builder-back-edge-style.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@objectstack/spec': patch ---- - -feat(spec): add the `back` edge style to the flow-builder canvas protocol - -`FlowCanvasEdgeStyleSchema` gains a `back` value alongside `solid`/`dashed`/`dotted`/`bold`, marking an ADR-0044 declared back-edge (a `revise` loop's resubmit edge). Flow-builder-protocol consumers can now render it as a distinct curved/dashed return arc, set apart from forward flow — matching the objectui designer's hand-rolled canvas (objectstack-ai/objectui#1954). Part of #2274. diff --git a/.changeset/flow-runas-identity-enforcement.md b/.changeset/flow-runas-identity-enforcement.md deleted file mode 100644 index 72600f580..000000000 --- a/.changeset/flow-runas-identity-enforcement.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -'@objectstack/spec': minor -'@objectstack/service-automation': minor -'@objectstack/runtime': minor -'@objectstack/trigger-record-change': minor ---- - -fix(security): enforce flow `runAs` execution identity (#1888) - -The `service-automation` engine now honors `flow.runAs` instead of ignoring it. -Previously the CRUD nodes passed **no identity** to ObjectQL, so the security -middleware was skipped entirely — every flow ran effectively elevated regardless -of `runAs`. A `runAs:'user'` flow did **not** de-elevate (a privilege-boundary -surprise), and `runAs:'system'` did not *explicitly* elevate. - -The engine now establishes the run's data-layer identity at setup and restores -the caller's context afterward: - -- **`runAs:'system'`** → an elevated, RLS-bypassing system principal - (`{ isSystem: true }`): the run can read/write records the triggering user - cannot. -- **`runAs:'user'`** (default) → the **triggering user's** identity - (`{ userId, roles, permissions, tenantId }`): CRUD nodes' ObjectQL reads/writes - respect that user's row-level security, and the run can never exceed the - triggering user's grants. - -To keep `runAs:'user'` faithful to a direct request by that user, the REST -trigger route (`@objectstack/runtime`) and the record-change trigger -(`@objectstack/trigger-record-change`) now forward the caller's resolved -`roles`/`tenantId` into the `AutomationContext` (new optional fields), not just -`userId`. The new `resolveRunDataContext` helper is the single place that maps a -run's effective `runAs` to the ObjectQL context, shared by every data node. - -The `[EXPERIMENTAL — not enforced]` marker is removed from `FlowSchema.runAs`. - -**Behavior change / migration.** Flows that previously relied on the implicit -elevation (the default `runAs:'user'` ran unscoped) now run as the triggering -user and are subject to their RLS. **Declare `runAs:'system'` on any flow that -must read or write beyond the triggering user's access** (e.g. system -automations, cross-owner roll-ups). Schedule-triggered runs have no trigger user; -under `user` they stay unscoped (there is no identity to scope to) — declare -`system` to make elevation explicit. - -Proven both directions by the dogfood regression gate -(`flow-runas.dogfood.test.ts` — a restricted member triggers system vs user -flows against an owner-scoped record) and service-automation unit + regression -tests (`crud-runas.test.ts`). diff --git a/.changeset/formula-infer-value-type.md b/.changeset/formula-infer-value-type.md deleted file mode 100644 index 76e4bad28..000000000 --- a/.changeset/formula-infer-value-type.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@objectstack/formula": minor -"@objectstack/spec": minor ---- - -Formula field typing: `inferExpressionType()` + a declared `returnType`. - -- `@objectstack/formula`: new `inferExpressionType()` (and lower-level `inferCelType()`) surfaces the cel-js type-checker's result for a CEL value/formula expression, mapped to `number | text | boolean | date | unknown`. Conservative — two `dyn` operands stay `unknown`; typed literals/stdlib returns pin a concrete type. -- `@objectstack/spec`: `FieldSchema` gains an optional `returnType` (`number|text|boolean|date`) so a formula field can carry its declared value type (the way Salesforce/Airtable do), letting consumers (dataset measures, formatting, validation) read a declared type instead of re-parsing the expression. diff --git a/.changeset/lint-approval-revise-loop.md b/.changeset/lint-approval-revise-loop.md deleted file mode 100644 index 7dff6d0dc..000000000 --- a/.changeset/lint-approval-revise-loop.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@objectstack/cli': patch ---- - -feat(cli): lint ADR-0044 approval revise-loop footguns at compile time - -`objectstack compile` now warns on two send-back-for-revision shapes an AI (or human) authoring an approval flow commonly gets wrong: - -- **Dead-end revise** — an approval node with a `revise` out-edge but no path looping back to it. This is a valid DAG, so `registerFlow` accepts it, yet the submitter reworks the record with nowhere to resubmit. The linter is the only place that catches the dead end. -- **Un-declared revise loop** — the loop returns to the approval but the closing edge isn't `type: 'back'`, so `registerFlow` rejects it as an un-declared cycle. The lint fires at compile time with the specific fix (mark the resubmit edge `type: 'back'`). - -Also flags `maxRevisions: 0` alongside a `revise` edge (send-back disabled, so the branch always auto-rejects and never runs). Advisory only — never fails the build. Part of #2274 / ADR-0044. diff --git a/.changeset/meta-item-cache-control-no-cache.md b/.changeset/meta-item-cache-control-no-cache.md deleted file mode 100644 index 2e385c728..000000000 --- a/.changeset/meta-item-cache-control-no-cache.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -"@objectstack/objectql": patch -"@objectstack/rest": patch ---- - -fix(objectql,rest): single-item meta reads must revalidate (no `max-age=3600`) - -`GET /api/v1/meta/object/:name` (and the other single-item meta reads served by -the cached path) sent `Cache-Control: public, max-age, max-age=3600`. Two bugs: - -1. **Stale metadata for up to an hour.** Object metadata is invalidated by - publish, but a one-hour TTL let browsers (and any CDN/proxy) serve a stale - schema *without revalidating* — e.g. the AI-build "New" create form kept - rendering pre-publish fields until the TTL lapsed. The list endpoint - `GET /api/v1/meta/object` is uncached, which is why list views updated but - single-object reads didn't. `getMetaItemCached` now returns - `directives: ['private', 'no-cache']` with no `maxAge`, so the ETag validator - (which already changes on publish) gates freshness: a cheap `304` when - unchanged, fresh fields the instant a publish bumps the ETag. `private` also - keeps per-tenant metadata out of shared caches. - -2. **Malformed header.** The directives array carried a bare `max-age` - placeholder *and* the REST layer appended `max-age=3600` from the `maxAge` - field, concatenating into `public, max-age, max-age=3600`. The header builder - now strips the bare `max-age` token before appending the real value, so a - `maxAge` is emitted once as a well-formed `max-age=N`. diff --git a/.changeset/meta-types-create-seed.md b/.changeset/meta-types-create-seed.md deleted file mode 100644 index 06ea23745..000000000 --- a/.changeset/meta-types-create-seed.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@objectstack/spec': minor -'@objectstack/objectql': minor ---- - -Expose authoritative create seeds via /meta/types (spec-derived create-shape contract, Phase 2) - -The minimal valid create seeds added in `@objectstack/spec/kernel` (`getMetadataCreateSeed`) now reach consumers through the real `/meta/types` registry response: each entry carries an optional `createSeed`. The Studio designer / CLI / API clients derive their create defaults from this single source of truth instead of re-inventing them — closing the drift that produced the dashboard-`layout` and action-`body` create→save 422s. - -- `@objectstack/spec`: barrel-export `getMetadataCreateSeed` / `listMetadataCreateSeedTypes` from `/kernel`; add optional `createSeed` to the `GetMetaTypesResponse` entry schema. -- `@objectstack/objectql`: `getMetaTypes()` attaches each type's seed (registry + runtime entries). Canvas-create types whose shape is built interactively (report) are intentionally absent. diff --git a/.changeset/page-hard-remove-dead-schemas.md b/.changeset/page-hard-remove-dead-schemas.md deleted file mode 100644 index 9f196b972..000000000 --- a/.changeset/page-hard-remove-dead-schemas.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -"@objectstack/spec": minor ---- - -chore(spec): hard-remove the dead `blank`/`record_review` page config (enforce-or-remove) - -Completes the enforce-or-remove started in framework#2265. The `blank` and -`record_review` page types were already removed from `PageTypeSchema` (no -renderer), their fields marked `@deprecated`, and objectui dropped all -references (objectui#1949). This deletes the now-unreachable surface: - -- `BlankPageLayoutSchema`, `BlankPageLayoutItemSchema`, `RecordReviewConfigSchema` - (and their inferred types `BlankPageLayout`, `BlankPageLayoutItem`, - `RecordReviewConfig`). -- The `blankLayout` and `recordReview` fields on `PageSchema`. -- `page-builder.zod.ts` (the `blank`-type drag-drop canvas config: - `PageBuilderConfigSchema` / `CanvasSnapSettingsSchema` / `CanvasZoomSettingsSchema` - / `ElementPaletteItemSchema` / `InterfaceBuilderConfigSchema` and their types) - and its `@objectstack/spec/studio` re-exports — nothing consumed them. - -The `page` liveness ledger drops to 15 properties (the 2 `dead` entries are gone). -No consumers in framework or objectui (objectui#1949 already merged). - -**Version note (kept `minor`, not `major`).** These exports shipped in the -published `10.3.0`, so under ADR-0059 §4 (the freeze contract) a removal would -normally demand a major bump. It is kept `minor` as a deliberate, documented -exception: the removed symbols are config schemas for the renderless -`blank`/`record_review` page types — authoring those already failed at runtime -("Unknown component type"), the frozen `@objectstack/downstream-contract` -fixture never referenced them, and the pre-publish hotcrm live gate guards -against any real consumer break. The `api-surface.json` snapshot is regenerated -alongside this so the removal is acknowledged, not silent. diff --git a/.changeset/page-liveness-ledger.md b/.changeset/page-liveness-ledger.md deleted file mode 100644 index fb1fa8223..000000000 --- a/.changeset/page-liveness-ledger.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@objectstack/spec": patch ---- - -chore(liveness): bring `page` under the spec liveness gate - -Onboards the `page` metadata type to the ADR-0049/#1919 liveness ledger -(`packages/spec/liveness/page.json`) and adds it to the governed-types list in -`check-liveness.mts`. Every authorable PageSchema property now declares a -status with evidence: 17 properties — 14 `live` (objectui renderer consumers -cited as prose), 1 `experimental` (`variables` — provider/hook exist, no -end-to-end consumer), 2 `dead` (`recordReview` / `blankLayout` — their page -types were removed in framework#2265 and objectui dropped all references in -objectui#1949; the fields stay @deprecated pending hard-removal). CI now fails -if a new page property lands unclassified. diff --git a/.changeset/page-type-enforce-or-remove.md b/.changeset/page-type-enforce-or-remove.md deleted file mode 100644 index 5c1d1ca5f..000000000 --- a/.changeset/page-type-enforce-or-remove.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -"@objectstack/spec": minor ---- - -fix(spec): remove unrendered roadmap page types from PageTypeSchema (enforce-or-remove) - -`PageTypeSchema` advertised six page types that never shipped a renderer — -`dashboard`, `form`, `record_detail`, `record_review`, `overview`, `blank`. -Authoring one passed schema validation but broke at runtime ("Unknown component -type"), a false affordance that's especially dangerous when templates are -AI-authored. Per ADR-0049 (enforce-or-remove), the enum is now the *live* set -(`record`, `home`, `app`, `utility`, `list`) — authoring a removed type now -fails fast at parse instead of silently at render. The removed types are tracked -in the new `PAGE_TYPE_ROADMAP` export and re-enter the enum only when a renderer -ships. A `page-type-liveness` gate test asserts the enum never re-grows a -roadmap type. - -The `recordReview`/`blankLayout` config schemas and fields are retained but -`@deprecated` (their page types are no longer authorizable) to avoid breaking -downstream imports; they will be removed in a coordinated follow-up. The -`variables` page field is documented `@experimental` — its state container is -wired but no consumer reads/writes it end-to-end yet. diff --git a/.changeset/page-variables-live.md b/.changeset/page-variables-live.md deleted file mode 100644 index 54a310715..000000000 --- a/.changeset/page-variables-live.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@objectstack/spec': patch ---- - -Promote `PageSchema.variables` from @experimental to live (ADR-0049) - -Page-local state is now wired end-to-end (runtime in objectui#1957: page -variables are injected into the visible/CEL expression context as `page.`, -and `element:record_picker` writes a variable via its `source` binding). The -spec docs are updated to describe the now-live behaviour and the binding -direction, and the liveness ledger entry is flipped `experimental → live`. diff --git a/.changeset/rest-export-route-before-getbyid.md b/.changeset/rest-export-route-before-getbyid.md deleted file mode 100644 index 283c53557..000000000 --- a/.changeset/rest-export-route-before-getbyid.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -"@objectstack/rest": patch ---- - -fix(rest): register static data-action routes before the greedy `:object/:id` matcher - -The REST router matches first-registered-wins with no specificity sorting, but -`registerDataActionEndpoints` (which holds `GET /data/:object/export`) ran AFTER -`registerCrudEndpoints` (which holds the greedy `GET /data/:object/:id`). A -request to `GET /data//export` was therefore captured by `:object/:id` — -`"export"` treated as a record id — returning `404 RECORD_NOT_FOUND` instead of -streaming the export. The data-action registration now runs first, mirroring the -existing `/meta/:type/:name/references`-before-`/meta/:type/:name` convention. -Reordering is safe both ways: `registerDataActionEndpoints` contains no greedy -2-segment `:object/:id` routes, so it cannot shadow any CRUD literal. A -regression test asserts the export route registers ahead of the get-by-id route. diff --git a/.changeset/scheduled-flow-runas-unscoped.md b/.changeset/scheduled-flow-runas-unscoped.md deleted file mode 100644 index 621d5879a..000000000 --- a/.changeset/scheduled-flow-runas-unscoped.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -'@objectstack/service-automation': minor -'@objectstack/cli': minor -'@objectstack/spec': patch -'@objectstack/trigger-schedule': patch ---- - -fix(security): surface the schedule/user-less `runAs:'user'` fail-open (#1888 follow-up) - -With `flow.runAs` now enforced (#1888), a **schedule-triggered** flow with the -default `runAs:'user'` has no trigger user. `resolveRunDataContext` returns -`undefined` for that case, so the CRUD nodes pass no ObjectQL `options.context` -and the security middleware — which *skips* when there is no identity (it -delegates auth to the auth layer) — runs the operation **UNSCOPED** (effectively -elevated). An author who left `runAs` at the `'user'` default expecting a -restricted run silently gets an unscoped one — a fail-open footgun (ADR-0049: a -security property must not silently do the opposite of what it implies). - -This is the **product decision** to make that explicit, chosen to keep legitimate -scheduled CRUD working (denying outright would break it, and silently elevating -would hide the author's intent). Prevention happens where the platform can tell -intent apart (author/build time); the runtime stays non-breaking but is no longer -silent: - -- **Author-time lint** (`@objectstack/cli`, `lintFlowPatterns`): a new advisory - rule `flow-schedule-runas-unscoped` flags a schedule-triggered flow whose - effective `runAs` is `user` (explicit or unset) and which performs a data - operation — pointing the author at `runAs:'system'`. Catches the footgun at - compile time, before deploy (most flows are AI-authored). -- **Runtime warning** (`@objectstack/service-automation`): the engine now emits a - clear one-per-run warning when a user-mode run resolves no trigger identity and - the flow touches data — the fail-open is *audible* rather than silent. Behavior - is otherwise unchanged (the run still executes), so scheduled CRUD that relied - on this is not broken. New helpers `runIsUnscopedUserMode`, `flowTouchesData`, - and `DATA_NODE_TYPES` are exported alongside `resolveRunDataContext`. -- **Spec describe** (`@objectstack/spec`): `FlowSchema.runAs` now states that a - scheduled run has no user, so under `user` it runs unscoped — declare `system`. - -The first-party example apps that tripped the new lint are fixed to declare -`runAs:'system'` explicitly (`stale_opportunity_sweep`, the app-todo -`task_reminder` / `overdue_escalation` sweeps) — they read/write across owners and -were running unscoped by default. - -Longer term, attributing scheduled runs to a dedicated service principal (so they -are scopable + audit-attributable rather than unscoped) is the right enforcement; -tracked as M2 follow-up. - -Proven by a service-automation unit test (the engine warns once for a user-less -user-mode data run; stays silent for `system`, for an identified user, and for a -data-less flow), an end-to-end test wiring the **real `ScheduleTrigger` to the -real engine** (`@objectstack/trigger-schedule`) that fires a job and asserts the -user-less identity reaches the engine + trips the warning through the actual cron -path, and a dogfood gate (`flow-runas-schedule.dogfood.test.ts`) that drives -user-less runs through the real automation + security + data stack: a -`runAs:'user'` run reads + writes an owner-scoped note a member cannot — audibly — -while `runAs:'system'` is the explicit, warning-free equivalent. - -Refs #1888, ADR-0049. diff --git a/.changeset/sdui-related-list-add.md b/.changeset/sdui-related-list-add.md deleted file mode 100644 index 89a696255..000000000 --- a/.changeset/sdui-related-list-add.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@objectstack/spec': minor ---- - -feat(spec): RecordRelatedListProps.add — add-existing-via-picker (generic m2m/junction assignment). A related list can now link existing records via a picker, not just create+navigate. Powers a generic "Assigned Users" / Manage Assignments UI on permission sets. diff --git a/.changeset/sdui-text-input-element.md b/.changeset/sdui-text-input-element.md deleted file mode 100644 index 846754a88..000000000 --- a/.changeset/sdui-text-input-element.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -'@objectstack/spec': minor ---- - -feat(ui): add `element:text_input` — free-text data-entry element for SDUI pages - -SDUI pages could display and navigate but not collect free-text input. This adds -that half of the contract: - -- `ElementTextInputPropsSchema` (label, placeholder, `inputType` — - text/email/number/tel/url/password — defaultValue, required, disabled, - description) wired into `PageComponentType` and `ComponentPropsMap` as - `element:text_input`. - -The objectui renderer binds the typed value into a page variable -(`PageVariableSchema.source`); a submit `element:button` reads it back via -`{{page.}}` token interpolation in the console action runtime. Showcase: -`showcase_contact_form` (text inputs → page variables → POST web-to-lead). diff --git a/.changeset/setup-advanced-nav-unlistable.md b/.changeset/setup-advanced-nav-unlistable.md deleted file mode 100644 index 49473e117..000000000 --- a/.changeset/setup-advanced-nav-unlistable.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -"@objectstack/platform-objects": patch ---- - -fix(setup): drop Advanced nav entries for non-listable objects (sys_verification, sys_device_code) - -Dogfooding every Setup menu surfaced two Advanced entries that always render -"无法加载记录 / failed to load": **Verifications** (`sys_verification`) and -**Device Codes** (`sys_device_code`). Both objects deliberately omit `list` -from `apiMethods` (sensitive, ephemeral secrets — verification tokens and OAuth -device-grant codes are not meant to be browsed), so the generic object/list-view -menu can only ever 405. Removed both nav entries (and their orphaned zh labels); -the objects remain reachable by id. Re-adding a browse menu would require -enabling `list` on the object — a security decision, not a nav fix. diff --git a/.changeset/setup-firstrun-nav-i18n.md b/.changeset/setup-firstrun-nav-i18n.md deleted file mode 100644 index 34541a07a..000000000 --- a/.changeset/setup-firstrun-nav-i18n.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@objectstack/platform-objects": patch -"@objectstack/service-settings": patch -"@objectstack/rest": patch ---- - -fix(setup): first-run admin polish — pin Company/Localization, gate dashboard widgets by `requiresService`, i18n + settings PUT envelope - -Dogfooding the Setup app as a brand-new system administrator surfaced a cluster of small first-run gaps, now fixed: - -- **platform-objects**: pin **Localization** and **Company** in the Setup sidebar's Configuration group — both are registered `service-settings` manifests (the two lowest-`order` Workspace settings) but were reachable only via the "All Settings" hub. Translate the previously-English nav labels Cloud Connection (云连接), Datasources (数据源) and Capabilities (能力). Tag the System Overview `widget_organizations` KPI with `requiresService: 'org-scoping'`. -- **rest**: extend the ADR-0057 D10 server-side visibility gate to **dashboard widgets** — strip widgets whose `requiresService` names an unregistered kernel service (mirrors the existing app-nav gate; `resolveRegisteredServices` now also discovers gates declared on widgets). In a single-tenant runtime this removes the orphan "Organizations" KPI, matching the already-hidden org nav entries. -- **service-settings**: add the missing zh `help` strings for the Localization manifest (number/currency/first-day-of-week/fiscal-year fields), and accept the `{ values: { … } }` envelope on `PUT /api/settings/:ns` symmetrically with what `GET` returns. diff --git a/.changeset/single-org-gate-membership-surfaces.md b/.changeset/single-org-gate-membership-surfaces.md deleted file mode 100644 index 702850383..000000000 --- a/.changeset/single-org-gate-membership-surfaces.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -"@objectstack/platform-objects": patch ---- - -fix(platform-objects): hide org/membership surfaces in single-org mode - -The platform gates multi-org features two ways — nav entries on -`requiresService: 'org-scoping'` (e.g. setup-nav Organizations/Invitations) -and object actions on `visible: 'features.multiOrgEnabled != false'` (e.g. -`sys_organization.create_organization`). That convention had only been applied -to a handful of spots, so a wide band of org/membership surface leaked into -single-org deployments where it is pure noise or a broken affordance: - -- The Account app's "My Organizations" entry (`sys_member` / `mine` view) was - gated on `requiresObject: 'sys_member'` — but `sys_member` is a system object - that is always registered, so the gate never fired. In single-org there are - no `sys_organization` rows and no auto-stamped memberships, so the view is - always empty for every user. Re-gated on `requiresService: 'org-scoping'`. -- The setup-nav "Teams" entry had no gate at all, while its sibling - Organizations/Invitations entries were correctly service-gated. Added - `requiresService: 'org-scoping'`. -- Org/membership mutation actions rendered (and on toolbars, were clickable) - in single-org but hit better-auth endpoints that resolve an active org that - does not exist, failing at the API. Gated each on - `features.multiOrgEnabled != false`: - - `sys_user.invite_user` (the most exposed — the Users list is always - reachable in single-org) - - `sys_member.add_member` / `update_member_role` / `remove_member`, and - `transfer_ownership` (combined with its existing `record.role != 'owner'` - condition) - - `sys_team.create_team` / `update_team` / `remove_team` - - `sys_team_member.add_team_member` / `remove_team_member` - - `sys_invitation.invite_user` / `resend_invitation` / `cancel_invitation` - (recipient-side accept/reject stay record-gated; they are unreachable in - single-org anyway since no invitation rows exist) - -Also tightened the remaining single-org rough edges on these objects: - -- `sys_organization` admin actions (`update` / `delete` / `set_active` / - `leave` / `change_slug`) are now all gated on - `features.multiOrgEnabled != false`, joining the already-gated - `create_organization` — previously only create was gated. -- `titleFormat` no longer renders a null organization: `sys_member` is titled - `'{user_id} ({role})'` (was `'… in {organization_id}'`) and `sys_invitation` - is titled `'Invitation for {email}'` (was `'Invitation to {organization_id}'`). - In single-org `organization_id` is null, so the old formats read "… in null". - The new fields are more useful identifiers in both modes. - -No behavior change in multi-org deployments (`OS_MULTI_ORG_ENABLED=true`): -`features.multiOrgEnabled` is true and the `org-scoping` service is present, so -every gate evaluates to visible exactly as before. This is metadata-only — no -schema, API, or runtime changes. diff --git a/.changeset/single-source-multi-org-flag.md b/.changeset/single-source-multi-org-flag.md deleted file mode 100644 index 211750eba..000000000 --- a/.changeset/single-source-multi-org-flag.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -"@objectstack/types": patch ---- - -refactor: single-source the multi-org (`OS_MULTI_ORG_ENABLED`) flag resolution - -"Is this deployment multi-org?" was resolved in 10 places across 8 packages -with three subtly different inline expressions: - -- the canonical `String(readEnvWithDeprecation('OS_MULTI_ORG_ENABLED', - 'OS_MULTI_TENANT') ?? 'false').toLowerCase() !== 'false'` (objectql registry, - plugin-dev, runtime app-plugin, cli serve/verify, cloud-connection), -- a redundant `env.OS_MULTI_ORG_ENABLED !== undefined ? … : …` variant in - plugin-auth (auth-manager `/auth/config` features + `beforeCreateOrganization` - guard), -- and a bare `process.env.OS_MULTI_ORG_ENABLED ?? process.env.OS_MULTI_TENANT` - read in the SQL driver's `isMultiTenantMode()` — which skipped the - `OS_MULTI_TENANT` deprecation warning every other site emits. - -Because the SQL driver computed the mode independently of the auth/security -layer, the driver's tenant-audit gate and the rest of the system could in -principle disagree about whether tenant isolation is active. - -Introduces `resolveMultiOrgEnabled()` in `@objectstack/types` (next to -`readEnvWithDeprecation`, the natural leaf dependency) as the single source of -truth, and routes all 10 sites through it. `@objectstack/driver-sql` gains a -direct `@objectstack/types` dependency (previously it read `process.env` -directly). - -Behaviour is unchanged everywhere except the SQL driver, which now also emits -the one-shot `OS_MULTI_TENANT`-is-deprecated warning — consistent with every -other site. This mirrors the `resolveAuthzContext` single-source pattern in -`@objectstack/core`. Follow-up (not in this change): a lint gate forbidding new -inline reads of these env vars outside the helper. diff --git a/.changeset/slotted-page-no-slots-required.md b/.changeset/slotted-page-no-slots-required.md deleted file mode 100644 index de9f6514f..000000000 --- a/.changeset/slotted-page-no-slots-required.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@objectstack/spec": patch ---- - -fix(spec): don't require `slots` on slotted pages - -`PageSchema`'s superRefine rejected any `kind: 'slotted'` page that didn't -provide a `slots` map — but a slotted page with no overrides is valid: every -slot falls through to the synthesized default layout, the natural starting -point before you add overrides. Requiring `slots` up front made the Studio -"New Page" form a dead-end the moment you picked "slotted" (the form can't -author a slot map), the same trap as the old required `regions`. diff --git a/.changeset/spec-create-seeds.md b/.changeset/spec-create-seeds.md deleted file mode 100644 index adaed62b8..000000000 --- a/.changeset/spec-create-seeds.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@objectstack/spec': minor ---- - -Add authoritative per-type create seeds (root-cause for the "designer shape ≠ spec" family) - -New `metadata-create-seeds.ts`: a single source of truth for the minimal valid create shape of each metadata type (`getMetadataCreateSeed(type)`), co-located with the schemas and asserted valid against each type's schema by `metadata-create-seeds.test.ts`. This anchors the create-form's default shape to the spec so it can't drift — the root cause of the recurring family where a freshly-created item (dashboard without `layout`, script action without `body`, report with stale `objectName`/`columns`) failed validation on save (422) yet passed every other gate. Seeds the 9 core Studio-designer types (dashboard, action, page, view, flow, validation, hook, dataset, object); the test surfaces remaining schema-backed types still needing a seed. (Follow-up: expose `createSeed` via `/meta/types` so the Studio designer consumes it instead of hardcoding `createDefaults`.) diff --git a/.changeset/sqlite-canonical-audit-timestamp.md b/.changeset/sqlite-canonical-audit-timestamp.md deleted file mode 100644 index 17bf848fb..000000000 --- a/.changeset/sqlite-canonical-audit-timestamp.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -'@objectstack/driver-sql': patch ---- - -Fix: store SQLite `created_at`/`updated_at` in one canonical, timezone-explicit format (ADR-0074) - -The two SQLite write paths disagreed on the audit-timestamp format. INSERT fell -back to the column default `CURRENT_TIMESTAMP` (`'YYYY-MM-DD HH:MM:SS'`) while -UPDATE stamped `toISOString().replace('T',' ').replace('Z','')` -(`'YYYY-MM-DD HH:MM:SS.mmm'`) — both **timezone-naive**, space-separated strings -that `Date.parse` reads as *local* time. On a non-UTC runtime a stored UTC -wall-clock silently shifted by the host offset; e.g. the objectos kernel -freshness probe compared a shifted `updated_at` against an absolute `builtAtMs` -and never evicted (publishes/installs/config toggles didn't take effect until the -LRU TTL expired). - -`create` / `bulkCreate` / `upsert` / `update` now stamp a single canonical -ISO-8601 instant with an explicit `Z` (`new Date().toISOString()`) — matching the -caller-stamped paths (`sys_metadata`, the service outboxes) and Postgres/MySQL's -native `now()`. Because the stamp is applied app-side (not via the column -default), **existing** tenant databases are fixed immediately, not just freshly -created tables. `formatOutput` additionally repairs any legacy/raw zone-naive -audit timestamp to the same format on read (idempotent), so old rows read back -unambiguously without a data migration. `upsert` now treats `created_at` as -insert-only — a conflicting merge never overwrites it. - -Postgres/MySQL are unaffected (they store a real zone-aware `TIMESTAMP`). diff --git a/.changeset/sqlite-time-of-day-read.md b/.changeset/sqlite-time-of-day-read.md deleted file mode 100644 index 0d7090d9d..000000000 --- a/.changeset/sqlite-time-of-day-read.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -'@objectstack/driver-sql': patch ---- - -Fix: present `Field.time` as a wall-clock time-of-day on read (SQLite) - -`Field.time` is a tz-naive time-of-day, not an instant (#2004). A -`defaultValue: 'NOW()'` time column historically took the full SQLite -`CURRENT_TIMESTAMP` default, so a defaulted/legacy row read back a full -`'YYYY-MM-DD HH:MM:SS'` timestamp instead of a time-of-day. - -`formatOutput` now repairs a `Field.time` value to just its time portion -(`toTimeOnly`): a legacy full timestamp — or a full ISO value that leaked into -the column — is sliced to `HH:MM[:SS[.fff]]`, while a value already stored as a -bare time-of-day is left untouched. This is a deliberately NARROW, read-only -normalization with no write/filter counterpart, so it introduces no write/read -asymmetry and preserves exact round-trips for bare time-of-day values (e.g. the -field-zoo `f_time` guard). Runs for every dialect (a native TIME column already -returns a time-of-day, so it is a no-op there). - -Completes the temporal-field read normalization alongside #2346: `datetime` -folds to a canonical ISO-8601-`Z` instant, `date` to `YYYY-MM-DD`, and `time` to -a wall-clock time-of-day. diff --git a/.changeset/sqlite-user-datetime-now-default.md b/.changeset/sqlite-user-datetime-now-default.md deleted file mode 100644 index b2a45a733..000000000 --- a/.changeset/sqlite-user-datetime-now-default.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -'@objectstack/driver-sql': patch ---- - -Fix: canonical storage + presentation for user-declared `NOW()`-default temporal fields on SQLite (ADR-0074 follow-up) - -A user-declared `Field.datetime` (or `date`/`time`) with `defaultValue: 'NOW()'` -took the `knex.fn.now()` → `CURRENT_TIMESTAMP` column default on SQLite, storing a -**timezone-naive**, space-separated `'YYYY-MM-DD HH:MM:SS'` (no millis, no zone). -`Date.parse` reads such a zone-less string as *local* time, so the stored UTC -wall-clock shifted by the host offset on a non-UTC runtime — the same class of bug -ADR-0074 fixed for the builtin `created_at`/`updated_at` audit columns, but left -scoped out for user fields. Worse, the **same** column mixed storage: an explicit -JS `Date` is bound by better-sqlite3 as INTEGER epoch ms, while an omitted value -took the naive TEXT default — so one column held both INTEGER ms and naive TEXT. - -This fix, SQLite-only: - -- **DDL default → canonical.** The `NOW()` default now emits a per-type canonical - via `strftime`: datetime → ISO-8601 with explicit `Z` - (`strftime('%Y-%m-%dT%H:%M:%fZ','now')`, e.g. `2026-06-26T10:34:13.891Z`, - matching `new Date().toISOString()`); date → `YYYY-MM-DD`; time → `HH:MM:SS.fff` - time-of-day (not a full timestamp). -- **Read → uniform instant.** `formatOutput` folds every `Field.datetime` storage - form — INTEGER epoch ms, canonical ISO-`Z`, and legacy naive `CURRENT_TIMESTAMP` - TEXT — to one canonical ISO-8601-`Z` instant (`normalizeSqliteDatetimeOutput`), - interpreting a naive wall-clock as UTC. Idempotent on already-zone-explicit - values; total on null/unparseable. This transparently repairs existing rows on - read (a DDL default only governs newly-created columns), so no data migration is - needed — mirroring the `Field.date`/numeric read-repairs already in place. - -Applied as DDL-default + read-normalization, NOT app-side write stamping (the -inverse of ADR-0074's audit-column fix): the read path already repairs -existing-table rows transparently, and an explicit `Date` is bound as INTEGER -epoch ms regardless of any write stamp, so stamping wouldn't make on-disk storage -uniform anyway — the INTEGER-vs-TEXT split is inherent to SQLite and resolved at -the read boundary. This keeps the hot insert/upsert/bulk paths untouched. - -The analytics SQL-bucketing path (`strftime`, bypasses `formatOutput`) is -unchanged: ISO-`Z` TEXT buckets identically to the old naive TEXT. Postgres/MySQL -keep native `now()` (a real zone-aware `TIMESTAMP`) and are entirely unaffected. - -Generalizes ADR-0074's `repairNaiveUtcAuditTimestamp` by also folding the INTEGER -epoch-ms storage form; the two read-repairs can be unified once both land. diff --git a/.changeset/studio-page-regions-properties-optional.md b/.changeset/studio-page-regions-properties-optional.md deleted file mode 100644 index 86eee6429..000000000 --- a/.changeset/studio-page-regions-properties-optional.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@objectstack/spec": patch ---- - -fix(spec): make page `regions` and component `properties` optional - -`PageSchema.regions` and `PageComponentSchema.properties` were required, which -made it impossible to create record/home/app pages in the Studio editor: the -New Page form has no region editor, and the create-form seeds a record page's -default layout from `buildDefaultPageSchema`, whose nodes carry props at the top -level — so every seeded block tripped `regions.N.components.M.properties: -expected record`. Both are now `.optional().default(...)`; an empty full page -falls back to the synthesized default layout, slotted pages compose via `slots`, -list pages ignore regions, and prop-less components (record:activity, -element:divider) no longer need `properties: {}`. diff --git a/.changeset/unify-apache-license.md b/.changeset/unify-apache-license.md deleted file mode 100644 index 82444a0c8..000000000 --- a/.changeset/unify-apache-license.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -"@objectstack/core": patch ---- - -chore(license): unify the framework repo to a single Apache-2.0 license - -The repo was left in a half-finished, self-contradictory source-available -transition: 44 package `LICENSE` files carried restrictive dual-license text -(a Licensor of "ObjectStack AI LLC", a four-year conversion date, and an -anti-competitive-hosting grant) while those same packages' `package.json` -already declared `"license": "Apache-2.0"` — and that license text pointed at -`LICENSING.md` for the authoritative list of restricted packages, which listed -none. The root also carried a redundant `LICENSE.apache` left over from that -transition. - -The framework is deliberately permissive Apache-2.0 to maximize adoption; value -capture lives in the separate closed-source cloud repo, not here. This change -makes that unambiguous: every package `LICENSE` now contains the canonical -Apache 2.0 text (copied from the root `LICENSE`), the redundant root -`LICENSE.apache` is removed, and `LICENSING.md` states the entire repository is -Apache-2.0 with no dual-license language. No restrictive-license residue remains -anywhere outside `node_modules`. - -This is a metadata-only change (license text and `package.json` already agreed); -the patch bump republishes the affected packages with the corrected `LICENSE`. diff --git a/.changeset/unify-authz-resolver.md b/.changeset/unify-authz-resolver.md deleted file mode 100644 index 1a2aabb62..000000000 --- a/.changeset/unify-authz-resolver.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@objectstack/rest": patch -"@objectstack/runtime": patch -"@objectstack/core": patch ---- - -fix(security): single-source the request authorization resolver — REST no longer drops sys_user_role - -The REST server and the runtime dispatcher each carried their own copy of the request → ExecutionContext identity/role resolver, and they drifted on a security path. The REST copy silently omitted `sys_user_role` (so custom roles granted via the ADR-0057 D4 platform-RBAC path did not apply over REST), `sys_role_permission_set`, the `owner→org_owner` membership normalization, the platform-admin derivation, and the `ai_seat` synthesis — fail-closed (legitimate access denied), not an escalation. - -Both entry points now delegate to a single shared resolver, `resolveAuthzContext` in `@objectstack/core/security` (joining the API-key verifier that already lived there). A contract test locks every authorization source and a lint gate (`check:authz-resolver`) prevents a future duplicate resolver or a dropped delegation. diff --git a/.changeset/user-field-type.md b/.changeset/user-field-type.md deleted file mode 100644 index e680ed7f1..000000000 --- a/.changeset/user-field-type.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -'@objectstack/spec': minor -'@objectstack/objectql': minor -'@objectstack/driver-sql': minor -'@objectstack/driver-mongodb': minor -'@objectstack/cli': patch -'@objectstack/plugin-approvals': patch ---- - -feat: add a first-class `user` field type (person picker) - -A new `user` field type — the equivalent of Airtable's Collaborator / Notion's -Person / Salesforce's `Lookup(User)`. Authored as `Field.user({ ... })`; use -`{ multiple: true }` for collaborators/watchers and `{ defaultValue: 'current_user' }` -to auto-fill the acting user on create. - -**Why a distinct type rather than telling authors to `Field.lookup('sys_user')`:** -selecting a person is table-stakes, but the value is in *modelling -discoverability* — a "User" entry in the Studio/AI field palette instead of -requiring authors (and AI) to know to reference the internal `sys_user` system -object — plus `current_user` defaults and a user-search picker. Storage and -runtime are unchanged. - -**Deliberately NOT a new storage primitive.** `user` is a *semantic -specialization of `lookup`* with the target fixed to `sys_user`: it shares the -exact lookup code path — same FK string column (`multiple` ⇒ JSON), same -`$expand` resolution, same indexing — so referential integrity and fresh display -names come for free, and nothing is re-implemented. An existing -`Field.lookup('sys_user')` is therefore equivalent at the storage layer (zero -data migration to adopt `Field.user`). - -Ownership semantics are **unchanged**: the existing `owner_id` convention + -`plugin-security` auto-stamp/RLS still apply. A declarative `owner` flag is a -possible future follow-up; intentionally not added here to avoid a second -field type for what is a system role (rationale: keep the `FieldType` surface -lean — see related ADR-0059 freeze discipline). - -Changes: `FieldType` gains `'user'` + `Field.user()` builder; the SQL/Mongo -drivers treat `user` exactly like `lookup`; the engine resolves `$expand` for -`user` fields and honours a new `defaultValue: 'current_user'` token (resolved -app-side from the execution context, mirroring the `NOW()` convention); kanban -group-by and symbolic seed references accept `user`; approvals enrich `user` -references. The public API surface is unchanged (additive enum member). diff --git a/examples/app-crm/CHANGELOG.md b/examples/app-crm/CHANGELOG.md index 46420fc23..4f286caad 100644 --- a/examples/app-crm/CHANGELOG.md +++ b/examples/app-crm/CHANGELOG.md @@ -1,5 +1,36 @@ # @objectstack/example-crm +## 4.0.59 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/runtime@10.4.0 + - @objectstack/spec@10.4.0 + ## 4.0.58 ### Patch Changes diff --git a/examples/app-crm/package.json b/examples/app-crm/package.json index 8075b0af3..5e86929bf 100644 --- a/examples/app-crm/package.json +++ b/examples/app-crm/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/example-crm", - "version": "4.0.58", + "version": "4.0.59", "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 cdeee1d6b..779609c0a 100644 --- a/examples/app-showcase/CHANGELOG.md +++ b/examples/app-showcase/CHANGELOG.md @@ -1,5 +1,43 @@ # @objectstack/example-showcase +## 0.2.5 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [98a1535] +- Updated dependencies [bc22a89] +- Updated dependencies [8a7e9f1] +- Updated dependencies [4a84c98] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/runtime@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/driver-sql@10.4.0 + - @objectstack/cloud-connection@10.4.0 + - @objectstack/connector-rest@10.4.0 + - @objectstack/connector-slack@10.4.0 + ## 0.2.4 ### Patch Changes diff --git a/examples/app-showcase/package.json b/examples/app-showcase/package.json index 1a9196bc2..1f65f816d 100644 --- a/examples/app-showcase/package.json +++ b/examples/app-showcase/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/example-showcase", - "version": "0.2.4", + "version": "0.2.5", "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, AI). 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 951d08c1e..be5931c53 100644 --- a/examples/app-todo/CHANGELOG.md +++ b/examples/app-todo/CHANGELOG.md @@ -1,5 +1,47 @@ # @objectstack/example-todo +## 4.0.59 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [d616e1d] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [1b00ba2] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [4b5ec6e] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [359c0aa] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/objectql@10.4.0 + - @objectstack/runtime@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/client@10.4.0 + - @objectstack/metadata@10.4.0 + - @objectstack/mcp@10.4.0 + - @objectstack/driver-sqlite-wasm@10.4.0 + - @objectstack/knowledge-memory@10.4.0 + - @objectstack/service-knowledge@10.4.0 + ## 4.0.58 ### Patch Changes diff --git a/examples/app-todo/package.json b/examples/app-todo/package.json index 2526b6f5d..25e5ac3a3 100644 --- a/examples/app-todo/package.json +++ b/examples/app-todo/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/example-todo", - "version": "4.0.58", + "version": "4.0.59", "description": "Example Todo App using ObjectStack Protocol", "license": "Apache-2.0", "private": true, diff --git a/packages/adapters/express/CHANGELOG.md b/packages/adapters/express/CHANGELOG.md index 858ddda81..5c6ff0670 100644 --- a/packages/adapters/express/CHANGELOG.md +++ b/packages/adapters/express/CHANGELOG.md @@ -1,5 +1,16 @@ # @objectstack/express +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [6c4fbd9] +- Updated dependencies [aa33b02] + - @objectstack/runtime@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/adapters/express/package.json b/packages/adapters/express/package.json index b0896abae..35281c8aa 100644 --- a/packages/adapters/express/package.json +++ b/packages/adapters/express/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/express", - "version": "10.3.0", + "version": "10.4.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/adapters/fastify/CHANGELOG.md b/packages/adapters/fastify/CHANGELOG.md index 21e8497f0..f82a1d97d 100644 --- a/packages/adapters/fastify/CHANGELOG.md +++ b/packages/adapters/fastify/CHANGELOG.md @@ -1,5 +1,16 @@ # @objectstack/fastify +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [6c4fbd9] +- Updated dependencies [aa33b02] + - @objectstack/runtime@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/adapters/fastify/package.json b/packages/adapters/fastify/package.json index 8f076dbb1..d7570f023 100644 --- a/packages/adapters/fastify/package.json +++ b/packages/adapters/fastify/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/fastify", - "version": "10.3.0", + "version": "10.4.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/adapters/hono/CHANGELOG.md b/packages/adapters/hono/CHANGELOG.md index 93f0f81ad..9d4f47464 100644 --- a/packages/adapters/hono/CHANGELOG.md +++ b/packages/adapters/hono/CHANGELOG.md @@ -1,5 +1,19 @@ # @objectstack/hono +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [6c4fbd9] +- Updated dependencies [795b6d1] +- Updated dependencies [aa33b02] + - @objectstack/runtime@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/plugin-hono-server@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/adapters/hono/package.json b/packages/adapters/hono/package.json index a0d188a23..55226f822 100644 --- a/packages/adapters/hono/package.json +++ b/packages/adapters/hono/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/hono", - "version": "10.3.0", + "version": "10.4.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/adapters/nestjs/CHANGELOG.md b/packages/adapters/nestjs/CHANGELOG.md index 590bf5c89..e73cd6129 100644 --- a/packages/adapters/nestjs/CHANGELOG.md +++ b/packages/adapters/nestjs/CHANGELOG.md @@ -1,5 +1,16 @@ # @objectstack/nestjs +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [6c4fbd9] +- Updated dependencies [aa33b02] + - @objectstack/runtime@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/adapters/nestjs/package.json b/packages/adapters/nestjs/package.json index d87a74782..7f77f6ef5 100644 --- a/packages/adapters/nestjs/package.json +++ b/packages/adapters/nestjs/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/nestjs", - "version": "10.3.0", + "version": "10.4.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/adapters/nextjs/CHANGELOG.md b/packages/adapters/nextjs/CHANGELOG.md index f9cfb8ee9..2ecdb9e52 100644 --- a/packages/adapters/nextjs/CHANGELOG.md +++ b/packages/adapters/nextjs/CHANGELOG.md @@ -1,5 +1,16 @@ # @objectstack/nextjs +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [6c4fbd9] +- Updated dependencies [aa33b02] + - @objectstack/runtime@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/adapters/nextjs/package.json b/packages/adapters/nextjs/package.json index 796616076..f41f6aaaf 100644 --- a/packages/adapters/nextjs/package.json +++ b/packages/adapters/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/nextjs", - "version": "10.3.0", + "version": "10.4.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/adapters/nuxt/CHANGELOG.md b/packages/adapters/nuxt/CHANGELOG.md index e35dc27ad..9ebc1ba44 100644 --- a/packages/adapters/nuxt/CHANGELOG.md +++ b/packages/adapters/nuxt/CHANGELOG.md @@ -1,5 +1,16 @@ # @objectstack/nuxt +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [6c4fbd9] +- Updated dependencies [aa33b02] + - @objectstack/runtime@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/adapters/nuxt/package.json b/packages/adapters/nuxt/package.json index be148f6f1..40be81c6f 100644 --- a/packages/adapters/nuxt/package.json +++ b/packages/adapters/nuxt/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/nuxt", - "version": "10.3.0", + "version": "10.4.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/adapters/sveltekit/CHANGELOG.md b/packages/adapters/sveltekit/CHANGELOG.md index 7337524ab..390bd3a57 100644 --- a/packages/adapters/sveltekit/CHANGELOG.md +++ b/packages/adapters/sveltekit/CHANGELOG.md @@ -1,5 +1,16 @@ # @objectstack/sveltekit +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [6c4fbd9] +- Updated dependencies [aa33b02] + - @objectstack/runtime@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/adapters/sveltekit/package.json b/packages/adapters/sveltekit/package.json index a1237ebcc..e4b127e3e 100644 --- a/packages/adapters/sveltekit/package.json +++ b/packages/adapters/sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/sveltekit", - "version": "10.3.0", + "version": "10.4.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 74ee7f0e4..3a881d257 100644 --- a/packages/apps/account/CHANGELOG.md +++ b/packages/apps/account/CHANGELOG.md @@ -1,5 +1,35 @@ # @objectstack/account +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/apps/account/package.json b/packages/apps/account/package.json index 3cd744b49..e72058729 100644 --- a/packages/apps/account/package.json +++ b/packages/apps/account/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/account", - "version": "10.3.0", + "version": "10.4.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 abcec8376..c0a604bdf 100644 --- a/packages/apps/setup/CHANGELOG.md +++ b/packages/apps/setup/CHANGELOG.md @@ -1,5 +1,35 @@ # @objectstack/setup +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/apps/setup/package.json b/packages/apps/setup/package.json index 2c374f7fc..a7cf097bc 100644 --- a/packages/apps/setup/package.json +++ b/packages/apps/setup/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/setup", - "version": "10.3.0", + "version": "10.4.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 cd238c214..a245fe1ed 100644 --- a/packages/apps/studio/CHANGELOG.md +++ b/packages/apps/studio/CHANGELOG.md @@ -1,5 +1,35 @@ # @objectstack/studio +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/apps/studio/package.json b/packages/apps/studio/package.json index 13c0f7650..be7906ac2 100644 --- a/packages/apps/studio/package.json +++ b/packages/apps/studio/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/studio", - "version": "10.3.0", + "version": "10.4.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 716a0dc59..64f18ccb1 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,218 @@ # @objectstack/cli +## 10.4.0 + +### Minor Changes + +- 4845c12: feat(cli): make the AI service opt-in via a declared dependency; honor `config.tiers` + + **AI edition boundary (cli).** The CLI auto-registered the headless `AIServicePlugin` + whenever the `ai` tier was enabled (default) and `@objectstack/service-ai` was + merely _resolvable_. In a workspace/monorepo the package is hoist-resolvable even + when an app does not declare it, so every app got the AI service — discovery + reported `services.ai: available` and the agent runtime served any + metadata-defined agents — including Community-Edition apps that ship no AI. + + Now the _declared_ dependency is the boundary: AIService auto-registers only when + the host app declares `@objectstack/service-ai` **or** `@objectstack/service-ai-studio` + (Studio attaches its personas via the base service's `ai:ready` hook, so declaring + Studio implies the base). A CE app that declares neither gets no AI service, no + agents, and `services.ai: { enabled: false, status: 'unavailable' }` in discovery + (so the console hides its AI surface). MCP and every other capability are + unaffected. The `app-showcase`/`app-crm` examples now declare `@objectstack/service-ai`. + + **`config.tiers` now honored (spec).** `ObjectStackDefinitionSchema` gains a `tiers` + field, so `defineStack` no longer strips it. `config.tiers` (e.g. a list WITHOUT + `ai`) now actually overrides the `--preset` default — previously it was silently + dropped by schema validation, making the `--preset` help text inaccurate. This is + a second, in-place way to disable AI for a deployment without touching dependencies. + +- ad143ce: fix(security): surface the schedule/user-less `runAs:'user'` fail-open (#1888 follow-up) + + With `flow.runAs` now enforced (#1888), a **schedule-triggered** flow with the + default `runAs:'user'` has no trigger user. `resolveRunDataContext` returns + `undefined` for that case, so the CRUD nodes pass no ObjectQL `options.context` + and the security middleware — which _skips_ when there is no identity (it + delegates auth to the auth layer) — runs the operation **UNSCOPED** (effectively + elevated). An author who left `runAs` at the `'user'` default expecting a + restricted run silently gets an unscoped one — a fail-open footgun (ADR-0049: a + security property must not silently do the opposite of what it implies). + + This is the **product decision** to make that explicit, chosen to keep legitimate + scheduled CRUD working (denying outright would break it, and silently elevating + would hide the author's intent). Prevention happens where the platform can tell + intent apart (author/build time); the runtime stays non-breaking but is no longer + silent: + + - **Author-time lint** (`@objectstack/cli`, `lintFlowPatterns`): a new advisory + rule `flow-schedule-runas-unscoped` flags a schedule-triggered flow whose + effective `runAs` is `user` (explicit or unset) and which performs a data + operation — pointing the author at `runAs:'system'`. Catches the footgun at + compile time, before deploy (most flows are AI-authored). + - **Runtime warning** (`@objectstack/service-automation`): the engine now emits a + clear one-per-run warning when a user-mode run resolves no trigger identity and + the flow touches data — the fail-open is _audible_ rather than silent. Behavior + is otherwise unchanged (the run still executes), so scheduled CRUD that relied + on this is not broken. New helpers `runIsUnscopedUserMode`, `flowTouchesData`, + and `DATA_NODE_TYPES` are exported alongside `resolveRunDataContext`. + - **Spec describe** (`@objectstack/spec`): `FlowSchema.runAs` now states that a + scheduled run has no user, so under `user` it runs unscoped — declare `system`. + + The first-party example apps that tripped the new lint are fixed to declare + `runAs:'system'` explicitly (`stale_opportunity_sweep`, the app-todo + `task_reminder` / `overdue_escalation` sweeps) — they read/write across owners and + were running unscoped by default. + + Longer term, attributing scheduled runs to a dedicated service principal (so they + are scopable + audit-attributable rather than unscoped) is the right enforcement; + tracked as M2 follow-up. + + Proven by a service-automation unit test (the engine warns once for a user-less + user-mode data run; stays silent for `system`, for an identified user, and for a + data-less flow), an end-to-end test wiring the **real `ScheduleTrigger` to the + real engine** (`@objectstack/trigger-schedule`) that fires a job and asserts the + user-less identity reaches the engine + trips the warning through the actual cron + path, and a dogfood gate (`flow-runas-schedule.dogfood.test.ts`) that drives + user-less runs through the real automation + security + data stack: a + `runAs:'user'` run reads + writes an owner-scoped note a member cannot — audibly — + while `runAs:'system'` is the explicit, warning-free equivalent. + + Refs #1888, ADR-0049. + +### Patch Changes + +- 84784fc: feat(cli): lint ADR-0044 approval revise-loop footguns at compile time + + `objectstack compile` now warns on two send-back-for-revision shapes an AI (or human) authoring an approval flow commonly gets wrong: + + - **Dead-end revise** — an approval node with a `revise` out-edge but no path looping back to it. This is a valid DAG, so `registerFlow` accepts it, yet the submitter reworks the record with nowhere to resubmit. The linter is the only place that catches the dead end. + - **Un-declared revise loop** — the loop returns to the approval but the closing edge isn't `type: 'back'`, so `registerFlow` rejects it as an un-declared cycle. The lint fires at compile time with the specific fix (mark the resubmit edge `type: 'back'`). + + Also flags `maxRevisions: 0` alongside a `revise` edge (send-back disabled, so the branch always auto-rejects and never runs). Advisory only — never fails the build. Part of #2274 / ADR-0044. + +- d980f0d: feat: add a first-class `user` field type (person picker) + + A new `user` field type — the equivalent of Airtable's Collaborator / Notion's + Person / Salesforce's `Lookup(User)`. Authored as `Field.user({ ... })`; use + `{ multiple: true }` for collaborators/watchers and `{ defaultValue: 'current_user' }` + to auto-fill the acting user on create. + + **Why a distinct type rather than telling authors to `Field.lookup('sys_user')`:** + selecting a person is table-stakes, but the value is in _modelling + discoverability_ — a "User" entry in the Studio/AI field palette instead of + requiring authors (and AI) to know to reference the internal `sys_user` system + object — plus `current_user` defaults and a user-search picker. Storage and + runtime are unchanged. + + **Deliberately NOT a new storage primitive.** `user` is a _semantic + specialization of `lookup`_ with the target fixed to `sys_user`: it shares the + exact lookup code path — same FK string column (`multiple` ⇒ JSON), same + `$expand` resolution, same indexing — so referential integrity and fresh display + names come for free, and nothing is re-implemented. An existing + `Field.lookup('sys_user')` is therefore equivalent at the storage layer (zero + data migration to adopt `Field.user`). + + Ownership semantics are **unchanged**: the existing `owner_id` convention + + `plugin-security` auto-stamp/RLS still apply. A declarative `owner` flag is a + possible future follow-up; intentionally not added here to avoid a second + field type for what is a system role (rationale: keep the `FieldType` surface + lean — see related ADR-0059 freeze discipline). + + Changes: `FieldType` gains `'user'` + `Field.user()` builder; the SQL/Mongo + drivers treat `user` exactly like `lookup`; the engine resolves `$expand` for + `user` fields and honours a new `defaultValue: 'current_user'` token (resolved + app-side from the execution context, mirroring the `NOW()` convention); kanban + group-by and symbolic seed references accept `user`; approvals enrich `user` + references. The public API surface is unchanged (additive enum member). + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [d616e1d] +- Updated dependencies [910a8f0] +- Updated dependencies [1e8a813] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [1b00ba2] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [4b5ec6e] +- Updated dependencies [b6a4972] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [359c0aa] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [9a810f8] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [98a1535] +- Updated dependencies [bc22a89] +- Updated dependencies [8a7e9f1] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/objectql@10.4.0 + - @objectstack/runtime@10.4.0 + - @objectstack/service-analytics@10.4.0 + - @objectstack/plugin-auth@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/client@10.4.0 + - @objectstack/service-automation@10.4.0 + - @objectstack/trigger-record-change@10.4.0 + - @objectstack/formula@10.4.0 + - @objectstack/rest@10.4.0 + - @objectstack/trigger-schedule@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/service-settings@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/driver-sql@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/driver-mongodb@10.4.0 + - @objectstack/plugin-approvals@10.4.0 + - @objectstack/plugin-sharing@10.4.0 + - @objectstack/verify@10.4.0 + - @objectstack/cloud-connection@10.4.0 + - @objectstack/account@10.4.0 + - @objectstack/setup@10.4.0 + - @objectstack/studio@10.4.0 + - @objectstack/lint@10.4.0 + - @objectstack/mcp@10.4.0 + - @objectstack/observability@10.4.0 + - @objectstack/driver-memory@10.4.0 + - @objectstack/driver-sqlite-wasm@10.4.0 + - @objectstack/plugin-audit@10.4.0 + - @objectstack/plugin-email@10.4.0 + - @objectstack/plugin-hono-server@10.4.0 + - @objectstack/plugin-org-scoping@10.4.0 + - @objectstack/plugin-reports@10.4.0 + - @objectstack/plugin-security@10.4.0 + - @objectstack/plugin-webhooks@10.4.0 + - @objectstack/service-cache@10.4.0 + - @objectstack/service-datasource@10.4.0 + - @objectstack/service-job@10.4.0 + - @objectstack/service-messaging@10.4.0 + - @objectstack/service-package@10.4.0 + - @objectstack/service-queue@10.4.0 + - @objectstack/service-realtime@10.4.0 + - @objectstack/service-storage@10.4.0 + - @objectstack/trigger-api@10.4.0 + - @objectstack/console@10.4.0 + ## 10.3.0 ### Minor Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 4a6ca7acd..1bd132de3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/cli", - "version": "10.3.0", + "version": "10.4.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 bf4ea5985..ce942deff 100644 --- a/packages/client-react/CHANGELOG.md +++ b/packages/client-react/CHANGELOG.md @@ -1,5 +1,36 @@ # @objectstack/client-react +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [1b00ba2] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/client@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/client-react/package.json b/packages/client-react/package.json index fa8029893..44feddfa7 100644 --- a/packages/client-react/package.json +++ b/packages/client-react/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/client-react", - "version": "10.3.0", + "version": "10.4.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 e1e2c3110..2052879fc 100644 --- a/packages/client/CHANGELOG.md +++ b/packages/client/CHANGELOG.md @@ -1,5 +1,46 @@ # @objectstack/client +## 10.4.0 + +### Patch Changes + +- 1b00ba2: chore(client): remove dead `projects.*` env-member SDK methods (cloud#533 / ADR-0024 D9) + + Removes `projects.listMembers` / `addMember` / `updateMemberRole` / `removeMember`, + which called `GET/POST/PATCH/DELETE /api/v1/cloud/environments/:id/members`. Those + control-plane endpoints were deleted in cloud#533 (retiring `sys_environment_member`), + so the methods returned 404. Org membership/invites now flow through the better-auth + `organization` plugin (`organization.inviteMember` / `listMembers` / …); objectui + already uses `organization.*` and no in-repo callers remained. + + The `membership` field on the `projects.get()` response is unchanged — cloud#533 still + returns it on the single-env GET (re-sourced to the caller's org `sys_member` role). + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/client/package.json b/packages/client/package.json index 179d7b6ed..3a16bf65f 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/client", - "version": "10.3.0", + "version": "10.4.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 43601e05c..d66c9bb39 100644 --- a/packages/cloud-connection/CHANGELOG.md +++ b/packages/cloud-connection/CHANGELOG.md @@ -1,5 +1,40 @@ # @objectstack/cloud-connection +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/runtime@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/cloud-connection/package.json b/packages/cloud-connection/package.json index bec3d2b27..d7e3e5d4c 100644 --- a/packages/cloud-connection/package.json +++ b/packages/cloud-connection/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/cloud-connection", - "version": "10.3.0", + "version": "10.4.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 8e4623818..398626c8e 100644 --- a/packages/connectors/connector-mcp/CHANGELOG.md +++ b/packages/connectors/connector-mcp/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/connector-mcp +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/connectors/connector-mcp/package.json b/packages/connectors/connector-mcp/package.json index aceb031bd..f3f6a9ea3 100644 --- a/packages/connectors/connector-mcp/package.json +++ b/packages/connectors/connector-mcp/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/connector-mcp", - "version": "10.3.0", + "version": "10.4.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 2c08cabd1..a0d96ce63 100644 --- a/packages/connectors/connector-openapi/CHANGELOG.md +++ b/packages/connectors/connector-openapi/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/connector-openapi +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/connectors/connector-openapi/package.json b/packages/connectors/connector-openapi/package.json index 5aad13e37..510b759b2 100644 --- a/packages/connectors/connector-openapi/package.json +++ b/packages/connectors/connector-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/connector-openapi", - "version": "10.3.0", + "version": "10.4.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 d6e88d24f..610140e1a 100644 --- a/packages/connectors/connector-rest/CHANGELOG.md +++ b/packages/connectors/connector-rest/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/connector-rest +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/connectors/connector-rest/package.json b/packages/connectors/connector-rest/package.json index b80d20846..db3040c78 100644 --- a/packages/connectors/connector-rest/package.json +++ b/packages/connectors/connector-rest/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/connector-rest", - "version": "10.3.0", + "version": "10.4.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 ca5746b0f..b1052a8da 100644 --- a/packages/connectors/connector-slack/CHANGELOG.md +++ b/packages/connectors/connector-slack/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/connector-slack +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/connectors/connector-slack/package.json b/packages/connectors/connector-slack/package.json index f1e0be437..d5aa8062a 100644 --- a/packages/connectors/connector-slack/package.json +++ b/packages/connectors/connector-slack/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/connector-slack", - "version": "10.3.0", + "version": "10.4.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 d89b6c18e..2fcf317f8 100644 --- a/packages/console/CHANGELOG.md +++ b/packages/console/CHANGELOG.md @@ -1,5 +1,7 @@ # @objectstack/console +## 10.4.0 + ## 10.3.0 ## 10.2.0 diff --git a/packages/console/package.json b/packages/console/package.json index 12cc0b64b..10ad70afa 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/console", - "version": "10.3.0", + "version": "10.4.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 81f505b30..544523baa 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,59 @@ # @objectstack/core +## 10.4.0 + +### Patch Changes + +- c715d25: chore(license): unify the framework repo to a single Apache-2.0 license + + The repo was left in a half-finished, self-contradictory source-available + transition: 44 package `LICENSE` files carried restrictive dual-license text + (a Licensor of "ObjectStack AI LLC", a four-year conversion date, and an + anti-competitive-hosting grant) while those same packages' `package.json` + already declared `"license": "Apache-2.0"` — and that license text pointed at + `LICENSING.md` for the authoritative list of restricted packages, which listed + none. The root also carried a redundant `LICENSE.apache` left over from that + transition. + + The framework is deliberately permissive Apache-2.0 to maximize adoption; value + capture lives in the separate closed-source cloud repo, not here. This change + makes that unambiguous: every package `LICENSE` now contains the canonical + Apache 2.0 text (copied from the root `LICENSE`), the redundant root + `LICENSE.apache` is removed, and `LICENSING.md` states the entire repository is + Apache-2.0 with no dual-license language. No restrictive-license residue remains + anywhere outside `node_modules`. + + This is a metadata-only change (license text and `package.json` already agreed); + the patch bump republishes the affected packages with the corrected `LICENSE`. + +- aa33b02: fix(security): single-source the request authorization resolver — REST no longer drops sys_user_role + + The REST server and the runtime dispatcher each carried their own copy of the request → ExecutionContext identity/role resolver, and they drifted on a security path. The REST copy silently omitted `sys_user_role` (so custom roles granted via the ADR-0057 D4 platform-RBAC path did not apply over REST), `sys_role_permission_set`, the `owner→org_owner` membership normalization, the platform-admin derivation, and the `ai_seat` synthesis — fail-closed (legitimate access denied), not an escalation. + + Both entry points now delegate to a single shared resolver, `resolveAuthzContext` in `@objectstack/core/security` (joining the API-key verifier that already lived there). A contract test locks every authorization source and a lint gate (`check:authz-resolver`) prevents a future duplicate resolver or a dropped delegation. + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index ce4232dfe..b8121b7d8 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/core", - "version": "10.3.0", + "version": "10.4.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 ccdd063e7..f2d8e2d36 100644 --- a/packages/create-objectstack/CHANGELOG.md +++ b/packages/create-objectstack/CHANGELOG.md @@ -1,5 +1,7 @@ # create-objectstack +## 10.4.0 + ## 10.3.0 ## 10.2.0 diff --git a/packages/create-objectstack/package.json b/packages/create-objectstack/package.json index afdbf506c..c2b91baa7 100644 --- a/packages/create-objectstack/package.json +++ b/packages/create-objectstack/package.json @@ -1,6 +1,6 @@ { "name": "create-objectstack", - "version": "10.3.0", + "version": "10.4.0", "description": "Create a new ObjectStack project — npx create-objectstack", "bin": { "create-objectstack": "./bin/create-objectstack.js" diff --git a/packages/dogfood/CHANGELOG.md b/packages/dogfood/CHANGELOG.md index d5001542e..0cada1868 100644 --- a/packages/dogfood/CHANGELOG.md +++ b/packages/dogfood/CHANGELOG.md @@ -1,5 +1,41 @@ # @objectstack/dogfood +## 0.0.7 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [d616e1d] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [359c0aa] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/objectql@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/example-showcase@0.2.5 + - @objectstack/verify@10.4.0 + - @objectstack/example-crm@4.0.59 + - @objectstack/plugin-security@10.4.0 + ## 0.0.6 ### Patch Changes diff --git a/packages/dogfood/package.json b/packages/dogfood/package.json index 2c44bf97c..3204e20b5 100644 --- a/packages/dogfood/package.json +++ b/packages/dogfood/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/dogfood", - "version": "0.0.6", + "version": "0.0.7", "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/downstream-contract/CHANGELOG.md b/packages/downstream-contract/CHANGELOG.md index 91ce23452..f37c510ac 100644 --- a/packages/downstream-contract/CHANGELOG.md +++ b/packages/downstream-contract/CHANGELOG.md @@ -1,5 +1,31 @@ # @objectstack/downstream-contract +## 0.0.5 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + ## 0.0.4 ### Patch Changes diff --git a/packages/downstream-contract/package.json b/packages/downstream-contract/package.json index c2bb2436a..16f075a1f 100644 --- a/packages/downstream-contract/package.json +++ b/packages/downstream-contract/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/downstream-contract", - "version": "0.0.4", + "version": "0.0.5", "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/formula/CHANGELOG.md b/packages/formula/CHANGELOG.md index 04bacacbe..27e258114 100644 --- a/packages/formula/CHANGELOG.md +++ b/packages/formula/CHANGELOG.md @@ -1,5 +1,38 @@ # @objectstack/formula +## 10.4.0 + +### Minor Changes + +- ef3ed67: Formula field typing: `inferExpressionType()` + a declared `returnType`. + + - `@objectstack/formula`: new `inferExpressionType()` (and lower-level `inferCelType()`) surfaces the cel-js type-checker's result for a CEL value/formula expression, mapped to `number | text | boolean | date | unknown`. Conservative — two `dyn` operands stay `unknown`; typed literals/stdlib returns pin a concrete type. + - `@objectstack/spec`: `FieldSchema` gains an optional `returnType` (`number|text|boolean|date`) so a formula field can carry its declared value type (the way Salesforce/Airtable do), letting consumers (dataset measures, formatting, validation) read a declared type instead of re-parsing the expression. + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/formula/package.json b/packages/formula/package.json index 32b1f1b46..5e398c7de 100644 --- a/packages/formula/package.json +++ b/packages/formula/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/formula", - "version": "10.3.0", + "version": "10.4.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 3a64098ea..dbdca6bd3 100644 --- a/packages/lint/CHANGELOG.md +++ b/packages/lint/CHANGELOG.md @@ -1,5 +1,32 @@ # @objectstack/lint +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/formula@10.4.0 + ## 10.3.0 ### Minor Changes diff --git a/packages/lint/package.json b/packages/lint/package.json index b1799fb86..e0e2baff7 100644 --- a/packages/lint/package.json +++ b/packages/lint/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/lint", - "version": "10.3.0", + "version": "10.4.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 62d9da89e..a51fbf3a7 100644 --- a/packages/mcp/CHANGELOG.md +++ b/packages/mcp/CHANGELOG.md @@ -1,5 +1,36 @@ # @objectstack/plugin-mcp-server +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/mcp/package.json b/packages/mcp/package.json index 27b90a560..9280f34c3 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/mcp", - "version": "10.3.0", + "version": "10.4.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 fea399d6a..177860afe 100644 --- a/packages/metadata-core/CHANGELOG.md +++ b/packages/metadata-core/CHANGELOG.md @@ -1,5 +1,42 @@ # @objectstack/metadata-core +## 10.4.0 + +### Minor Changes + +- 4d99a5c: Package-scoped commit history & rollback for AI authoring (ADR-0067) + + Each authoring apply now lands as one revertible **commit** on a package timeline, on top of `sys_metadata_history`: + + - New `sys_metadata_commit` object groups a turn's metadata changes (by `event_seq` range). + - `publishPackageDrafts` records each publish as one commit (best-effort) with a per-artifact revert plan and an optional `message` / `aiModel`. + - New protocol methods `listCommits`, `revertCommit`, `rollbackToPackageCommit` (reusing `restoreVersion` + delete; a revert is itself an append-only commit). + - New REST routes: `GET /packages/:id/commits`, `POST /packages/:id/commits/:commitId/revert`, `POST /packages/:id/rollback`. + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/metadata-core/package.json b/packages/metadata-core/package.json index b3ef2d661..808e0e3d4 100644 --- a/packages/metadata-core/package.json +++ b/packages/metadata-core/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/metadata-core", - "version": "10.3.0", + "version": "10.4.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 d18df801c..f76d134f9 100644 --- a/packages/metadata-fs/CHANGELOG.md +++ b/packages/metadata-fs/CHANGELOG.md @@ -1,5 +1,12 @@ # @objectstack/metadata-fs +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] + - @objectstack/metadata-core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/metadata-fs/package.json b/packages/metadata-fs/package.json index cc7dd1d70..2a93392a4 100644 --- a/packages/metadata-fs/package.json +++ b/packages/metadata-fs/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/metadata-fs", - "version": "10.3.0", + "version": "10.4.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/CHANGELOG.md b/packages/metadata/CHANGELOG.md index dc3e7035b..52cf031cd 100644 --- a/packages/metadata/CHANGELOG.md +++ b/packages/metadata/CHANGELOG.md @@ -1,5 +1,65 @@ # @objectstack/metadata +## 10.4.0 + +### Patch Changes + +- 4b5ec6e: fix(automation): re-bind scheduled-flow jobs on `os dev` hot-reload + + Editing a schedule-triggered flow under `objectstack dev` silently kept firing + the OLD definition until a full server restart. The dev watcher recompiles + `dist/objectstack.json` and MetadataPlugin reloads it into the MetadataManager + (so GET /meta reads + UI HMR are fresh), but the AutomationEngine pulls its flow + definitions and trigger/job bindings ONCE at boot — nothing re-registered them + on reload. So the scheduled job bound at boot kept running the pre-edit flow + (old `runAs`, schedule, or logic) on its timer, with no signal that the edit had + no effect. + + Fix: MetadataPlugin now fires a generic `metadata:reloaded` hook after each + artifact reload (the HMR POST handler and the server-side artifact-file watcher; + never on the initial boot load). AutomationServicePlugin subscribes and re-syncs + the engine from the metadata service — re-registering every current flow + (idempotent: `registerFlow` re-binds the trigger, and `ScheduleTrigger.start` + cancels + reschedules the job) and unregistering flows removed from the artifact + so their jobs stop firing. This covers all auto-triggered flow types + (schedule / record-change / api), not just scheduled ones, since record-change + flows were also executing their boot-time definitions after an edit. Production + deployments are unaffected — nothing reloads the artifact there. + +- Updated dependencies [4d99a5c] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/metadata-core@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/metadata-fs@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/metadata/package.json b/packages/metadata/package.json index 257a26157..a6f56407e 100644 --- a/packages/metadata/package.json +++ b/packages/metadata/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/metadata", - "version": "10.3.0", + "version": "10.4.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 db60346cb..0351893f7 100644 --- a/packages/objectql/CHANGELOG.md +++ b/packages/objectql/CHANGELOG.md @@ -1,5 +1,156 @@ # @objectstack/objectql +## 10.4.0 + +### Minor Changes + +- 4d99a5c: Package-scoped commit history & rollback for AI authoring (ADR-0067) + + Each authoring apply now lands as one revertible **commit** on a package timeline, on top of `sys_metadata_history`: + + - New `sys_metadata_commit` object groups a turn's metadata changes (by `event_seq` range). + - `publishPackageDrafts` records each publish as one commit (best-effort) with a per-artifact revert plan and an optional `message` / `aiModel`. + - New protocol methods `listCommits`, `revertCommit`, `rollbackToPackageCommit` (reusing `restoreVersion` + delete; a revert is itself an append-only commit). + - New REST routes: `GET /packages/:id/commits`, `POST /packages/:id/commits/:commitId/revert`, `POST /packages/:id/rollback`. + +- cd51229: Expose authoritative create seeds via /meta/types (spec-derived create-shape contract, Phase 2) + + The minimal valid create seeds added in `@objectstack/spec/kernel` (`getMetadataCreateSeed`) now reach consumers through the real `/meta/types` registry response: each entry carries an optional `createSeed`. The Studio designer / CLI / API clients derive their create defaults from this single source of truth instead of re-inventing them — closing the drift that produced the dashboard-`layout` and action-`body` create→save 422s. + + - `@objectstack/spec`: barrel-export `getMetadataCreateSeed` / `listMetadataCreateSeedTypes` from `/kernel`; add optional `createSeed` to the `GetMetaTypesResponse` entry schema. + - `@objectstack/objectql`: `getMetaTypes()` attaches each type's seed (registry + runtime entries). Canvas-create types whose shape is built interactively (report) are intentionally absent. + +- d980f0d: feat: add a first-class `user` field type (person picker) + + A new `user` field type — the equivalent of Airtable's Collaborator / Notion's + Person / Salesforce's `Lookup(User)`. Authored as `Field.user({ ... })`; use + `{ multiple: true }` for collaborators/watchers and `{ defaultValue: 'current_user' }` + to auto-fill the acting user on create. + + **Why a distinct type rather than telling authors to `Field.lookup('sys_user')`:** + selecting a person is table-stakes, but the value is in _modelling + discoverability_ — a "User" entry in the Studio/AI field palette instead of + requiring authors (and AI) to know to reference the internal `sys_user` system + object — plus `current_user` defaults and a user-search picker. Storage and + runtime are unchanged. + + **Deliberately NOT a new storage primitive.** `user` is a _semantic + specialization of `lookup`_ with the target fixed to `sys_user`: it shares the + exact lookup code path — same FK string column (`multiple` ⇒ JSON), same + `$expand` resolution, same indexing — so referential integrity and fresh display + names come for free, and nothing is re-implemented. An existing + `Field.lookup('sys_user')` is therefore equivalent at the storage layer (zero + data migration to adopt `Field.user`). + + Ownership semantics are **unchanged**: the existing `owner_id` convention + + `plugin-security` auto-stamp/RLS still apply. A declarative `owner` flag is a + possible future follow-up; intentionally not added here to avoid a second + field type for what is a system role (rationale: keep the `FieldType` surface + lean — see related ADR-0059 freeze discipline). + + Changes: `FieldType` gains `'user'` + `Field.user()` builder; the SQL/Mongo + drivers treat `user` exactly like `lookup`; the engine resolves `$expand` for + `user` fields and honours a new `defaultValue: 'current_user'` token (resolved + app-side from the execution context, mirroring the `NOW()` convention); kanban + group-by and symbolic seed references accept `user`; approvals enrich `user` + references. The public API surface is unchanged (additive enum member). + +### Patch Changes + +- 61d441f: feat(objectql): duplicate a writable base — ADR-0070 D4 ("duplicate base") + + `protocol.duplicatePackage` clones every ACTIVE item a base owns into a NEW + package, **re-namespacing** object names (the blueprint prefixes a base's object + names with its namespace, e.g. `iojn_repair_ticket`, and `sys_metadata` keys on + `(type,name,org)` so a same-name copy would collide with the source) and + **rewriting every intra-package reference** (lookup `reference`, view `object`, + expressions, …) to the new names via a longest-first, identifier-boundary + replace. Exposed as `POST /packages/:id/duplicate` (body + `{ targetPackageId, targetName?, targetNamespace? }`). + + Completes ADR-0070 D4 (package = lifecycle unit): delete-cascade and export + already shipped; this adds the duplicate gesture. + +- c224e18: feat(objectql): adopt orphaned metadata into a base — ADR-0070 D5 migration + + `protocol.reassignOrphanedMetadata` bulk-rebinds every package-less orphan + (`package_id` null / `""` / the `sys_metadata` sentinel left by the pre- + package-first stopgaps) onto a target base, leaving already-owned rows + untouched. Exposed as `POST /packages/:id/adopt-orphans`. This is the migration + affordance behind retiring the "Local / Custom" scope (D5): once an env has no + orphans, that scope can be dropped from the selector. Pairs with the kernel's + `writable_package_required` (D1) so no NEW orphans are created. + +- d616e1d: feat(objectql): enforce package-first authoring at the kernel (ADR-0070 D1/D2) + + A runtime-only metadata **create** that targets a read-only code/installed + package now throws `writable_package_required` (status 422) instead of silently + coercing `package_id` to `null`. The old coercion (#2252 stopgap) unblocked + editing but scattered orphans into a package-less bucket with no container to + delete (#1946); the rejection instead directs the authoring surface (Studio / + AI) to pick or create a writable base first. + + `isLoadedPackage` is generalized into `isWritablePackage` (D2): a package is + writable unless it is a booted code package (registered in the engine manifest + map) or a `system`/`cloud`-scoped installed package. The old "owns ≥1 registered + object" heuristic is dropped — it was the read-only-after-publish trap (#2252), + since a writable base accrues registered objects once its drafts publish. + + `null` is still accepted as the legacy org-overlay destination; ADR-0070 D5 + retires it after the orphan migration. + +- 359c0aa: fix(objectql,rest): single-item meta reads must revalidate (no `max-age=3600`) + + `GET /api/v1/meta/object/:name` (and the other single-item meta reads served by + the cached path) sent `Cache-Control: public, max-age, max-age=3600`. Two bugs: + + 1. **Stale metadata for up to an hour.** Object metadata is invalidated by + publish, but a one-hour TTL let browsers (and any CDN/proxy) serve a stale + schema _without revalidating_ — e.g. the AI-build "New" create form kept + rendering pre-publish fields until the TTL lapsed. The list endpoint + `GET /api/v1/meta/object` is uncached, which is why list views updated but + single-object reads didn't. `getMetaItemCached` now returns + `directives: ['private', 'no-cache']` with no `maxAge`, so the ETag validator + (which already changes on publish) gates freshness: a cheap `304` when + unchanged, fresh fields the instant a publish bumps the ETag. `private` also + keeps per-tenant metadata out of shared caches. + + 2. **Malformed header.** The directives array carried a bare `max-age` + placeholder _and_ the REST layer appended `max-age=3600` from the `maxAge` + field, concatenating into `public, max-age, max-age=3600`. The header builder + now strips the bare `max-age` token before appending the real value, so a + `maxAge` is emitted once as a well-formed `max-age=N`. + +- Updated dependencies [4d99a5c] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/metadata-core@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/formula@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/objectql/package.json b/packages/objectql/package.json index 32af8e3d4..7168d63d1 100644 --- a/packages/objectql/package.json +++ b/packages/objectql/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/objectql", - "version": "10.3.0", + "version": "10.4.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 8cc8a004a..70471d9cd 100644 --- a/packages/observability/CHANGELOG.md +++ b/packages/observability/CHANGELOG.md @@ -1,5 +1,31 @@ # @objectstack/observability +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/observability/package.json b/packages/observability/package.json index e27aadfc6..9ad3ff06c 100644 --- a/packages/observability/package.json +++ b/packages/observability/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/observability", - "version": "10.3.0", + "version": "10.4.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 2c5026324..b991cd65c 100644 --- a/packages/platform-objects/CHANGELOG.md +++ b/packages/platform-objects/CHANGELOG.md @@ -1,5 +1,101 @@ # @objectstack/platform-objects +## 10.4.0 + +### Patch Changes + +- 5737261: fix(setup): drop Advanced nav entries for non-listable objects (sys_verification, sys_device_code) + + Dogfooding every Setup menu surfaced two Advanced entries that always render + "无法加载记录 / failed to load": **Verifications** (`sys_verification`) and + **Device Codes** (`sys_device_code`). Both objects deliberately omit `list` + from `apiMethods` (sensitive, ephemeral secrets — verification tokens and OAuth + device-grant codes are not meant to be browsed), so the generic object/list-view + menu can only ever 405. Removed both nav entries (and their orphaned zh labels); + the objects remain reachable by id. Re-adding a browse menu would require + enabling `list` on the object — a security decision, not a nav fix. + +- a619a3a: fix(setup): first-run admin polish — pin Company/Localization, gate dashboard widgets by `requiresService`, i18n + settings PUT envelope + + Dogfooding the Setup app as a brand-new system administrator surfaced a cluster of small first-run gaps, now fixed: + + - **platform-objects**: pin **Localization** and **Company** in the Setup sidebar's Configuration group — both are registered `service-settings` manifests (the two lowest-`order` Workspace settings) but were reachable only via the "All Settings" hub. Translate the previously-English nav labels Cloud Connection (云连接), Datasources (数据源) and Capabilities (能力). Tag the System Overview `widget_organizations` KPI with `requiresService: 'org-scoping'`. + - **rest**: extend the ADR-0057 D10 server-side visibility gate to **dashboard widgets** — strip widgets whose `requiresService` names an unregistered kernel service (mirrors the existing app-nav gate; `resolveRegisteredServices` now also discovers gates declared on widgets). In a single-tenant runtime this removes the orphan "Organizations" KPI, matching the already-hidden org nav entries. + - **service-settings**: add the missing zh `help` strings for the Localization manifest (number/currency/first-day-of-week/fiscal-year fields), and accept the `{ values: { … } }` envelope on `PUT /api/settings/:ns` symmetrically with what `GET` returns. + +- f44c1bd: fix(platform-objects): hide org/membership surfaces in single-org mode + + The platform gates multi-org features two ways — nav entries on + `requiresService: 'org-scoping'` (e.g. setup-nav Organizations/Invitations) + and object actions on `visible: 'features.multiOrgEnabled != false'` (e.g. + `sys_organization.create_organization`). That convention had only been applied + to a handful of spots, so a wide band of org/membership surface leaked into + single-org deployments where it is pure noise or a broken affordance: + + - The Account app's "My Organizations" entry (`sys_member` / `mine` view) was + gated on `requiresObject: 'sys_member'` — but `sys_member` is a system object + that is always registered, so the gate never fired. In single-org there are + no `sys_organization` rows and no auto-stamped memberships, so the view is + always empty for every user. Re-gated on `requiresService: 'org-scoping'`. + - The setup-nav "Teams" entry had no gate at all, while its sibling + Organizations/Invitations entries were correctly service-gated. Added + `requiresService: 'org-scoping'`. + - Org/membership mutation actions rendered (and on toolbars, were clickable) + in single-org but hit better-auth endpoints that resolve an active org that + does not exist, failing at the API. Gated each on + `features.multiOrgEnabled != false`: + - `sys_user.invite_user` (the most exposed — the Users list is always + reachable in single-org) + - `sys_member.add_member` / `update_member_role` / `remove_member`, and + `transfer_ownership` (combined with its existing `record.role != 'owner'` + condition) + - `sys_team.create_team` / `update_team` / `remove_team` + - `sys_team_member.add_team_member` / `remove_team_member` + - `sys_invitation.invite_user` / `resend_invitation` / `cancel_invitation` + (recipient-side accept/reject stay record-gated; they are unreachable in + single-org anyway since no invitation rows exist) + + Also tightened the remaining single-org rough edges on these objects: + + - `sys_organization` admin actions (`update` / `delete` / `set_active` / + `leave` / `change_slug`) are now all gated on + `features.multiOrgEnabled != false`, joining the already-gated + `create_organization` — previously only create was gated. + - `titleFormat` no longer renders a null organization: `sys_member` is titled + `'{user_id} ({role})'` (was `'… in {organization_id}'`) and `sys_invitation` + is titled `'Invitation for {email}'` (was `'Invitation to {organization_id}'`). + In single-org `organization_id` is null, so the old formats read "… in null". + The new fields are more useful identifiers in both modes. + + No behavior change in multi-org deployments (`OS_MULTI_ORG_ENABLED=true`): + `features.multiOrgEnabled` is true and the `org-scoping` service is present, so + every gate evaluates to visible exactly as before. This is metadata-only — no + schema, API, or runtime changes. + +- Updated dependencies [4d99a5c] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/metadata-core@10.4.0 + - @objectstack/spec@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/platform-objects/package.json b/packages/platform-objects/package.json index d45a90f1c..6b57ffdba 100644 --- a/packages/platform-objects/package.json +++ b/packages/platform-objects/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/platform-objects", - "version": "10.3.0", + "version": "10.4.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 1c8580bd5..8295f73f8 100644 --- a/packages/plugins/driver-memory/CHANGELOG.md +++ b/packages/plugins/driver-memory/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/driver-memory +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/driver-memory/package.json b/packages/plugins/driver-memory/package.json index ba6ba2dce..c46852a72 100644 --- a/packages/plugins/driver-memory/package.json +++ b/packages/plugins/driver-memory/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/driver-memory", - "version": "10.3.0", + "version": "10.4.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 a82207945..535507c29 100644 --- a/packages/plugins/driver-mongodb/CHANGELOG.md +++ b/packages/plugins/driver-mongodb/CHANGELOG.md @@ -1,5 +1,71 @@ # @objectstack/driver-mongodb +## 10.4.0 + +### Minor Changes + +- d980f0d: feat: add a first-class `user` field type (person picker) + + A new `user` field type — the equivalent of Airtable's Collaborator / Notion's + Person / Salesforce's `Lookup(User)`. Authored as `Field.user({ ... })`; use + `{ multiple: true }` for collaborators/watchers and `{ defaultValue: 'current_user' }` + to auto-fill the acting user on create. + + **Why a distinct type rather than telling authors to `Field.lookup('sys_user')`:** + selecting a person is table-stakes, but the value is in _modelling + discoverability_ — a "User" entry in the Studio/AI field palette instead of + requiring authors (and AI) to know to reference the internal `sys_user` system + object — plus `current_user` defaults and a user-search picker. Storage and + runtime are unchanged. + + **Deliberately NOT a new storage primitive.** `user` is a _semantic + specialization of `lookup`_ with the target fixed to `sys_user`: it shares the + exact lookup code path — same FK string column (`multiple` ⇒ JSON), same + `$expand` resolution, same indexing — so referential integrity and fresh display + names come for free, and nothing is re-implemented. An existing + `Field.lookup('sys_user')` is therefore equivalent at the storage layer (zero + data migration to adopt `Field.user`). + + Ownership semantics are **unchanged**: the existing `owner_id` convention + + `plugin-security` auto-stamp/RLS still apply. A declarative `owner` flag is a + possible future follow-up; intentionally not added here to avoid a second + field type for what is a system role (rationale: keep the `FieldType` surface + lean — see related ADR-0059 freeze discipline). + + Changes: `FieldType` gains `'user'` + `Field.user()` builder; the SQL/Mongo + drivers treat `user` exactly like `lookup`; the engine resolves `$expand` for + `user` fields and honours a new `defaultValue: 'current_user'` token (resolved + app-side from the execution context, mirroring the `NOW()` convention); kanban + group-by and symbolic seed references accept `user`; approvals enrich `user` + references. The public API surface is unchanged (additive enum member). + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/driver-mongodb/package.json b/packages/plugins/driver-mongodb/package.json index 4c8343355..887d9dc38 100644 --- a/packages/plugins/driver-mongodb/package.json +++ b/packages/plugins/driver-mongodb/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/driver-mongodb", - "version": "10.3.0", + "version": "10.4.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 23c8886a4..0c7c3cba6 100644 --- a/packages/plugins/driver-sql/CHANGELOG.md +++ b/packages/plugins/driver-sql/CHANGELOG.md @@ -1,5 +1,158 @@ # @objectstack/driver-sql +## 10.4.0 + +### Minor Changes + +- d980f0d: feat: add a first-class `user` field type (person picker) + + A new `user` field type — the equivalent of Airtable's Collaborator / Notion's + Person / Salesforce's `Lookup(User)`. Authored as `Field.user({ ... })`; use + `{ multiple: true }` for collaborators/watchers and `{ defaultValue: 'current_user' }` + to auto-fill the acting user on create. + + **Why a distinct type rather than telling authors to `Field.lookup('sys_user')`:** + selecting a person is table-stakes, but the value is in _modelling + discoverability_ — a "User" entry in the Studio/AI field palette instead of + requiring authors (and AI) to know to reference the internal `sys_user` system + object — plus `current_user` defaults and a user-search picker. Storage and + runtime are unchanged. + + **Deliberately NOT a new storage primitive.** `user` is a _semantic + specialization of `lookup`_ with the target fixed to `sys_user`: it shares the + exact lookup code path — same FK string column (`multiple` ⇒ JSON), same + `$expand` resolution, same indexing — so referential integrity and fresh display + names come for free, and nothing is re-implemented. An existing + `Field.lookup('sys_user')` is therefore equivalent at the storage layer (zero + data migration to adopt `Field.user`). + + Ownership semantics are **unchanged**: the existing `owner_id` convention + + `plugin-security` auto-stamp/RLS still apply. A declarative `owner` flag is a + possible future follow-up; intentionally not added here to avoid a second + field type for what is a system role (rationale: keep the `FieldType` surface + lean — see related ADR-0059 freeze discipline). + + Changes: `FieldType` gains `'user'` + `Field.user()` builder; the SQL/Mongo + drivers treat `user` exactly like `lookup`; the engine resolves `$expand` for + `user` fields and honours a new `defaultValue: 'current_user'` token (resolved + app-side from the execution context, mirroring the `NOW()` convention); kanban + group-by and symbolic seed references accept `user`; approvals enrich `user` + references. The public API surface is unchanged (additive enum member). + +### Patch Changes + +- 98a1535: Fix: store SQLite `created_at`/`updated_at` in one canonical, timezone-explicit format (ADR-0074) + + The two SQLite write paths disagreed on the audit-timestamp format. INSERT fell + back to the column default `CURRENT_TIMESTAMP` (`'YYYY-MM-DD HH:MM:SS'`) while + UPDATE stamped `toISOString().replace('T',' ').replace('Z','')` + (`'YYYY-MM-DD HH:MM:SS.mmm'`) — both **timezone-naive**, space-separated strings + that `Date.parse` reads as _local_ time. On a non-UTC runtime a stored UTC + wall-clock silently shifted by the host offset; e.g. the objectos kernel + freshness probe compared a shifted `updated_at` against an absolute `builtAtMs` + and never evicted (publishes/installs/config toggles didn't take effect until the + LRU TTL expired). + + `create` / `bulkCreate` / `upsert` / `update` now stamp a single canonical + ISO-8601 instant with an explicit `Z` (`new Date().toISOString()`) — matching the + caller-stamped paths (`sys_metadata`, the service outboxes) and Postgres/MySQL's + native `now()`. Because the stamp is applied app-side (not via the column + default), **existing** tenant databases are fixed immediately, not just freshly + created tables. `formatOutput` additionally repairs any legacy/raw zone-naive + audit timestamp to the same format on read (idempotent), so old rows read back + unambiguously without a data migration. `upsert` now treats `created_at` as + insert-only — a conflicting merge never overwrites it. + + Postgres/MySQL are unaffected (they store a real zone-aware `TIMESTAMP`). + +- bc22a89: Fix: present `Field.time` as a wall-clock time-of-day on read (SQLite) + + `Field.time` is a tz-naive time-of-day, not an instant (#2004). A + `defaultValue: 'NOW()'` time column historically took the full SQLite + `CURRENT_TIMESTAMP` default, so a defaulted/legacy row read back a full + `'YYYY-MM-DD HH:MM:SS'` timestamp instead of a time-of-day. + + `formatOutput` now repairs a `Field.time` value to just its time portion + (`toTimeOnly`): a legacy full timestamp — or a full ISO value that leaked into + the column — is sliced to `HH:MM[:SS[.fff]]`, while a value already stored as a + bare time-of-day is left untouched. This is a deliberately NARROW, read-only + normalization with no write/filter counterpart, so it introduces no write/read + asymmetry and preserves exact round-trips for bare time-of-day values (e.g. the + field-zoo `f_time` guard). Runs for every dialect (a native TIME column already + returns a time-of-day, so it is a no-op there). + + Completes the temporal-field read normalization alongside #2346: `datetime` + folds to a canonical ISO-8601-`Z` instant, `date` to `YYYY-MM-DD`, and `time` to + a wall-clock time-of-day. + +- 8a7e9f1: Fix: canonical storage + presentation for user-declared `NOW()`-default temporal fields on SQLite (ADR-0074 follow-up) + + A user-declared `Field.datetime` (or `date`/`time`) with `defaultValue: 'NOW()'` + took the `knex.fn.now()` → `CURRENT_TIMESTAMP` column default on SQLite, storing a + **timezone-naive**, space-separated `'YYYY-MM-DD HH:MM:SS'` (no millis, no zone). + `Date.parse` reads such a zone-less string as _local_ time, so the stored UTC + wall-clock shifted by the host offset on a non-UTC runtime — the same class of bug + ADR-0074 fixed for the builtin `created_at`/`updated_at` audit columns, but left + scoped out for user fields. Worse, the **same** column mixed storage: an explicit + JS `Date` is bound by better-sqlite3 as INTEGER epoch ms, while an omitted value + took the naive TEXT default — so one column held both INTEGER ms and naive TEXT. + + This fix, SQLite-only: + + - **DDL default → canonical.** The `NOW()` default now emits a per-type canonical + via `strftime`: datetime → ISO-8601 with explicit `Z` + (`strftime('%Y-%m-%dT%H:%M:%fZ','now')`, e.g. `2026-06-26T10:34:13.891Z`, + matching `new Date().toISOString()`); date → `YYYY-MM-DD`; time → `HH:MM:SS.fff` + time-of-day (not a full timestamp). + - **Read → uniform instant.** `formatOutput` folds every `Field.datetime` storage + form — INTEGER epoch ms, canonical ISO-`Z`, and legacy naive `CURRENT_TIMESTAMP` + TEXT — to one canonical ISO-8601-`Z` instant (`normalizeSqliteDatetimeOutput`), + interpreting a naive wall-clock as UTC. Idempotent on already-zone-explicit + values; total on null/unparseable. This transparently repairs existing rows on + read (a DDL default only governs newly-created columns), so no data migration is + needed — mirroring the `Field.date`/numeric read-repairs already in place. + + Applied as DDL-default + read-normalization, NOT app-side write stamping (the + inverse of ADR-0074's audit-column fix): the read path already repairs + existing-table rows transparently, and an explicit `Date` is bound as INTEGER + epoch ms regardless of any write stamp, so stamping wouldn't make on-disk storage + uniform anyway — the INTEGER-vs-TEXT split is inherent to SQLite and resolved at + the read boundary. This keeps the hot insert/upsert/bulk paths untouched. + + The analytics SQL-bucketing path (`strftime`, bypasses `formatOutput`) is + unchanged: ISO-`Z` TEXT buckets identically to the old naive TEXT. Postgres/MySQL + keep native `now()` (a real zone-aware `TIMESTAMP`) and are entirely unaffected. + + Generalizes ADR-0074's `repairNaiveUtcAuditTimestamp` by also folding the INTEGER + epoch-ms storage form; the two read-repairs can be unified once both land. + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/driver-sql/package.json b/packages/plugins/driver-sql/package.json index de1a17555..4a4d04848 100644 --- a/packages/plugins/driver-sql/package.json +++ b/packages/plugins/driver-sql/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/driver-sql", - "version": "10.3.0", + "version": "10.4.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 f390ddb94..80edf94b5 100644 --- a/packages/plugins/driver-sqlite-wasm/CHANGELOG.md +++ b/packages/plugins/driver-sqlite-wasm/CHANGELOG.md @@ -1,5 +1,38 @@ # @objectstack/driver-sqlite-wasm +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [98a1535] +- Updated dependencies [bc22a89] +- Updated dependencies [8a7e9f1] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/driver-sql@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/driver-sqlite-wasm/package.json b/packages/plugins/driver-sqlite-wasm/package.json index bc9d1760d..03964a721 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": "10.3.0", + "version": "10.4.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 58e23529c..0a7d03479 100644 --- a/packages/plugins/embedder-openai/CHANGELOG.md +++ b/packages/plugins/embedder-openai/CHANGELOG.md @@ -1,5 +1,31 @@ # @objectstack/embedder-openai +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/embedder-openai/package.json b/packages/plugins/embedder-openai/package.json index 1788b970f..5375dedde 100644 --- a/packages/plugins/embedder-openai/package.json +++ b/packages/plugins/embedder-openai/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/embedder-openai", - "version": "10.3.0", + "version": "10.4.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 228f7635f..9295571aa 100644 --- a/packages/plugins/knowledge-memory/CHANGELOG.md +++ b/packages/plugins/knowledge-memory/CHANGELOG.md @@ -1,5 +1,35 @@ # @objectstack/knowledge-memory +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/service-knowledge@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/knowledge-memory/package.json b/packages/plugins/knowledge-memory/package.json index 419ecf80b..f1d42dd68 100644 --- a/packages/plugins/knowledge-memory/package.json +++ b/packages/plugins/knowledge-memory/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/knowledge-memory", - "version": "10.3.0", + "version": "10.4.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 ca5d58522..f5886ec88 100644 --- a/packages/plugins/knowledge-ragflow/CHANGELOG.md +++ b/packages/plugins/knowledge-ragflow/CHANGELOG.md @@ -1,5 +1,35 @@ # @objectstack/knowledge-ragflow +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/service-knowledge@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/knowledge-ragflow/package.json b/packages/plugins/knowledge-ragflow/package.json index 5b89f3c8e..d4c59bd34 100644 --- a/packages/plugins/knowledge-ragflow/package.json +++ b/packages/plugins/knowledge-ragflow/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/knowledge-ragflow", - "version": "10.3.0", + "version": "10.4.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 4591ba505..1379f6ab8 100644 --- a/packages/plugins/plugin-approvals/CHANGELOG.md +++ b/packages/plugins/plugin-approvals/CHANGELOG.md @@ -1,5 +1,76 @@ # @objectstack/plugin-approvals +## 10.4.0 + +### Patch Changes + +- d980f0d: feat: add a first-class `user` field type (person picker) + + A new `user` field type — the equivalent of Airtable's Collaborator / Notion's + Person / Salesforce's `Lookup(User)`. Authored as `Field.user({ ... })`; use + `{ multiple: true }` for collaborators/watchers and `{ defaultValue: 'current_user' }` + to auto-fill the acting user on create. + + **Why a distinct type rather than telling authors to `Field.lookup('sys_user')`:** + selecting a person is table-stakes, but the value is in _modelling + discoverability_ — a "User" entry in the Studio/AI field palette instead of + requiring authors (and AI) to know to reference the internal `sys_user` system + object — plus `current_user` defaults and a user-search picker. Storage and + runtime are unchanged. + + **Deliberately NOT a new storage primitive.** `user` is a _semantic + specialization of `lookup`_ with the target fixed to `sys_user`: it shares the + exact lookup code path — same FK string column (`multiple` ⇒ JSON), same + `$expand` resolution, same indexing — so referential integrity and fresh display + names come for free, and nothing is re-implemented. An existing + `Field.lookup('sys_user')` is therefore equivalent at the storage layer (zero + data migration to adopt `Field.user`). + + Ownership semantics are **unchanged**: the existing `owner_id` convention + + `plugin-security` auto-stamp/RLS still apply. A declarative `owner` flag is a + possible future follow-up; intentionally not added here to avoid a second + field type for what is a system role (rationale: keep the `FieldType` surface + lean — see related ADR-0059 freeze discipline). + + Changes: `FieldType` gains `'user'` + `Field.user()` builder; the SQL/Mongo + drivers treat `user` exactly like `lookup`; the engine resolves `$expand` for + `user` fields and honours a new `defaultValue: 'current_user'` token (resolved + app-side from the execution context, mirroring the `NOW()` convention); kanban + group-by and symbolic seed references accept `user`; approvals enrich `user` + references. The public API surface is unchanged (additive enum member). + +- Updated dependencies [4d99a5c] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/metadata-core@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/formula@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-approvals/package.json b/packages/plugins/plugin-approvals/package.json index c7d84beb8..bf8ab3771 100644 --- a/packages/plugins/plugin-approvals/package.json +++ b/packages/plugins/plugin-approvals/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-approvals", - "version": "10.3.0", + "version": "10.4.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 f0443a7bd..b11105239 100644 --- a/packages/plugins/plugin-audit/CHANGELOG.md +++ b/packages/plugins/plugin-audit/CHANGELOG.md @@ -1,5 +1,38 @@ # @objectstack/plugin-audit +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-audit/package.json b/packages/plugins/plugin-audit/package.json index b5619d54f..4525b60b5 100644 --- a/packages/plugins/plugin-audit/package.json +++ b/packages/plugins/plugin-audit/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-audit", - "version": "10.3.0", + "version": "10.4.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 6b0f13853..0196b8613 100644 --- a/packages/plugins/plugin-auth/CHANGELOG.md +++ b/packages/plugins/plugin-auth/CHANGELOG.md @@ -1,5 +1,61 @@ # Changelog +## 10.4.0 + +### Patch Changes + +- 1e8a813: feat(auth): surface `features.sso` in the public `/auth/config` response + + `getPublicConfig()` reported every other auth capability flag (`oidcProvider`, + `twoFactor`, `multiOrgEnabled`, …) but omitted enterprise SSO, even though the + manager already computes whether the domain-routed `@better-auth/sso` plugin is + wired (`OS_SSO_ENABLED` / `plugins.sso`). Without it the login UI had no signal + to gate on, so it rendered a "Sign in with SSO" button unconditionally — and on + a self-hosted / local deployment where SSO isn't wired, clicking it only then + surfaced "No SSO provider is configured for this email domain." + + The config now includes `features.sso`. `getPublicConfig()` returns the coarse + "is the plugin wired" flag — resolved with the EXACT logic that decides whether + the plugin is mounted in `buildPlugins()`, so the advertised capability can never + disagree with the actual `/sign-in/sso` route. The `/auth/config` route then + refines it to "usable" via the new `AuthManager.isSsoUsable()`, which additionally + requires at least one `sys_sso_provider` row to exist — so a freshly-enabled but + unconfigured SSO setup doesn't advertise a button that errors for everyone. + `isSsoUsable()` only queries when wired and fails open to the wired flag on any + introspection error (no data engine, query failure), so config never 500s. The + console login form consumes `features.sso` to hide the button (objectui side). + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-auth/package.json b/packages/plugins/plugin-auth/package.json index 50b39c7e2..2a5db9044 100644 --- a/packages/plugins/plugin-auth/package.json +++ b/packages/plugins/plugin-auth/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-auth", - "version": "10.3.0", + "version": "10.4.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 e358146bd..2f02106f2 100644 --- a/packages/plugins/plugin-dev/CHANGELOG.md +++ b/packages/plugins/plugin-dev/CHANGELOG.md @@ -1,5 +1,56 @@ # @objectstack/plugin-dev +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [d616e1d] +- Updated dependencies [1e8a813] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [359c0aa] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [9a810f8] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [a619a3a] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/objectql@10.4.0 + - @objectstack/runtime@10.4.0 + - @objectstack/plugin-auth@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/rest@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/account@10.4.0 + - @objectstack/setup@10.4.0 + - @objectstack/studio@10.4.0 + - @objectstack/driver-memory@10.4.0 + - @objectstack/plugin-hono-server@10.4.0 + - @objectstack/plugin-org-scoping@10.4.0 + - @objectstack/plugin-security@10.4.0 + - @objectstack/service-i18n@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-dev/package.json b/packages/plugins/plugin-dev/package.json index 493dfbcfb..19b3d90bb 100644 --- a/packages/plugins/plugin-dev/package.json +++ b/packages/plugins/plugin-dev/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-dev", - "version": "10.3.0", + "version": "10.4.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 d7eafb85a..80071ba21 100644 --- a/packages/plugins/plugin-email/CHANGELOG.md +++ b/packages/plugins/plugin-email/CHANGELOG.md @@ -1,5 +1,39 @@ # @objectstack/plugin-email +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/formula@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-email/package.json b/packages/plugins/plugin-email/package.json index 828172a59..127e01e88 100644 --- a/packages/plugins/plugin-email/package.json +++ b/packages/plugins/plugin-email/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-email", - "version": "10.3.0", + "version": "10.4.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 e4cc197ae..9dc35c8d6 100644 --- a/packages/plugins/plugin-hono-server/CHANGELOG.md +++ b/packages/plugins/plugin-hono-server/CHANGELOG.md @@ -1,5 +1,36 @@ # @objectstack/plugin-hono-server +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-hono-server/package.json b/packages/plugins/plugin-hono-server/package.json index e5d207de2..20692a4af 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": "10.3.0", + "version": "10.4.0", "license": "Apache-2.0", "description": "Standard Hono Server Adapter for ObjectStack Runtime", "main": "dist/index.js", diff --git a/packages/plugins/plugin-msw/CHANGELOG.md b/packages/plugins/plugin-msw/CHANGELOG.md index 9a0a2ad2c..e33c65b57 100644 --- a/packages/plugins/plugin-msw/CHANGELOG.md +++ b/packages/plugins/plugin-msw/CHANGELOG.md @@ -1,5 +1,43 @@ # @objectstack/plugin-msw +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [d616e1d] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [359c0aa] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/objectql@10.4.0 + - @objectstack/runtime@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-msw/package.json b/packages/plugins/plugin-msw/package.json index 83a6c4742..b84581994 100644 --- a/packages/plugins/plugin-msw/package.json +++ b/packages/plugins/plugin-msw/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-msw", - "version": "10.3.0", + "version": "10.4.0", "description": "MSW (Mock Service Worker) Plugin for ObjectStack Runtime", "license": "Apache-2.0", "main": "dist/index.js", diff --git a/packages/plugins/plugin-org-scoping/CHANGELOG.md b/packages/plugins/plugin-org-scoping/CHANGELOG.md index 66c622c4c..a3cf3eeed 100644 --- a/packages/plugins/plugin-org-scoping/CHANGELOG.md +++ b/packages/plugins/plugin-org-scoping/CHANGELOG.md @@ -1,5 +1,38 @@ # @objectstack/plugin-org-scoping +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-org-scoping/package.json b/packages/plugins/plugin-org-scoping/package.json index 19d1a1f0e..513cec49a 100644 --- a/packages/plugins/plugin-org-scoping/package.json +++ b/packages/plugins/plugin-org-scoping/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-org-scoping", - "version": "10.3.0", + "version": "10.4.0", "license": "Apache-2.0", "description": "Organization-Scoping Plugin for ObjectStack — row-level Organization isolation, per-org seed replay, default-org bootstrap", "main": "dist/index.js", diff --git a/packages/plugins/plugin-reports/CHANGELOG.md b/packages/plugins/plugin-reports/CHANGELOG.md index c0dc60901..edcd27dde 100644 --- a/packages/plugins/plugin-reports/CHANGELOG.md +++ b/packages/plugins/plugin-reports/CHANGELOG.md @@ -1,5 +1,38 @@ # @objectstack/plugin-reports +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-reports/package.json b/packages/plugins/plugin-reports/package.json index 5829729a6..d836dcb3e 100644 --- a/packages/plugins/plugin-reports/package.json +++ b/packages/plugins/plugin-reports/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-reports", - "version": "10.3.0", + "version": "10.4.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 4693d4e4b..ded216a70 100644 --- a/packages/plugins/plugin-security/CHANGELOG.md +++ b/packages/plugins/plugin-security/CHANGELOG.md @@ -1,5 +1,39 @@ # @objectstack/plugin-security +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/formula@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-security/package.json b/packages/plugins/plugin-security/package.json index 3706cf4a2..6525af008 100644 --- a/packages/plugins/plugin-security/package.json +++ b/packages/plugins/plugin-security/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-security", - "version": "10.3.0", + "version": "10.4.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 e3ef76a10..f7107b1c2 100644 --- a/packages/plugins/plugin-sharing/CHANGELOG.md +++ b/packages/plugins/plugin-sharing/CHANGELOG.md @@ -1,5 +1,45 @@ # @objectstack/plugin-sharing +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [d616e1d] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [359c0aa] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/objectql@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/formula@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-sharing/package.json b/packages/plugins/plugin-sharing/package.json index 09aad764f..2afbe5160 100644 --- a/packages/plugins/plugin-sharing/package.json +++ b/packages/plugins/plugin-sharing/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-sharing", - "version": "10.3.0", + "version": "10.4.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 3d2591789..f42a44d01 100644 --- a/packages/plugins/plugin-webhooks/CHANGELOG.md +++ b/packages/plugins/plugin-webhooks/CHANGELOG.md @@ -1,5 +1,35 @@ # @objectstack/plugin-webhooks +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/service-messaging@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/plugins/plugin-webhooks/package.json b/packages/plugins/plugin-webhooks/package.json index af3a64f4d..65735a646 100644 --- a/packages/plugins/plugin-webhooks/package.json +++ b/packages/plugins/plugin-webhooks/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/plugin-webhooks", - "version": "10.3.0", + "version": "10.4.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/rest/CHANGELOG.md b/packages/rest/CHANGELOG.md index 45684c990..3ef1d6d34 100644 --- a/packages/rest/CHANGELOG.md +++ b/packages/rest/CHANGELOG.md @@ -1,5 +1,84 @@ # @objectstack/rest +## 10.4.0 + +### Patch Changes + +- 359c0aa: fix(objectql,rest): single-item meta reads must revalidate (no `max-age=3600`) + + `GET /api/v1/meta/object/:name` (and the other single-item meta reads served by + the cached path) sent `Cache-Control: public, max-age, max-age=3600`. Two bugs: + + 1. **Stale metadata for up to an hour.** Object metadata is invalidated by + publish, but a one-hour TTL let browsers (and any CDN/proxy) serve a stale + schema _without revalidating_ — e.g. the AI-build "New" create form kept + rendering pre-publish fields until the TTL lapsed. The list endpoint + `GET /api/v1/meta/object` is uncached, which is why list views updated but + single-object reads didn't. `getMetaItemCached` now returns + `directives: ['private', 'no-cache']` with no `maxAge`, so the ETag validator + (which already changes on publish) gates freshness: a cheap `304` when + unchanged, fresh fields the instant a publish bumps the ETag. `private` also + keeps per-tenant metadata out of shared caches. + + 2. **Malformed header.** The directives array carried a bare `max-age` + placeholder _and_ the REST layer appended `max-age=3600` from the `maxAge` + field, concatenating into `public, max-age, max-age=3600`. The header builder + now strips the bare `max-age` token before appending the real value, so a + `maxAge` is emitted once as a well-formed `max-age=N`. + +- 9a810f8: fix(rest): register static data-action routes before the greedy `:object/:id` matcher + + The REST router matches first-registered-wins with no specificity sorting, but + `registerDataActionEndpoints` (which holds `GET /data/:object/export`) ran AFTER + `registerCrudEndpoints` (which holds the greedy `GET /data/:object/:id`). A + request to `GET /data//export` was therefore captured by `:object/:id` — + `"export"` treated as a record id — returning `404 RECORD_NOT_FOUND` instead of + streaming the export. The data-action registration now runs first, mirroring the + existing `/meta/:type/:name/references`-before-`/meta/:type/:name` convention. + Reordering is safe both ways: `registerDataActionEndpoints` contains no greedy + 2-segment `:object/:id` routes, so it cannot shadow any CRUD literal. A + regression test asserts the export route registers ahead of the get-by-id route. + +- a619a3a: fix(setup): first-run admin polish — pin Company/Localization, gate dashboard widgets by `requiresService`, i18n + settings PUT envelope + + Dogfooding the Setup app as a brand-new system administrator surfaced a cluster of small first-run gaps, now fixed: + + - **platform-objects**: pin **Localization** and **Company** in the Setup sidebar's Configuration group — both are registered `service-settings` manifests (the two lowest-`order` Workspace settings) but were reachable only via the "All Settings" hub. Translate the previously-English nav labels Cloud Connection (云连接), Datasources (数据源) and Capabilities (能力). Tag the System Overview `widget_organizations` KPI with `requiresService: 'org-scoping'`. + - **rest**: extend the ADR-0057 D10 server-side visibility gate to **dashboard widgets** — strip widgets whose `requiresService` names an unregistered kernel service (mirrors the existing app-nav gate; `resolveRegisteredServices` now also discovers gates declared on widgets). In a single-tenant runtime this removes the orphan "Organizations" KPI, matching the already-hidden org nav entries. + - **service-settings**: add the missing zh `help` strings for the Localization manifest (number/currency/first-day-of-week/fiscal-year fields), and accept the `{ values: { … } }` envelope on `PUT /api/settings/:ns` symmetrically with what `GET` returns. + +- aa33b02: fix(security): single-source the request authorization resolver — REST no longer drops sys_user_role + + The REST server and the runtime dispatcher each carried their own copy of the request → ExecutionContext identity/role resolver, and they drifted on a security path. The REST copy silently omitted `sys_user_role` (so custom roles granted via the ADR-0057 D4 platform-RBAC path did not apply over REST), `sys_role_permission_set`, the `owner→org_owner` membership normalization, the platform-admin derivation, and the `ai_seat` synthesis — fail-closed (legitimate access denied), not an escalation. + + Both entry points now delegate to a single shared resolver, `resolveAuthzContext` in `@objectstack/core/security` (joining the API-key verifier that already lived there). A contract test locks every authorization source and a lint gate (`check:authz-resolver`) prevents a future duplicate resolver or a dropped delegation. + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/service-package@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/rest/package.json b/packages/rest/package.json index 70d620f35..e62b6ce43 100644 --- a/packages/rest/package.json +++ b/packages/rest/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/rest", - "version": "10.3.0", + "version": "10.4.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 7dcb254f4..e40a218cc 100644 --- a/packages/runtime/CHANGELOG.md +++ b/packages/runtime/CHANGELOG.md @@ -1,5 +1,144 @@ # @objectstack/runtime +## 10.4.0 + +### Minor Changes + +- 4d99a5c: Package-scoped commit history & rollback for AI authoring (ADR-0067) + + Each authoring apply now lands as one revertible **commit** on a package timeline, on top of `sys_metadata_history`: + + - New `sys_metadata_commit` object groups a turn's metadata changes (by `event_seq` range). + - `publishPackageDrafts` records each publish as one commit (best-effort) with a per-artifact revert plan and an optional `message` / `aiModel`. + - New protocol methods `listCommits`, `revertCommit`, `rollbackToPackageCommit` (reusing `restoreVersion` + delete; a revert is itself an append-only commit). + - New REST routes: `GET /packages/:id/commits`, `POST /packages/:id/commits/:commitId/revert`, `POST /packages/:id/rollback`. + +- 6c4fbd9: fix(security): enforce flow `runAs` execution identity (#1888) + + The `service-automation` engine now honors `flow.runAs` instead of ignoring it. + Previously the CRUD nodes passed **no identity** to ObjectQL, so the security + middleware was skipped entirely — every flow ran effectively elevated regardless + of `runAs`. A `runAs:'user'` flow did **not** de-elevate (a privilege-boundary + surprise), and `runAs:'system'` did not _explicitly_ elevate. + + The engine now establishes the run's data-layer identity at setup and restores + the caller's context afterward: + + - **`runAs:'system'`** → an elevated, RLS-bypassing system principal + (`{ isSystem: true }`): the run can read/write records the triggering user + cannot. + - **`runAs:'user'`** (default) → the **triggering user's** identity + (`{ userId, roles, permissions, tenantId }`): CRUD nodes' ObjectQL reads/writes + respect that user's row-level security, and the run can never exceed the + triggering user's grants. + + To keep `runAs:'user'` faithful to a direct request by that user, the REST + trigger route (`@objectstack/runtime`) and the record-change trigger + (`@objectstack/trigger-record-change`) now forward the caller's resolved + `roles`/`tenantId` into the `AutomationContext` (new optional fields), not just + `userId`. The new `resolveRunDataContext` helper is the single place that maps a + run's effective `runAs` to the ObjectQL context, shared by every data node. + + The `[EXPERIMENTAL — not enforced]` marker is removed from `FlowSchema.runAs`. + + **Behavior change / migration.** Flows that previously relied on the implicit + elevation (the default `runAs:'user'` ran unscoped) now run as the triggering + user and are subject to their RLS. **Declare `runAs:'system'` on any flow that + must read or write beyond the triggering user's access** (e.g. system + automations, cross-owner roll-ups). Schedule-triggered runs have no trigger user; + under `user` they stay unscoped (there is no identity to scope to) — declare + `system` to make elevation explicit. + + Proven both directions by the dogfood regression gate + (`flow-runas.dogfood.test.ts` — a restricted member triggers system vs user + flows against an owner-scoped record) and service-automation unit + regression + tests (`crud-runas.test.ts`). + +### Patch Changes + +- 61d441f: feat(objectql): duplicate a writable base — ADR-0070 D4 ("duplicate base") + + `protocol.duplicatePackage` clones every ACTIVE item a base owns into a NEW + package, **re-namespacing** object names (the blueprint prefixes a base's object + names with its namespace, e.g. `iojn_repair_ticket`, and `sys_metadata` keys on + `(type,name,org)` so a same-name copy would collide with the source) and + **rewriting every intra-package reference** (lookup `reference`, view `object`, + expressions, …) to the new names via a longest-first, identifier-boundary + replace. Exposed as `POST /packages/:id/duplicate` (body + `{ targetPackageId, targetName?, targetNamespace? }`). + + Completes ADR-0070 D4 (package = lifecycle unit): delete-cascade and export + already shipped; this adds the duplicate gesture. + +- c224e18: feat(objectql): adopt orphaned metadata into a base — ADR-0070 D5 migration + + `protocol.reassignOrphanedMetadata` bulk-rebinds every package-less orphan + (`package_id` null / `""` / the `sys_metadata` sentinel left by the pre- + package-first stopgaps) onto a target base, leaving already-owned rows + untouched. Exposed as `POST /packages/:id/adopt-orphans`. This is the migration + affordance behind retiring the "Local / Custom" scope (D5): once an env has no + orphans, that scope can be dropped from the selector. Pairs with the kernel's + `writable_package_required` (D1) so no NEW orphans are created. + +- aa33b02: fix(security): single-source the request authorization resolver — REST no longer drops sys_user_role + + The REST server and the runtime dispatcher each carried their own copy of the request → ExecutionContext identity/role resolver, and they drifted on a security path. The REST copy silently omitted `sys_user_role` (so custom roles granted via the ADR-0057 D4 platform-RBAC path did not apply over REST), `sys_role_permission_set`, the `owner→org_owner` membership normalization, the platform-admin derivation, and the `ai_seat` synthesis — fail-closed (legitimate access denied), not an escalation. + + Both entry points now delegate to a single shared resolver, `resolveAuthzContext` in `@objectstack/core/security` (joining the API-key verifier that already lived there). A contract test locks every authorization source and a lint gate (`check:authz-resolver`) prevents a future duplicate resolver or a dropped delegation. + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [d616e1d] +- Updated dependencies [1e8a813] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [4b5ec6e] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [359c0aa] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [9a810f8] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [a619a3a] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [98a1535] +- Updated dependencies [bc22a89] +- Updated dependencies [8a7e9f1] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/objectql@10.4.0 + - @objectstack/plugin-auth@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/metadata@10.4.0 + - @objectstack/formula@10.4.0 + - @objectstack/rest@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/driver-sql@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/observability@10.4.0 + - @objectstack/driver-memory@10.4.0 + - @objectstack/driver-sqlite-wasm@10.4.0 + - @objectstack/plugin-org-scoping@10.4.0 + - @objectstack/plugin-security@10.4.0 + - @objectstack/service-cluster@10.4.0 + - @objectstack/service-datasource@10.4.0 + - @objectstack/service-i18n@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 14de9dd1b..c72beecb2 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/runtime", - "version": "10.3.0", + "version": "10.4.0", "license": "Apache-2.0", "description": "ObjectStack Core Runtime & Query Engine", "type": "module", diff --git a/packages/services/service-analytics/CHANGELOG.md b/packages/services/service-analytics/CHANGELOG.md index 1c6d9e362..73717a88c 100644 --- a/packages/services/service-analytics/CHANGELOG.md +++ b/packages/services/service-analytics/CHANGELOG.md @@ -1,5 +1,75 @@ # Changelog — @objectstack/service-analytics +## 10.4.0 + +### Minor Changes + +- 5eef4cf: feat(analytics): multi-hop relationship joins for datasets (ADR-0071) + + A dataset's `include` and dimension/measure `field` paths may now traverse up to + 3 to-one relationship hops (`account.owner.region`), not just one. The compiler + expands each declared path into the ordered join chain (one `cube.join` per path + prefix, aliased dot-free as `account__owner` so it stays a single valid SQL + identifier), and the NativeSQLStrategy emits the chained `LEFT JOIN`s. Per-hop + tenant/RLS read-scope is enforced for EVERY object in the chain — the + alias-driven scope loop already generalizes, so no security path is rewritten. + + Restricted to **to-one** (lookup / master_detail) relationships, which never fan + out — aggregates stay correct with no symmetric-aggregate machinery; to-many + traversal is out of scope. Single-hop datasets are byte-for-byte unchanged (the + dot-free alias is a no-op for a single segment). Undeclared paths are still + rejected (ADR-0021 D-C); paths beyond 3 hops are rejected at both parse and + compile time. + +### Patch Changes + +- 910a8f0: fix(analytics): compare boolean filters/group-by against the real boolean, not stringified '1' + + The analytics filter normalizer stringified boolean `true` → `'1'`, which the + ObjectQL strategy then coerced back to the number `1` before calling + `engine.aggregate`. Boolean fields hold a real `true`/`false`, so `1 !== true` + never matched: a metric widget filtered on a boolean field (e.g. + `{ is_critical: true }`) always returned 0, and pie/donut/bar charts grouped by + a boolean dimension failed to bucket. `stringifyForCube` now serializes booleans + as the tokens `'true'`/`'false'`, and a new `coerceFilterValueForObjectQL` + recovers a real boolean for the ObjectQL engine while the SQL path keeps binding + `1`/`0` (better-sqlite3 cannot bind a JS boolean). + +- 715d667: fix(analytics): qualify base-object columns in joined dataset queries + + A dataset that joins a related object (`include` + a `relationship.field` + dimension/measure) emitted BARE base-table columns in SELECT/GROUP BY while the + joined columns were alias-qualified. When the base and joined tables share a + column name (e.g. both have `status`), the query failed at runtime with + "ambiguous column name". `NativeSQLStrategy` now qualifies plain base-column + identifiers with the base table when the cube has joins; single-object cubes + are unchanged (byte-for-byte identical SQL). + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-analytics/package.json b/packages/services/service-analytics/package.json index 85aada693..996a3aab3 100644 --- a/packages/services/service-analytics/package.json +++ b/packages/services/service-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-analytics", - "version": "10.3.0", + "version": "10.4.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 d0d533eb6..169bda564 100644 --- a/packages/services/service-automation/CHANGELOG.md +++ b/packages/services/service-automation/CHANGELOG.md @@ -1,5 +1,172 @@ # @objectstack/service-automation +## 10.4.0 + +### Minor Changes + +- 6c4fbd9: fix(security): enforce flow `runAs` execution identity (#1888) + + The `service-automation` engine now honors `flow.runAs` instead of ignoring it. + Previously the CRUD nodes passed **no identity** to ObjectQL, so the security + middleware was skipped entirely — every flow ran effectively elevated regardless + of `runAs`. A `runAs:'user'` flow did **not** de-elevate (a privilege-boundary + surprise), and `runAs:'system'` did not _explicitly_ elevate. + + The engine now establishes the run's data-layer identity at setup and restores + the caller's context afterward: + + - **`runAs:'system'`** → an elevated, RLS-bypassing system principal + (`{ isSystem: true }`): the run can read/write records the triggering user + cannot. + - **`runAs:'user'`** (default) → the **triggering user's** identity + (`{ userId, roles, permissions, tenantId }`): CRUD nodes' ObjectQL reads/writes + respect that user's row-level security, and the run can never exceed the + triggering user's grants. + + To keep `runAs:'user'` faithful to a direct request by that user, the REST + trigger route (`@objectstack/runtime`) and the record-change trigger + (`@objectstack/trigger-record-change`) now forward the caller's resolved + `roles`/`tenantId` into the `AutomationContext` (new optional fields), not just + `userId`. The new `resolveRunDataContext` helper is the single place that maps a + run's effective `runAs` to the ObjectQL context, shared by every data node. + + The `[EXPERIMENTAL — not enforced]` marker is removed from `FlowSchema.runAs`. + + **Behavior change / migration.** Flows that previously relied on the implicit + elevation (the default `runAs:'user'` ran unscoped) now run as the triggering + user and are subject to their RLS. **Declare `runAs:'system'` on any flow that + must read or write beyond the triggering user's access** (e.g. system + automations, cross-owner roll-ups). Schedule-triggered runs have no trigger user; + under `user` they stay unscoped (there is no identity to scope to) — declare + `system` to make elevation explicit. + + Proven both directions by the dogfood regression gate + (`flow-runas.dogfood.test.ts` — a restricted member triggers system vs user + flows against an owner-scoped record) and service-automation unit + regression + tests (`crud-runas.test.ts`). + +- ad143ce: fix(security): surface the schedule/user-less `runAs:'user'` fail-open (#1888 follow-up) + + With `flow.runAs` now enforced (#1888), a **schedule-triggered** flow with the + default `runAs:'user'` has no trigger user. `resolveRunDataContext` returns + `undefined` for that case, so the CRUD nodes pass no ObjectQL `options.context` + and the security middleware — which _skips_ when there is no identity (it + delegates auth to the auth layer) — runs the operation **UNSCOPED** (effectively + elevated). An author who left `runAs` at the `'user'` default expecting a + restricted run silently gets an unscoped one — a fail-open footgun (ADR-0049: a + security property must not silently do the opposite of what it implies). + + This is the **product decision** to make that explicit, chosen to keep legitimate + scheduled CRUD working (denying outright would break it, and silently elevating + would hide the author's intent). Prevention happens where the platform can tell + intent apart (author/build time); the runtime stays non-breaking but is no longer + silent: + + - **Author-time lint** (`@objectstack/cli`, `lintFlowPatterns`): a new advisory + rule `flow-schedule-runas-unscoped` flags a schedule-triggered flow whose + effective `runAs` is `user` (explicit or unset) and which performs a data + operation — pointing the author at `runAs:'system'`. Catches the footgun at + compile time, before deploy (most flows are AI-authored). + - **Runtime warning** (`@objectstack/service-automation`): the engine now emits a + clear one-per-run warning when a user-mode run resolves no trigger identity and + the flow touches data — the fail-open is _audible_ rather than silent. Behavior + is otherwise unchanged (the run still executes), so scheduled CRUD that relied + on this is not broken. New helpers `runIsUnscopedUserMode`, `flowTouchesData`, + and `DATA_NODE_TYPES` are exported alongside `resolveRunDataContext`. + - **Spec describe** (`@objectstack/spec`): `FlowSchema.runAs` now states that a + scheduled run has no user, so under `user` it runs unscoped — declare `system`. + + The first-party example apps that tripped the new lint are fixed to declare + `runAs:'system'` explicitly (`stale_opportunity_sweep`, the app-todo + `task_reminder` / `overdue_escalation` sweeps) — they read/write across owners and + were running unscoped by default. + + Longer term, attributing scheduled runs to a dedicated service principal (so they + are scopable + audit-attributable rather than unscoped) is the right enforcement; + tracked as M2 follow-up. + + Proven by a service-automation unit test (the engine warns once for a user-less + user-mode data run; stays silent for `system`, for an identified user, and for a + data-less flow), an end-to-end test wiring the **real `ScheduleTrigger` to the + real engine** (`@objectstack/trigger-schedule`) that fires a job and asserts the + user-less identity reaches the engine + trips the warning through the actual cron + path, and a dogfood gate (`flow-runas-schedule.dogfood.test.ts`) that drives + user-less runs through the real automation + security + data stack: a + `runAs:'user'` run reads + writes an owner-scoped note a member cannot — audibly — + while `runAs:'system'` is the explicit, warning-free equivalent. + + Refs #1888, ADR-0049. + +### Patch Changes + +- 4b5ec6e: fix(automation): re-bind scheduled-flow jobs on `os dev` hot-reload + + Editing a schedule-triggered flow under `objectstack dev` silently kept firing + the OLD definition until a full server restart. The dev watcher recompiles + `dist/objectstack.json` and MetadataPlugin reloads it into the MetadataManager + (so GET /meta reads + UI HMR are fresh), but the AutomationEngine pulls its flow + definitions and trigger/job bindings ONCE at boot — nothing re-registered them + on reload. So the scheduled job bound at boot kept running the pre-edit flow + (old `runAs`, schedule, or logic) on its timer, with no signal that the edit had + no effect. + + Fix: MetadataPlugin now fires a generic `metadata:reloaded` hook after each + artifact reload (the HMR POST handler and the server-side artifact-file watcher; + never on the initial boot load). AutomationServicePlugin subscribes and re-syncs + the engine from the metadata service — re-registering every current flow + (idempotent: `registerFlow` re-binds the trigger, and `ScheduleTrigger.start` + cancels + reschedules the job) and unregistering flows removed from the artifact + so their jobs stop firing. This covers all auto-triggered flow types + (schedule / record-change / api), not just scheduled ones, since record-change + flows were also executing their boot-time definitions after an edit. Production + deployments are unaffected — nothing reloads the artifact there. + +- b6a4972: fix(automation): honor the `assignments` wrapper shape on assignment nodes + + The built-in `assignment` node executor set each TOP-LEVEL `config` key as a flow + variable. But the surfaces that author these nodes all emit an `assignments` + wrapper instead: + + - Studio's visual Assignment editor → `config: { assignments: { : } }` + - bundled example flows (app-crm, showcase) → `config: { assignments: [{ variable, value }] }` + + So a node designed in Studio (or any of the shipped examples) silently set a + single variable literally named `assignments` to the whole map/array and never + set the intended variables — it passed build and no-oped at run time, leaving + every downstream reference unresolved. + + The executor now normalizes all three shapes (`assignments` map, `assignments` + array of `{ variable | name | key, value }`, and the legacy flat + `{ : }`) and interpolates `{var}` templates in the values, matching + the CRUD / screen nodes. Adds `logic-nodes.test.ts` covering each shape as a + regression guard. + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/formula@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-automation/package.json b/packages/services/service-automation/package.json index c7a83605a..38b4fb4b7 100644 --- a/packages/services/service-automation/package.json +++ b/packages/services/service-automation/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-automation", - "version": "10.3.0", + "version": "10.4.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 912d7a94d..613e70b2c 100644 --- a/packages/services/service-cache/CHANGELOG.md +++ b/packages/services/service-cache/CHANGELOG.md @@ -1,5 +1,35 @@ # @objectstack/service-cache +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/observability@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-cache/package.json b/packages/services/service-cache/package.json index 5d93985d1..20ee66e87 100644 --- a/packages/services/service-cache/package.json +++ b/packages/services/service-cache/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-cache", - "version": "10.3.0", + "version": "10.4.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 aa8844d82..8600a9fba 100644 --- a/packages/services/service-cluster-redis/CHANGELOG.md +++ b/packages/services/service-cluster-redis/CHANGELOG.md @@ -1,5 +1,32 @@ # @objectstack/service-cluster-redis +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/service-cluster@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-cluster-redis/package.json b/packages/services/service-cluster-redis/package.json index 543b7fbf9..d9da2a2b7 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": "10.3.0", + "version": "10.4.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 d3377ba17..9db65363c 100644 --- a/packages/services/service-cluster/CHANGELOG.md +++ b/packages/services/service-cluster/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/service-cluster +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Minor Changes diff --git a/packages/services/service-cluster/package.json b/packages/services/service-cluster/package.json index 8fed5b8dc..baec33426 100644 --- a/packages/services/service-cluster/package.json +++ b/packages/services/service-cluster/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-cluster", - "version": "10.3.0", + "version": "10.4.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 2267065ed..c523bf357 100644 --- a/packages/services/service-datasource/CHANGELOG.md +++ b/packages/services/service-datasource/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/service-external-datasource +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-datasource/package.json b/packages/services/service-datasource/package.json index 573a35041..ed6ded88d 100644 --- a/packages/services/service-datasource/package.json +++ b/packages/services/service-datasource/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-datasource", - "version": "10.3.0", + "version": "10.4.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 5d0a75202..ebcd384e8 100644 --- a/packages/services/service-i18n/CHANGELOG.md +++ b/packages/services/service-i18n/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/service-i18n +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-i18n/package.json b/packages/services/service-i18n/package.json index 85c784128..8542318b4 100644 --- a/packages/services/service-i18n/package.json +++ b/packages/services/service-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-i18n", - "version": "10.3.0", + "version": "10.4.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 a65f64d90..641dea3bf 100644 --- a/packages/services/service-job/CHANGELOG.md +++ b/packages/services/service-job/CHANGELOG.md @@ -1,5 +1,38 @@ # @objectstack/service-job +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-job/package.json b/packages/services/service-job/package.json index c53d86709..6339d1a27 100644 --- a/packages/services/service-job/package.json +++ b/packages/services/service-job/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-job", - "version": "10.3.0", + "version": "10.4.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 1eaeeebde..a601aeafe 100644 --- a/packages/services/service-knowledge/CHANGELOG.md +++ b/packages/services/service-knowledge/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/service-knowledge +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-knowledge/package.json b/packages/services/service-knowledge/package.json index c6994aa3f..67a9dcfbe 100644 --- a/packages/services/service-knowledge/package.json +++ b/packages/services/service-knowledge/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-knowledge", - "version": "10.3.0", + "version": "10.4.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 66e80fd5b..76e9c368b 100644 --- a/packages/services/service-messaging/CHANGELOG.md +++ b/packages/services/service-messaging/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/service-messaging +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-messaging/package.json b/packages/services/service-messaging/package.json index 093a24b18..bd5690284 100644 --- a/packages/services/service-messaging/package.json +++ b/packages/services/service-messaging/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-messaging", - "version": "10.3.0", + "version": "10.4.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 c1a353828..7a9ae48d3 100644 --- a/packages/services/service-package/CHANGELOG.md +++ b/packages/services/service-package/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/service-package +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-package/package.json b/packages/services/service-package/package.json index 8ec9b19cd..ab6d58b1b 100644 --- a/packages/services/service-package/package.json +++ b/packages/services/service-package/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-package", - "version": "10.3.0", + "version": "10.4.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 0d0dfcf9f..00b9ca429 100644 --- a/packages/services/service-queue/CHANGELOG.md +++ b/packages/services/service-queue/CHANGELOG.md @@ -1,5 +1,38 @@ # @objectstack/service-queue +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-queue/package.json b/packages/services/service-queue/package.json index d1eb42adf..f0c282c49 100644 --- a/packages/services/service-queue/package.json +++ b/packages/services/service-queue/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-queue", - "version": "10.3.0", + "version": "10.4.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 5fa06fa52..08efe7b26 100644 --- a/packages/services/service-realtime/CHANGELOG.md +++ b/packages/services/service-realtime/CHANGELOG.md @@ -1,5 +1,38 @@ # @objectstack/service-realtime +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-realtime/package.json b/packages/services/service-realtime/package.json index 2df732b4a..70ecf123c 100644 --- a/packages/services/service-realtime/package.json +++ b/packages/services/service-realtime/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-realtime", - "version": "10.3.0", + "version": "10.4.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 e6c770644..f9a646481 100644 --- a/packages/services/service-settings/CHANGELOG.md +++ b/packages/services/service-settings/CHANGELOG.md @@ -1,5 +1,48 @@ # @objectstack/service-settings +## 10.4.0 + +### Patch Changes + +- a619a3a: fix(setup): first-run admin polish — pin Company/Localization, gate dashboard widgets by `requiresService`, i18n + settings PUT envelope + + Dogfooding the Setup app as a brand-new system administrator surfaced a cluster of small first-run gaps, now fixed: + + - **platform-objects**: pin **Localization** and **Company** in the Setup sidebar's Configuration group — both are registered `service-settings` manifests (the two lowest-`order` Workspace settings) but were reachable only via the "All Settings" hub. Translate the previously-English nav labels Cloud Connection (云连接), Datasources (数据源) and Capabilities (能力). Tag the System Overview `widget_organizations` KPI with `requiresService: 'org-scoping'`. + - **rest**: extend the ADR-0057 D10 server-side visibility gate to **dashboard widgets** — strip widgets whose `requiresService` names an unregistered kernel service (mirrors the existing app-nav gate; `resolveRegisteredServices` now also discovers gates declared on widgets). In a single-tenant runtime this removes the orphan "Organizations" KPI, matching the already-hidden org nav entries. + - **service-settings**: add the missing zh `help` strings for the Localization manifest (number/currency/first-day-of-week/fiscal-year fields), and accept the `{ values: { … } }` envelope on `PUT /api/settings/:ns` symmetrically with what `GET` returns. + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [795b6d1] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/types@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-settings/package.json b/packages/services/service-settings/package.json index 083d43a12..414065a95 100644 --- a/packages/services/service-settings/package.json +++ b/packages/services/service-settings/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-settings", - "version": "10.3.0", + "version": "10.4.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-storage/CHANGELOG.md b/packages/services/service-storage/CHANGELOG.md index e513e4241..caeb56505 100644 --- a/packages/services/service-storage/CHANGELOG.md +++ b/packages/services/service-storage/CHANGELOG.md @@ -1,5 +1,39 @@ # @objectstack/service-storage +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [5737261] +- Updated dependencies [a619a3a] +- Updated dependencies [f44c1bd] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/platform-objects@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/observability@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/services/service-storage/package.json b/packages/services/service-storage/package.json index 61d63b325..5458dcb3e 100644 --- a/packages/services/service-storage/package.json +++ b/packages/services/service-storage/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/service-storage", - "version": "10.3.0", + "version": "10.4.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 784921699..6a026c410 100644 --- a/packages/spec/CHANGELOG.md +++ b/packages/spec/CHANGELOG.md @@ -1,5 +1,347 @@ # @objectstack/spec +## 10.4.0 + +### Minor Changes + +- 4845c12: feat(cli): make the AI service opt-in via a declared dependency; honor `config.tiers` + + **AI edition boundary (cli).** The CLI auto-registered the headless `AIServicePlugin` + whenever the `ai` tier was enabled (default) and `@objectstack/service-ai` was + merely _resolvable_. In a workspace/monorepo the package is hoist-resolvable even + when an app does not declare it, so every app got the AI service — discovery + reported `services.ai: available` and the agent runtime served any + metadata-defined agents — including Community-Edition apps that ship no AI. + + Now the _declared_ dependency is the boundary: AIService auto-registers only when + the host app declares `@objectstack/service-ai` **or** `@objectstack/service-ai-studio` + (Studio attaches its personas via the base service's `ai:ready` hook, so declaring + Studio implies the base). A CE app that declares neither gets no AI service, no + agents, and `services.ai: { enabled: false, status: 'unavailable' }` in discovery + (so the console hides its AI surface). MCP and every other capability are + unaffected. The `app-showcase`/`app-crm` examples now declare `@objectstack/service-ai`. + + **`config.tiers` now honored (spec).** `ObjectStackDefinitionSchema` gains a `tiers` + field, so `defineStack` no longer strips it. `config.tiers` (e.g. a list WITHOUT + `ai`) now actually overrides the `--preset` default — previously it was silently + dropped by schema validation, making the `--preset` help text inaccurate. This is + a second, in-place way to disable AI for a deployment without touching dependencies. + +- 715d667: feat(spec): dataset authoring form + derived measures without a dummy aggregate + + `dataset` was the only UI-authorable metadata type without a `defineForm` + layout, so Studio's create surface fell back to the auto-generated flat layout + (free-text `object`, no grouping). Adds `dataset.form.ts` (registered in + `METADATA_FORM_REGISTRY`): sectioned Basics / Source / Dimensions / Measures + with an `object` picker (`ref:object`) and guidance — matching the sibling + `report` editor. + + Also makes `DatasetMeasureSchema.aggregate` optional. A derived measure + (`derived: { op, of }`) combines other measures by name and `aggregate` is + ignored for it at compile time, but the schema still required it — so a derived + measure failed validation unless you added a meaningless aggregate. `aggregate` + is now required only for non-derived measures (enforced in the existing + `superRefine`). Backward compatible: existing measures that carry an aggregate + stay valid. + +- 5eef4cf: feat(analytics): multi-hop relationship joins for datasets (ADR-0071) + + A dataset's `include` and dimension/measure `field` paths may now traverse up to + 3 to-one relationship hops (`account.owner.region`), not just one. The compiler + expands each declared path into the ordered join chain (one `cube.join` per path + prefix, aliased dot-free as `account__owner` so it stays a single valid SQL + identifier), and the NativeSQLStrategy emits the chained `LEFT JOIN`s. Per-hop + tenant/RLS read-scope is enforced for EVERY object in the chain — the + alias-driven scope loop already generalizes, so no security path is rewritten. + + Restricted to **to-one** (lookup / master_detail) relationships, which never fan + out — aggregates stay correct with no symmetric-aggregate machinery; to-many + traversal is out of scope. Single-hop datasets are byte-for-byte unchanged (the + dot-free alias is a no-op for a single segment). Undeclared paths are still + rejected (ADR-0021 D-C); paths beyond 3 hops are rejected at both parse and + compile time. + +- 6c4fbd9: fix(security): enforce flow `runAs` execution identity (#1888) + + The `service-automation` engine now honors `flow.runAs` instead of ignoring it. + Previously the CRUD nodes passed **no identity** to ObjectQL, so the security + middleware was skipped entirely — every flow ran effectively elevated regardless + of `runAs`. A `runAs:'user'` flow did **not** de-elevate (a privilege-boundary + surprise), and `runAs:'system'` did not _explicitly_ elevate. + + The engine now establishes the run's data-layer identity at setup and restores + the caller's context afterward: + + - **`runAs:'system'`** → an elevated, RLS-bypassing system principal + (`{ isSystem: true }`): the run can read/write records the triggering user + cannot. + - **`runAs:'user'`** (default) → the **triggering user's** identity + (`{ userId, roles, permissions, tenantId }`): CRUD nodes' ObjectQL reads/writes + respect that user's row-level security, and the run can never exceed the + triggering user's grants. + + To keep `runAs:'user'` faithful to a direct request by that user, the REST + trigger route (`@objectstack/runtime`) and the record-change trigger + (`@objectstack/trigger-record-change`) now forward the caller's resolved + `roles`/`tenantId` into the `AutomationContext` (new optional fields), not just + `userId`. The new `resolveRunDataContext` helper is the single place that maps a + run's effective `runAs` to the ObjectQL context, shared by every data node. + + The `[EXPERIMENTAL — not enforced]` marker is removed from `FlowSchema.runAs`. + + **Behavior change / migration.** Flows that previously relied on the implicit + elevation (the default `runAs:'user'` ran unscoped) now run as the triggering + user and are subject to their RLS. **Declare `runAs:'system'` on any flow that + must read or write beyond the triggering user's access** (e.g. system + automations, cross-owner roll-ups). Schedule-triggered runs have no trigger user; + under `user` they stay unscoped (there is no identity to scope to) — declare + `system` to make elevation explicit. + + Proven both directions by the dogfood regression gate + (`flow-runas.dogfood.test.ts` — a restricted member triggers system vs user + flows against an owner-scoped record) and service-automation unit + regression + tests (`crud-runas.test.ts`). + +- ef3ed67: Formula field typing: `inferExpressionType()` + a declared `returnType`. + + - `@objectstack/formula`: new `inferExpressionType()` (and lower-level `inferCelType()`) surfaces the cel-js type-checker's result for a CEL value/formula expression, mapped to `number | text | boolean | date | unknown`. Conservative — two `dyn` operands stay `unknown`; typed literals/stdlib returns pin a concrete type. + - `@objectstack/spec`: `FieldSchema` gains an optional `returnType` (`number|text|boolean|date`) so a formula field can carry its declared value type (the way Salesforce/Airtable do), letting consumers (dataset measures, formatting, validation) read a declared type instead of re-parsing the expression. + +- cd51229: Expose authoritative create seeds via /meta/types (spec-derived create-shape contract, Phase 2) + + The minimal valid create seeds added in `@objectstack/spec/kernel` (`getMetadataCreateSeed`) now reach consumers through the real `/meta/types` registry response: each entry carries an optional `createSeed`. The Studio designer / CLI / API clients derive their create defaults from this single source of truth instead of re-inventing them — closing the drift that produced the dashboard-`layout` and action-`body` create→save 422s. + + - `@objectstack/spec`: barrel-export `getMetadataCreateSeed` / `listMetadataCreateSeedTypes` from `/kernel`; add optional `createSeed` to the `GetMetaTypesResponse` entry schema. + - `@objectstack/objectql`: `getMetaTypes()` attaches each type's seed (registry + runtime entries). Canvas-create types whose shape is built interactively (report) are intentionally absent. + +- 7697a0e: chore(spec): hard-remove the dead `blank`/`record_review` page config (enforce-or-remove) + + Completes the enforce-or-remove started in framework#2265. The `blank` and + `record_review` page types were already removed from `PageTypeSchema` (no + renderer), their fields marked `@deprecated`, and objectui dropped all + references (objectui#1949). This deletes the now-unreachable surface: + + - `BlankPageLayoutSchema`, `BlankPageLayoutItemSchema`, `RecordReviewConfigSchema` + (and their inferred types `BlankPageLayout`, `BlankPageLayoutItem`, + `RecordReviewConfig`). + - The `blankLayout` and `recordReview` fields on `PageSchema`. + - `page-builder.zod.ts` (the `blank`-type drag-drop canvas config: + `PageBuilderConfigSchema` / `CanvasSnapSettingsSchema` / `CanvasZoomSettingsSchema` + / `ElementPaletteItemSchema` / `InterfaceBuilderConfigSchema` and their types) + and its `@objectstack/spec/studio` re-exports — nothing consumed them. + + The `page` liveness ledger drops to 15 properties (the 2 `dead` entries are gone). + No consumers in framework or objectui (objectui#1949 already merged). + + **Version note (kept `minor`, not `major`).** These exports shipped in the + published `10.3.0`, so under ADR-0059 §4 (the freeze contract) a removal would + normally demand a major bump. It is kept `minor` as a deliberate, documented + exception: the removed symbols are config schemas for the renderless + `blank`/`record_review` page types — authoring those already failed at runtime + ("Unknown component type"), the frozen `@objectstack/downstream-contract` + fixture never referenced them, and the pre-publish hotcrm live gate guards + against any real consumer break. The `api-surface.json` snapshot is regenerated + alongside this so the removal is acknowledged, not silent. + +- cfd5ac4: fix(spec): remove unrendered roadmap page types from PageTypeSchema (enforce-or-remove) + + `PageTypeSchema` advertised six page types that never shipped a renderer — + `dashboard`, `form`, `record_detail`, `record_review`, `overview`, `blank`. + Authoring one passed schema validation but broke at runtime ("Unknown component + type"), a false affordance that's especially dangerous when templates are + AI-authored. Per ADR-0049 (enforce-or-remove), the enum is now the _live_ set + (`record`, `home`, `app`, `utility`, `list`) — authoring a removed type now + fails fast at parse instead of silently at render. The removed types are tracked + in the new `PAGE_TYPE_ROADMAP` export and re-enter the enum only when a renderer + ships. A `page-type-liveness` gate test asserts the enum never re-grows a + roadmap type. + + The `recordReview`/`blankLayout` config schemas and fields are retained but + `@deprecated` (their page types are no longer authorizable) to avoid breaking + downstream imports; they will be removed in a coordinated follow-up. The + `variables` page field is documented `@experimental` — its state container is + wired but no consumer reads/writes it end-to-end yet. + +- 5c4a8c8: feat(spec): RecordRelatedListProps.add — add-existing-via-picker (generic m2m/junction assignment). A related list can now link existing records via a picker, not just create+navigate. Powers a generic "Assigned Users" / Manage Assignments UI on permission sets. +- 3afaeed: feat(ui): add `element:text_input` — free-text data-entry element for SDUI pages + + SDUI pages could display and navigate but not collect free-text input. This adds + that half of the contract: + + - `ElementTextInputPropsSchema` (label, placeholder, `inputType` — + text/email/number/tel/url/password — defaultValue, required, disabled, + description) wired into `PageComponentType` and `ComponentPropsMap` as + `element:text_input`. + + The objectui renderer binds the typed value into a page variable + (`PageVariableSchema.source`); a submit `element:button` reads it back via + `{{page.}}` token interpolation in the console action runtime. Showcase: + `showcase_contact_form` (text inputs → page variables → POST web-to-lead). + +- 3d04e06: Add authoritative per-type create seeds (root-cause for the "designer shape ≠ spec" family) + + New `metadata-create-seeds.ts`: a single source of truth for the minimal valid create shape of each metadata type (`getMetadataCreateSeed(type)`), co-located with the schemas and asserted valid against each type's schema by `metadata-create-seeds.test.ts`. This anchors the create-form's default shape to the spec so it can't drift — the root cause of the recurring family where a freshly-created item (dashboard without `layout`, script action without `body`, report with stale `objectName`/`columns`) failed validation on save (422) yet passed every other gate. Seeds the 9 core Studio-designer types (dashboard, action, page, view, flow, validation, hook, dataset, object); the test surfaces remaining schema-backed types still needing a seed. (Follow-up: expose `createSeed` via `/meta/types` so the Studio designer consumes it instead of hardcoding `createDefaults`.) + +- d980f0d: feat: add a first-class `user` field type (person picker) + + A new `user` field type — the equivalent of Airtable's Collaborator / Notion's + Person / Salesforce's `Lookup(User)`. Authored as `Field.user({ ... })`; use + `{ multiple: true }` for collaborators/watchers and `{ defaultValue: 'current_user' }` + to auto-fill the acting user on create. + + **Why a distinct type rather than telling authors to `Field.lookup('sys_user')`:** + selecting a person is table-stakes, but the value is in _modelling + discoverability_ — a "User" entry in the Studio/AI field palette instead of + requiring authors (and AI) to know to reference the internal `sys_user` system + object — plus `current_user` defaults and a user-search picker. Storage and + runtime are unchanged. + + **Deliberately NOT a new storage primitive.** `user` is a _semantic + specialization of `lookup`_ with the target fixed to `sys_user`: it shares the + exact lookup code path — same FK string column (`multiple` ⇒ JSON), same + `$expand` resolution, same indexing — so referential integrity and fresh display + names come for free, and nothing is re-implemented. An existing + `Field.lookup('sys_user')` is therefore equivalent at the storage layer (zero + data migration to adopt `Field.user`). + + Ownership semantics are **unchanged**: the existing `owner_id` convention + + `plugin-security` auto-stamp/RLS still apply. A declarative `owner` flag is a + possible future follow-up; intentionally not added here to avoid a second + field type for what is a system role (rationale: keep the `FieldType` surface + lean — see related ADR-0059 freeze discipline). + + Changes: `FieldType` gains `'user'` + `Field.user()` builder; the SQL/Mongo + drivers treat `user` exactly like `lookup`; the engine resolves `$expand` for + `user` fields and honours a new `defaultValue: 'current_user'` token (resolved + app-side from the execution context, mirroring the `NOW()` convention); kanban + group-by and symbolic seed references accept `user`; approvals enrich `user` + references. The public API surface is unchanged (additive enum member). + +### Patch Changes + +- c1a754a: feat(spec): type ChartConfig `colors` as a palette OR a value→color map + + `ChartConfigSchema.colors` now accepts either a positional palette (`string[]`) + or an explicit value→color map (`Record`, kanban-style). A + value→color map — and a select/lookup dimension's option colors — take + precedence over the positional palette per category, so semantic charts + (health, status) paint their own colors instead of the generic palette. + +- 6fbe91f: fix(spec): make dashboard widget `layout` optional (auto-flowed when omitted) + + `DashboardWidgetSchema.layout` was required, but the entire runtime treats it as + optional: the renderer (`DashboardGridLayout`) auto-flows any widget without a + layout (`x: (i % 4) * 3, y: ⌊i/4⌋ * 4, w: 3, h: 4`), and the Studio dashboard + designer adds widgets **without** a layout by design. + + The mismatch meant every dashboard authored in the Studio designer failed spec + validation the moment a widget was added — the draft `PUT /meta/dashboard/...` + returned **422** ("widgets: Invalid type: expected object, received undefined"), + so the draft never saved and **Publish stayed disabled**, even though the widget + rendered correctly in the canvas. Found by dogfooding the dashboard designer in + the browser. + + `layout` is now optional; absence means "auto-place". Authors may still pin an + explicit grid position. Backward-compatible — existing dashboards that specify + `layout` are unaffected. + +- 72759e1: feat(spec): add the `back` edge style to the flow-builder canvas protocol + + `FlowCanvasEdgeStyleSchema` gains a `back` value alongside `solid`/`dashed`/`dotted`/`bold`, marking an ADR-0044 declared back-edge (a `revise` loop's resubmit edge). Flow-builder-protocol consumers can now render it as a distinct curved/dashed return arc, set apart from forward flow — matching the objectui designer's hand-rolled canvas (objectstack-ai/objectui#1954). Part of #2274. + +- e7e04f1: chore(liveness): bring `page` under the spec liveness gate + + Onboards the `page` metadata type to the ADR-0049/#1919 liveness ledger + (`packages/spec/liveness/page.json`) and adds it to the governed-types list in + `check-liveness.mts`. Every authorable PageSchema property now declares a + status with evidence: 17 properties — 14 `live` (objectui renderer consumers + cited as prose), 1 `experimental` (`variables` — provider/hook exist, no + end-to-end consumer), 2 `dead` (`recordReview` / `blankLayout` — their page + types were removed in framework#2265 and objectui dropped all references in + objectui#1949; the fields stay @deprecated pending hard-removal). CI now fails + if a new page property lands unclassified. + +- 2be5c1f: Promote `PageSchema.variables` from @experimental to live (ADR-0049) + + Page-local state is now wired end-to-end (runtime in objectui#1957: page + variables are injected into the visible/CEL expression context as `page.`, + and `element:record_picker` writes a variable via its `source` binding). The + spec docs are updated to describe the now-live behaviour and the binding + direction, and the liveness ledger entry is flipped `experimental → live`. + +- ad143ce: fix(security): surface the schedule/user-less `runAs:'user'` fail-open (#1888 follow-up) + + With `flow.runAs` now enforced (#1888), a **schedule-triggered** flow with the + default `runAs:'user'` has no trigger user. `resolveRunDataContext` returns + `undefined` for that case, so the CRUD nodes pass no ObjectQL `options.context` + and the security middleware — which _skips_ when there is no identity (it + delegates auth to the auth layer) — runs the operation **UNSCOPED** (effectively + elevated). An author who left `runAs` at the `'user'` default expecting a + restricted run silently gets an unscoped one — a fail-open footgun (ADR-0049: a + security property must not silently do the opposite of what it implies). + + This is the **product decision** to make that explicit, chosen to keep legitimate + scheduled CRUD working (denying outright would break it, and silently elevating + would hide the author's intent). Prevention happens where the platform can tell + intent apart (author/build time); the runtime stays non-breaking but is no longer + silent: + + - **Author-time lint** (`@objectstack/cli`, `lintFlowPatterns`): a new advisory + rule `flow-schedule-runas-unscoped` flags a schedule-triggered flow whose + effective `runAs` is `user` (explicit or unset) and which performs a data + operation — pointing the author at `runAs:'system'`. Catches the footgun at + compile time, before deploy (most flows are AI-authored). + - **Runtime warning** (`@objectstack/service-automation`): the engine now emits a + clear one-per-run warning when a user-mode run resolves no trigger identity and + the flow touches data — the fail-open is _audible_ rather than silent. Behavior + is otherwise unchanged (the run still executes), so scheduled CRUD that relied + on this is not broken. New helpers `runIsUnscopedUserMode`, `flowTouchesData`, + and `DATA_NODE_TYPES` are exported alongside `resolveRunDataContext`. + - **Spec describe** (`@objectstack/spec`): `FlowSchema.runAs` now states that a + scheduled run has no user, so under `user` it runs unscoped — declare `system`. + + The first-party example apps that tripped the new lint are fixed to declare + `runAs:'system'` explicitly (`stale_opportunity_sweep`, the app-todo + `task_reminder` / `overdue_escalation` sweeps) — they read/write across owners and + were running unscoped by default. + + Longer term, attributing scheduled runs to a dedicated service principal (so they + are scopable + audit-attributable rather than unscoped) is the right enforcement; + tracked as M2 follow-up. + + Proven by a service-automation unit test (the engine warns once for a user-less + user-mode data run; stays silent for `system`, for an identified user, and for a + data-less flow), an end-to-end test wiring the **real `ScheduleTrigger` to the + real engine** (`@objectstack/trigger-schedule`) that fires a job and asserts the + user-less identity reaches the engine + trips the warning through the actual cron + path, and a dogfood gate (`flow-runas-schedule.dogfood.test.ts`) that drives + user-less runs through the real automation + security + data stack: a + `runAs:'user'` run reads + writes an owner-scoped note a member cannot — audibly — + while `runAs:'system'` is the explicit, warning-free equivalent. + + Refs #1888, ADR-0049. + +- 8801c02: fix(spec): don't require `slots` on slotted pages + + `PageSchema`'s superRefine rejected any `kind: 'slotted'` page that didn't + provide a `slots` map — but a slotted page with no overrides is valid: every + slot falls through to the synthesized default layout, the natural starting + point before you add overrides. Requiring `slots` up front made the Studio + "New Page" form a dead-end the moment you picked "slotted" (the form can't + author a slot map), the same trap as the old required `regions`. + +- 4a84c98: fix(spec): make page `regions` and component `properties` optional + + `PageSchema.regions` and `PageComponentSchema.properties` were required, which + made it impossible to create record/home/app pages in the Studio editor: the + New Page form has no region editor, and the create-form seeds a record page's + default layout from `buildDefaultPageSchema`, whose nodes carry props at the top + level — so every seeded block tripped `regions.N.components.M.properties: +expected record`. Both are now `.optional().default(...)`; an empty full page + falls back to the synthesized default layout, slotted pages compose via `slots`, + list pages ignore regions, and prop-less components (record:activity, + element:divider) no longer need `properties: {}`. + ## 10.3.0 ## 10.2.0 diff --git a/packages/spec/package.json b/packages/spec/package.json index 1e89b37c4..13f7849c7 100644 --- a/packages/spec/package.json +++ b/packages/spec/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/spec", - "version": "10.3.0", + "version": "10.4.0", "description": "ObjectStack Protocol & Specification - TypeScript Interfaces, JSON Schemas, and Convention Configurations", "license": "Apache-2.0", "main": "dist/index.js", diff --git a/packages/triggers/trigger-api/CHANGELOG.md b/packages/triggers/trigger-api/CHANGELOG.md index 6860028eb..9ff3ff5c3 100644 --- a/packages/triggers/trigger-api/CHANGELOG.md +++ b/packages/triggers/trigger-api/CHANGELOG.md @@ -1,5 +1,34 @@ # @objectstack/trigger-api +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/triggers/trigger-api/package.json b/packages/triggers/trigger-api/package.json index 61faa63e2..2da0bd73d 100644 --- a/packages/triggers/trigger-api/package.json +++ b/packages/triggers/trigger-api/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/trigger-api", - "version": "10.3.0", + "version": "10.4.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 ba502288f..4db2c9805 100644 --- a/packages/triggers/trigger-record-change/CHANGELOG.md +++ b/packages/triggers/trigger-record-change/CHANGELOG.md @@ -1,5 +1,77 @@ # @objectstack/plugin-trigger-record-change +## 10.4.0 + +### Minor Changes + +- 6c4fbd9: fix(security): enforce flow `runAs` execution identity (#1888) + + The `service-automation` engine now honors `flow.runAs` instead of ignoring it. + Previously the CRUD nodes passed **no identity** to ObjectQL, so the security + middleware was skipped entirely — every flow ran effectively elevated regardless + of `runAs`. A `runAs:'user'` flow did **not** de-elevate (a privilege-boundary + surprise), and `runAs:'system'` did not _explicitly_ elevate. + + The engine now establishes the run's data-layer identity at setup and restores + the caller's context afterward: + + - **`runAs:'system'`** → an elevated, RLS-bypassing system principal + (`{ isSystem: true }`): the run can read/write records the triggering user + cannot. + - **`runAs:'user'`** (default) → the **triggering user's** identity + (`{ userId, roles, permissions, tenantId }`): CRUD nodes' ObjectQL reads/writes + respect that user's row-level security, and the run can never exceed the + triggering user's grants. + + To keep `runAs:'user'` faithful to a direct request by that user, the REST + trigger route (`@objectstack/runtime`) and the record-change trigger + (`@objectstack/trigger-record-change`) now forward the caller's resolved + `roles`/`tenantId` into the `AutomationContext` (new optional fields), not just + `userId`. The new `resolveRunDataContext` helper is the single place that maps a + run's effective `runAs` to the ObjectQL context, shared by every data node. + + The `[EXPERIMENTAL — not enforced]` marker is removed from `FlowSchema.runAs`. + + **Behavior change / migration.** Flows that previously relied on the implicit + elevation (the default `runAs:'user'` ran unscoped) now run as the triggering + user and are subject to their RLS. **Declare `runAs:'system'` on any flow that + must read or write beyond the triggering user's access** (e.g. system + automations, cross-owner roll-ups). Schedule-triggered runs have no trigger user; + under `user` they stay unscoped (there is no identity to scope to) — declare + `system` to make elevation explicit. + + Proven both directions by the dogfood regression gate + (`flow-runas.dogfood.test.ts` — a restricted member triggers system vs user + flows against an owner-scoped record) and service-automation unit + regression + tests (`crud-runas.test.ts`). + +### Patch Changes + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/triggers/trigger-record-change/package.json b/packages/triggers/trigger-record-change/package.json index ec54bc085..af11b5398 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": "10.3.0", + "version": "10.4.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 e1ca46285..206b6ac4d 100644 --- a/packages/triggers/trigger-schedule/CHANGELOG.md +++ b/packages/triggers/trigger-schedule/CHANGELOG.md @@ -1,5 +1,86 @@ # @objectstack/plugin-trigger-schedule +## 10.4.0 + +### Patch Changes + +- ad143ce: fix(security): surface the schedule/user-less `runAs:'user'` fail-open (#1888 follow-up) + + With `flow.runAs` now enforced (#1888), a **schedule-triggered** flow with the + default `runAs:'user'` has no trigger user. `resolveRunDataContext` returns + `undefined` for that case, so the CRUD nodes pass no ObjectQL `options.context` + and the security middleware — which _skips_ when there is no identity (it + delegates auth to the auth layer) — runs the operation **UNSCOPED** (effectively + elevated). An author who left `runAs` at the `'user'` default expecting a + restricted run silently gets an unscoped one — a fail-open footgun (ADR-0049: a + security property must not silently do the opposite of what it implies). + + This is the **product decision** to make that explicit, chosen to keep legitimate + scheduled CRUD working (denying outright would break it, and silently elevating + would hide the author's intent). Prevention happens where the platform can tell + intent apart (author/build time); the runtime stays non-breaking but is no longer + silent: + + - **Author-time lint** (`@objectstack/cli`, `lintFlowPatterns`): a new advisory + rule `flow-schedule-runas-unscoped` flags a schedule-triggered flow whose + effective `runAs` is `user` (explicit or unset) and which performs a data + operation — pointing the author at `runAs:'system'`. Catches the footgun at + compile time, before deploy (most flows are AI-authored). + - **Runtime warning** (`@objectstack/service-automation`): the engine now emits a + clear one-per-run warning when a user-mode run resolves no trigger identity and + the flow touches data — the fail-open is _audible_ rather than silent. Behavior + is otherwise unchanged (the run still executes), so scheduled CRUD that relied + on this is not broken. New helpers `runIsUnscopedUserMode`, `flowTouchesData`, + and `DATA_NODE_TYPES` are exported alongside `resolveRunDataContext`. + - **Spec describe** (`@objectstack/spec`): `FlowSchema.runAs` now states that a + scheduled run has no user, so under `user` it runs unscoped — declare `system`. + + The first-party example apps that tripped the new lint are fixed to declare + `runAs:'system'` explicitly (`stale_opportunity_sweep`, the app-todo + `task_reminder` / `overdue_escalation` sweeps) — they read/write across owners and + were running unscoped by default. + + Longer term, attributing scheduled runs to a dedicated service principal (so they + are scopable + audit-attributable rather than unscoped) is the right enforcement; + tracked as M2 follow-up. + + Proven by a service-automation unit test (the engine warns once for a user-less + user-mode data run; stays silent for `system`, for an identified user, and for a + data-less flow), an end-to-end test wiring the **real `ScheduleTrigger` to the + real engine** (`@objectstack/trigger-schedule`) that fires a job and asserts the + user-less identity reaches the engine + trips the warning through the actual cron + path, and a dogfood gate (`flow-runas-schedule.dogfood.test.ts`) that drives + user-less runs through the real automation + security + data stack: a + `runAs:'user'` run reads + writes an owner-scoped note a member cannot — audibly — + while `runAs:'system'` is the explicit, warning-free equivalent. + + Refs #1888, ADR-0049. + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + - @objectstack/core@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/triggers/trigger-schedule/package.json b/packages/triggers/trigger-schedule/package.json index b88b4c8df..0d480a518 100644 --- a/packages/triggers/trigger-schedule/package.json +++ b/packages/triggers/trigger-schedule/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/trigger-schedule", - "version": "10.3.0", + "version": "10.4.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 0913aba2e..23ed4ff4a 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -1,5 +1,62 @@ # @objectstack/types +## 10.4.0 + +### Patch Changes + +- 795b6d1: refactor: single-source the multi-org (`OS_MULTI_ORG_ENABLED`) flag resolution + + "Is this deployment multi-org?" was resolved in 10 places across 8 packages + with three subtly different inline expressions: + + - the canonical `String(readEnvWithDeprecation('OS_MULTI_ORG_ENABLED', +'OS_MULTI_TENANT') ?? 'false').toLowerCase() !== 'false'` (objectql registry, + plugin-dev, runtime app-plugin, cli serve/verify, cloud-connection), + - a redundant `env.OS_MULTI_ORG_ENABLED !== undefined ? … : …` variant in + plugin-auth (auth-manager `/auth/config` features + `beforeCreateOrganization` + guard), + - and a bare `process.env.OS_MULTI_ORG_ENABLED ?? process.env.OS_MULTI_TENANT` + read in the SQL driver's `isMultiTenantMode()` — which skipped the + `OS_MULTI_TENANT` deprecation warning every other site emits. + + Because the SQL driver computed the mode independently of the auth/security + layer, the driver's tenant-audit gate and the rest of the system could in + principle disagree about whether tenant isolation is active. + + Introduces `resolveMultiOrgEnabled()` in `@objectstack/types` (next to + `readEnvWithDeprecation`, the natural leaf dependency) as the single source of + truth, and routes all 10 sites through it. `@objectstack/driver-sql` gains a + direct `@objectstack/types` dependency (previously it read `process.env` + directly). + + Behaviour is unchanged everywhere except the SQL driver, which now also emits + the one-shot `OS_MULTI_TENANT`-is-deprecated warning — consistent with every + other site. This mirrors the `resolveAuthzContext` single-source pattern in + `@objectstack/core`. Follow-up (not in this change): a lint gate forbidding new + inline reads of these env vars outside the helper. + +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [d980f0d] + - @objectstack/spec@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/types/package.json b/packages/types/package.json index 265c8b62a..0b7af9827 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/types", - "version": "10.3.0", + "version": "10.4.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 38e66dde5..c43c28ad7 100644 --- a/packages/verify/CHANGELOG.md +++ b/packages/verify/CHANGELOG.md @@ -1,5 +1,59 @@ # @objectstack/verify +## 10.4.0 + +### Patch Changes + +- Updated dependencies [4d99a5c] +- Updated dependencies [61d441f] +- Updated dependencies [c224e18] +- Updated dependencies [d616e1d] +- Updated dependencies [910a8f0] +- Updated dependencies [1e8a813] +- Updated dependencies [4845c12] +- Updated dependencies [c1a754a] +- Updated dependencies [6fbe91f] +- Updated dependencies [715d667] +- Updated dependencies [715d667] +- Updated dependencies [5eef4cf] +- Updated dependencies [4b5ec6e] +- Updated dependencies [b6a4972] +- Updated dependencies [72759e1] +- Updated dependencies [6c4fbd9] +- Updated dependencies [ef3ed67] +- Updated dependencies [359c0aa] +- Updated dependencies [cd51229] +- Updated dependencies [7697a0e] +- Updated dependencies [e7e04f1] +- Updated dependencies [cfd5ac4] +- Updated dependencies [2be5c1f] +- Updated dependencies [9a810f8] +- Updated dependencies [ad143ce] +- Updated dependencies [5c4a8c8] +- Updated dependencies [3afaeed] +- Updated dependencies [a619a3a] +- Updated dependencies [8801c02] +- Updated dependencies [3d04e06] +- Updated dependencies [4a84c98] +- Updated dependencies [c715d25] +- Updated dependencies [aa33b02] +- Updated dependencies [d980f0d] + - @objectstack/objectql@10.4.0 + - @objectstack/runtime@10.4.0 + - @objectstack/service-analytics@10.4.0 + - @objectstack/plugin-auth@10.4.0 + - @objectstack/spec@10.4.0 + - @objectstack/service-automation@10.4.0 + - @objectstack/rest@10.4.0 + - @objectstack/service-settings@10.4.0 + - @objectstack/core@10.4.0 + - @objectstack/plugin-sharing@10.4.0 + - @objectstack/driver-sqlite-wasm@10.4.0 + - @objectstack/plugin-hono-server@10.4.0 + - @objectstack/plugin-org-scoping@10.4.0 + - @objectstack/plugin-security@10.4.0 + - @objectstack/service-datasource@10.4.0 + ## 10.3.0 ### Patch Changes diff --git a/packages/verify/package.json b/packages/verify/package.json index 48605cd54..0b57f998a 100644 --- a/packages/verify/package.json +++ b/packages/verify/package.json @@ -1,6 +1,6 @@ { "name": "@objectstack/verify", - "version": "10.3.0", + "version": "10.4.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 ec10851fc..630e7bc85 100644 --- a/packages/vscode-objectstack/CHANGELOG.md +++ b/packages/vscode-objectstack/CHANGELOG.md @@ -1,5 +1,7 @@ # objectstack-vscode +## 10.4.0 + ## 10.3.0 ## 10.2.0 diff --git a/packages/vscode-objectstack/package.json b/packages/vscode-objectstack/package.json index cdabe0b62..358aa8c0a 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": "10.3.0", + "version": "10.4.0", "publisher": "objectstack", "license": "Apache-2.0", "repository": {