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:
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.