Repository navigation
feat(webui): forward port the Mini App contract and accept the newer manifest keys - #261
Conversation
Record the decisions the grilling settled, and shrink the open list to the two implementation details that remain. Taken: the shipped contract minus the window block; the loopback credential guard with readiness proving it is in the path; the postMessage bridge, with the origin-local shim recorded as rejected; the agent capability in scope, since parity with the desktop client's page is the acceptance standard; the connector's frames moving onto the IPC channel that already carries lifecycle, leaving stdout and stderr as logs; the workspace panel's miniapp tab as the inline home, opened from the launcher's tile and listed in the catalogue's apps area; the standalone route with a service-held presentation lease; the agent open call mapped onto the session rail; one proxy listener per Mini App with a per-plugin port; and single-client ownership, where the second client reports the owner and refuses to start. The client's Mini App work is one business, with three crossings one line wide. CONTEXT.md follows: the bridge no longer describes a window handle, the view records that both presentations belong to the client, and the presentation lease is defined.
…manifest keys The Mini App contract moves to the generation the desktop client ships, minus its window block, and the package reader stops rejecting a package built for that generation. The contract file is now a contiguous copy of the shipped file's leading part (shipped lines 1-964 of 1267): the start/page-open split, detached and presentationRevision, the loopback token header, the composer block, and the whole agent block with its nine run events and their mapping from runtime failure codes. The window block is the omitted tail: the argv surface id, the surface.window whitelist and the page's getState/update/focus handle. One private helper has to come out of that tail. The agent parsers above use isPlainRecord nine times, and the shipped file declares it at line 1156, inside the window block, so it is kept at the seam between the copied part and the omission. It is the one local divergence a future copy has to reconcile. The reader accepts the three keys the newer generation declares. surface.window is accepted and ignored, because the window block is not part of this contract and the value therefore has no effect. agentAccess (only session.run, deduplicated) and agentConcurrency (an integer from 1 to MINIAPP_AGENT_MAX_CONCURRENCY) are validated and preserved on the contribution, so the agent service can enforce them when it lands. Both allowlists stay strict: an unknown top-level key still fails as MINIAPP_MANIFEST_SCHEMA_INVALID, and an unknown key beside surface.window still fails as MINIAPP_SURFACE_INVALID. No runtime behaviour changes: the service still does not start for this client's owner kind, and nothing reads the agent fields yet. ADR 0020's contract-baseline section is corrected from measurement: the shipped leading part is a strict superset of the old 54 lines but not a line-identical copy of them, and the omitted tail is not purely window code. Verified: pnpm typecheck; pnpm typecheck:webui; pnpm run test:capabilities (235 files, 5811 passed, 18 skipped); pnpm build; pnpm check:source after node scripts/source-inventory.mjs --write. The new reader suite fails 13 of 16 cases against the previous reader and passes 16 of 16 here.
Unit suites for this package live under packages/local-runtime-v2/test, not beside the module they exercise, so the reader suite goes to test/unit/plugin-system/. Registered at its new path in test/vitest-suites.json and the source inventory is regenerated for the rename. Verified at the new path: pnpm typecheck; pnpm run test:capabilities (235 files, 5811 passed, 18 skipped); pnpm check:source.
Findings from the independent review of #261. The two reader rejection codes this branch introduced were unmapped in the failure diagnostic layer: `PREPARATION_REASON_BY_HOST_CODE` carries every other MINIAPP_* reader code, so a package rejected for `agentAccess` or `agentConcurrency` fell through to `INTERNAL_ERROR` with no reason code and no hint — a worse answer than the `WORKSPACE_PLUGIN_INVALID` it got before the branch started accepting those keys. Both now map to `MINIAPP_MANIFEST_INVALID`, the reason the other manifest rejections use, so the catalog entry that already exists supplies the message. Two test gaps the review found are closed: `agentConcurrency` without `agentAccess` is asserted accepted (1, 4 and 32, the documented no-effect case and both bounds), and the changed surface message is pinned rather than left to drift. Two ADR sentences were wrong about facts: the omitted tail declares the window state and patch contracts, not a page handle — `getState`/`update`/`focus` live in the preload and appear nowhere in the reference file — and the agent fields are validated and preserved here, not enforced. Verified on this branch: pnpm typecheck; pnpm run test:capabilities (5814 passed, 18 skipped); pnpm check:source.
|
Independent review, done by a separate read-only reviewer agent ( Verdict from the reviewerChanges requested — one blocking item, rest clean. Blocking (fixed in
|
Closes #252.
Change
The Mini App contract moves to the generation the desktop client ships, minus its window block, and
the plugin package reader stops rejecting a package written for that generation. Scope and user
stories: #251. Decisions:
packages/webui/docs/adr/0020-webui-miniapp-view-and-runtime-seams.md.Three commits: the ADR 0020 revision this ticket implements (
docs(webui): settle ADR 0020 for hosting Mini Apps in the WebUI, previously local-only), the port itself, and a rename that keeps thereader suite under
test/unitinstead of beside the module.packages/shared/src/miniapp-surface.tsis now a contiguous copy of the shipped file's leading part(shipped lines 1-964 of 1267): the start/page-open split,
detachedandpresentationRevision,the loopback token header, the composer block, and the whole agent block with its nine run events
and their mapping from runtime failure codes. The window block is the omitted tail.
isPlainRecordnine timesand the shipped file declares it inside the window block (shipped line 1156), so it is kept at the
seam between the copied part and the omission. It is the one local divergence a future copy has to
reconcile, and ADR 0020 now records it.
surface.windowaccepted andignored,
agentAccessandagentConcurrencyvalidated and preserved on the contribution so theagent service can enforce them when it lands. Both allowlists stay strict — an unknown top-level
key still fails as
MINIAPP_MANIFEST_SCHEMA_INVALID, and an unknown key besidesurface.windowstill fails as
MINIAPP_SURFACE_INVALID.nothing reads the agent fields yet.
strict superset of the old 54 lines but not a line-identical copy of them, and the omitted tail is
not purely window code.
Validation
pnpm typecheck— passedpnpm typecheck:webui— passed (server, client and test projects, plus the host-event catalogue check), rerun at the branch headpnpm run test:capabilities— 235 files, 5811 passed, 18 skippedpnpm build— passednode scripts/source-inventory.mjs --writethenpnpm check:source— 5451 files, passedpackages/local-runtime-v2/test/unit/plugin-system/miniapp-manifest.test.ts,registered in
test/vitest-suites.json: fails 13 of 16 cases against the previous reader, passes16 of 16 here
pnpm verifyin full, including thetest:webui-browserand release-package steps. Thechange is content-only and touches no client behaviour and no export path, so those gates are left
to CI.
Publication and contribution checks
release/public-source.json; new tests are declared intest/vitest-suites.jsonwhere applicable.Maintainer handoff
Publication scope or license changes (if any): none.
Shared-source port: not needed — every changed file is already published in this repository, and the
contract content comes from this repository's own shipped generation.