--- id: canvases-task-canvas-workspace-preview-design title: Task canvas workspace data preview design status: draft system: canvases owners: - canvases created: 2026-09-23 last_updated: 2026-09-23 requirements: - REQ-CANVASES-WORKSPACE-PREVIEW-001 --- # Task canvas workspace data preview System Design ## Boundary and mapping Canvases owns when a locally requested task canvas gains workspace data scope, how an older canvas can opt in, and when promotion changes placement. Plugins persists the instance's effective data scope and enforces it through the shared web-app runtime. Task services remain authoritative for data and current user access. This design implements `REQ-CANVASES-WORKSPACE-PREVIEW-001`. | Criteria | Design sections | | --- | --- | | `AC-CANVASES-WORKSPACE-PREVIEW-001.1`, `.2`, `.8` | Data scope and runtime enforcement | | `AC-CANVASES-WORKSPACE-PREVIEW-001.3`, `.4` | Lifecycle and presentation | | `AC-CANVASES-WORKSPACE-PREVIEW-001.5`, `.6`, `.7` | Existing canvas upgrade and host flow | See [the workspace preview decision](../../../decisions/2026-09-23-task-canvas-workspace-data.md) and [the existing creation authority](local-creation-authority.md). ## Data scope and persistence Keep `plugin_instances.scope_kind` as the placement/lifecycle scope. Add a nullable `data_scope_kind` to `plugin_instances`; null means the existing `scope_kind` so older rows and non-canvas plugins retain their behavior. A non-null value is valid only when it equals the placement scope, or when a `local_canvas` task instance uses `workspace` data scope with its existing trusted `workspace_id` and `task_id`. Reject `instance` and foreign workspace data scope for canvases. Do not accept the field from agent, manifest, or browser input. Store it through SQLite and PostgreSQL schema paths, backup, snapshot, and instance row mapping. At trusted canvas creation, record workspace data scope only for a new task canvas with owner-authorized creation provenance. The task remains the canvas owner and the plugin instance's placement scope. The first valid release derives grants from exactly its declared supported capabilities with a `workspace` ceiling, then consumes creation authority and activates in the existing transaction. Raise `CreationAuthorityPolicyVersion` for newly issued authority; consumed version-1 rows remain historical evidence and are never reissued. If provenance or current owner checks fail, publication follows the normal permission-review path and cannot infer a workspace grant. All grant-fit, release activation, and runtime-binding validation for a web app use its effective data scope. A grant ceiling cannot be interpreted as covering a wider data scope merely because it covers the placement scope. A later declaration increase still creates a pending release. Revocation bumps the existing grant generation and invalidates runtime tokens. ## Runtime enforcement `webapp.CapabilityBinding` carries both placement `ScopeKind` and effective `DataScopeKind`. Issue both from the persisted instance, and compare both with the current instance on every token validation. Existing bindings with an empty data scope resolve to placement scope. The relative `./_kandev/v1/context` response retains `scope_kind` for placement and adds `data_scope_kind` for authors to label the available data accurately. Use the effective data scope for the web-app task list, single-task read, task update, message dispatch, workflow list and steps, task dependency edge projection, and subscribed task events. A workspace data scope binds all queries and mutations to the instance's trusted `workspace_id`, including explicit `workspace_id` filters. It does not derive workspace IDs from the request or allow `ScopeInstance`. The task-list route uses its existing pagination path instead of the bound-task shortcut. Each operation still checks the declared capability, effective grant, and current user/domain authorization. Other plugin instances continue to use their existing scope rules. Never use the ordinary authenticated Kandev HTTP API as an implicit escape from the canvas protocol. The [same-origin trust decision](../../../decisions/2026-09-19-trusted-same-origin-canvases.md) acknowledges that browser code can call those APIs, but the documented canvas contract and capability-only runtime must remain coherent. ## Lifecycle and presentation `canvas_lifecycle_metadata.task_id` and the instance's placement scope retain task discovery and deletion semantics. Workspace data scope does not add the canvas to workspace navigation. Promotion remains a reviewed human action: it changes placement to workspace, clears task placement, preserves the active release, and leaves workspace data scope intact. The review states that data access is already workspace-wide when that is true. A task-only legacy canvas still has its existing promotion behavior, including grant expansion. Project `data_scope_kind` alongside `scope_kind` in the canvas and runtime responses. The task host exposes a compact data-scope label in its existing header/action surface. Releases and permissions and promotion review explain placement separately from data access. The bundled authoring guidance and public canvas documentation tell authors to read both context fields and to declare only capabilities they use. Revise the saved `create-canvas` prompt's promotion guidance so it describes workspace navigation rather than saying that workspace data always requires promotion. No generated package rewrite is needed. ## Existing canvas upgrade Do not silently widen a retained release. An active task canvas with task-only data scope offers **Enable workspace data** in the existing host action menu. The backend returns a review snapshot of the active release, permission digest, grant generation, current/target data scope, and exact declared permissions. Only a currently authorized workspace owner may confirm it. Confirmation rechecks the canvas's task and workspace identity, owner, active release, permission digest, and grant generation inside one transaction. It upserts workspace-ceiling grants only for that release's declared permissions, sets `data_scope_kind=workspace`, increments grant generation, and publishes a single lifecycle refresh after commit. It neither promotes the canvas nor republishes the artifact. On stale review or any failed check it changes nothing. A canceled review has no write. Imported or legacy packages receive no automatic exemption. Use the existing canvas HTTP controller's preview/confirm pattern with `GET /api/v1/canvases/{id}/workspace-data-preview` and `POST /api/v1/canvases/{id}/workspace-data`. The request carries the same release ID, permission digest, and grant generation preconditions as promotion. Return an updated canvas projection after success. Keep the action unavailable for pending, archived, removed, already workspace-data, or foreign canvases. ## Desktop and phone host flow Desktop keeps the current canvas panel and action toolbar. The data-scope label sits with existing host metadata, and a legacy canvas exposes the upgrade action from its current actions. Phone keeps the focused canvas route and secondary-action drawer; the same upgrade opens the existing full-height review surface. The header and actions remain fixed while one body region scrolls, with safe-area clearance and touch targets. Both presentations share one review state and backend snapshot; neither relies on canvas-authored UI. ## Failure and observability Denied or stale access review returns the existing safe error style and leaves the active release and old scope usable. A missing task or workspace makes its runtime binding stale. Scope or grant changes invalidate old tokens; the host reloads the runtime through its existing recovery path. Record bounded scope-transition result counters and IDs already allowed for canvas lifecycle logging. Do not log package source, permission bodies, tokens, or task data. ## Verification strategy - Instance-store tests cover null fallback, invalid combinations, transaction rollback, snapshot/backup mapping, and grant-generation invalidation. - Canvas service tests cover version-2 owner authority, exact declarations, legacy review, stale snapshots, owner drift, and promotion without data expansion. - Web-app protocol tests cover list pagination, task read/write, workflow, message, event, dependency projection, foreign-workspace denial, and old task-scoped behavior. - Desktop and mobile Playwright exercise an owner-created task canvas with at least two tasks, refresh before promotion, and an older canvas's explicit access upgrade. The mobile route and review remain touch-usable. ## Related designs - [Canvas lifecycle and promotion](agent-authored-web-apps.md) - [Owner-authorized first publication](local-creation-authority.md) - [Plugin web-app runtime](../../plugins/system-design/isolated-web-app-contributions.md) - [Plugin canvas data-scope runtime](../../plugins/system-design/canvas-workspace-data-scope.md)