Skip to content

Tier 1: errors, right to left, permissions, saved layouts, performance, security - #1

Open
DanFessler wants to merge 7 commits into
mainfrom
tier-1
Open

DanFessler wants to merge 7 commits into
mainfrom
tier-1

Conversation

@DanFessler

Copy link
Copy Markdown
Owner

Enterprise readiness work, prioritised from a prospect's evaluation criteria (availability, accessibility including RTL, performance, locked layouts, server-saved layouts, a security questionnaire).

What's in it

  • Error isolation. A view whose content fails to mount or render shows a fallback with Try again; the rest of the workspace carries on. React views each render in their own error boundary. Everything that throws goes to a new error event (source, view, type); ws.reportError, errorFallback, and React onError / errorFallback props.
  • Right to left. direction ("auto" follows the page). The layout mirrors at the screen boundary, so documents stay direction-neutral and every pointer path follows the pointer: dividers, docking, tab reordering, floating windows, collapsed groups, navigation gestures. Keys follow reading order; menus open toward the start edge.
  • Permissions. permissions: false | { rearrange, resize, close, float, hide }, changeable at runtime, covering every path to each action. Code is never limited. Fixes Close other tabs closing non-closable tabs.
  • Saved layouts. sanitize accepts any value and repairs it (fuzzed with 3,000 corrupted layouts). A malformed persisted layout falls back to the default; unknown view types keep their records until registered.
  • Performance. Rendering indexed views per document instead of walking the tree per view per frame: at 300 views with the CPU slowed 4×, slow frames during a tab drag go from 98% to 3%, during a zoom from 84% to 22%. npm run bench measures startup, memory and frame timing.
  • Strict CSP and Trusted Types. Built-in icons and collapsed-group lines no longer use markup or inline style attributes; an e2e scenario runs under style-src-attr 'none' and require-trusted-types-for 'script'.
  • Docs. New Errors, Permissions, Right to left, Performance and Security pages; persistence covers damaged layouts and several layouts per user or team; references updated.

Testing

Each feature was written test-first; new tests were checked to fail before the change. Locally: 216 e2e tests (Chromium, Firefox), 111 unit tests, typecheck, verify:pack (React 18 and 19), the IDE and desktop example checks. CI adds WebKit.

🤖 Generated with Claude Code

DanFessler and others added 7 commits September 28, 2026 18:28
A view whose content fails to mount (or whose iframe function throws) shows a
fallback with its title, the error and Try again, and the rest of the workspace
carries on. In React, every view's content, icon and accessory renders inside its
own error boundary, so one throwing component no longer unmounts the workspace.

Everything that throws, from view code, callbacks, close guards or event
listeners, goes to a new error event with its source, view and type; without a
listener it goes to the console. ws.reportError sends an app's own errors down the
same channel, errorFallback replaces the fallback (core and React, per workspace or
per type), and React gets an onError prop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With direction "rtl" (or "auto", the default, on a right-to-left page) the
workspace mirrors: a row's first child sits on the right, tabs and menus run right
to left, and floating windows are placed from the right. The document stays
direction-neutral; the mirror is applied where layout coordinates meet the screen,
so dividers, docking, tab reordering, floating resize, collapsed groups and every
navigation gesture follow the pointer. Arrow keys follow reading order in tab
lists and menus and move dividers the way they point. Key combinations in menus
keep reading left to right. React gets a direction prop, the web component a
direction attribute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A permissions option (and React prop) sets what users may change through the
interface: rearrange, resize, close, float and hide, each on by default, or false
to lock everything. Each one covers every path to its action: drags, dividers and
their keys, floating-window edges, close buttons, middle-click, Delete, panel menu
items and shortcuts. Locked dividers and resize handles aren't shown. Calls from
code are never limited, and permissions can change at any time.

Also fixes Close other tabs closing tabs whose type isn't closable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sanitize now trusts nothing about its input: any value at all comes back as a
valid document without throwing. Wrong types, nulls, missing or duplicate ids,
non-numeric rects, bad restore targets and malformed framings are repaired, with
fresh ids rather than lost content. A fuzz test runs 3000 corrupted layouts
through it and checks every invariant the workspace relies on.

The workspace repairs a document before deciding on unregistered view types, so
setDocument accepts anything, and a saved layout with the wrong shape falls back to
the default layout. Placeholders for unregistered types are marked view-missing,
and their records survive saving until the type is registered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rendering looked up every view's panel and region by walking the whole layout, for
each view on every frame: views × panels work per frame, 30,000 tree visits at 300
views. The workspace now indexes views and panels once per document change. Views
in background tabs aren't repositioned while things move, and dividers hide
during camera moves as they already do during layout animations.

With the CPU slowed 4× and 300 views, slow frames during a tab drag fall from 98%
to 3%, during a zoom from 84% to 22%.

scripts/bench.mjs measures startup, memory and frame timing for 16, 108 and 300
views, at full speed and slowed 4×, and prints the tables docs/performance.md
quotes. The e2e stress scenario takes its grid size from the URL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The built-in icons were parsed from markup, which throws where Trusted Types are
enforced, so the workspace couldn't start at all. Collapsed groups drew their
lines with inline style attributes, which a policy blocking them leaves
unpositioned, and icon-only panels copied their icon by re-parsing its markup.
All three now build elements and set positions through the style object. A new
e2e scenario runs under style-src-attr 'none' and require-trusted-types-for
'script' and checks icons, menus, collapsed groups and icon tiles, with no
violations.

Icon markup that an app passes as a string is still HTML, and documented as such.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…erformance, security

New guides for handling errors, locking and permissions, and right-to-left
layouts; new Performance (measured with npm run bench) and Security pages.
Persistence covers damaged and outdated layouts, unknown view types and several
layouts per user or team. The API references, theming and keyboard pages cover
the new options, events, parts and attributes. The core's size is now quoted as
37 kB gzipped, and the changelog has an Unreleased entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant