@@ -525,13 +525,11 @@ re-exports from `spec/ui` are dropped; import them from `@objectstack/spec`
525525directly) 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