This document owns code-chan's trust boundaries, the bounded data shapes that
cross them, and the reporting path. AGENTS.md owns the policy that forbids
sending workspace data to the device; this document records which bounded shapes
were actually accepted and what each boundary currently admits.
Statements here describe current implementation. Where a limit or message shape
is named, the owning document — PROTOCOL.md for message semantics,
HOST_BRIDGE.md for host behavior — remains authoritative.
code-chan runs entirely on one machine and one USB cable. It has no server, no account, no telemetry, and no network listener reachable from outside the host.
The assets worth protecting are the developer's workspace contents — prompts, source, command strings, file paths, conversation history — and the authority to approve a coding agent's tool use. The boundaries below exist to keep the first away from the device and to keep the second correlated to a real request.
An attacker who already runs code as the developer's user account is outside this model. Such an attacker can read the workspace directly and does not need code-chan; the loopback listener grants no authority the attacker lacks.
HOST_BRIDGE.md owns the ingress behavior and the listener-ownership rule. The
security-relevant shape of it is that the listener binds the loopback interface
explicitly, so it is not reachable from another host, and that the ingress
accepts POST only, on an allowlist of exact paths, under a body cap enforced
while the body streams, admitting a body only if it decodes as strict UTF-8 and
parses to a JSON object.
The endpoint carries no authentication. Any process running as the same user can post to it, and that is the accepted boundary: such a process already has the developer's privileges. What the endpoint does not offer is an escalation — a posted decision is admitted only under the correlation rules below.
HOST_BRIDGE.md owns what the relay strips and what the host may send;
PROTOCOL.md owns the message vocabulary and states that the protocol never
carries the raw command, prompt, file path, source text, or tool-input object.
Neither rule is restated here.
What this document adds is why the rule is structural rather than a discipline that could lapse. The vocabulary offers nowhere to put such content: outside enums, bounded counts, usage percentages, and identifiers, the only free-text fields in the whole contract are the two optional labels on a decision request, and one of them is populated by no caller at all. No producer adapter reads a tool's input, so no source for the content exists even where a field does. A regression would therefore have to add both a field and a reader, which the contract check and the protocol generator make visible rather than silent.
Identifiers on the wire derive from the coding agent's own opaque ids, not from content, so a captured transcript of the serial link reveals which turn was running and never what it was doing.
The optional status line is the one path that receives a payload code-chan does not define. Claude Code invokes the status-line command with a session JSON object on standard input; the relay accepts up to 256 KiB of it and treats every field it did not ask for as data to be discarded.
The relay reduces that object to {sessionId, promptId, usage} — two opaque ids
and up to three integers in 0..100 — before anything leaves the local
command. It reads only the version, the two ids, and the usage metrics.
Whatever else the object carries is never sent, logged, or retained, so the
boundary holds without depending on which fields the coding agent includes.
The host does not trust that reduction. At ingress it independently re-validates the exact shape, rejecting any object whose key set differs from the three expected keys or whose metrics are not integers in range.
The device returns acknowledgements, runtime status, touch events, and decisions. It reports nothing about its own display or body state.
A decision is admitted only when the coordinator is running a turn, the turn id matches the running turn, and the request id matches the permission request currently pending. A decision for a stale, absent, or mismatched request is refused. Body touch is telemetry: it cannot wake the screen, select a foreground session, or answer a permission request.
A permission timeout leaves the coding agent's own permission flow in control. The device never approves by default and never approves by inaction.
The host bridge has zero runtime dependencies. The only installed packages
are development-time: typescript, @types/node, and undici-types.
npm audit --omit=dev reports no vulnerabilities.
The firmware links no network stack. It has no Wi-Fi, Bluetooth, OTA, or TLS code path, and no credential of any kind is compiled into it. Its only external interface is the USB serial connection.
.gitignore excludes .env*, *.pem, *.key, and the .WORK/ working
directory, which holds plans, progress notes, and hardware identifiers such as
the development board's serial number.
Tracked hook configuration resolves paths at run time — $CLAUDE_PROJECT_DIR in
.claude/settings.json and git rev-parse --show-toplevel in
.codex/hooks.json — so no contributor's absolute path is committed. The
personal status-line installation is written to the ignored
.claude/settings.local.json.
docs/README.md states the rule this section implements: public documents stay
free of credentials, private captures, local absolute paths, and user-specific
configuration.
Report suspected vulnerabilities through a GitHub security advisory on
stelis-dev/code-chan rather than a public issue. This is a personal project
with no service component and no security SLA; expect best-effort response.
- code-chan is not a security control. It reports agent activity and relays one explicit permission choice; it does not sandbox, audit, or restrict what a coding agent does.
- The loopback endpoint is not an authentication boundary between processes on the same machine, and no future feature should treat it as one.
- No remote or cross-host operation is supported. Should a wireless transport be added, its authentication and confidentiality must be decided in this document before the transport is implemented.