feat: preview task canvases with workspace data (#3887)

This commit is contained in:
Carlos Florêncio
2026-09-23 20:51:55 +01:00
committed by GitHub
parent 9874ac4cf5
commit 4bebf7c511
79 changed files with 3369 additions and 282 deletions
@@ -0,0 +1,168 @@
---
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)