8.8 KiB
created, status, requirements, system_design, legacy_specs
| created | status | requirements | system_design | legacy_specs | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2026-09-21 | done |
|
|
Implementation Plan: Canvas runtime and task-entry recovery
Overview
Prevent automatic proxy injection into canvas responses. Then show unseen published canvases when users return to their tasks. Both changes reuse the existing runtime and host surfaces.
Evidence and diagnosis
The incident involved task f6136adf-46a6-422f-831c-5a35caf04b3d and canvas
09549bca-9ad4-4169-9d4f-2913e8bfc1b3. The author reported active release
21bf0113-73fe-42c8-8b11-9bbf4ca0db27 as valid.
Backend logs recorded canvas.release.activated at 10:19:28 UTC on September 21.
Browser logs recorded task restoration without its canvas panel at 13:14:02 UTC.
The user confirmed that they returned after publication.
The screenshot showed Canvas unavailable. The reported console error identified
a CSP-blocked Cloudflare beacon. The exact embedded startup JavaScript reproduced
the failure mechanism in an isolated Node VM. Without a resource error, it
requested context once and reported Ready. A simulated beacon script error
reported failed/document_error and made no context request.
This is a source-level reproduction, not a capture of the live frame handshake. The diagnostic archive was partial and lacked publication-time browser events. The source nonetheless establishes both relevant paths:
hostRuntimeBootstraprejects resource errors.setRuntimeHeaderscurrently sends onlyno-store, leaving no explicit prohibition on proxy transformation.useTaskCanvasLifecycleActivationdepends on volatile lifecycle hints. Task entry does not reconcile the published HTTP inventory with the workbench.
The runtime design already prohibits proxy HTML injection. Preserve that
contract. Cloudflare documents the transformation directive in its
Web Analytics FAQ.
The first-release requirement covers live publication. New criteria
AC-CANVASES-AGENT-WEB-APPS-001.13 through .16 define later task entry.
Scope
In scope
- Runtime
no-transformresponse policy and realistic HTTPS proxy coverage. - HTTP inventory reconciliation on task entry, reload, and reconnect.
- Main editor placement, one focus change, and browser-tab dismissal memory.
- Phone route behavior and prevention of Back-navigation loops.
- Operator and user documentation in
docs/public/canvases.md.
Out of scope
- Live Cloudflare configuration changes or live canvas republishing.
- CSP relaxation, ignored script errors, new grants, or new runtime flags.
- Cross-device presentation history or changes to canvas package storage.
- Claims that this investigation verified the live deployment after correction.
Technical approach
Task 01 changes setRuntimeHeaders in the shared plugin runtime. Extend the
existing authenticated proxy fixture with directive-aware HTML injection.
Its negative control removes no-transform and demonstrates the existing failure.
Keep package bytes, capability checks, cookie forwarding, and SSE intact.
Task 02 shares the task-page canvas inventory with the activation hook. Reconcile only after the target environment finishes layout restoration. Use current HTTP metadata for every candidate. Record offered canvases after presentation, following the existing PR-panel session-storage pattern. Receipt identity includes user, workspace, task, and canvas, not release. Manual opening and restored panels also record presentation.
Desktop adds every eligible unseen canvas and focuses only the deterministic
last candidate. Existing panels never move. Phones open one candidate and mark
the batch offered after confirmed navigation. Other candidates remain in the picker.
The nearest phone exemplars are task-layout.tsx and CanvasHostFrame.
Their full-height route suits primary content and retains existing scroll ownership,
safe areas, accessible controls, and touch targets.
Related completed packages remain historical evidence: same-origin authentication and first-release UX. Their existing happy-path scenarios must remain covered alongside these regressions. No new ADR is needed: this preserves the runtime boundary and extends the existing tab-local offered-marker pattern. Specifications retain the local rationale.
ASCII UI preview
UI-01: Returning to a task after publication, desktop.
Before: main editor [Agent] [Plan] [+]
Canvas requires manual selection.
After: main editor [Agent] [Plan] [Task coordinator *] [+]
+-------------------------------------------+
| Existing canvas toolbar |
| Canvas application fills remaining space |
+-------------------------------------------+
UI-02: Returning to the same task, phone.
+--------------------------------+
| Existing navigation | Canvas |
| Existing host actions |
| |
| Focused canvas application |
| One content scroll region |
+--------------------------------+
Back -> task, without redirecting again
The main editor group, one focused canvas, and existing phone route are required. Spacing and titles are illustrative. No new toolbar or visible copy is required. Permission-review canvases show the existing review state before execution. Real runtime failures keep the existing unavailable state and Retry action.
Tests
AC-PLUGINS-ISOLATED-WEB-APPS-013.8: extendruntime_test.gowithTestRuntimeNoTransformHeadersfor entry HTML, nested assets, and bootstrap.AC-PLUGINS-ISOLATED-WEB-APPS-012.1: preserve startup error tests and the injected-script negative control.AC-CANVASES-AGENT-WEB-APPS-001.2,.13through.16: extenddockview-canvas-activation.test.tsx,use-task-canvases.test.ts, and a focused receipt-storage test. Include mixed eligible and ineligible inventory.
E2E tests
- Desktop and phone authenticated-proxy specs prove retained runtime startup with transformation prevention, plus the negative control on desktop.
- Desktop and phone plugin-canvas specs prove publication before navigation, reload, receipt persistence, manual reopening, and no focus/navigation loops.
- Desktop also proves main editor placement after delayed layout restoration.
- Feature-disabled, wrong-task, unavailable, and permission-review paths retain focused unit/component coverage and existing rendered scenarios.
Work orders
Execute sequentially. Each work order contains exact commands and owns its tests. No delegation is authorized.
Verification results
Planning: the isolated bootstrap probe reproduced the failure mechanism.
Implementation and rendered verification are complete. Backend runtime tests,
focused web tests, full web lint, i18n checks, web typecheck, and the managed
desktop and phone E2E suites passed. make -C apps/backend build and
pnpm --filter @kandev/web build:vite passed. The authenticated proxy suites
passed with 5 desktop and 2 phone tests; the task-entry suites passed with 6
desktop and 4 phone tests. The focused component and hook suite passed 61 tests,
including deferred request invalidation, authenticated identity, mixed inventory,
delayed layout ownership, batch focus, restored-panel receipts, and duplicated-tab
receipt isolation. Full web lint
passed with zero warnings. pnpm run i18n:check passed; it reported the
repository's existing orphan catalog warnings without failing. Public-doc validation passed 62 tests and
validated 47 pages. python3 scripts/list-docs.py validate passed with 294
decisions and 1068 specifications, python3 scripts/lint-spec-files.py --all
passed, and python3 scripts/lint-spec-files.test.py passed all 36 tests.
git diff --check passed.
Risks
- A proxy can override origin headers. The real deployment still needs an operator smoke check, and can require a runtime-path analytics exclusion.
- Old canvases have no presentation receipts. The first corrected task visit can offer them once. Existing panels count as already presented.
- Blocked session storage falls back to memory. Reload persistence then cannot be guaranteed, but manual access must continue to work.
- Async restoration and task switches can misplace panels unless generation and environment checks occur immediately before insertion.