Y.js POC Deployment Guide¶
The 3 Y.js + WebRTC POC tools are the only parts of Nexus SecOps that load external runtime dependencies. Everything else is zero-dependency, vendor-self-hosted. These POCs document the exception and the operational discipline required to keep them shippable.
Tools covered¶
- Purple Team Arena POC — real-time whiteboard + threat board + presence
- Peer Review POC — collaborative artifact review with severity-tagged comments + sign-offs
- Team Leaderboards POC — real-time multi-user leaderboard reading sibling-tool localStorage
Pinned dependencies (s53 verified)¶
| Package | Pinned version | URL | SRI hash |
|---|---|---|---|
| yjs | 13.6.18 | https://cdn.jsdelivr.net/npm/yjs@13.6.18/dist/yjs.mjs | sha384-ghlZMZ/j8iYg2QKKfDUo2/h7LTtqgqEDJZLR58Aha3XZ9l4K/MTy+y2mTTbKNPa9 |
| y-webrtc | 10.3.0 | https://cdn.jsdelivr.net/npm/y-webrtc@10.3.0/+esm | sha384-RKwQKt46wors3na9Q6Qb84Zjf8xvNiTF3T7ntMTLvRg/Kt+2GdH7owP4oiDhUBXn |
Why /+esm for y-webrtc: y-webrtc@10.3.0 ships only CJS (/dist/y-webrtc.cjs), not ESM. The pinned URL /dist/y-webrtc.mjs returns HTTP 404 — that file does not exist. jsdelivr's /+esm path auto-converts CJS to a minimal ESM wrapper. This is documented at https://www.jsdelivr.com/esm. Switching y-webrtc versions to one that ships native ESM (if released) lets you go back to a static /dist/y-webrtc.mjs path.
Cloudflare _headers CSP overrides (s53)¶
The site's default CSP (in /* block of docs/_headers) does not allow WebSocket connections to the y-webrtc default signaling servers. Per-route overrides relax CSP only for the 3 Y.js POCs:
/tools/purple-team-arena-poc.html
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' wss://signaling.yjs.dev wss://y-webrtc-signaling-eu.herokuapp.com wss://y-webrtc-signaling-us.herokuapp.com stun:stun.l.google.com:19302; frame-src 'none'
/tools/peer-review-poc.html
Content-Security-Policy: ... (same connect-src)
/tools/team-leaderboards-poc.html
Content-Security-Policy: ... (same connect-src)
The rest of the site keeps the stricter default CSP. Granular per-route override avoids relaxing posture for the whole site.
Manual test checklist (pre-deploy)¶
Open the deployed site (or mkdocs serve locally) and verify each of the 3 POCs:
- Resource loading
- Open DevTools Network tab
- Load the POC page
- Confirm both
yjs.mjsandy-webrtc/+esmrequests return 200 - Confirm SRI verification passes (no console error like "Failed to find a valid digest")
-
Confirm CSP allows the script-src + connect-src (no console CSP violation reports)
-
Real-time sync (Arena + Peer Review)
- Open the same room in 2 browser tabs (or 2 different browsers)
- Make changes in tab A; verify they appear in tab B within ~1-2 seconds
-
Verify presence indicator shows the other peer
-
localStorage cross-tool reads (Leaderboards only)
- Open Skill Mastery Map; mark a few concepts mastered
- Open Daily Practice; review a few cards
- Open Skill Portfolio; issue a badge if eligible
-
Open Team Leaderboards; verify your stats appear in the local-stats panel
-
Honest-framing UX
- Confirm each POC's top-of-page warning admonitions are visible
- Confirm the "what this POC does NOT do" lists are present at the bottom
Regenerating SRI hashes¶
Hashes change when the upstream package version changes (i.e., when bumping yjs@13.6.18 to a newer version). To regenerate:
python scripts/regenerate_sri_hashes.py # print only
python scripts/regenerate_sri_hashes.py --update # in-place patch the 3 POCs
Verification after --update: the script greps for PLACEHOLDER strings in the 3 POC HTML files and exits non-zero if any survive.
The hashes are deterministic for any given pinned version — anyone running the script later against the same versions will get the same SRI strings.
Pre-merge checklist for any future Y.js dep bump¶
When bumping yjs or y-webrtc to a newer version:
- Update version constants in all 3 POC HTML files:
YJS_URLinpurple-team-arena-poc.html,peer-review-poc.html,team-leaderboards-poc.htmlYWEBRTC_URLin same 3 files- In-page documentation comments mentioning the pinned version
- Verify the URL pattern still works for the new version. y-webrtc may eventually ship native ESM and the
/dist/y-webrtc.mjspath may become valid. yjs has shipped ESM since 13.x. - Update
MODULESdict inscripts/regenerate_sri_hashes.py - Run
python scripts/regenerate_sri_hashes.py --update - Verify the script reports both hashes computed + zero PLACEHOLDER survivors
- Run strict build
python -m mkdocs build --strict - Manual test the POCs locally per the checklist above (especially Network tab for SRI verification + CSP allow)
- Git commit with both the version bump and the SRI hash update in the same commit (atomic)
Honest limitations of the POCs (carried forward)¶
These are documented in each POC's "what this POC does NOT do" list, restated here as a deployment-time reminder:
- Public signaling servers: room name leaks plaintext to the y-webrtc default signaling endpoints (
signaling.yjs.dev,*.herokuapp.com). For private use, self-host signaling. - No persistence: state is ephemeral and lost when the last peer leaves. For persistence, integrate
y-leveldbory-indexeddb. - No authentication: anyone with the room name joins. For real use, gate behind OAuth or a shared-secret signaling layer.
- No NAT traversal beyond STUN: symmetric NAT / strict corporate firewalls will fail. Add TURN servers for production.
- No moderation: no kick, no rate-limit, no content filter. CRDT growth is unbounded.
- Public-CDN dependency: if
cdn.jsdelivr.netis down or the pinned version is yanked, the POCs fail. For high-availability, mirror the modules to your own CDN or self-host them.
Deployment status (as of s53)¶
- ✅ Real SRI hashes applied (deterministic)
- ✅ Per-route CSP overrides in
docs/_headers - ✅ y-webrtc URL bug fixed (switched to
/+esm) - ✅ Strict build passing
- ⏳ End-to-end manual test in production (requires deployed instance + 2 browsers)
- ⏳ Self-hosted signaling decision (current default = public servers)
References¶
- Y.js: https://github.com/yjs/yjs
- y-webrtc: https://github.com/yjs/y-webrtc
- Subresource Integrity (W3C): https://www.w3.org/TR/SRI/
- jsdelivr
/+esmdocumentation: https://www.jsdelivr.com/esm - Cloudflare Pages
_headers: https://developers.cloudflare.com/pages/configuration/headers/ - WebSocket signaling default endpoints: defined in
y-webrtcsource (not Nexus-controlled)