Skip to content

Framework chrome: trusted code, position+secret authentication, input suspension - the shell's own UI #22

Description

@lannbot

Provisional plan — recorded 2026-08-16 from the chrome design discussion. Every ruling here is provisional until the prototype has been user-tested; user testing of the chrome prototype is the conversion checkpoint (per explicit direction). Related: #5 (anti-spoofing line, ruling table), #6 (powerbox UX), #16 (app execution model); prototype in spikes/todomvc (chrome strip + consent sheet over the three guests).

Rulings (provisional)

  • Chrome is trusted shell code, not a component. It is the reference monitor's face — TCB by definition; sandboxing it buys nothing and costs the deliberately-narrow app surface. Plain trusted Preact (in-family, proven small) + normal DOM, shipped with the framework release. The "shell is just an app with more grants" symmetry is rejected. Exception, named: third-party chrome-ish things (a storage backend's config panel) are apps — own sandboxed region, own grants, launched from chrome, never rendered as chrome.
  • Style never authenticates; position and secrets do. Apps can copy any CSS, so the design system is shared freely with apps (coherent product, no security cost). Trust anchors instead:
    • Position: apps render only inside their frame rectangle (the root() grant is the geometry contract); chrome renders only outside it. Trusted may overlay untrusted (consent sheets over a dimmed app); never the reverse. Fullscreen/PiP/popups stay withheld (App-frame sandboxing: a ruling table per sandbox flag and CSP directive; residual channels; anti-spoofing chrome #5 table) because they break the rectangle.
    • A persistent strip apps can never paint: petname, capability-in-use indicators (mic-light analogy), audit entry point, and a kill/suspend affordance the app cannot intercept.
    • A user-chosen personalization secret in every real prompt Dropped 2026-08-16 (directive + analysis; see the secrets-vs-decisions comment): it defends only at a moment the secret-entry rules eliminate, and the SiteKey literature says it fails there anyway.
    • Untrusted-string discipline inside chrome: petnames are primary identity; app-supplied text is always quoted, length-clamped, styled as foreign — never interpolated into chrome's own sentence structure.
  • Chrome owns input and lifecycle, not just pixels. The shell owns event delivery (the runner queue), so modal chrome = pause the app's queue — the app cannot observe or race the user's interaction with a prompt. Routing already belongs to the shell (route()/on-route in the spike WIT). Trap/death screens are chrome-rendered (fed by the future diagnostics channel). Later: launcher/switcher/multi-app = N app regions, each with its own root grant and queue.

Non-goals (stated, not discovered)

Prototype (spike scope)

Chrome strip above the app rectangle (petname + guest/backend indicators + kill), one fake consent sheet showing the personalization secret, and event-queue suspension while the sheet is open — validated against all three guests. The spike strip is vanilla DOM (framework ruling says Preact; the spike shell predates that plumbing).

Open sub-questions

  • Modal event policy: queue-and-deliver-on-dismiss (prototype behavior) vs drop vs deliver-with-a-"was-suspended" marker.
  • A11y variant of the personalization secret (moot: secret dropped 2026-08-16).
  • Secret lifecycle: per-device vs synced; recovery on re-enrollment (moot: secret dropped 2026-08-16).
  • Kill semantics: real instance teardown needs a deltic embedder API check (drop references vs explicit terminate).
  • Mobile geometry: safe-area insets, strip height budget, iOS URL-bar collapse interactions.
  • When multi-app arrives: strip-per-region vs global strip with focus indication.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions