WAI Studio on the web: one front end, two hosts (the core in WebAssembly; wai dev at /_wai/), actions from the operation catalogue with a drift check #522
Loading…
Reference in a new issue
No description provided.
Delete branch "wai/studio-web"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
WAI Studio on the web, v1 (build order step 7, "Studio web at
/studio/and/_wai/"): one front end inwai/wai-studio/, Apache-2.0, with two hosts chosen when the page starts.studio-v1(WAI site repository) hosts it at/studio/.wai devat/_wai/on the origin it already serves on loopback; the core in WebAssembly does what a tab can, and the localwaithe rest, reached through the dev stack's own routes (/_wai/api/).Operation names are provisional until #506 lands. Studio reads the catalogue from
wai/catalogue/ops.jsononce it exists on main; until then fromwai/wai-studio/ops.pending.json, a byte-for-byte copy of #506's export at270be911a. When #506 merges I mergeorigin/main, delete the copy (the drift check fails until it is gone) and regenerate.The panels, and which host shows each
wai devrefines,derived_from,security), SPEC §4 verdict at this sink, receipts when the index is opened with itwai's ownwai inspectreportwai verifyrunswrapof any registered capabilitywaiholdsroom.show, join as a viewer (the room client in a frame), leave; a pre-call test of a relayservice.check,session.show, logs followedHow the actions are generated, and the drift check
scripts/actions.mjswritessrc/actions.generated.jsfrom the catalogue export (every operation: id, menu/item, palette name, summary, placement, effect, CLI, MCP tool, route, thenoun_verbcall name).src/bindings.jsbinds by hand the operations Studio runs: panel, and per hosttab/local/tab+local/page/ none.--checkfails on:wai devLOCAL_OPS entry whose id the catalogue lacks);clientorbothwith no binding (the catalogue has no "browser" placement; a page is a client of the service it names, soclientandbothare what a browser runs);noun_verb; a core call or LOCAL_OPS entry bound to another host; an op id in the source (data-op,op:,.op() that names no operation.What it found on this tree: nothing. 92 operations read (
ops.pending.json), 15 actions bound: 13 run on a host (envelope.inspect,envelope.unwrap,registry.list,receipt.verify,media.decode,media.encode,envelope.wrap,room.show,room.join,room.leave,dev.start,service.check,session.show), 2 browser-placed operations bound to the command line (http.load,receipt.fetch). The other 77 are in the palette with where they run, from the catalogue.The site branch
studio-v1in the WAI site repository (pushed, not merged, not deployed), head5803bb4:/studio/mounts Studio's hosted host on the site's own room service, relay, room client and Quantum Studio;scripts/sync-wai-studio.mjsbuilds Studio at one commit intopublic/studio/the waysync-room.mjscopies the room client (strict, each file's SHA-256 inBUILD.json), withroom.htmlthe room client's own page at the commit/roomcomes from (noindex: the frame's alone); the core is astudiorow ofscripts/wasm-pkgs.tsv, built reproducibly bybuild-wasm-pkg.sh(no local path in it; the same bytes froma745de9baand1f1d5f0ad). Synced at1f1d5f0ad; re-sync at the merge commit before a deploy. On the Studio host:npm run build(routes, public text with the name denylist, device names) ok;e2e/studio.e2e.mjsevery check passed;e2e/pages.e2e.mjs /studio/ /quantum-studio/307 passed, 0 failed. Its Quantum axe check leaves out#qs-critique, and says so: the site's Quantum Studio build (defc8c6f8) names it without a role; this PR names it a group (quantum-studio/src/critique-view.js), and the site has that when it next syncs Quantum Studio.Decisions
ws-in place ofqs-), and the site's design tokens copied as Quantum Studio copies them. No new visual idiom.wai/wai-studio/core(wai-studio-core), not a feature ofwai-web: thewaicrate withfloor,httpandreceipt_claimsonly, bound for WebAssembly (2 MB). Each binding is namednoun_verbafter its operation and answers the command line's JSON envelope (envelope/1). The command line's inspect, wrap and verify wording lives in thewaibinary, not the library, so the core states the same checks (dispatch, pins, roles, candidates, framing,check_index) in its own JSON; folding the binary's text onto shared library functions waits for #506, which rewriteswai.rs.clientorboth.wai.ops/1has no browser placement; a page is a client of the service it names. Today those arehttp.load,receipt.fetch,room.join,room.leave,session.show. The first two are boundelsewhere: cli(the palette sayswai http bench/wai http receipts); the check holds that the catalogue gives them a command line./_wai/api/(state,log,sessions,op/<id>), on the originwai devalready serves: no listener of its own. An operation runs thiswai(its current executable) on the bytes the page sends, in.wai/dev/studio/op-*, removed after; one at a time, 120 s, 64 MiB in and out. Every API request must name the origin as its Host (no DNS rebinding), carryX-WAI-Studio: 1(a cross-origin page cannot without a preflight this origin never answers), and state no other Origin orSec-Fetch-Site. Until #506 the localwaiprints text, so the page shows its report; after it,--jsongives the envelope.wai devflag. Studio's files come from$WAI_STUDIOorshare/wai/studiobeside the binary. A--studio DIRflag would changedev.start's catalogue entry while #506 holds it./room/underwai dev; on the site/studio/room.html, the client's ownindex.htmlat the commit/roomcomes from, its script pointed at/room/room-client.js), entered by its own Watch button once it reportsidle, left by its Leave. Nothing of the client is rewritten.room.testis in the study but not in #506's table, and an action with no operation fails the drift check. Addroom.test(placementclient) to the catalogue and the check will then require Studio to bind it.#studiomount element (data-embedded) and imports its module, which mounts itself. On the site it is the/quantum-studio/build; underwai dev, Studio's build carries it (build.mjs --quantum).#qs-critique) carriedaria-labelwith no role, which axe refuses (aria-prohibited-attr); it is nowrole="group". Nothing else of it is touched.no publisher within RENDEZVOUS_TIMEOUT. The e2e puts a publisher in the room first (the room page in Chromium with its fake camera and microphone), and Studio shows the room client's own error when a join fails.wai dev --checkchecks Studio too (the page at/_wai/, and the stack's state through the API) when its files are found.waicrate with different features must not share a cargo target directory (on the Studio hostwai's bin linked another workspace'slibwaiand failed;e2e/run.shgives each workspace its own); and the floor's zstd is C, so on macOS its wasm32 archive needsllvm-ar(AR_wasm32_unknown_unknown): macOS'sarwrites an archive with no index the linker can read.Checks
1f1d5f0ad(the head's code; the head changes one job name)bash wai/wai-studio/e2e/run.sh --browsers chromium,firefox27a6e7796(the head)STUDIO_PHASES=build bash wai/wai-studio/e2e/run.sh, thenSTUDIO_PHASES=node … --browsers webkitin the imagenode --test --test-reporter=tap test/*.test.mjswithWAI_STUDIO_CORE_PKG# pass 19,# fail 0,# skipped 0node scripts/actions.mjs --checkStudio's actions hold to the cataloguecd wai/wai-studio/core && cargo test --lockedcargo clippy --locked --all-targets -- -D warnings;--target wasm32-unknown-unknowncargo metadata --locked --offline --format-version 1wai-rs/Cargo.lock: every version is one wai-rs already locks)waibinary tests,cli_studio,cli_dx,floorcargo test --locked --no-default-features --features quickstart --bin wai --test cli_studio --test cli_dx --test floorwaifilescargo clippy --locked --no-default-features --features quickstart --bin wai --test cli_studio; and--no-default-features --bin waidx/dev.rs,dx/studio.rs,tests/cli_studio.rswai-rslockcargo metadata --locked --offlinecheck-tests-in-ci.py,check-workflow-concurrency.sh,check-spec-refs.py,check-wai-section-refs.py,check-no-vanity-metrics.sh,test-public-text-checks.sh,check-comparative-prose.sh,check-orphan-sources.py, YAML parse of every workflowcheck-public-names.shon every changed file; commit messages and this body against the same patternsorigin/mainwfsteps.py HEAD <base> HEAD^1 HEAD^2wai-conformance.yml, which both sides changed; resolved as the union (--test cli_fleet --test cli_studio), diff against main is exactly this PR's linesFalsifications (committed first; each mutation an explicit edit whose anchor matched once, run in an rb checkout)
Drift check (Studio host,
node scripts/actions.mjs --check; unmutated exit 0, restored exit 0):envelope.inspectbound asenvelope.inspektroom.joinremoved fromops.pending.jsonroom.leaveunboundenvelope_inspectrenamedenvelope_read"menu":"Rooms")wai dev's LOCAL_OPS runsmedia.decodeasmedia.unpack/_wai/and loopback (Framework,cargo test --test cli_studio; unmutated ok, restored ok):wai dev's origin bound to0.0.0.00.0.0.0/_wai/not routed to StudioNot built, and why
share/wai/studio), sowai devfrom the quickstart archive serves/_wai/only once Studio's files are given (WAI_STUDIO). The archive (wai/quickstart/build.sh,build-web.sh,wai-release.yml) is step 7's bundle, which #506 also edits; building the core into it needs Node and wasm-bindgen in the release job.room.test,wai inspect --jsonand--studio DIRwait on #506 (see Decisions).webkit · linuxjob.studio-v1is pushed for review (WAI site repository); its/studio/serves this PR's head and must be re-synced at the merge commit before a deploy.🤖 Generated with Claude Code