oficina / docs Public

Plan: the constraint is zero imports, not no-wasm-bindgen

Amended during execution. As written it could never have been satisfied
-- yrs enables fastrand's js feature unconditionally, so wasm-bindgen is
in the wasm32 graph of any crate using it. Zero imports is the property
actually required and is directly assertable.
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 91852995c23fb2a7aa5a4c71d4a8db6fd2e62c54 parent b6a5c09
1 file changed, +2 −1
  • docs/superpowers/plans/2026-08-30-rust-core-wire-compat.md +2 −1
diff --git a/docs/superpowers/plans/2026-08-30-rust-core-wire-compat.md b/docs/superpowers/plans/2026-08-30-rust-core-wire-compat.md
index 196452c..4673ab1 100644
--- a/docs/superpowers/plans/2026-08-30-rust-core-wire-compat.md
+++ b/docs/superpowers/plans/2026-08-30-rust-core-wire-compat.md
@@ -21,7 +21,8 @@ This is the load-bearing bet of the whole design, and revision 1 of the spec got
## Global Constraints
- **No cgo, ever.** `CGO_ENABLED=0` on every Go build and test command. A cgo dependency sneaking in is a bug, not a tradeoff.
-- **No wasm-bindgen, no `wasm-pack`.** Target is `wasm32-unknown-unknown` with `crate-type = ["cdylib"]` and `extern "C"` exports.
+- **The compiled wasm module must import nothing.** *(Amended during execution, 2026-08-30. This originally read "no wasm-bindgen, no wasm-pack" and was **untestable as written**: `yrs` unconditionally enables `fastrand`'s `js` feature, so wasm-bindgen is in the wasm32 dependency graph of any crate using it.)* The property actually required is that the module needs no JS host, and zero imports is that property, asserted by `core/tests/no_host_imports.rs`. Target stays `wasm32-unknown-unknown` with `crate-type = ["cdylib", "rlib"]` and `extern "C"` exports; `wasm-pack` is still never used.
+- **Never call `yrs::Doc::new()`.** It reaches `fastrand` for a random client ID, which is what pulls JS entropy. Always `Doc::with_client_id()` — an assigned client ID is what the server wants anyway. `fastrand` is also reachable from `yrs`'s observer paths, which is why the gate is a build-time assertion rather than a rule somebody remembers.
- **Fixtures are generated by the JS side and are the contract.** They are never edited to make a test pass. A rule change regenerates them in the same commit.
- **Pin exact versions.** No `*` or caret-only ranges in `Cargo.toml` or `package.json` for `yrs`/`yjs`.
- Commit after every task. Small commits, pushed.