# Experimental browser application contract

Preserve bundled original interfaces and exact assets; this source contract does not install a runtime.

# Browser application bundles — experimental source contract

This is an additive source and execution-evidence contract under development.
The exact reviewed Method Draw package has a private desktop install, editing
and SVG export path. This does not admit arbitrary browser applications or
make this runtime available through portable archives. Other repositories
still require their own review and working acceptance evidence.

The intended profile preserves a real built application's HTML, JavaScript,
CSS, fonts, images and optional single-thread WebAssembly, plus a small
Block-owned adapter. Original styling is the default. It does not rebuild the
application UI using StillMade controls. The shared host supplies navigation,
identity, storage authority, permissions and execution; application-specific
behavior remains in the bundle and its independently versioned adapter.

## Bundle identity and resources

`defineBrowserApplication` validates a detached `desktop-browser-application/1`
bundle. Every asset has a canonical relative path, MIME type, decoded byte count,
SHA-256 and canonical base64 payload. Entry HTML and adapter JavaScript must be
present. The contract rejects URL paths, path traversal, file/directory collisions,
case collisions, unsupported file metadata, invalid encoding and changed bytes.
`encodeBrowserApplicationFiles` accepts already-read regular-file bytes;
filesystem importers remain responsible for rejecting links and escaping paths.

Limits are explicit and independent of the older portable archive format. A
bundle can contain at most 2,048 assets, 64 MiB per asset and 128 MiB total decoded
bytes. Input, state and output messages remain bounded separately. Successful
validation proves byte integrity and schema conformance, not code safety, license
permission, dependency closure, build success or application behavior.

The first profile declares no ambient networking, workers, native services or
paid integration access. Single-thread WASM is an explicit requirement, not an
automatic permission. Arbitrary development servers, native Node modules,
service workers, threaded WASM and full-stack backends need distinct profiles
and verified host capabilities. Existing SDK restrictions are not removed.

Inspect compiled dependencies as well as asset extensions. For example, a
checked-in editor bundle may contain base64 WebAssembly or dynamically create
workers without shipping any `.wasm` file. The current asset/declaration check
does not prove those paths are absent. Admission must record which paths are
needed, and the selected runtime must enforce its CSP, target and resource
policy when code executes. A dead or explicitly unavailable feature is different
from a verified fallback. The current development Linux worker rejects declared
WASM and blocks worker creation; it does not establish general WASM support.

## Adapter lifecycle and completion

An adapter needs to receive meaningful typed inputs, restore host-scoped editable
state, checkpoint changes, export the actual result, cancel and dispose. Use
original application APIs and controls. Keep autosave separate from explicit
completion; mounting a UI or retaining the original input is not evidence of
the requested transformation.

`prepareBrowserApplicationMount` binds a mount request to the exact package,
bundle, input and state revision. A mount acknowledgement carries no outputs and
cannot pass execution validation.

`prepareBrowserApplicationExecution` additionally binds the named declared
operation. Interactive applications require an explicitly interactive host;
headless execution needs an implemented operation. The trusted host must issue
the completion receipt only after the actual operation, output checks and
current permission/state checks. `validateBrowserApplicationExecutionResult`
and the saved-record validator check those bindings; their result explicitly
keeps `independentlyVerified:false`. Arbitrary callers can fabricate JSON, so
these pure helpers do not authenticate evidence or authorize adoption.

`runBrowserApplication` requires an explicitly supplied trusted executor. It
never falls back to evaluating source in the host or treating a mounted page as
success. Cancellation and timeout signal the executor; actual process/resource
termination is the executor's responsibility and needs independent verification.

## Guest registration

`installBrowserApplicationGuest({target,operations,messageBytes})` is the
framework-neutral lifecycle dispatcher for a trusted bootstrap. It installs only
`target.stillmadeApplication.register(adapter)` and returns a separate controller
to that bootstrap. It does not install a runtime or grant host access.

The Block-owned adapter registers exactly these four methods once:

| Method | Adapter result |
| --- | --- |
| `mount({inputs,state,signal})` | Restore the original UI and return exactly `{mounted:true}`. |
| `serialize({signal})` | Return the versioned editable document as plain JSON. This is a snapshot, not output completion. |
| `execute({operation,inputs,stateRevision,signal})` | Run a declared operation and return its raw typed output map; the dispatcher adds the `{outputs}` envelope. |
| `dispose()` | Release adapter-owned resources. Return values are discarded. |

Use closures or explicitly bound functions when application methods depend on
their original receiver. The controller enforces mounting before serialization
or execution, one active call, exact mounted inputs, declared operation names,
bounded plain JSON, and rejection of guest receipt fields. Cancellation discards
late results and leaves the guest usable only for disposal. Disposal itself is
cooperative; a hung application must be terminated by the trusted host.

The dispatcher is self-contained for inclusion in a reviewed bootstrap. Its
JavaScript object checks are correctness checks inside an untrusted realm, not
security boundaries. The host must revalidate every message, own checkpoint
identity and UI-event sequencing, issue receipts, check current permissions,
persist revisions and enforce resource limits outside the guest. No account
token, filesystem access, native proxy or generic network function is exposed.

## Runtime gates still required

- Serve only exact verified bundle assets. Keep application sessions isolated
  from host origin, cookies, local files, native IPC, credentials and one another.
- Enforce navigation, external request and device denial. A sandboxed iframe,
  request interceptor or CSP alone does not establish complete egress denial.
- Keep the host responsive under infinite JavaScript/WASM loops and memory
  pressure. Resource and cancellation enforcement must live outside the guest.
- Scope persistence to account/project/placement and exact source. Shared state
  needs permission checks, revision conflicts, recovery and flush-on-completion;
  origin-global `localStorage` cannot establish that contract.
- Build in a disposable secret-free worker with pinned dependencies, bounded
  resources and no unrestricted network during source execution. Preserve
  licenses, binary assets and exact output identities.
- Run original UI operations and compare upstream/adapted exports. Then prove
  a real producer → application → consumer chain, save/reopen, two placements,
  cancellation, revocation, stale-result rejection and adversarial isolation.

Method Draw is being used to study the first complete static editor route.
Its remote fonts, global localStorage and SVG import behavior require explicit
adaptation; an original-page baseline is not a completed Block integration.

## Reproduce the reviewed package outside the repository

The downloadable SDK zip includes `packages/block-sdk/browser-application.js`
and `browser-application-execution.js`. The Method Draw source folder contains
its own pinned upstream bytes, adapter, source hashes and package builder. With
Node.js 22 or later, extract the SDK zip, place the complete Method Draw folder
at `blocks/repository/methoddraw` inside the extracted directory, and run:

```sh
node --input-type=module -e 'import {buildMethodDrawPackage} from "./blocks/repository/methoddraw/build-package.mjs"; import {digest} from "./packages/block-sdk/contracts.js"; const source=await buildMethodDrawPackage(); console.log(await digest(source));'
```

For the reviewed source and SDK 0.1.0 archive the digest is
`084ed75a82a66011344bcb609a12de018ccb4e20b828fabc2afef60399c5f6eb`.
This reproduces source packaging only. It does not execute the editor, grant
private installation, or show that a different GitHub repository is eligible.
