# Mission: MessageChannel

## Why
A private two-port pipe should be a deliberate tool — not “another way to spell `window.postMessage`” and not “spin up BroadcastChannel when you only need two ends you can hand off.” After the window-addressing track (#15), this track owns the entangled-port surface so iframe, worker, and multi-frame designs can mint a pair, move one end, and talk without origin checks on every message.

## Success looks like
- Mint `new MessageChannel()`, keep `port1`, transfer `port2` into another context, and send structured-cloned messages both ways on the ports.
- Choose MessageChannel over addressing a window, over a named BroadcastChannel, over a dedicated worker’s implicit port, and over a same-context function call — and reject it when those alternatives already fit.
- Use `start()` vs `onmessage`, `close()`, and transfer-neuter correctly; catch `DataCloneError` when a port is cloned instead of transferred.
- Treat a port as a capability (“who you transferred it to”), not as a window with an `origin`.

## Constraints
- Decision fluency plus light hands-on, not a multiplayer architecture or SharedArrayBuffer course.
- Prefer modern Chromium + Firefox + Safari. Note `start()` and transfer-neuter wherever they change the design default.
- Structured clone (#13) owns the algorithm; this track only cares that `MessagePort` is transfer-only.
- Window/iframe `postMessage` + `targetOrigin` (#15) is out of this track except as the *delivery vehicle* that carries a port.

## Out of scope
- Re-teaching origin checks, `event.source`, and “who can hear a window message”
- The structured-clone type matrix and `structuredClone()` itself
- BroadcastChannel’s named same-origin bus
- SharedArrayBuffer / Atomics
- Production multiplayer or service-mesh designs
