Skip to content

Commit d02a1b4

Browse files
authored
Merge pull request #3357 from objectstack-ai/claude/v16-release-page-zdfgbw
2 parents bf72a35 + 75ef178 commit d02a1b4

1 file changed

Lines changed: 144 additions & 38 deletions

File tree

content/docs/releases/v16.mdx

Lines changed: 144 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -525,13 +525,11 @@ re-exports from `spec/ui` are dropped; import them from `@objectstack/spec`
525525
directly) and the removal of the Gantt mobile QR-share context action
526526
(#2687).
527527

528-
> **Console vs. pin.** The Console section below is sourced from **objectui's
529-
> own changesets**, not only the `@objectstack/console` bundle-bump summaries
530-
> (a bump pins a SHA and can lag objectui `main`). Four 16.0-line frontend
531-
> changes had merged in objectui but landed *after* the `94d4876` pin — two of
532-
> them minor features — so they are not in the `rc.0` bundle yet; they ship
533-
> with the next console pin and are called out under
534-
> [Landed in objectui, pending the next console pin](#landed-in-objectui-pending-the-next-console-pin).
528+
> **Console vs. pin.** This section is sourced from **objectui's own
529+
> changesets**, not only the `@objectstack/console` bundle-bump summaries (a
530+
> bump pins a SHA and can lag objectui `main`). The `rc.0` bundle pins
531+
> `94d4876`; the pin has since advanced to `af1b0db` on `main` — that later
532+
> Console work is under [Landed since 16.0.0-rc.0](#landed-since-1600-rc0).
535533
536534
### Approvals inbox goes metadata-driven (#2678 line)
537535

@@ -654,37 +652,138 @@ and curated capability labels + picker group headers localize (B5).
654652
editors are fixed (#2666); AgentPreview drops the removed agent
655653
`visibility` (#2665).
656654

657-
### Landed in objectui, pending the next console pin
658-
659-
These 16.0-line frontend changes merged in objectui **after** the `94d4876`
660-
SHA that `@objectstack/console` `rc.0` pins, so they are not in the `rc.0`
661-
bundle — they ship with the next console pin (folded here for a complete
662-
frontend picture; sourced from objectui's changesets, not the bump summary):
663-
664-
- **Import wizard defaults to the `auto` password policy (objectui#2701,
665-
minor).** The Console counterpart to framework#3236: the "Sign-in setup for
666-
imported users" selector gains an **Automatic (recommended)** option, now the
667-
default (was "No password"). It decides per row server-side — reachable users
668-
are invited (email / SMS), unreachable ones get a one-time password shown
669-
once on the result screen — and the one-time-password reveal now surfaces
670-
only the rows that actually fell back, not the whole batch.
671-
- **Schema-driven `keyValue` / `numberList` mapping in the flow inspector
672-
(objectui#2708, minor).** `jsonSchemaToFlowFields` (ADR-0018) now maps an
673-
object with `additionalProperties` and no fixed `properties` → a `keyValue`
674-
editor, and a number/integer array → `numberList` — the objectui half of
675-
framework#3304, giving previously schema-less flow nodes (assignment, the
676-
CRUD quartet, script, subflow, screen) a server-driven config form.
677-
- **ActionParamDialog upload guard + `autonumber` mapping (objectui#2707,
678-
ADR-0059 follow-up).** Confirm is disabled while a `file`/`image` param is
679-
still uploading (its value only becomes the fileId once the presigned upload
680-
settles), and the spec `autonumber` field/param spelling now maps to the
681-
AutoNumber widget instead of falling through to a text input.
682-
- **System-field classification consolidated (objectui#2706).** The grid
683-
record-detail drawer, record picker (`deriveLookupColumns`), and
684-
`RecordDetailDrawer` route through the shared
685-
`isSystemManagedField` / `SYSTEM_MANAGED_FIELD_NAMES` classifier, so the
686-
framework-injected `owner_id` lands in the muted meta section consistently
687-
(follow-up to the #2702 leading-column fix).
655+
### Console changes after the `rc.0` pin
656+
657+
The four frontend changes that were pending when this page was first written
658+
(import wizard `auto` policy — objectui#2701; schema-driven `keyValue` /
659+
`numberList` flow mapping — objectui#2708; ActionParamDialog upload guard +
660+
`autonumber`objectui#2707; system-field classifier consolidation —
661+
objectui#2706) **are now bundled**: the console pin advanced `94d4876 →
662+
af1b0db` on `main`. They plus a further wave of Console work are described
663+
under [Landed since 16.0.0-rc.0](#landed-since-1600-rc0) below.
664+
665+
## Landed since 16.0.0-rc.0
666+
667+
These changes are on `main` after the `rc.0` cut and **roll into the next 16.0
668+
RC** — backend from the pending changesets, Console from the objectui pin
669+
advancing `94d4876 → af1b0db` (objectui #2706#2736). Sourced from each repo's
670+
own changesets.
671+
672+
### Breaking / behavior
673+
674+
- **Deprecated `aiStudio` / `aiSeat` capability aliases removed (#3308,
675+
breaking-as-minor).** The one-cycle deprecation window from #3265 is over:
676+
the camelCase `requires` spellings are no longer canonicalized — they are now
677+
plain unknown tokens `defineStack` rejects like any typo, and the serve
678+
resolver stops rewriting them on raw artifacts. `canonicalizePlatformCapability`
679+
/ `DEPRECATED_PLATFORM_CAPABILITY_ALIASES` are dropped from `@objectstack/spec`.
680+
**Migration:** use the canonical kebab-case `ai-studio` / `ai-seat`.
681+
- **Date arithmetic in a `Field.formula` is now a build-time error (#3306).**
682+
`record.end_date - record.start_date + 1`, `today() + 30`, `record.date + n`
683+
type-check clean (operands are `dyn`) but always faulted to `null` at
684+
runtime. `objectstack build` / `validateStackExpressions` now types
685+
`date`/`datetime` fields as `Timestamp` and **rejects arithmetic against a
686+
number**, with a message pointing at `daysBetween(a, b)` / `daysFromNow(n)` /
687+
`addDays(d, n)` / `addMonths(d, n)`. Only fires for genuinely-broken
688+
expressions that already returned `null`; ordering, equality (#3183) and
689+
string concatenation stay runtime-tolerated.
690+
- **Per-option `visibleWhen` enforced on `checkboxes`, and option values
691+
matched by string form (objectui#2729, #3350).** Server-side per-option
692+
gating already covered `select` / `multiselect` / `radio`; `checkboxes` was
693+
omitted from `CHOICE_FIELD_TYPES`, so a gated option hidden in the UI was
694+
still accepted from a crafted write. It is now re-evaluated element-wise on
695+
insert/update/bulk. Separately, option matching now coerces both sides with
696+
`String(...)` so a numeric option value submitted as a string (a normal JSON
697+
round-trip) can no longer slip its gate. Fail-open on unbound `current_user`
698+
is preserved.
699+
700+
### New capabilities (backend)
701+
702+
- **Formulas that compute dates/durations stop silently nulling (#3306).**
703+
Two long-standing CEL gaps are closed alongside the build error above: the
704+
null-guard idiom `cond ? <value> : null` now compiles and evaluates (an AST
705+
pre-pass wraps the non-null branch in `dyn(...)`, so `true ? 5 : null` no
706+
longer faults the type-unifier), and `floor(x)` / `ceil(x)` are registered
707+
(round toward −∞ / +∞) and advertised in the catalog. Shipped template
708+
formulas like `hr_employee.tenure_years` compute again.
709+
- **`engine-owned` becomes an explicit `managedBy` value (ADR-0103 addendum,
710+
#3343).** The overloaded `system` bucket is split: a new `engine-owned` enum
711+
value carries the same all-locked default affordance and joins the write
712+
guard / `apiMethods` reconciliation / `/me/permissions` clamp that already
713+
covered it by resolved affordance. **20 engine-owned objects** are relabelled
714+
`system → engine-owned` (the metadata store, jobs, approval-runtime rows,
715+
sharing rows, `sys_automation_run`, the messaging pipeline, `sys_secret`,
716+
settings); **8 admin-writable objects keep `system`** (now reading as
717+
"engine-managed schema, writable via `userActions`"). Enforcement-, wire- and
718+
behavior-identical — a self-documenting relabel; the full `system` retirement
719+
is a v17 rename.
720+
- **Approvals — precise decision-action gating (#3344).** `getRequest` /
721+
`listRequests` attach a per-viewer `viewer: { can_act, is_submitter }`
722+
computed server-side (`can_act` = the caller is a current pending approver by
723+
the same check the decision methods authorize with). The declared decision
724+
actions now gate on it — approver actions on `record.viewer.can_act`,
725+
submitter levers on `record.viewer.is_submitter` — so a submitter no longer
726+
sees approver buttons that 403, and a position-addressed approver is no
727+
longer wrongly hidden by a client heuristic. Fails closed when `viewer` is
728+
absent.
729+
- **Approvals — file attachments on approve/reject decisions (#3332).** The
730+
declared `approval_approve` / `approval_reject` actions gain an optional
731+
multi-file `attachments` param, rendered through the shared upload widget and
732+
persisted to the existing `sys_approval_action.attachments` column — letting
733+
the inbox retire its hand-wired attachment composer. Purely additive metadata.
734+
- **Discovery advertises a `transactionalBatch` capability bit (#3298).**
735+
`WellKnownCapabilitiesSchema` gains a required `transactionalBatch: boolean`
736+
so clients negotiate the atomic cross-object batch (`POST {basePath}/batch`)
737+
declaratively at connect time instead of probing `404`/`405`/`501`. Every
738+
discovery producer fills it honestly (`true` ⟺ the route is mounted **and**
739+
the engine can honour a transaction); `@objectstack/plugin-hono-server`
740+
under-reports `false` (the safe direction). Exposed as
741+
`client.capabilities.transactionalBatch`.
742+
- **i18n — action `resultDialog` copy is translatable (#3347).** The one-shot
743+
secret-reveal dialogs (temporary passwords, 2FA backup codes, OAuth client
744+
secrets) gain an `ActionResultDialogTranslationSchema` slot
745+
(`title` / `description` / `acknowledge` / `fields` keyed by literal
746+
result-field path); `os i18n extract` emits the keys and en/zh-CN/ja-JP/es-ES
747+
bundles ship copy for all six shipped dialogs.
748+
- **i18n — collaboration notifications and storage objects localize; the
749+
notifications REST routes are wired (#3354).** Assignment / @mention bell
750+
titles resolve through the i18n service in the **recipient's** locale (new
751+
`assignedToYou` / `mentionedYou` templates), `sys_file` / `sys_upload_session`
752+
ship their own translation bundle, and — the functional fix — `GET
753+
/api/v1/notifications` + the two `read` routes are now explicitly mounted in
754+
the standalone dispatcher (they only reached cloud's hono catch-all before),
755+
so mark-as-read works on `os dev` / standalone instead of leaving unread
756+
state that could never clear.
757+
758+
### New in Console (objectui, now bundled `94d4876 → af1b0db`)
759+
760+
- **Option-widget `visibleWhen` parity.** Per-option cascading + `dependsOn`
761+
gating lands across the widget family so client and server agree on which
762+
options are visible: `MultiSelectField` (objectui#2715/#2717), `RadioField`
763+
(objectui#2728, single-sourcing the option resolver), and `CheckboxesField`
764+
(objectui#2735) — the Console side of the framework enforcement above. A
765+
`select` + `multiple` field renders as a multi-value chip picker (objectui#2709).
766+
- **Approvals inbox finishes going metadata-driven.** Participant gating aligns
767+
with the server-computed `viewer` block (objectui#2719), and the bespoke
768+
approve/reject composer is retired now that declared actions carry file
769+
attachments (objectui#2710, pairing framework#3332).
770+
- **Related lists paginate by default (objectui#2711/#2722):** server-side
771+
`$top` / `$skip` windows instead of loading every child row.
772+
- **Dashboard cleanup:** the pre-ADR-0021 inline-analytics renderer branches
773+
are retired (objectui#2723, framework#3320), and dashboard bars draw on first
774+
paint via a single settle re-mount (objectui#2727).
775+
- **`provider:'api'` data sources thread the host's authenticated fetch
776+
(objectui#2725/#2732),** so external API-backed views carry the session's
777+
credentials.
778+
- **Action result dialogs render the new translation slot (objectui#2736),** the
779+
client half of framework#3347.
780+
- **`engine-owned` lifecycle bucket in the Console (objectui#2739 + the
781+
#2712/#2724 `userActions` parser consolidation),** the UI union that unblocked
782+
the framework enum split.
783+
- **Fixes:** kanban / calendar surface write failures instead of swallowing
784+
them (objectui#2716); the earlier post-`rc.0` items (import wizard `auto`,
785+
flow `keyValue`/`numberList`, ActionParamDialog upload guard, system-field
786+
classifier) are included in this pin.
688787

689788
## Upgrade checklist
690789

@@ -713,6 +812,13 @@ frontend picture; sourced from objectui's changesets, not the bump summary):
713812
legitimately need; otherwise generic writes are now rejected (ADR-0103).
714813
- **Approvals:** rewrite `ApproverType 'role'``org_membership_level` (or
715814
`position` if the value names one) before the alias is removed next major.
815+
- **Capability tokens:** replace any `aiStudio` / `aiSeat` in `requires` with
816+
the canonical `ai-studio` / `ai-seat` — the aliases no longer canonicalize
817+
and are now rejected as unknown tokens (#3308).
818+
- **Formulas:** replace date arithmetic in `Field.formula` / predicates
819+
(`end - start + 1`, `today() + 30`) with `daysBetween` / `daysFromNow` /
820+
`addDays` / `addMonths` — it is now a build-time error instead of a silent
821+
runtime `null` (#3306).
716822
- **Identity import integrations:** pass `passwordPolicy: 'none'` explicitly
717823
if you relied on the old identity-only default.
718824
- **Sandbox:** update anything matching the old `exceeded timeout of Nms`

0 commit comments

Comments
 (0)