Skip to content

fix(app-shell): a declared flow action's button starts its flow through the action door (objectui#12037) - #12046

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-12037-flow-action-door
Oct 9, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-12037-flow-action-door

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #12037

Clause-②: no

Built on triage ruling B (card comment 6077692839): a flow click goes through the action door exactly when it names a declared flow action; every other flow start stays on the trigger route. Ruling A landed in objectstack-ai/objectstack#22424. Implemented by session https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU (seat domain:ui#2).

What changes

Both console flow-launch handlers used to start every flow through POST /api/v1/automation/:flow/trigger: flowHandler in useConsoleActionRuntime (list, page and root runtime) and flowHandler in RecordDetailView. That route starts a flow by name, so a declared flow action's own server gates never ran for the click. Those gates are its requiredPermissions (ADR-0066 D4, whose console half only hides the button), its activation switch, its param contract and the caller-scoped load of its subject record.

  • The route rule lives in one module-internal launcher, launchConsoleFlow in the new packages/app-shell/src/utils/flowLaunch.ts, which both handlers call. A click goes through POST /api/v1/actions/:object/:action exactly when findDeclaredFlowAction finds, in the object metadata the console already holds, an action of the click's name on the click's object with type: 'flow' and the same target. Otherwise the click stays on the trigger route. Both handlers' docblocks record why: an undeclared flow start has no action gate to apply, and ruling A's elevation refusal already holds on the trigger route. Those starts are an inline page button with no or a non-matching name, and a dashboard header's synthesized name: actionUrl.
  • Who owns the door's exchange. The /actions request is built by core's createServerActionHandler (name-only identity, { recordId, params }, _rowRecord stripped), so app-shell still names that route nowhere (actions-envelope.ratchet.test.ts stays green, unedited). The answer is the flow's AutomationResult, read by interpretFlowResponse / judgeFlowLaunch through an injected transport. So a paused screen still opens FlowRunner, a refused end still opens the Close-only notice, and FLOW_FAILED still prefers the author's errorMessage. Core's own interpretActionResponse has none of those arms.
  • Ride-along, related-list toolbar. RecordDetailView's flow path no longer hands the parent page's record id to a child object's action that carries no row. A related list's toolbar flow action is now an object-level start; a row action still addresses the child row.
  • Docs. In content/docs/guide/architecture-overview.md, the Supported Action Types flow row now says what the type does and which endpoint each kind of click uses.
  • flow-envelope.ratchet.test.ts names the callers that are true now: utils/flowLaunch.ts (launch) and views/FlowRunner.tsx (resume). It also pins that both handlers delegate to launchConsoleFlow.

Nothing published changes: no export, prop or packages/i18n key is added. flowLaunch.ts is reachable only through the two handlers. No spec change, and nameless flow buttons are not refused (ruling B, not A).

Measured before building

The door was read at objectstack origin/main 081e6a09, which contains c572fe2a36 (git merge-base --is-ancestor exit 0); the files read were dispatchFlowAction and the flow arm of handleActionsRequest.

The handlers read Where the door's answer carries it
transport envelope deps.success(result) / deps.error(...), the same builders as the trigger route (ADR-0112)
paused screen: runId, screen, flowLabel the raw AutomationResult as data; a paused result is neither a refusal row nor caught by the residual success === false arm
refused end: status: 'refused', refusalMessage passes through deps.success unchanged
successMessage unchanged
ran and failed 400 with error.code FLOW_FAILED and error.details.errorMessage, via FlowActionRefusal
404 / 409 / 422 / ruling A's 403 the same shared table and admission rule at both doors

The door does not carry the flow name. FlowRunner resumes under the handler's flow, which on the door path is the declaration's target; the lookup requires the two to be equal.

Related-list row action on a child. RelatedRecordActionsBridge.runRowAction dispatches the child object's declared action with objectName set to the child and recordId to the child row. At the door that is POST /api/v1/actions/CHILD/CHILD_ACTION_NAME. resolveRouteActionDeclaration resolves the declaration on the child. loadActionSubjectRecord loads the child row under the caller's scope, and refuseDeniedSubjectLoad answers 404 when that row cannot be read.

Where the lookup's metadata comes from. It reads object metadata only. The runtime reads the caller's objects first, then the console store's object type, awaiting ensureType('object') before deciding, as the param dialog already does. The record page reads its objects prop. That metadata carries an object's own actions[], which includes every defineAction({ objectName }): defineStack's bound-action merge puts them there. The console's list row actions render from objectDef.actions alone; e2e/live/screen-flow.spec.ts clicks the bound showcase_bulk_reassign that way. The metadata does not carry an object-less declared action, nor a standalone authored action row that no object definition embeds. A click on either keeps the trigger route, as every flow click did before, so that is no regression; a pin holds it as a control. No click-time action metadata fetch was added.

Pins

  • useConsoleActionRuntime.flowActionDoor-12037.test.tsx runs through the real ConsoleActionRuntimeProvider, runner and FlowRunner:
    • a declared flow action whose requiredPermissions the caller lacks is refused by the server with 403 PERMISSION_DENIED, and its message is the error toast;
    • control: an allowed click pauses, and Submit resumes at /api/v1/automation/showcase_reassign_wizard/runs/run-1/resume, the declaration's target;
    • the store is read (ensureType('object')) when the caller holds no objects;
    • an inline button with no name, a dashboard synthesized name, a name whose declaration has another target or type, and an object-less declared action (the control) all stay on the trigger route;
    • an elevated self-triggered target is refused there, and that refusal is the error toast.
  • RecordDetailView.flowActionDoor-12037.test.tsx runs through the real record page and FlowRunner:
    • a related-list row action on the child goes to /api/v1/actions/lead_task/escalate_task with recordId set to the child row, is refused 403, and the refusal is shown;
    • the related list's toolbar action sends no parent id, on both doors;
    • control: a header click pauses and resumes under the declaration's target;
    • an undeclared header start stays on the trigger route, where the elevated refusal is shown.

Reverse leg. The implementation was committed first (66291b17c). The trap-guarded script then checked out main's blobs (47b1f0bb7) of the two handler files and ran the two pin files plus the ratchet: Tests 8 failed | 8 passed (16). The 8 failures were every door pin, the two parent-id pins and the delegation pin. The 8 that passed are the trigger-route controls, which hold on main too. After the restore, git diff HEAD showed 0 lines, and git hash-object equalled the HEAD blob for both files. Re-run on head: Tests 16 passed (16).

Gates, on head 66291b17c

  • Every suite that mounts either handler, plus FlowRunner's suites, flowResponse, the app-shell ratchets, column-identity.ratchet.test.ts and one-authority-per-exported-name-6273.test.ts: 84 files. Run with repo-root pnpm exec vitest run, under the verify lock, after the final commit: Test Files 84 passed (84), Tests 596 passed (596).
  • pnpm --filter @object-ui/app-shell type-check, echoed tsc --noEmit && tsc -p tsconfig.test.json, gave VERDICT command-exit 0. The upstream closure was built first. --listFilesOnly on the test tsconfig lists all four new or edited files.
  • check-changeset-presence and check-changeset-no-major pass. check:new-line-citations reports 0 new citation(s). check:control-bytes, docs:check-links, check:spec-symbols, check-vi-mock-override-shape, check-test-path-roots and check-lint-coverage are all OK.
  • pnpm exec eslint on the 6 touched TS files (count from --format json) gives 0 errors. Warnings on the two handler files equal their base blobs: 110 and 38. The repo's eslint.config.js has no projectService / parserOptions.project, so linting is not type-aware and the diff cannot move an untouched file's verdict. The full pnpm lint and pnpm test are left to CI.

First-load bytes

Both handlers ship eagerly: the runtime's code is in the eager DeclaredActionsBar chunk, and the record page's is in the eager RecordDetailView chunk. A console vite build under the lock, from apps/console/dist/eager-closure.json, gives eagerGzipBytes 3,238,611 at base 47b1f0bb7 and 3,238,879 at head: +268 B gzip, with 289 eager chunks in both builds.

Acceptance notes, not changed here

  • RecordDetailView's script handler has the same parent-id fallback for a related list's toolbar (its resolveRecordId override). It is outside the flow path this PR rewrites, so it is reported only.
  • _rowRecord.id against _rowRecord[recordIdField] was not aligned. The door treats the body's recordId as the subject row's primary id and seeds recordIdParam from record[recordIdField] itself (seedFlowActionParams; the spec describes recordIdField as "Row field whose value seeds recordIdParam"). So _rowRecord.id is the read the door wants. Core's resolveServerActionRecordId reads _rowRecord[recordIdField] as the record address; the only producer with a non-id recordIdField (sys_session's revoke_session) is an api action that never reaches that reader.
  • An object-less declared flow action keeps the trigger route. A nav item does resolve one from action metadata, so seeing it would take a new provenance signal or a click-time fetch; neither was added.
  • The packages/app-shell README has no section on the flow launch, so nothing there became false.

Surface

The two handler files, the two new pin files, flow-envelope.ratchet.test.ts, the docs page and the changeset. One file outside the claim's literal list: the new module-internal utils/flowLaunch.ts, the shared call shape (H2) the build round asked to keep module-internal. ObjectView.tsx and everything in objectstack are untouched.


Generated by Claude Code

…gh the action door (objectui#12037)

Both console flow-launch handlers started every flow through
POST /api/v1/automation/:flow/trigger, so a declared flow action's own
server-side gates (requiredPermissions per ADR-0066 D4, activation, param
contract, caller-scoped subject load) never ran for the click.

Triage ruling B: a click whose object and name resolve to a declared
type 'flow' action with the same target, in the object metadata the
console already holds, goes through POST /api/v1/actions/:object/:action
(request built by core's createServerActionHandler, answer read by the
flow rule). Every other flow start (an inline page button with no or a
non-matching name, a dashboard header action) stays on the trigger
route: it has no action gate to apply, and ruling A's elevation refusal
holds there. One module-internal launcher, utils/flowLaunch, serves both
handlers.

The record page's related-list toolbar flow action (no row) no longer
sends the parent page's id against the child object.

Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests package: app-shell labels Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 289 chunks) 3163.8 KB 3204.6 KB
Main entry chunk (gzip) 72.5 KB 350 KB
Entry file index-BIw9TIu8.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 19.52KB 7.19KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 587.83KB 141.44KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 240.39KB 67.09KB
fields (index.js) 268.74KB 68.04KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 41.50KB 11.82KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 53.43KB 15.54KB
plugin-charts (index.js) 84.71KB 23.25KB
plugin-chatbot (index.js) 201.52KB 47.99KB
plugin-dashboard (index.js) 144.20KB 38.95KB
plugin-designer (index.js) 233.53KB 49.80KB
plugin-detail (index.js) 248.57KB 65.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.11KB 45.88KB
plugin-gantt (index.js) 179.17KB 45.07KB
plugin-grid (index.js) 249.62KB 69.16KB
plugin-kanban (index.js) 52.77KB 16.56KB
plugin-list (index.js) 120.25KB 30.26KB
plugin-map (index.js) 27.24KB 9.03KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.12KB 12.29KB
plugin-timeline (index.js) 39.10KB 11.81KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.27KB 23.06KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.25KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

claude added 2 commits October 9, 2026 10:16
… starts through the action door (objectui#12037)

The live lane's `screen-flow.spec.ts` asserted a POST to
/api/v1/automation/:flow/trigger. Under triage ruling B the declared
`showcase_bulk_reassign` row action now starts its run through
POST /api/v1/actions/showcase_task/showcase_bulk_reassign, so the run
paused, rendered its screen, resumed and wrote the row, and only that
request-shape assertion failed. The spec now asserts the action-door
launch and that no trigger-route start happened; the resume and
persisted-data assertions are unchanged.

Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 289 chunks) 3163.8 KB 3204.6 KB
Main entry chunk (gzip) 72.5 KB 350 KB
Entry file index-BIw9TIu8.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 19.52KB 7.19KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 587.83KB 141.44KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 240.39KB 67.09KB
fields (index.js) 268.74KB 68.04KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 41.50KB 11.82KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 53.43KB 15.54KB
plugin-charts (index.js) 84.71KB 23.25KB
plugin-chatbot (index.js) 201.52KB 47.99KB
plugin-dashboard (index.js) 144.20KB 38.95KB
plugin-designer (index.js) 233.53KB 49.80KB
plugin-detail (index.js) 248.57KB 65.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.11KB 45.88KB
plugin-gantt (index.js) 179.17KB 45.07KB
plugin-grid (index.js) 249.62KB 69.16KB
plugin-kanban (index.js) 52.77KB 16.56KB
plugin-list (index.js) 120.25KB 30.26KB
plugin-map (index.js) 27.24KB 9.03KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.12KB 12.29KB
plugin-timeline (index.js) 39.10KB 11.81KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.27KB 23.06KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.25KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 9, 2026 10:49
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 9, 2026 10:49
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 9, 2026
Merged via the queue into main with commit e97a0e2 Oct 9, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-12037-flow-action-door branch October 9, 2026 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation package: app-shell tests

Projects

None yet

2 participants