Skip to content

fix(components): page wrapper filters DOM attributes through the shared whitelist - #7958

Merged
os-sam merged 2 commits into
mainfrom
claude/issue-7933-page-dom-leak-whitelist
Sep 6, 2026
Merged

fix(components): page wrapper filters DOM attributes through the shared whitelist#7958
os-sam merged 2 commits into
mainfrom
claude/issue-7933-page-dom-leak-whitelist

Conversation

@os-sam

@os-sam os-sam commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Fixes #7933

PageRenderer closed its DOM leak with a hand-maintained destructure list and
spread the remainder onto its wrapper div, under a comment telling the next
reader to keep that list aligned with PageSchema. The alignment is what failed:
React forwards an unknown lowercase attribute in silence and stringifies object
values, so a key the list did not name was not dropped — it was emitted.

Clause-2

no. No schema's accept/reject behaviour changes (BaseSchema.passthrough()
is untouched), no public surface widens, and no gate's scan population moves —
the five names this PR expires from the leak ledger stay in
COMPONENTS_PLAIN_TYPES, so they are still SWEPT, just no longer recorded as
leaking. What moves is a behaviour population, which the survey below
measures.

The mechanism, not a longer list

The set of keys an author may put on a node is unbounded; the set a widget may
put on an element is declared. A deny-list bounded by enumeration cannot be
finished — the objectui#4425 ruling — and toDomProps is the one executor it
promoted to @object-ui/core for exactly this. page.tsx was one of the last
faces still closing the leak with an enumeration of its own. This PR makes it
call the shared whitelist; it invents nothing.

style stays forwarded BY NAME (it is not on the element-agnostic whitelist,
so nothing else would deliver it), as does the data-obj-id / data-obj-type
designer channel.

Survey — the behaviour population this moves

Corpus: every statically-readable authored node in the repo whose type is one
of the five registry keys PageRenderer is registered under, from .json,
fenced json in .md/.mdx, and object literals in .ts/.tsx.

reading value
page-family nodes read 119, across 82 files (json 6 · md-fence 2 · ts/tsx 111)
distinct authored keys 39
blind spots (could not read) 28 — 2 unparsable md fences, 14 type: 'page' with no enclosing object literal (TS type positions), 6 whose keys would not extract, 6 nodes built with a spread
type-name collisions excluded 105 (e.g. a type: 'record' FIELD definition), counted separately, never silently dropped

A static key list is not a leak measurement, so every key was then driven
through the real SchemaRenderer path and the wrapper's attributes read off the
rendered element, on all five registry keys:

registry key attributes before after dropped added
page 32 7 25 0
app 32 7 25 0
home 32 7 25 0
utility 32 7 25 0
record 32 7 25 0

Dropped: actions alloworgoverride anchors badge barekey canonicalkey
context createdefaults createderive createfields createschema
createseed data domain href interfaceconfig item label labelkey
listcolumns name pagename properties slots somerendererprop.

Kept, unchanged: class id aria-label data-obj-id data-obj-type
data-page-type data-canary.

Two findings the corpus scan alone would have missed:

  • context is host-injected. app-shell's PageView.tsx adds a context
    bag to every page it renders, so context="[object Object]" was on the
    wrapper of every page the console showed — the leak never needed an unusual
    author to reach production.
  • slots and label are declared spec keys that the hand list did not
    name, so a spec-conformant page leaked them.

Safety gate — is any leaked attribute consumed downstream as a DOM
attribute?
No. Searched for CSS attribute selectors ([actions], [actions=,
…), getAttribute('KEY'), e2e locators, and snapshot pins over all 25 names.
Every hit was JS array-destructuring or a computed key ([canonicalKey]:), an
unrelated a[href] focus selector, or ASCII art. No snapshot pins the wrapper.
Nothing reads these as attributes, so the replacement is safe.

The nail

packages/components/src/__tests__/page-dom-leak-whitelist-7933.test.tsx — 10
cases, 2 per registry key.

Positive control. Restoring the hand-maintained destructure list turns the
pin red and it names itself, rather than reporting a generic assertion failure:

FAIL  packages/components/src/__tests__/page-dom-leak-whitelist-7933.test.tsx
      > type:'page' — an undeclared authored key never reaches the wrapper
- Expected                          + Received
  "illegitimateAttributes": []      "illegitimateAttributes": [
                                      "actions", "context", "label",
                                      "name", "pagename", "slots" ]
  "pin": "objectui#7933 — page wrapper DOM pass-through whitelist"
  "surface": "PageRenderer wrapper div[data-page-type] for registry key 'page'"

Restored by STATE, not by exit code: the worktree blob returned to
be8b9d332c1696554caf82e7bb95f6b69eb226b9, identical to the HEAD blob, with
git diff HEAD at 0 bytes and git status --short empty. The mutation was
confirmed on disk first (rawPageProps 0 to 2 occurrences, toDomProps(props)
1 to 0) so a no-op edit could not have been read as a passing control.

Negative control. Five more cases assert the attributes the wrapper genuinely
needs are still delivered — class, data-page-type, data-obj-id,
data-obj-type, style, id, role, tabindex, and the open data-* /
aria-* families. A whitelist is a dropping mechanism, so "the leak is gone" is
half a measurement; style in particular survives only because it is forwarded
by name, and nothing but this half is watching it. Writing it caught a real
fact: data-obj-id / data-obj-type are DERIVED by SchemaRenderer from the
node's id and type, not authored, so the pin asserts the values the pipeline
actually produces.

The coupled ledger expiry (second commit)

packages/app-shell/src/__tests__/widget-dom-leak-sweep.test.tsx carries a
two-way ratchet: a new leaked attribute fails it, and so does FIXING one, until
the row is deleted in the same change — "Rows leave this ledger by being
DELETED in the change that fixes them."
With only the first commit the gate
read Tests 5 failed | 197 passed (202), found: [] against
ledgered: [14 attributes] on ui:app ui:home ui:page ui:record
ui:utility. The registry resolves ui:page and bare page to the same
registration, which is how the sweep reaches PageRenderer at all.

Causality was proven by ablation rather than assumed: with the pre-fix mechanism
restored the same gate is 202/202 green, so those five were this change's doing
and not a pre-existing red.

The second commit deletes exactly those five names from the targets list of
the BARE_SPREAD group in COMPONENTS_LEAK_GROUPS. The list goes 91 to 86
entries — five fewer, no more and no less. Nothing else in that file moves: no
structural change, no docstring edit, no new group, no other target touched. All
five remain in COMPONENTS_PLAIN_TYPES, so they are still swept on every run,
now expected to be clean.

Verification

All Vitest runs from the repo root (RUN v4.1.10 /home/user/objectui-issue-7933),
never a package cwd. Re-run after the final commit bdf78fc4c, at which
git diff HEAD is 0 bytes.

check exit reading
widget-dom-leak-sweep after the expiry 0 202/202 passed (was 5 failed / 197 passed)
pin + sweep together, at bdf78fc4c 0 2 files, 212 tests passed
vitest run packages/components/ 0 234 files / 2158 tests passed
the pin, under ablation 1 5 failed / 5 passed — the positive control
@object-ui/components type-check 0 0 error TS; --listFiles proves page.tsx in both programs, the pin in the test program
@object-ui/app-shell type-check 0 0 error TS; --listFiles proves the sweep file is in the test program
@object-ui/components lint 0 0 errors; changed files add 0 errors, 0 new warnings
@object-ui/app-shell lint 0 0 errors
check:control-bytes 0 6412 tracked text files scanned
check:vi-mock-specifiers 0 4338 files, 2615 test-named
check:vi-mock-inherit 0 4338 files, 2615 test-named
check:handler-key-reads 0
check:action-forward-parity 0 5 surfaces vs 39 runtime-read keys
check:element-data-source-declaration 0
check:side-effects-array 0
check:unreferenced-sources 0
check:self-import 0
check:phantom-deps 0
check:entry-guard 0
check:sdui-registration-pins 2 NOT MEASURED — "No console build to weigh at apps/console/dist/assets… This is exit 2, not a pass"
check:eager-closure 2 NOT MEASURED — no apps/console/dist/eager-closure.json; needs a console build CI does

node scripts/check-changeset-presence.mjs re-run after the app-shell file
entered the diff (not carried over), verbatim:

3 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s): .changeset/spotty-pages-drop-leaks.md.

node scripts/check-changeset-no-major.mjs: No changeset declares a major bump.

https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3

…ed whitelist (objectui#7933)

`PageRenderer` stripped PageSchema's descriptor keys with a hand-maintained
destructure list and spread the remainder onto its wrapper <div>, under a
comment instructing the next reader to keep the list aligned with PageSchema.
The alignment is what failed: React forwards an unknown lowercase attribute in
silence and stringifies object values, so an authored key the list did not name
was not dropped but emitted — `actions="[object Object],[object Object]"`.

Replace the enumeration with `toDomProps` from `@object-ui/core`, the one
executor objectui#4425 promoted for exactly this. `style` stays forwarded by
name (it is not on the element-agnostic whitelist), as does the
`data-obj-id` / `data-obj-type` designer channel.

Measured on all five registry keys PageRenderer is registered under
(page/app/home/utility/record): 25 illegitimate attributes before, 0 after,
with all 7 legitimate attributes unchanged and none added.

No schema accept/reject behaviour changes and no read point is added for any
previously leaking key.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3189.3 KB 3191.4 KB
Main entry chunk (gzip) 143.5 KB 350 KB
Entry file index-C0fhTIje.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) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 5.13KB 2.35KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 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) 510.24KB 116.03KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.98KB 10.98KB
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) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
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) 15.75KB 3.80KB
plugin-calendar (index.js) 47.87KB 13.31KB
plugin-charts (index.js) 70.92KB 19.75KB
plugin-chatbot (index.js) 196.19KB 46.37KB
plugin-dashboard (index.js) 132.88KB 34.69KB
plugin-designer (index.js) 212.86KB 43.19KB
plugin-detail (index.js) 250.55KB 64.06KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 132.87KB 32.66KB
plugin-gantt (index.js) 167.26KB 41.00KB
plugin-grid (index.js) 209.29KB 56.78KB
plugin-kanban (index.js) 52.71KB 14.55KB
plugin-list (index.js) 113.56KB 27.70KB
plugin-map (index.js) 20.44KB 6.78KB
plugin-markdown (index.js) 13.93KB 4.81KB
plugin-report (index.js) 43.59KB 11.97KB
plugin-timeline (index.js) 30.40KB 8.76KB
plugin-tree (index.js) 9.20KB 3.19KB
plugin-view (index.js) 85.24KB 20.94KB
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.66KB 3.50KB
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) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
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) 0.20KB 0.18KB
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) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
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

…losed (objectui#7933)

The leak ledger in widget-dom-leak-sweep is a two-way ratchet: a new leaked
attribute fails it, and so does FIXING one, until the row is deleted in the
same change. The previous commit routed PageRenderer's wrapper through
`toDomProps`, so `found` went empty for the five registry keys the registry
resolves to that renderer (`ui:page` and bare `page` are the same
registration), while the ledger still recorded 14 attributes each.

Delete exactly those five names -- 'ui:app', 'ui:home', 'ui:page',
'ui:record', 'ui:utility' -- from the BARE_SPREAD group's `targets`. The list
goes 91 -> 86 entries; nothing else in the file moves, and all five stay in
COMPONENTS_PLAIN_TYPES, so they are still SWEPT, just no longer ledgered.

Gate reading after the deletion: 202/202 passed (was 5 failed | 197 passed).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3189.3 KB 3191.4 KB
Main entry chunk (gzip) 143.5 KB 350 KB
Entry file index-C0fhTIje.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) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 5.13KB 2.35KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 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) 510.24KB 116.03KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.98KB 10.98KB
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) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
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) 15.75KB 3.80KB
plugin-calendar (index.js) 47.87KB 13.31KB
plugin-charts (index.js) 70.92KB 19.75KB
plugin-chatbot (index.js) 196.19KB 46.37KB
plugin-dashboard (index.js) 132.88KB 34.69KB
plugin-designer (index.js) 212.86KB 43.19KB
plugin-detail (index.js) 250.55KB 64.06KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 132.87KB 32.66KB
plugin-gantt (index.js) 167.26KB 41.00KB
plugin-grid (index.js) 209.29KB 56.78KB
plugin-kanban (index.js) 52.71KB 14.55KB
plugin-list (index.js) 113.56KB 27.70KB
plugin-map (index.js) 20.44KB 6.78KB
plugin-markdown (index.js) 13.93KB 4.81KB
plugin-report (index.js) 43.59KB 11.97KB
plugin-timeline (index.js) 30.40KB 8.76KB
plugin-tree (index.js) 9.20KB 3.19KB
plugin-view (index.js) 85.24KB 20.94KB
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.66KB 3.50KB
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) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
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) 0.20KB 0.18KB
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) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
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

@os-sam
os-sam marked this pull request as ready for review September 6, 2026 05:07
@os-sam
os-sam added this pull request to the merge queue Sep 6, 2026
Merged via the queue into main with commit 45d8288 Sep 6, 2026
34 checks passed
@os-sam
os-sam deleted the claude/issue-7933-page-dom-leak-whitelist branch September 6, 2026 05:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants