chore: release packages#1407
Open
github-actions[bot] wants to merge 1 commit into
Open
Conversation
6b78a08 to
9912a2c
Compare
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
f505f11 to
e0f786b
Compare
bbc6d59 to
c072c7c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@object-ui/app-shell@6.3.0
Minor Changes
c12986e: Add resultDialog + target interpolation for one-shot action reveals
Some platform actions return values the user MUST copy now because the
server will not surface them again — 2FA TOTP URI + backup codes, freshly
minted OAuth client_secret, regenerated recovery codes. Previously these
had to ship as bespoke pages in
apps/accountbecause actions onlyemitted a fire-and-forget toast.
@object-ui/core— ActionRunnerActionDef.resultDialog: ResultDialogSpecfield. When set on asuccessful action, the runner suppresses the
successMessagetoast andawaits the registered
ResultDialogHandlerinstead. Missing handler isnon-fatal (logs a warning); rejected handler is treated as acknowledged.
setResultDialogHandler(handler)setter.ResultDialogSpec,ResultDialogFieldSpec,ResultDialogHandler.executeUrlandexecuteAPInow run${param.X}and${ctx.X}interpolation against
targetbefore fetching / navigating. Values areencodeURIComponent'd, missing keys resolve to empty string.ctxexposes
origin,user,org,recordIdby default; consumers caninject more via
context.ctx.@object-ui/reactActionProvideranduseActionRunnerboth gained anonResultDialogoption that wires straight through to the runner.
@object-ui/app-shellActionResultDialogcomponent — promise-based, blocks click-outsideand Escape (the user MUST click acknowledge), renders five field
formats:
qrcode(client-side via theqrcodepackage — never sentoff-device, so 2FA URIs stay secret),
code-list,secret,text,json. Falls back tojsonwhen a value's shape doesn't match itsdeclared format.
ObjectViewandRecordDetailViewinstall the handler and mount thedialog automatically, so any action with
resultDialogdeclared inmetadata now works without code changes.
qrcode@^1.5.xfor client-side QR rendering.Pairs with the framework-side
Action.resultDialogschema added in@objectstack/specand thesys_two_factor/sys_oauth_application/sys_accountupdates in@objectstack/platform-objects.1c25b56: ADR-0032: author-time condition validation in the flow inspectors.
Flow node and edge condition editors now flag a malformed predicate as you
type — most importantly the
{record.x}template-brace-in-CEL mistake (#1491),which
{…}parses as a CEL map literal and silently fails — with the samecorrective message the build and the
validate_expressionagent tool emit.Client-side check for now (no CEL parser in the browser); swaps to
@objectstack/formula's sharedvalidateExpressiononce it is published.30ee761: feat(studio): surface pending drafts on the package detail (ADR-0033)
After an AI builds an app, its objects/views land as drafts bound to the app package — but Studio's active-only browsers hid them, so the package looked empty and there was no obvious way to find what to review/publish.
MetadataClient.listDrafts({ packageId?, type? })calls the newGET /api/v1/meta/_draftsendpoint, returning pending draft headers (withpackageId).?review=1) so the user can publish it. A just-built app package is no longer shown as empty.81c0777: feat(studio): ADR-0033 Phase B — draft review surface (chat → designer → generic diff)
Closes the AI metadata-authoring loop in Studio. The framework (ADR-0033 Phases A + C) makes the assistant stage every change as a DRAFT; this lets a human see and review those drafts.
@object-ui/plugin-chatbotmapMessagesnow detects the framework's draft envelopes —{ status:'drafted', type, name, … }(single) and{ status:'drafted', drafted:[{type,name}] }(apply_blueprint batch) — and lifts the reviewable targets ontoChatToolInvocation.draftReview(mirrors the existing HITLpendingActionIdpath; the Vercel{type:'text',value}wrapper is peeled).blueprint_proposedis intentionally not surfaced (no draft yet).ChatbotEnhancedrenders a "Review N change(s)" button on drafted tool results, driven by a newonReviewDraftcallback prop.@object-ui/app-shellassistantBusgains a review channel (requestReview/requestAssistantReview);ConsoleFloatingChatbotwires the chat button to it; a small navigator insideAppContent(which knows the app base) routes to/apps/:appName/metadata/:type/:name?review=1.ResourceEditPagehonours?review=1: it force-reloads the pending draft (covers the case where the AI drafted the item after the page mounted) and opens the review/diff.DraftReviewPanel— a generic, type-agnostic draft↔published structural diff (added / changed / removed by key), reusingLayeredDiff'scomputeDiffRows. It gives every metadata type (view, dashboard, flow, …) a real "what will publishing change" review, surfaced as a toolbar affordance + sheet whenever a draft exists. The object designer keeps its richer per-field review.Nothing is published by any of this — the human still clicks Publish.
672f854: feat(studio): add "Publish app" button to publish all package drafts (ADR-0033)
The package detail's Pending changes section gains a primary Publish app (N) button that calls
POST /api/v1/packages/:id/publish-draftsto promote every drafted item of the app in one shot, then refreshes the pending list. Complements the per-item review/publish links — so after an AI builds an app you can review item-by-item or publish the whole thing at once.5c23088: Wire
App.hiddenshell hint — App Switcher + avatar dropdownHonour the new
App.hiddenfield from@objectstack/spec/ui:AppSwitcher.tsx— filterapp.hidden === trueout of the top-bar app dropdown so personal-settings-style apps don't appear next to business apps.AppHeader.tsx— render hidden apps as entries in the avatar / user dropdown (immediately after the hardcoded Profile / Settings items). Uses the app'sicon+labelvia the existinggetIcon+appLabelutilities, and navigates to/apps/${app.name}.This is the front-end side of the Account-app split: the
accountapp shipped by@objectstack/platform-objectsdeclareshidden: trueand now surfaces through the avatar menu — same pattern as GitHub Settings, Google account chip, and Salesforce Personal Settings.No new dependencies; pure metadata-driven wiring.
80f9796: Repoint the Console bell to
sys_inbox_message+sys_notification_receipt(ADR-0030)The notification bell read the legacy
sys_notificationobject'srecipient_id/is_read/title/bodycolumns. ADR-0030 re-modeledsys_notificationinto the L2 event (no recipient/read-state), so the bellreturned nothing — every notification the new pipeline produced was invisible.
The bell now reads the L5 in-app materialization instead:
sys_inbox_messagefiltered byuser_id(theminescope), 20most-recent, ordered by
created_at.sys_notification_receipt(filtered byuser_id+channel:'inbox'). A message is unread until its event has aread/clicked/dismissedreceipt; the unread count drives the badge.UPDATEs the existingdeliveredreceipt toread(keyed
(notification_id, user_id, channel)), inserting only as a fallbackwhen no receipt exists. Replaces the old
sys_notification.is_readwrite.action_url(absolute,/apps/..., or app-relative/{object}/{id}), falling back to the legacysource_object/source_idpointer./apps/setup/sys_inbox_message?view=mine.Pairs with the framework ADR-0030 pipeline (
@objectstack/service-messaging).Verified in-browser (showcase Console): a materialized inbox message + its
deliveredreceipt lit the bell badge; the popover rendered the row;"mark all read" flipped the receipt to
readin place (no duplicate) andcleared the badge.
1c8f775: Add the External Datasource Federation Studio surface (ADR-0015 P5)
Federated datasources (
schemaMode !== 'managed') now get a dedicatedpanel inside their Studio Preview tab, so connecting a mature external
database and registering its tables as ObjectStack objects is a
point-and-click flow instead of a CLI-only one. The panel pairs with the
framework backend shipped in feat: External Datasource Federation (ADR-0015) — backend (P1–P4, P6) framework#1390
(
registerExternalDatasourceRoutes→/api/v1/datasources/:name/external/*).ObjectStack is metadata-driven:
datasourceis a metadata type, so it isbrowsed and edited through the standard metadata-admin engine
(
metadata:resource) reached from the Studio app's left-side menu —not a hand-written page. The Studio app (framework
packages/platform-objects/src/apps/studio.app.ts, Integration group)gains a
Datasourcesnav item pointing atmetadata:resource?type=datasource; the federation panel is contributedto that standard surface via
registerMetadataPreview('datasource', …).@object-ui/app-shell—views/metadata-admin/external/api.ts— a thin, typed REST client over the four federation routes(
tables,tables/:remote/draft,refresh-catalog,validate) plus animportObjectDrafthelper that PUTs a generated draft to/meta/object.All calls go through
createAuthenticatedFetch()(Bearer +X-Tenant-IDAccept-Language). A503 external_service_unavailablereply is mappedto a typed
ExternalServiceUnavailableErrorso the UI shows a friendly"federation not enabled on this server" hint. Contract types are inlined
(they were added in framework 7.3; objectui pins
@objectstack/spec^7.2.1).SchemaBrowser— lists remote tables (allowedSchemas-filtered server-side)with a text filter, on-demand Refresh (never a timer — warehouse
introspection is expensive), and a per-table Import action.
ImportObjectDialog— generates an Object draft, surfaces thetype-compat matrix's
// REVIEW:columns and the generated*.object.tssource, then imports it as a real object. Never mutates the remote schema.
ValidationPanel— runs validation on demand and renders per-objectstructured schema diffs (missing column, type mismatch, …). Doubles as an
on-demand drift view.
ExternalDatasourcePanel— Tables / Validation tabs plus a header stripwith "Refresh catalog" and the snapshot timestamp.
DatasourcePreview— registered viaregisterMetadataPreview('datasource', …),it renders the panel automatically inside the standard resource edit
page's Preview tab when the saved datasource is federated
(
schemaMode !== 'managed'), keyed off the item name. This is the onlywiring needed: no bespoke page, no extra route, no
@object-ui/app-shellsurface to re-export — the metadata-admin engine + left-side nav own the
navigation. Federated datasources are read-only code artifacts (the
datasourcetype forbids runtime create), which the standard list viewalready reflects (no "Create" button).
Out of scope (blocked on backend follow-ups): the connection wizard
(driver/credentials/secrets — belongs in System Settings) and a push-based
drift inbox (needs an event feed). The framework exposes no
test-connection, secrets, or drift-feed routes yet.
4e060b7: Polish the Studio flow-designer canvas visuals
A refinement pass over the metadata-admin flow designer (
FlowCanvas+flow-canvas-parts) — purely presentational, no behavioral or API changes,theme-aware (light/dark), and still dependency-free.
color-coded icon chip (the card's primary category cue), with a bolder
label, refined uppercase type caption, layered hover elevation
(
-translate-y-0.5+ soft shadow), and clearer selected / run-state rings.Per-category
chiptone tokens (soft bg + inset ring) added alongside theexisting icon/accent/label tones. Added distinct tones for
loop(sky),screen/user_task(pink) andassignment(purple) — previously they fellback to the generic slate "task" tone, so every node type now reads as a
distinct color in the canvas.
right-hand column onto a second line, so the label now gets the full card
width (it was badly truncated — "Manager Re…", "Budget Ab…"). A native title
tooltip surfaces the full text on the rare remaining truncation.
its parent (which stacked every sibling on the same spot) — it's left to the
layered auto-layout, which slots it beside its siblings.
the diagram instead of floating behind a static texture), plus a subtle inset
vignette for depth.
pill-shaped (rounded-full, frosted) branch/condition labels.
hover affordance; the palette gains an "Add node" header and matching tinted
icon chips per row.
Verified in-browser (Studio → flow → designer) in both light and dark themes.
e02aedd: Group the flow add-node palette by category, and offer every node type
The quick-add palette listed 12 node types as a flat list;
assignment,screen,delete_recordand the parallel gateways could only be reached byadding a node and switching its type in the inspector. Building flows, that's a
real friction point.
(assignment), Screen, Parallel split and Parallel join too — so every common
node type is one click away.
Flow sections with headers and dividers, so the (now longer) list stays
scannable. A new
nodeCategory(type)helper drives the grouping and givesengine-only / plugin-contributed node types a sensible section;
mergePalettepreserves a base item's category and infers one for engine-only types.
Verified in-browser: the grouped palette renders all sections with tinted icon
chips, and the newly-offered types add to the canvas with the correct icon/tone
and no overlap.
7130d4e: Add FlowRunner — render & resume interactive screen-flows
A
type: 'flow'action whose run pauses at ascreennode now opens aFlowRunnermodal that renders the screen's fields, submits the values to theframework resume endpoint (
POST /api/v1/automation/{flow}/runs/{runId}/resume),and advances to the next screen or closes + refreshes on completion. Previously
such flows launched server-side but the screen was never rendered, so the input
was never collected.
FlowRunnercomponent (fields → form → resume loop).ObjectView+RecordDetailViewflow handlers detect a paused-screen launchresponse (
{ status:'paused', runId, screen }) and open the runner; forlist_item actions the row's id (
_rowRecord.id) flows in as the flow'srecordId.Pairs with the framework screen-flow runtime (
@objectstack/service-automation@objectstack/runtime). Verified in-browser: showcase task row → "Reassign…"→ form → submit → the task is reassigned.
652f9b2: feat(packages): "Discard changes" and "Delete app" buttons in the package detail sheet
Adds two one-click package-lifecycle actions next to the existing "Publish app", mirroring the new backend endpoints:
POST /packages/:id/discard-drafts, reverting the app to its last published baseline. Non-destructive (published metadata + data untouched), then refreshes the pending list.DELETE /packages/:id(active + draft metadata + drops each object's table). Confirms first ("this cannot be undone"); closes the sheet on success, keeps it open and shows the error on failure.Together with "Publish app", this gives the full AI-build review loop a UI: publish to preview → keep, discard all changes, or delete the app.
Patch Changes
fe69471: Flow designer: start a new flow with a trigger, and stop the edge "+" overlapping branch labels
Two more dogfooding fixes for the Studio flow designer:
generic
tasknode; it now seeds astart(trigger) node — the canonicalentry point every flow needs — so the canvas opens on the trigger and the
author builds forward from there.
node"
+button and the branch/condition label pill were both centered on theedge midpoint, so on a labeled edge (
approve,if …) the+sat on top ofthe label. The
+now slides to the right of the label when one is present(unlabeled edges keep the centered
+).Verified in-browser: labeled edges show the label and a clear, separate insert
handle;
tsc --noEmitclean.18d0339: Relabel metadata-driven UI on a language switch without a page refresh (chore: release packages #1319)
Switching the UI language left server-resolved metadata labels (object/field/
view labels, action-dialog text) in the old language until a hard refresh,
because renderers cache those labels by object name and never refetch on a
language change.
@object-ui/auth—createAuthenticatedFetchnow folds the active<html lang>intoAccept-Languageon API calls (never clobbering an explicitheader), so a switch carries the new locale on every subsequent request.
@object-ui/app-shell—ConnectedShellInnerdrops the adapter'slocale-blind metadata cache in the render phase and remounts the metadata
subtree via
key={language}, so every renderer refetches in the new locale.The adapter and its connection sit above the key and are preserved — an in-app
relabel, not a reconnect.
@object-ui/i18n— dev-mode missing-key warnings:createI18ngainswarnMissingKeys(default on outside production) wiring a deduped i18nextmissingKeyHandler.useObjectLabel's convention-key probes are flagged sotheir intentional misses (which fall back to server metadata) stay silent.
Pairs with the framework-side locale-aware metadata changes in
@objectstack/client/@objectstack/objectql/@objectstack/rest.3cc38fe: perf(detail/header): lazy + dedupe related-list fan-out, coalesce header polls
Opening a record detail fired ~50 concurrent
/api/v1requests thathead-of-line-blocked one another on a single control-plane container.
RecordDetailViewno longer eager-preloads reverse-reference childrenwhen the reference rail renders them (that data was discarded while the
rail re-fetched the same collections).
record:reference_railnow gates fetching on visibility(
IntersectionObserver; the rail ishidden xl:flex), caps concurrencyat 3, and fetches once per
(parentId + entries)via a signature guard,applying results through a mounted ref.
AppHeaderinbox/notification, approvals, and activity pollers gainedin-flight guards so bootstrap effect re-runs coalesce to one request; the
approvals poll now sends one request with all identities comma-joined
instead of one per identity.
Measured locally: opening an environment detail dropped from ~52 to ~17
requests, related collections from ×3–5 each to ×1, approvals from ×9 to ≤3.
053a164: fix(metadata): keep form-family views out of the runtime list-view switcher
The backend now exposes each view as an independent ViewItem (ADR-0017,
"Object has-many View"):
{ name: '<object>.<key>', object, viewKind: 'list' | 'form', config }. The Studio preview was already taught this shape,but the runtime console path was not —
MetadataProvider.mergeViewsIntoObjectsonly understood the legacy aggregated container (
{ list, form, listViews, formViews }) and ignoredviewKindentirely. As a result a form-family view(e.g.
crm_activity.default, expanded fromformViews.default) was neitherrecognized nor excluded: navigating to its
/view/<name>URL silently fellback to the default grid list instead of being treated as a record form.
mergeViewsIntoObjectsnow recognizes the ViewItem shape and routes byviewKind—'list'→objectDef.listViews,'form'→objectDef.formViews— so FORM-family views never enter the list-view switcher (which reads only
listViews). Each item'sconfigbody is flattened to the renderer shape sotype/columns/calendar/… survive, the canonical<object>.<key>name isused as the view id (so
/view/<name>resolves), and the legacy container isskipped for any object that already has expanded ViewItems (no double-listing).
Objects served only as a legacy container are unaffected.
2f31406: Refine Studio package-scoped navigation and home overview.
Studio now treats the selected package as the home overview scope, flattens the root Overview sidebar group, hides the duplicate all-metadata sidebar entry, redirects the invalid package metadata route to package management, preserves the selected package across package-management navigation, and adds a localized package-management sidebar label.
8d1195d: Fix
type: 'url'actions so they actually reach the backend in split-origin dev setups, and so reveal-once result dialogs render.ActionRunner.executeUrl: when context providesapiBase, relative/api/...,/_auth/..., and/_account/...URLs are now promoted to absolute (${apiBase}${path}) before navigation. Same-origin API paths (with or withoutapiBase) trigger a full-pagewindow.location.hrefrather than React-Router push — this is required for server-side OAuth redirect dances (e.g. better-auth/sign-in/social) that React Router would otherwise swallow into the SPA's fallback route.ActionRunner.buildInterpolationContext: surfacesctx.apiBasefor action targets that want to template it explicitly.ObjectView: passesapiBase: import.meta.env.VITE_SERVER_URLinto the toolbarActionProvidercontext so the above resolves.action-buttonandaction-menurenderers now forwardresultDialogwhen invoking the runner. Previously this field was silently dropped by an explicit whitelist, breaking every "show once, then hide" flow (2FA QR/backup codes, OAuth client_secret, regenerated tokens).Updated dependencies [c12986e]
Updated dependencies [30ee761]
Updated dependencies [a58c6b8]
Updated dependencies [bd398df]
Updated dependencies [18d0339]
Updated dependencies [abe8ebc]
Updated dependencies [2f31406]
Updated dependencies [8d1195d]
@object-ui/auth@6.3.0
Minor Changes
18d0339: Relabel metadata-driven UI on a language switch without a page refresh (chore: release packages #1319)
Switching the UI language left server-resolved metadata labels (object/field/
view labels, action-dialog text) in the old language until a hard refresh,
because renderers cache those labels by object name and never refetch on a
language change.
@object-ui/auth—createAuthenticatedFetchnow folds the active<html lang>intoAccept-Languageon API calls (never clobbering an explicitheader), so a switch carries the new locale on every subsequent request.
@object-ui/app-shell—ConnectedShellInnerdrops the adapter'slocale-blind metadata cache in the render phase and remounts the metadata
subtree via
key={language}, so every renderer refetches in the new locale.The adapter and its connection sit above the key and are preserved — an in-app
relabel, not a reconnect.
@object-ui/i18n— dev-mode missing-key warnings:createI18ngainswarnMissingKeys(default on outside production) wiring a deduped i18nextmissingKeyHandler.useObjectLabel's convention-key probes are flagged sotheir intentional misses (which fall back to server metadata) stay silent.
Pairs with the framework-side locale-aware metadata changes in
@objectstack/client/@objectstack/objectql/@objectstack/rest.Patch Changes
@object-ui/core@6.3.0
Minor Changes
c12986e: Add resultDialog + target interpolation for one-shot action reveals
Some platform actions return values the user MUST copy now because the
server will not surface them again — 2FA TOTP URI + backup codes, freshly
minted OAuth client_secret, regenerated recovery codes. Previously these
had to ship as bespoke pages in
apps/accountbecause actions onlyemitted a fire-and-forget toast.
@object-ui/core— ActionRunnerActionDef.resultDialog: ResultDialogSpecfield. When set on asuccessful action, the runner suppresses the
successMessagetoast andawaits the registered
ResultDialogHandlerinstead. Missing handler isnon-fatal (logs a warning); rejected handler is treated as acknowledged.
setResultDialogHandler(handler)setter.ResultDialogSpec,ResultDialogFieldSpec,ResultDialogHandler.executeUrlandexecuteAPInow run${param.X}and${ctx.X}interpolation against
targetbefore fetching / navigating. Values areencodeURIComponent'd, missing keys resolve to empty string.ctxexposes
origin,user,org,recordIdby default; consumers caninject more via
context.ctx.@object-ui/reactActionProvideranduseActionRunnerboth gained anonResultDialogoption that wires straight through to the runner.
@object-ui/app-shellActionResultDialogcomponent — promise-based, blocks click-outsideand Escape (the user MUST click acknowledge), renders five field
formats:
qrcode(client-side via theqrcodepackage — never sentoff-device, so 2FA URIs stay secret),
code-list,secret,text,json. Falls back tojsonwhen a value's shape doesn't match itsdeclared format.
ObjectViewandRecordDetailViewinstall the handler and mount thedialog automatically, so any action with
resultDialogdeclared inmetadata now works without code changes.
qrcode@^1.5.xfor client-side QR rendering.Pairs with the framework-side
Action.resultDialogschema added in@objectstack/specand thesys_two_factor/sys_oauth_application/sys_accountupdates in@objectstack/platform-objects.Patch Changes
type: 'url'actions so they actually reach the backend in split-origin dev setups, and so reveal-once result dialogs render.ActionRunner.executeUrl: when context providesapiBase, relative/api/...,/_auth/..., and/_account/...URLs are now promoted to absolute (${apiBase}${path}) before navigation. Same-origin API paths (with or withoutapiBase) trigger a full-pagewindow.location.hrefrather than React-Router push — this is required for server-side OAuth redirect dances (e.g. better-auth/sign-in/social) that React Router would otherwise swallow into the SPA's fallback route.ActionRunner.buildInterpolationContext: surfacesctx.apiBasefor action targets that want to template it explicitly.ObjectView: passesapiBase: import.meta.env.VITE_SERVER_URLinto the toolbarActionProvidercontext so the above resolves.action-buttonandaction-menurenderers now forwardresultDialogwhen invoking the runner. Previously this field was silently dropped by an explicit whitelist, breaking every "show once, then hide" flow (2FA QR/backup codes, OAuth client_secret, regenerated tokens).@object-ui/data-objectstack@6.3.0
Minor Changes
30ee761: feat(studio): surface pending drafts on the package detail (ADR-0033)
After an AI builds an app, its objects/views land as drafts bound to the app package — but Studio's active-only browsers hid them, so the package looked empty and there was no obvious way to find what to review/publish.
MetadataClient.listDrafts({ packageId?, type? })calls the newGET /api/v1/meta/_draftsendpoint, returning pending draft headers (withpackageId).?review=1) so the user can publish it. A just-built app package is no longer shown as empty.Patch Changes
a58c6b8: fix(datasource): exclude form-family views from
listViews()OBJECTSTACKDataSource.listViews(objectName)feeds the object list-viewswitcher (
ObjectView→ViewTabBar), but returned every view bound tothe object — including form-family ones. With the backend now exposing each
view as an independent ViewItem carrying a
viewKinddiscriminant(ADR-0017, "Object has-many View"), a form view such as
crm_activity.default(expanded from
formViews.default) leaked in as a spurious switcher tab and,when opened, fell back to the default grid.
listViews()now filters outviewKindform/detailitems so onlylist-family views reach the switcher. Bare view specs without a
viewKind(legacy artifacts and user-saved views) are still treated as list views.
Updated dependencies [c12986e]
Updated dependencies [8d1195d]
@object-ui/i18n@6.3.0
Minor Changes
18d0339: Relabel metadata-driven UI on a language switch without a page refresh (chore: release packages #1319)
Switching the UI language left server-resolved metadata labels (object/field/
view labels, action-dialog text) in the old language until a hard refresh,
because renderers cache those labels by object name and never refetch on a
language change.
@object-ui/auth—createAuthenticatedFetchnow folds the active<html lang>intoAccept-Languageon API calls (never clobbering an explicitheader), so a switch carries the new locale on every subsequent request.
@object-ui/app-shell—ConnectedShellInnerdrops the adapter'slocale-blind metadata cache in the render phase and remounts the metadata
subtree via
key={language}, so every renderer refetches in the new locale.The adapter and its connection sit above the key and are preserved — an in-app
relabel, not a reconnect.
@object-ui/i18n— dev-mode missing-key warnings:createI18ngainswarnMissingKeys(default on outside production) wiring a deduped i18nextmissingKeyHandler.useObjectLabel's convention-key probes are flagged sotheir intentional misses (which fall back to server metadata) stay silent.
Pairs with the framework-side locale-aware metadata changes in
@objectstack/client/@objectstack/objectql/@objectstack/rest.Patch Changes
2f31406: Refine Studio package-scoped navigation and home overview.
Studio now treats the selected package as the home overview scope, flattens the root Overview sidebar group, hides the duplicate all-metadata sidebar entry, redirects the invalid package metadata route to package management, preserves the selected package across package-management navigation, and adds a localized package-management sidebar label.
@object-ui/plugin-chatbot@6.3.0
Minor Changes
81c0777: feat(studio): ADR-0033 Phase B — draft review surface (chat → designer → generic diff)
Closes the AI metadata-authoring loop in Studio. The framework (ADR-0033 Phases A + C) makes the assistant stage every change as a DRAFT; this lets a human see and review those drafts.
@object-ui/plugin-chatbotmapMessagesnow detects the framework's draft envelopes —{ status:'drafted', type, name, … }(single) and{ status:'drafted', drafted:[{type,name}] }(apply_blueprint batch) — and lifts the reviewable targets ontoChatToolInvocation.draftReview(mirrors the existing HITLpendingActionIdpath; the Vercel{type:'text',value}wrapper is peeled).blueprint_proposedis intentionally not surfaced (no draft yet).ChatbotEnhancedrenders a "Review N change(s)" button on drafted tool results, driven by a newonReviewDraftcallback prop.@object-ui/app-shellassistantBusgains a review channel (requestReview/requestAssistantReview);ConsoleFloatingChatbotwires the chat button to it; a small navigator insideAppContent(which knows the app base) routes to/apps/:appName/metadata/:type/:name?review=1.ResourceEditPagehonours?review=1: it force-reloads the pending draft (covers the case where the AI drafted the item after the page mounted) and opens the review/diff.DraftReviewPanel— a generic, type-agnostic draft↔published structural diff (added / changed / removed by key), reusingLayeredDiff'scomputeDiffRows. It gives every metadata type (view, dashboard, flow, …) a real "what will publishing change" review, surfaced as a toolbar affordance + sheet whenever a draft exists. The object designer keeps its richer per-field review.Nothing is published by any of this — the human still clicks Publish.
Patch Changes
@object-ui/react@6.3.0
Minor Changes
c12986e: Add resultDialog + target interpolation for one-shot action reveals
Some platform actions return values the user MUST copy now because the
server will not surface them again — 2FA TOTP URI + backup codes, freshly
minted OAuth client_secret, regenerated recovery codes. Previously these
had to ship as bespoke pages in
apps/accountbecause actions onlyemitted a fire-and-forget toast.
@object-ui/core— ActionRunnerActionDef.resultDialog: ResultDialogSpecfield. When set on asuccessful action, the runner suppresses the
successMessagetoast andawaits the registered
ResultDialogHandlerinstead. Missing handler isnon-fatal (logs a warning); rejected handler is treated as acknowledged.
setResultDialogHandler(handler)setter.ResultDialogSpec,ResultDialogFieldSpec,ResultDialogHandler.executeUrlandexecuteAPInow run${param.X}and${ctx.X}interpolation against
targetbefore fetching / navigating. Values areencodeURIComponent'd, missing keys resolve to empty string.ctxexposes
origin,user,org,recordIdby default; consumers caninject more via
context.ctx.@object-ui/reactActionProvideranduseActionRunnerboth gained anonResultDialogoption that wires straight through to the runner.
@object-ui/app-shellActionResultDialogcomponent — promise-based, blocks click-outsideand Escape (the user MUST click acknowledge), renders five field
formats:
qrcode(client-side via theqrcodepackage — never sentoff-device, so 2FA URIs stay secret),
code-list,secret,text,json. Falls back tojsonwhen a value's shape doesn't match itsdeclared format.
ObjectViewandRecordDetailViewinstall the handler and mount thedialog automatically, so any action with
resultDialogdeclared inmetadata now works without code changes.
qrcode@^1.5.xfor client-side QR rendering.Pairs with the framework-side
Action.resultDialogschema added in@objectstack/specand thesys_two_factor/sys_oauth_application/sys_accountupdates in@objectstack/platform-objects.Patch Changes
abe8ebc: Repoint
useClientNotificationsto the ADR-0030@objectstack/clientsurfaceThe
useClientNotificationsbridge hook calledclient.notifications.*withsignatures that no longer exist on
@objectstack/client@7.x:registerDevice(token, platform)→ the SDK takes a singleRegisterDeviceRequestobject ({ token, platform }).markAsRead(id)→ there is no single-id method; the SDK exposesmarkRead(ids: string[]). The hook keeps its friendly single-id API andadapts to the batch call.
These helpers are the stable transport contract for ADR-0030 (Notification
Convergence): server-side they route to the L5
sys_inbox_messagematerialization and the
sys_notification_receiptread-state spine — there-modeled
sys_notificationL2 event no longer carries recipient/readcolumns. (The Console bell itself reads the inbox + receipts directly via the
generic data API; see the
@object-ui/app-shellbell cut-over.)Cut-over sequence (operational — run in this order)
The Console UI repoint must land together with the framework pipeline and
the data migration so the bell is never blank and read-state is never lost:
emit()+ producers). Newnotifications now land in
sys_inbox_message+sys_notification_receipt.migrateSysNotificationToEvent({ driver, data })from@objectstack/metadata/migrations. It splits each legacysys_notificationinbox row into a
sys_inbox_message+ receipt, rewrites the row to the eventshape, and clears the legacy columns. It is idempotent and reports
not_applicableon fresh installs. This runs against the ObjectStackserver/data engine — it is not a Console (frontend) step.
@object-ui/app-shellbellcut-over).
Updated dependencies [c12986e]
Updated dependencies [30ee761]
Updated dependencies [a58c6b8]
Updated dependencies [18d0339]
Updated dependencies [2f31406]
Updated dependencies [8d1195d]
@object-ui/cli@6.3.0
Patch Changes
@object-ui/collaboration@6.3.0
Patch Changes
@object-ui/components@6.3.0
Patch Changes
8d1195d: Fix
type: 'url'actions so they actually reach the backend in split-origin dev setups, and so reveal-once result dialogs render.ActionRunner.executeUrl: when context providesapiBase, relative/api/...,/_auth/..., and/_account/...URLs are now promoted to absolute (${apiBase}${path}) before navigation. Same-origin API paths (with or withoutapiBase) trigger a full-pagewindow.location.hrefrather than React-Router push — this is required for server-side OAuth redirect dances (e.g. better-auth/sign-in/social) that React Router would otherwise swallow into the SPA's fallback route.ActionRunner.buildInterpolationContext: surfacesctx.apiBasefor action targets that want to template it explicitly.ObjectView: passesapiBase: import.meta.env.VITE_SERVER_URLinto the toolbarActionProvidercontext so the above resolves.action-buttonandaction-menurenderers now forwardresultDialogwhen invoking the runner. Previously this field was silently dropped by an explicit whitelist, breaking every "show once, then hide" flow (2FA QR/backup codes, OAuth client_secret, regenerated tokens).Updated dependencies [c12986e]
Updated dependencies [18d0339]
Updated dependencies [abe8ebc]
Updated dependencies [2f31406]
Updated dependencies [8d1195d]
@object-ui/fields@6.3.0
Patch Changes
bd398df: Render reference/lookup cells as labels, not raw JSON
A
lookup/master_detailvalue can arrive as a JSON-encoded object string —e.g. an unresolved external-id reference
{"externalId":"Website Relaunch"}.LookupCellRenderertreated the whole JSON string as an opaque id, failed toresolve it, and fell through to
String(value), leaking raw JSON into the gridcell (and detail/kanban surfaces).
LookupCellRenderernow parses a JSON-object-looking string value and rendersa human label (
name→label→externalId→id).coerceToSafeValue(the shared safe-render helper used by 8 cell renderers)gains the same JSON-string parsing, and
externalIdis added to thereference-label precedence for plain object values and arrays.
Verified in the browser (showcase task grid: Project column shows "Website
Relaunch" instead of
{"externalId":"Website Relaunch"}) and by unit tests.Updated dependencies [c12986e]
Updated dependencies [18d0339]
Updated dependencies [abe8ebc]
Updated dependencies [2f31406]
Updated dependencies [8d1195d]
@object-ui/layout@6.3.0
Patch Changes
@object-ui/mobile@6.3.0
Patch Changes
@object-ui/permissions@6.3.0
Patch Changes
@object-ui/plugin-ai@6.3.0
Patch Changes
@object-ui/plugin-calendar@6.3.0
Patch Changes
@object-ui/plugin-charts@6.3.0
Patch Changes
@object-ui/plugin-dashboard@6.3.0
Patch Changes
@object-ui/plugin-designer@6.3.0
Patch Changes
@object-ui/plugin-detail@6.3.0
Patch Changes
3cc38fe: perf(detail/header): lazy + dedupe related-list fan-out, coalesce header polls
Opening a record detail fired ~50 concurrent
/api/v1requests thathead-of-line-blocked one another on a single control-plane container.
RecordDetailViewno longer eager-preloads reverse-reference childrenwhen the reference rail renders them (that data was discarded while the
rail re-fetched the same collections).
record:reference_railnow gates fetching on visibility(
IntersectionObserver; the rail ishidden xl:flex), caps concurrencyat 3, and fetches once per
(parentId + entries)via a signature guard,applying results through a mounted ref.
AppHeaderinbox/notification, approvals, and activity pollers gainedin-flight guards so bootstrap effect re-runs coalesce to one request; the
approvals poll now sends one request with all identities comma-joined
instead of one per identity.
Measured locally: opening an environment detail dropped from ~52 to ~17
requests, related collections from ×3–5 each to ×1, approvals from ×9 to ≤3.
@object-ui/plugin-editor@6.3.0
Patch Changes
@object-ui/plugin-form@6.3.0
Patch Changes
@object-ui/plugin-gantt@6.3.0
Patch Changes
@object-ui/plugin-grid@6.3.0
Patch Changes
@object-ui/plugin-kanban@6.3.0
Patch Changes
@object-ui/plugin-map@6.3.0
Patch Changes
@object-ui/plugin-markdown@6.3.0
Patch Changes
@object-ui/plugin-report@6.3.0
Patch Changes
@object-ui/plugin-timeline@6.3.0
Patch Changes
@object-ui/plugin-view@6.3.0
Patch Changes
@object-ui/plugin-workflow@6.3.0
Patch Changes
@object-ui/providers@6.3.0
Patch Changes
@object-ui/runner@6.3.0
Patch Changes
@object-ui/tenant@6.3.0
Patch Changes
@object-ui/console@6.3.0
@object-ui/create-plugin@6.3.0
@object-ui/plugin-list@6.3.0
@object-ui/types@6.3.0
object-ui@6.3.0
Patch Changes