oficina / docs Public

Spec: add the zero-host-imports gate, found by executing plan 1

Task 1's review found wasm-bindgen in the wasm32 dependency graph via
yrs -> fastrand("js") -> getrandom("wasm_js"). yrs enables that feature
unconditionally, so "no wasm-bindgen in the graph" is untestable while
using yrs -- the constraint as written could never have been satisfied.

The property we actually need is that the module requires no JS host,
and that is directly checkable: zero imports. A dependency that is never
called is dead-stripped and harmless; one that is called shows up as an
import and fails the gate.

The corollary is that Doc::new() must never be called, since it reaches
fastrand for a random client ID. Doc::with_client_id() is what an
assigned server-side client ID wants anyway. fastrand is also reachable
from yrs's observer paths -- which is the argument for a build-time
assertion over a rule, because I cannot enumerate the paths.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011F5CivVm4CmL9ByfSSAaXA
Paul Campbell pushed by paul@keymail.dev 37f108a3532f4e89674e397712214e453ff70d37 parent f5a1202
1 file changed, +15 −0
  • docs/superpowers/specs/2026-08-30-docs-design.md +15 −0

No CI script — run details

diff --git a/docs/superpowers/specs/2026-08-30-docs-design.md b/docs/superpowers/specs/2026-08-30-docs-design.md
index 2da9a67..370a3fc 100644
--- a/docs/superpowers/specs/2026-08-30-docs-design.md
+++ b/docs/superpowers/specs/2026-08-30-docs-design.md
@@ -696,6 +696,21 @@ Corrected.
- **Wire compatibility:** our Rust `y-crdt` updates are applied by upstream JS
`yjs` and vice versa, against checked-in fixtures generated by the JS side.
This is the CRDT half of §0 and the fixtures are the contract.
+- **Zero host imports:** the compiled wasm module must import nothing.
+ *(Added 2026-08-30, from executing plan 1 — the review found `wasm-bindgen`
+ in the wasm32 dependency graph via `yrs → fastrand("js") →
+ getrandom("wasm_js")`.)* "No wasm-bindgen in the dependency graph" turned
+ out to be **untestable while using `yrs`**, which enables that feature
+ unconditionally. The property actually required is that the module needs no
+ JS host, and that is directly checkable: zero imports. A dependency that is
+ never called is dead-stripped and harmless; one that is called appears as an
+ import and fails the gate.
+ The corollary, which the gate enforces rather than trusts: **never call
+ `yrs::Doc::new()`** — it reaches `fastrand` for a random client ID, which is
+ what would pull JS entropy. Always `Doc::with_client_id()`, which is what an
+ assigned server-side client ID wants anyway. `fastrand` is also reached from
+ `yrs`'s observer paths, which is precisely why this is a build-time
+ assertion rather than a rule somebody remembers.
- **Layout agreement:** a browser drive renders fixture documents and asserts
the DOM's actual page-break positions match the engine's computed ones. This
is the gate revision 1 lacked — its conformance test compared wazero to a