62 lines
3.1 KiB
Markdown
62 lines
3.1 KiB
Markdown
# Browser displays
|
|||
|
|
|
||
|
|
This package owns ordinary graph transactions for browser enrollment, assignment
|
||
|
|
and reported mount state. Studio supplies the host adapter; the package contains
|
||
|
|
no browser heartbeat, DOM code or private storage API.
|
||
|
|
|
||
|
|
A workspace entry conforms to `WebStudioDisplayDirectory`. Its conformance owns
|
||
|
|
an enrollment edge, and `enroll({nonce,label})` returns the same target for that
|
||
|
|
nonce. Each directory currently permits 128 targets and rejects further enrollment
|
||
|
|
explicitly. This is a bounded prototype, not an automatic device inventory GC.
|
||
|
|
|
||
|
|
`WebStudioDisplayTarget.assign` accepts an optional subject/presentation pair.
|
||
|
|
The subject conforms to `WebStudioPresentable`, whose `canPresent` validates the
|
||
|
|
selected registered presentation. This role does not require Canvas or placements;
|
||
|
|
the example workspace adapters forward their existing presentation check. Named
|
||
|
|
presentations have checked subject-only module contracts; callbacks cannot be
|
||
|
|
stored in assignments. The target's subject is a graph edge, not a string ID in
|
||
|
|
JSON. Changing the edge and desired generation is one transaction.
|
||
|
|
|
||
|
|
Assignments and observed outcomes are durable. `acknowledge` accepts a generation,
|
||
|
|
monotonic report sequence, status (`mounted`, `failed`, `empty`) and bounded error.
|
||
|
|
Old generations and reordered reports return false without modifying state.
|
||
|
|
Reported success describes a client mount; it is not a claim of trusted execution.
|
||
|
|
|
||
|
|
The browser adapter uses a per-tab nonce and Web Lock. Duplicated tabs get distinct
|
||
|
|
nonces; reloading resumes enrollment. Enrollment is a host startup/user action,
|
||
|
|
never business-object creation from a component render. Multiple displays may
|
||
|
|
mount the same subject. Losing the connection does not clear its desired state.
|
||
|
|
|
||
|
|
Studio's authenticated presence adapter validates target references against Camino
|
||
|
|
before issuing an opaque connection lease. Leases expire after 45 seconds; recent
|
||
|
|
connection observations remain for at most ten minutes, with a 256-record cap.
|
||
|
|
A target ID is not a credential. There is no persistent heartbeat history.
|
||
|
|
|
||
|
|
## Headless calls
|
||
|
|
|
||
|
|
A headless session uses the same generated descriptors and public operations as
|
||
|
|
Studio. The caller supplies normal workspace authorization when opening its
|
||
|
|
session; graph references alone grant no access.
|
||
|
|
|
||
|
|
```ts
|
||
|
|
const directory = await session.acquire(
|
||
|
|
{ enroll: interfaces.WebStudioDisplayDirectory.enroll },
|
||
|
|
session.bootstrap.entry,
|
||
|
|
);
|
||
|
|
const enrollment = await directory.enroll.call({
|
||
|
|
nonce: savedClientNonce,
|
||
|
|
label: "Preview display",
|
||
|
|
}).settled;
|
||
|
|
if (enrollment.status !== "accepted") throw Error(enrollment.status);
|
||
|
|
const target = await session.acquire(interfaces.WebStudioDisplayTarget, enrollment.value);
|
||
|
|
const result = await target.assign.call({
|
||
|
|
subject: presentableSubject,
|
||
|
|
presentation: "presentation:studio:canvas",
|
||
|
|
}).settled;
|
||
|
|
```
|
||
|
|
|
||
|
|
`tools/local-first/studio-session.test.mjs` is the executable example, including
|
||
|
|
reference rejection and stale-report tests. `package.nix` selects the server-only
|
||
|
|
TypeScript artifact. Native fields and relationships remain queryable in browser
|
||
|
|
replicas without bundling mutation implementations there.
|