Repository navigation
Description
Summary
Design the output-safety contract beyond plain terminal text: HTML/JS-bearing output modes, safe-plain rendering as a user choice, and servers ingesting arbitrary data without executing it. This is the follow-on #3455's own record flags as not covered.
Motivation
#3455 (closed, sub-issues 4/4) settled the plain-output contract: a value cannot act on the terminal — one Cf/Cc set, escape-at-render, printer-not-ingest. But the answers review (PR #5707, §10) records three extensions Drew raised that the filed contract explicitly does not cover, plus one open question the design doc itself left filed-nowhere:
"Explicitly NOT covered by #3455: ANSI/OSC terminal sequences — 'no filed instance,' listed in the design doc's open questions." And Drew's extensions: "HTML/JS-bearing output modes that some applications require; safe-plain rendering offered as a user choice; servers ingesting arbitrary data without executing it" — "flagged as a candidate follow-on design, not as part of #3455."
This issue is that follow-on. The risk shape is the same one #3455 named — a value acts on its consumer — with the consumer changed: a browser DOM, a rendering mode the user picked, or a server process that stores and forwards data it must never execute.
Sketch
- HTML/JS-bearing output modes: which ID surfaces may emit markup at all (programs-as-websites, id(serve): design — how does a program appear as a website? (program-only ports, mixed ports, path mounts) #2146/id: design: Markup & styling model for programs-as-websites — semantic markup, style-override mapping #5679, is the obvious one), and under what contract a data value may enter markup — escaping contexts (text, attribute, URL, script), the equivalent of Design: a value cannot act on the terminal — one format-character (Cf) contract for pkgs/id plain output #3455's "one shared set" for markup contexts, and who owns the set.
- Safe-plain as a user choice: rendering offered as a user-selected mode (plain-safe vs rich) per surface — what the choice means, its default, and whether it is per-client, per-world, or per-field; the plain mode's contract is Design: a value cannot act on the terminal — one format-character (Cf) contract for pkgs/id plain output #3455's, this design covers the choice and the rich side.
- Ingest without execution: servers (and bridges/relays) that ingest arbitrary data — the guarantees that stored data is never evaluated anywhere downstream: no template evaluation, no markup rendering without the contract above, no terminal emission without Design: a value cannot act on the terminal — one format-character (Cf) contract for pkgs/id plain output #3455 — stated as one ingest-side rule composing the two render-side contracts.
- ANSI/OSC: disposition the open question — are terminal escape sequences a Design: a value cannot act on the terminal — one format-character (Cf) contract for pkgs/id plain output #3455-class problem (values acting on the terminal through a second channel), and if so which surfaces refuse, escape, or pass them?
Open questions
- Does the markup contract live beside the Cf set as a sibling shared definition, or is one "output safety" module the home for both?
- Is safe-plain a rendering mode or a data classification (sensitivity-style, per id: design: Querying local and remote ID servers v1 #5675's model)?
- Which existing surfaces already emit markup with data values in them today — the audit list is a deliverable.
Relations
Parent: epic #2056. Relations: #3455 (the plain contract this extends; its open questions and Drew's extensions are the source), #2146 + #5679 (markup-emitting surfaces), #5675 (classification model), #3231 (receipt-side sibling: values validated as strictly as built — this is the emission-side counterpart). Filed in the 2026-11-04 gap pass (WS-F).
Activity
developing-today commentedon Nov 5, 2026
CODE-1468
developing-today commentedon Nov 5, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 5, 2026
🤖 Agent note · state: handed off
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off
85 remaining items
dezren39 commentedon Nov 6, 2026
🤖 Agent note · handed off
opencode); claimant launches the bound opencode session. Issue id: design: output safety beyond plain text — HTML/JS output modes, safe-plain as a user choice, ingest without execution (follow-on to #3455) #5785 re-verified OPEN with no hard-stop labels and no open PR this shift. Attempts 4/6.dezren39 commentedon Nov 6, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 6, 2026
Triage outcome — task 10188 (2026-11-06)
Verdict: #5785 is a valid, live design/audit follow-on, not a duplicate or a currently demonstrated runtime bug. Revalidated OPEN at current
origin/main2871969537; no PR or decision record for #5785 was found. No hard-stop labels are present. Keep this issue open; no code-fix packet is justified before the security contract is settled.Current-main evidence and boundaries
pkgs/id/src/commands/text.rs:37-69,80-82(Cc, U+2028/U+2029 and shared Cf handling; affected fields are escaped). It leaves--jsonand general ingest validation outside scope (doc/2026-11-01_design_id3455.md:121-153,239-249).doc/2026-11-01_design_id2146.md:34,68,84specify trusted text/screen output, not guest-authored HTML/CSS/JS. Current clients use text-only sinks (pkgs/id/web/src/world.ts:261-264,pkgs/id/web/src/world-surface.ts:638-642,739-751); templates escape the world name (pkgs/id/src/web/templates.rs:1038-1055). Open id: design: Markup & styling model for programs-as-websites — semantic markup, style-override mapping #5679 proposes raw HTML/CSS and leaves mixing/sanitization unsettled, so this boundary must be reconciled before that expansion is implemented.pkgs/id/src/web/routes.rs:891-938,993-1014). Markdown preserves inline HTML as source, while the editor represents it as inert text (pkgs/id/src/web/markdown.rs:92,3104-3118;pkgs/id/web/src/editor.ts:335-355).ContentMode::Plainis an editor mode, not a safe-rendering toggle (pkgs/id/src/web/content_mode.rs:8-49).routes.rs:1985-2016,2064-2073); program uploads are intentionally compiled/run in the import-free Wasmtime sandbox (templates.rs:891-903). Design: a signed artifact is validated as strictly as it is built — one receipt contract for pkgs/id artifacts #3231's signed-artifact receipt checks are not a universal no-evaluation guarantee. Keep confidentiality classification (id: design: Querying local and remote ID servers v1 #5675) distinct from output encoding and distinguish passive data from code a user explicitly installs/runs.pkgs/id/src/world_ssh.rs:1842-1853,3078-3098;pkgs/id/crates/id-core/src/world_presentation.rs:622-650,710-740,1236-1272), but the policy question remains open.Bounded design path and ordering
Keep #5785 a source-to-sink design/audit, not a broad sanitizer implementation. Inventory server-owned templates, stored Markdown/blob downloads, world text/screen output, and explicitly executable program inputs. Settle context-specific markup rules (text/attribute/URL/script), authored markup versus runtime data, safe-plain's meaning/default/scope, inert passive ingestion versus explicit execution, and an evidence-based ANSI/OSC disposition.
Coordinate the security contract with the foundational vocabulary designs #5849/#5850. Resolve its compatibility with #5679 before implementing target mappings #5851–#5853; per-target customization and the conformance pipeline (#5854/#5855) follow those decisions. No access or Drew-only decision blocks this design stage. No additional follow-up task is needed yet; split implementation packets only after concrete gaps are established.
🤖 Agent note · triaged