Skip to content

design: TDD 0070 rev 2 — render isolation enforced by the browser - #193

Merged
cahenesy merged 1 commit into
masterfrom
docs/design/0070-render-isolation
Oct 7, 2026
Merged

cahenesy merged 1 commit into
masterfrom
docs/design/0070-render-isolation

Conversation

@cahenesy

@cahenesy cahenesy commented Oct 7, 2026

Copy link
Copy Markdown
Owner

/build-tdds run 20261006-220142 halted three times on the same class:
an out-of-repo local file baked into a committed PNG through the
file:// render. Each regex-scanner fix was bypassed by the next gate:

  • script navigation;
  • <!--> before the doctype;
  • unquoted, backtick and NBSP attribute values;
  • base64 data:text/css;
  • url() in tokens.css or another CSS file.

Rev 2 moves the boundary into the browser:

  • render copies docs/ux/ to a private mkdtemp dir outside the repo,
    after a whole-tree symlink check and a re-check of the copy;
  • every HTML file starts with plus a CSP meta at byte 0;
  • a loopback-only ThreadingHTTPServer serves the copy, with the same CSP
    as a header on every response;
  • Chrome loads http://127.0.0.1:/..., with a dead proxy that
    excludes other loopback ports.
    An http page cannot load file: URLs, absolute and ../ paths 404 on a
    server that holds only the copy, and default-src 'self' data: blocks
    everything else. The scan stays as defence in depth.

Also in this revision:

  • capture leaves out the proxy flags;
  • the scanner rules are written down as built;
  • the probe-matrix obs 10b requires the CSS and base64 vectors to pass
    validate and still show 0 canary pixels;
  • honest per-file diff estimates with exceptions;
  • tests/implement-gate.test.sh is declared;
  • a revision record.

Design critique (design-reviewer, fresh worker)

DESIGN_REVIEW: PASS. The isolation was judged sound point by point
(file: from http, translate_path, CSP 'self', the bypass list failing
closed, port binding). All 9 minor findings and nits were folded in
after the PASS:

  • the copy lives outside the repo;
  • the capture proxy flags are dropped;
  • CSP is sent as an HTTP header on every response;
  • the symlink scope and scanner rules are written down;
  • 10b is strengthened;
  • obs 7 now has an observable;
  • the FR-94 trace is corrected;
  • the revision record is moved;
  • the override count is corrected.

Mechanical pre-pass

Structural lint is clean.
PRECHECK_FAIL: tdd-doc-size 612 > 500 is WAIVED via a
## Scope override, chosen by the user. The excess is gate-driven
hardening of an already-built unit, and splitting would orphan the
retained build branch. The reviewer graded the justification
acceptable.

Open assumptions & waivers

  • Render isolation mechanism — resolved: the user chose "Revise TDD,
    then Retry" with loopback-HTTP + CSP isolation over patching the
    scanner.
  • tdd-doc-size bound — waived: Scope override (rationale above).

After merge: /build-tdds Retry 3 builds rev 2 on the retained branch
build/20261006-220142/0070-ux-record-lib, with no escalation.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NpGG21Y2VGGhTQaFr4oshB

/build-tdds run 20261006-220142 halted three times on the same class:
an out-of-repo local file baked into a committed PNG through the
file:// render. Each regex-scanner fix was bypassed by the next gate:
- script navigation;
- `<!-->` before the doctype;
- unquoted, backtick and NBSP attribute values;
- base64 data:text/css;
- url() in tokens.css or another CSS file.

Rev 2 moves the boundary into the browser:
- render copies docs/ux/ to a private mkdtemp dir outside the repo,
  after a whole-tree symlink check and a re-check of the copy;
- every HTML file starts with <!DOCTYPE html> plus a CSP meta at byte 0;
- a loopback-only ThreadingHTTPServer serves the copy, with the same CSP
  as a header on every response;
- Chrome loads http://127.0.0.1:<port>/..., with a dead proxy that
  excludes other loopback ports.
An http page cannot load file: URLs, absolute and ../ paths 404 on a
server that holds only the copy, and default-src 'self' data: blocks
everything else. The scan stays as defence in depth.

Also in this revision:
- capture leaves out the proxy flags;
- the scanner rules are written down as built;
- the probe-matrix obs 10b requires the CSS and base64 vectors to pass
  validate and still show 0 canary pixels;
- honest per-file diff estimates with exceptions;
- tests/implement-gate.test.sh is declared;
- a revision record.

## Design critique (design-reviewer, fresh worker)
DESIGN_REVIEW: PASS. The isolation was judged sound point by point
(file: from http, translate_path, CSP 'self', the bypass list failing
closed, port binding). All 9 minor findings and nits were folded in
after the PASS:
- the copy lives outside the repo;
- the capture proxy flags are dropped;
- CSP is sent as an HTTP header on every response;
- the symlink scope and scanner rules are written down;
- 10b is strengthened;
- obs 7 now has an observable;
- the FR-94 trace is corrected;
- the revision record is moved;
- the override count is corrected.

## Mechanical pre-pass
Structural lint is clean.
`PRECHECK_FAIL: tdd-doc-size 612 > 500` is WAIVED via a
`## Scope override`, chosen by the user. The excess is gate-driven
hardening of an already-built unit, and splitting would orphan the
retained build branch. The reviewer graded the justification
acceptable.

## Open assumptions & waivers
- Render isolation mechanism — resolved: the user chose "Revise TDD,
  then Retry" with loopback-HTTP + CSP isolation over patching the
  scanner.
- tdd-doc-size bound — waived: Scope override (rationale above).

After merge: /build-tdds Retry 3 builds rev 2 on the retained branch
build/20261006-220142/0070-ux-record-lib, with no escalation.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NpGG21Y2VGGhTQaFr4oshB
@cahenesy
cahenesy merged commit 226c5c1 into master Oct 7, 2026
1 check passed
@cahenesy
cahenesy deleted the docs/design/0070-render-isolation branch October 7, 2026 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant