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
@@ -7,6 +7,8 @@
The initial-grant rule is amended by
[owner-authorized canvas creation](2026-09-10-canvas-creation-authority.md).
Task placement and data scope are separated for owner-authorized canvases by
[task canvas workspace data](2026-09-23-task-canvas-workspace-data.md).
The bounded startup acknowledgement is specified in the
[runtime design](../specs/plugins/system-design/isolated-web-app-contributions.md#runtime-startup-protocol);
it adds no privileged host API.
@@ -4,6 +4,10 @@
**Date:** 2026-09-10
**Area:** backend, protocol, security
The task-data initial grant ceiling below is amended by
[task canvas workspace data](2026-09-23-task-canvas-workspace-data.md).
It remains the historical rule for version-1 authority.
## Context
A user asks their task agent to create a canvas, then must approve its first
@@ -0,0 +1,72 @@
# ADR-2026-09-23-task-canvas-workspace-data: Separate canvas placement from data scope
**Status:** accepted
**Date:** 2026-09-23
**Area:** backend, frontend, protocol, security
## Context
Users create canvases from tasks and review their behavior before promotion.
The original canvas contract binds task placement and data scope together. A
task coordinator that calls the supported canvas task-list endpoint therefore
receives only its creating task, even when the package declares task reads and
the workspace has many tasks. Granting every capability would not remove that
scope filter.
The [owner-authorized creation decision](2026-09-10-canvas-creation-authority.md)
already treats the user's request as authority for the first release's exact
declared grants. The [same-origin decision](2026-09-19-trusted-same-origin-canvases.md)
also establishes that locally run canvas code has the viewer's ordinary browser
authority. The relative canvas API should provide a coherent supported path
without relying on direct first-party API calls.
## Decision
A task canvas has separate placement and data scopes. For a newly
owner-authorized local canvas, the first valid release receives only its
declared supported capabilities, with data scope limited to its current
workspace. It remains placed in the creating task until the user promotes it.
The task-list API can show every task in that workspace before promotion;
current user authorization still applies. Promotion governs placement and
sharing, and still requires human confirmation.
The data scope is server-owned, persisted, included in runtime bindings, and
checked alongside grants on every canvas-protocol request. Agent or manifest
input cannot choose a different workspace. Existing task-only releases retain
their scope until a workspace owner reviews their exact declared permissions
and explicitly enables workspace data access. Later permission increases and
imported packages continue through their existing review paths.
This amends the task-scoped first-grant ceiling in the 2026-09-10 decision and
the coupling of task canvas and task data scope in the 2026-08-26 decision. It
does not change the same-origin trust decision or grant undeclared capabilities.
## Consequences
- An owner-created canvas can be evaluated with representative live workspace
data and supported actions before it appears in workspace navigation.
- Permission review remains tied to the exact capabilities a release uses;
there is no blanket read, write, network, secret, or backend permission.
- The runtime, persistence, review projection, and authoring guidance must
carry placement and data scopes independently.
- Existing task canvases require an explicit access upgrade or promotion to
show workspace data. No retained release is silently broadened on upgrade.
- The upgrade path must check current ownership and a versioned review
snapshot atomically, then invalidate older runtime tokens.
## Alternatives Considered
- **Grant all possible permissions by default:** Does not remove the task-list
scope filter and gives unused writes and network access to generated code.
- **Require promotion before representative preview:** Leaves the user unable
to judge the app before placing it in workspace navigation.
- **Call ordinary Kandev APIs from canvas code:** Works only with browser user
authority and bypasses the supported capability contract; capability-only
hosts would still show one task.
- **Silently widen all existing task canvases:** Changes retained release
authority without a review of the code and exact declared capabilities.
## Related contracts
- [Workspace preview requirements](../specs/canvases/requirements/task-canvas-workspace-preview.md)
- [Workspace preview design](../specs/canvases/system-design/task-canvas-workspace-preview.md)
@@ -0,0 +1,152 @@
---
created: 2026-09-23
status: complete
requirements:
- REQ-CANVASES-WORKSPACE-PREVIEW-001
- REQ-CANVASES-LOCAL-CREATION-001
- REQ-CANVASES-AGENT-WEB-APPS-003
system_design:
- ../../specs/canvases/system-design/task-canvas-workspace-preview.md
- ../../specs/canvases/system-design/local-creation-authority.md
- ../../specs/canvases/system-design/agent-authored-web-apps.md
- ../../specs/plugins/system-design/canvas-workspace-data-scope.md
legacy_specs: []
---
# Implementation Plan: Task canvas workspace data preview
## Overview
Let an owner-created canvas use its declared capabilities across the current
workspace while it remains in the creating task. First add the server-owned
data-scope and review transaction, then expose the scope and legacy upgrade
in the host, authoring guidance, and browser tests. Promotion continues to
control workspace placement.
## Scope
### In scope
- Workspace task lists and all currently supported declared canvas data,
write, event, state, and network capabilities before promotion.
- A separate server-owned data scope on plugin instances and runtime bindings.
- An explicit, reviewed workspace-data upgrade for existing task canvases.
- Desktop and phone host scope presentation, localized copy, authoring and
public documentation, and focused browser coverage.
### Out of scope
- Cross-workspace and installation-wide data access.
- Blanket grants for undeclared capabilities, new capability kinds, or
managed agent-generated backend code.
- Silent widening of retained releases.
## Technical approach
1. Add nullable `data_scope_kind` to plugin instance persistence with null
fallback to the existing placement `scope_kind`. Create version-2 local
canvas authority with workspace data scope and exact workspace-ceiling
declared grants. Keep other instances and historical authority unchanged.
2. Carry data scope through `webapp.CapabilityBinding`, grant validation, and
the relative browser protocol. Use it for tasks, workflows, writes,
messages, dependency projection, and events. Bind every operation to the
trusted workspace and current user authorization. Follow the
[plugin runtime design](../../specs/plugins/system-design/canvas-workspace-data-scope.md).
3. Add an owner-reviewed workspace-data upgrade for retained task canvases
using the active release ID, permission digest, and grant generation as
conditional transaction inputs. Keep placement and package unchanged.
4. Project placement and data scope separately in canvas context and host
review. Update authoring instructions and public canvas/API docs. Use the
existing desktop action menu and phone action drawer for legacy upgrade.
Likely backend files include `internal/plugins/instances/store.go`,
`internal/plugins/webapp/tokens.go`, `internal/plugins/webapp_protocol*.go`,
`internal/canvas/authoring.go`, `internal/canvas/service.go`, and the canvas
HTTP handler/controller. Existing E2E fixture expectations for one task must
change to a multi-task workspace fixture.
## ASCII UI preview
`UI-01: Task canvas host, new release (desktop)`. Entry: task canvas panel.
The host header stays fixed; the application owns its existing scroll region.
The badge reports data scope, while Promote controls placement. Labels are
illustrative; the distinction is required by
`AC-CANVASES-WORKSPACE-PREVIEW-001.3-.4`.
```text
Task coordinator [Workspace data] [Releases and permissions] [Promote canvas]
--------------------------------------------------------------------------
Existing tasks [Refresh]
Available 3 Active 2 Completed 1
Task A Task B Task C
```
`UI-02: Existing task-only canvas (desktop)`. Entry: the same task panel.
The upgrade dialog uses the current permission-review layout and keeps
Cancel and Enable actions visible. It does not promote the canvas.
```text
Task coordinator [Task data] [Enable workspace data] [Promote canvas]
|
Enable workspace data for this canvas?
Release: Task coordinator 1.0.0
Reads: tasks in this workspace
Writes/events/network: exact declared permissions
[Cancel] [Enable workspace data]
```
`UI-03: Existing task-only canvas (phone)`. Entry: focused task canvas route.
The existing Actions drawer exposes the upgrade; the review opens as a
full-height view with one scrolling permission region and safe-area actions.
```text
< Task Task coordinator [Actions]
Task data
| Actions drawer: Enable workspace data
v
Enable workspace data
Release and declared permissions [scrolls]
-------------------------------------------
[Cancel] [Enable workspace data] [fixed, safe area]
```
## Tests
| Criteria | Evidence |
| --- | --- |
| `.1`, `.2`, `.8` | Plugin instance and web-app protocol tests for exact grants, all workspace pages, foreign denial, writes, workflows, messages, events, and dependencies. |
| `.3`, `.4` | Canvas service promotion and projection tests. |
| `.5`, `.6` | Conditional legacy-upgrade transaction and stale/owner/revocation tests. |
| `.7` | Canvas host component tests and desktop/mobile E2E. |
## E2E tests
- `apps/web/e2e/tests/canvas/plugin-canvas.spec.ts` (`chromium`): owner-created
task canvas sees two or more workspace tasks and refreshes before promotion;
promotion leaves the list intact. Covers `.1`, `.3`, `.4`.
- `apps/web/e2e/tests/canvas/mobile-plugin-canvas.spec.ts`
(`mobile-chrome`): same data before promotion plus task-only legacy upgrade
from the phone action drawer. Covers `.5`, `.7`.
## Work orders
- [x] [Task 01: Workspace data scope and legacy upgrade](task-01-workspace-data-scope.md)
- [x] [Task 02: Host scope review and browser proof](task-02-host-scope-review.md)
Task 02 depends on Task 01. Both run in the primary session unless the user
later explicitly authorizes another arrangement.
## Verification results
Passed: backend canvas/plugin tests, focused frontend Vitest coverage, web
typecheck, i18n validation, desktop and mobile canvas Playwright suites, spec
index validation, specification lint, and public documentation validation.
## Risks
- Grant checks currently equate instance scope with data scope. Missing a
validation or event path could leak data or leave preview inconsistent.
- Existing task releases must retain their one-task behavior until reviewed;
a broad migration would silently change authority.
- Same-origin canvas code can call ordinary user APIs already; the supported
relative protocol must remain internally coherent in capability-only hosts.
@@ -0,0 +1,112 @@
---
id: "01-workspace-data-scope"
title: "Workspace data scope and legacy upgrade"
status: complete
wave: 1
depends_on: []
plan: "plan.md"
requirements:
- REQ-CANVASES-WORKSPACE-PREVIEW-001
- REQ-CANVASES-LOCAL-CREATION-001
- REQ-CANVASES-AGENT-WEB-APPS-003
acceptance_criteria:
- AC-CANVASES-WORKSPACE-PREVIEW-001.1
- AC-CANVASES-WORKSPACE-PREVIEW-001.2
- AC-CANVASES-WORKSPACE-PREVIEW-001.3
- AC-CANVASES-WORKSPACE-PREVIEW-001.5
- AC-CANVASES-WORKSPACE-PREVIEW-001.6
- AC-CANVASES-WORKSPACE-PREVIEW-001.8
- AC-CANVASES-LOCAL-CREATION-001.2
- AC-CANVASES-AGENT-WEB-APPS-003.2
system_design:
- ../../specs/canvases/system-design/task-canvas-workspace-preview.md
- ../../specs/canvases/system-design/local-creation-authority.md
- ../../specs/canvases/system-design/agent-authored-web-apps.md
- ../../specs/plugins/system-design/canvas-workspace-data-scope.md
---
# Task 01: Workspace data scope and legacy upgrade
## Summary
Persist a separate data scope for canvas instances and honor it throughout the
relative web-app protocol. New owner-authorized task canvases get exact
declared workspace grants on first publication; existing task-only canvases
can obtain them only through a conditional owner-reviewed upgrade.
## In scope
- SQLite/PostgreSQL instance mapping and null fallback; version-2 creation
authority and first-publication transaction.
- Runtime binding, grant checks, task/workflow/write/message/event/dependency
enforcement, and additive context projection.
- Bounded expvar counters for first publication, reviewed upgrades, and
promotion data-scope results, without per-canvas metric labels.
- Workspace-data preview and confirmation endpoints for retained task canvases.
- Promotion behavior with an already workspace-data task canvas and tests for
foreign workspaces, stale reviews, owner drift, and revoked grants.
## Out of scope
- Host action, dialog, translations, browser tests, and public docs.
## Acceptance
1. A new task-placed local canvas can list and operate on all authorized tasks
in its own workspace through declared capabilities before promotion; no
foreign workspace or undeclared capability is admitted.
2. Existing task-only instances keep their current behavior until an owner
confirms an exact, current release review; confirmation changes grants and
data scope atomically without changing placement or release.
3. Promotion preserves workspace data access when it already exists, while
stale or invalid runtime bindings and reviews fail closed.
## Verification
Run from the repository root:
```bash
(cd apps/backend && go test ./internal/canvas ./internal/plugins/instances ./internal/plugins ./internal/plugins/webapp ./internal/backendapp)
python3 scripts/list-docs.py validate
```
## Files likely touched
- `apps/backend/internal/plugins/instances/store.go`
- `apps/backend/internal/plugins/webapp/tokens.go`
- `apps/backend/internal/plugins/webapp_protocol.go`
- `apps/backend/internal/plugins/webapp_protocol_data.go`
- `apps/backend/internal/plugins/webapp_events.go`
- `apps/backend/internal/plugins/webapp_protocol_json.go`
- `apps/backend/internal/canvas/authoring.go`
- `apps/backend/internal/canvas/service.go`
- `apps/backend/internal/canvas/types.go`
- `apps/backend/internal/backendapp/` canvas HTTP handlers and tests
- Adjacent `*_test.go` files
## Dependencies
None.
## Risks
Every route that uses placement scope today must be classified by whether it
filters data, determines discovery, or checks grant validity. Missing a route
could make the preview inconsistent or broaden an unintended path.
## Parallelism
`sequential`
## Inputs
- [Workspace preview requirements](../../specs/canvases/requirements/task-canvas-workspace-preview.md)
- [Workspace preview design](../../specs/canvases/system-design/task-canvas-workspace-preview.md)
- [Scope decision](../../decisions/2026-09-23-task-canvas-workspace-data.md)
## Results
Passed: `go test ./internal/canvas ./internal/plugins/instances
./internal/plugins ./internal/plugins/webapp ./internal/backendapp` and
`python3 scripts/list-docs.py validate`. The canvas tests verify fixed-label
counter increments for initial publication, reviewed upgrade, and promotion.
@@ -0,0 +1,141 @@
---
id: "02-host-scope-review"
title: "Host scope review and browser proof"
status: complete
wave: 2
depends_on:
- "01-workspace-data-scope"
plan: "plan.md"
requirements:
- REQ-CANVASES-WORKSPACE-PREVIEW-001
- REQ-CANVASES-AGENT-WEB-APPS-003
acceptance_criteria:
- AC-CANVASES-WORKSPACE-PREVIEW-001.1
- AC-CANVASES-WORKSPACE-PREVIEW-001.4
- AC-CANVASES-WORKSPACE-PREVIEW-001.5
- AC-CANVASES-WORKSPACE-PREVIEW-001.7
- AC-CANVASES-AGENT-WEB-APPS-003.1
system_design:
- ../../specs/canvases/system-design/task-canvas-workspace-preview.md
- ../../specs/canvases/system-design/agent-authored-web-apps.md
---
# Task 02: Host scope review and browser proof
## Summary
Show task placement and workspace data access separately in the host and
promotion review. Give older task-only canvases an owner-reviewed access
action on desktop and phone, update author guidance, and prove live workspace
task refresh before promotion in browser tests.
## In scope
- Canvas API client/projections, existing host actions and review component,
localized copy in six catalogs, and phone action drawer.
- Versioned bundled authoring reference, public canvas and plugin API docs,
and concise scoped `AGENTS.md` updates if implementation changes their
current statements.
- Component and desktop/mobile Playwright tests using multiple tasks in one
workspace and a foreign-workspace negative case.
## Out of scope
- New canvas-authored UI template, broad UI redesign, installation-wide task
listing, and silent legacy grant migration.
## Acceptance
1. Desktop and phone hosts label the data scope accurately and offer the
upgrade review only for eligible task-only canvases; the action does not
promote or republish.
2. Promotion review distinguishes placement from data access and keeps exact
declared permission details visible on both viewports.
3. Browser tests show a new task canvas refreshing at least two workspace
tasks before promotion and an existing one expanding access after review.
## ASCII UI preview
`UI-01: Task canvas host, new release (desktop)` and
`UI-02: Existing task-only canvas (desktop)` use the same header shown in
[the full plan](plan.md#ascii-ui-preview):
```text
New: Task coordinator [Workspace data] [Releases] [Promote canvas]
Existing: Task coordinator [Task data] [Enable workspace data] [Promote canvas]
```
`UI-03: Existing task-only canvas (phone)` uses the existing focused route
and Actions drawer. Its review is full-height with one scroll region and
fixed safe-area actions:
```text
< Task Task coordinator [Actions]
Task data
Actions > Enable workspace data
Review declared permissions [scrolls]
[Cancel] [Enable workspace data] [fixed, safe area]
```
The scope label and action availability are required by
`AC-CANVASES-WORKSPACE-PREVIEW-001.4-.5` and `.7`; text spacing is
illustrative. Reuse the shipped canvas host and phone drawer.
## Verification
Run from the repository root:
```bash
(cd apps/web && pnpm exec vitest run components/settings/canvas-lifecycle-dialogs.test.tsx components/settings/canvas-host-components.test.tsx lib/api/domains/canvas-api.test.ts)
(cd apps/web && pnpm run typecheck)
(cd apps/web && pnpm run i18n:check)
(cd apps/web && pnpm e2e:run --host --project chromium tests/canvas/plugin-canvas.spec.ts)
(cd apps/web && pnpm e2e:run --host --project mobile-chrome tests/canvas/mobile-plugin-canvas.spec.ts)
python3 scripts/list-docs.py validate
python3 scripts/lint-spec-files.py --all
node scripts/validate-public-docs.mjs
```
## Files likely touched
- `apps/web/lib/api/domains/canvas-api.ts`
- `apps/web/components/settings/canvas-host-actions.tsx`
- `apps/web/components/settings/canvas-lifecycle-dialogs.tsx`
- `apps/web/components/settings/canvas-host-route*.tsx`
- `apps/web/src/locales/*/canvases.json`
- `apps/web/e2e/tests/canvas/plugin-canvas.spec.ts`
- `apps/web/e2e/tests/canvas/mobile-plugin-canvas.spec.ts`
- `apps/backend/internal/mcp/canvasskill/files/references/browser-api.md`
- `apps/backend/config/prompts/create-canvas.md`
- `docs/public/canvases.md`
- `docs/public/plugins-authoring.md`
- Adjacent component tests and `AGENTS.md` files when needed
## Dependencies
Task 01 supplies the data-scope projection and conditional access endpoint.
## Risks
The current canvas fixture expects one task. The browser proof must create a
second task in the same workspace and retain a foreign-workspace negative case
without changing unrelated fixture behavior.
## Parallelism
`sequential`
## Inputs
- [Workspace preview requirements](../../specs/canvases/requirements/task-canvas-workspace-preview.md)
- [Workspace preview design](../../specs/canvases/system-design/task-canvas-workspace-preview.md)
- [Full UI preview](plan.md#ascii-ui-preview)
## Results
Passed: focused Vitest suite (41 tests), web typecheck, i18n checks, desktop
canvas Playwright suite, mobile canvas Playwright suite (5 tests), spec index
validation, specification lint, and public documentation validation. The phone
browser test verifies both scope labels and the legacy review flow; it uses a
test-only legacy API response, while backend service/store tests verify the
transactional grant upgrade.
+20 -5
View File
@@ -53,7 +53,18 @@ Kandev validates the package before it stores or runs the release. An invalid dr
## Use a canvas
A task canvas belongs to one task. A workspace canvas appears in workspace navigation and uses workspace scope. Promotion changes the same canvas from task scope to workspace scope. It does not copy the canvas.
A task canvas stays in its creating task until promotion. After the first valid
release, a new owner-authorized task canvas can use its declared supported
permissions across the current workspace. This lets the app preview the full
workspace task list before it appears in workspace navigation. Imported and
older task canvases keep their existing data scope until an authorized review
widens it.
A workspace canvas appears in workspace navigation. Promotion changes the
canvas placement and keeps its identity, active release, state, and release
history. For a new canvas that already has workspace data access, promotion
changes placement only. The host review identifies whether it changes data
access for a legacy canvas.
The app uses relative requests such as `./_kandev/v1/data/tasks` and `./_kandev/v1/state`. Kandev remains the source of truth for task, workflow, and message data. Canvas state stores app-specific shared state. It does not replace Kandev domain data.
@@ -115,7 +126,7 @@ and **Releases and permissions** outside the failed frame. Retry creates a new
runtime binding and startup attempt. This check confirms document and context
startup; it does not certify application business health.
Kandev calculates effective access from the package declaration, instance grant, trusted task or workspace scope, and current caller authorization. A release receives only the intersection of those permissions. See [Security and trust](security.md#isolated-web-applications) for the security boundary.
Kandev calculates effective access from the package declaration, instance grant, trusted data scope, and current caller authorization. A release receives only the intersection of those permissions. See [Security and trust](security.md#isolated-web-applications) for the security boundary.
### Return to a task after publication
@@ -136,13 +147,17 @@ Only a user can promote a task canvas. An agent cannot promote, demote, grant pe
1. Open the task canvas and choose its promotion action.
2. Read the review dialog before you continue.
3. Review every Kandev data read and write, event subscription, shared-state permission, and exact external HTTPS origin.
4. Confirm the task-to-workspace scope change and workspace placement.
4. Confirm the placement change to workspace navigation.
The confirmation includes the active release ID, permission declaration
digest, and grant generation that you reviewed. If any of these changes before
confirmation, Kandev rejects the request as stale and requires a new review.
The promotion keeps the canvas identity, active release, state, and release history. A workspace canvas then appears in workspace navigation. Canceling the review leaves the task canvas unchanged.
The promotion keeps the canvas identity, active release, state, and release
history. A workspace canvas then appears in workspace navigation. A new
owner-authorized task canvas already has workspace data access, so promotion
changes placement only. A legacy task canvas uses the permission review shown
by its host. Canceling the review leaves the task canvas unchanged.
If promotion adds a permission, Kandev keeps the current active release until a user approves the new grant. The new release stays pending permission until that review finishes.
@@ -193,7 +208,7 @@ Use these recovery actions:
- Roll back to the retained prior release after a failed publish.
- Restore the database and matching artifact directory after a storage loss. See [Canvas artifacts and recovery](operations.md#canvas-artifacts-and-recovery).
- Archive a canvas to hide it from normal discovery. Restore it from the canvas controls.
- Remove a task canvas to remove its task-scoped data. Removing a task does not remove a canvas already promoted to a workspace.
- Remove a task canvas to remove the canvas and its data. Removing a task does not remove a canvas already promoted to a workspace.
- Remove a workspace canvas to remove its grants, state, tokens, releases, and artifacts after cleanup completes.
Kandev records artifact cleanup before it removes release ownership. A worker completes cleanup after the database transaction and retries it after a restart.
+12 -8
View File
@@ -121,11 +121,12 @@ does not need a Go backend or an injected Kandev JavaScript API.
the app needs.
5. Package the manifest and static files as a gzip-compressed tar archive.
For a new owner-created task canvas, the first valid release can receive the
declared supported task-scoped permissions through its initial permission
policy. Imported packages and later permission increases need human approval.
Keep `network_origins` as exact HTTPS origins. Do not use wildcards, paths,
credentials, query strings, or fragments.
For a new owner-authorized task canvas, the first valid release can receive
only its declared supported permissions through the initial permission policy.
Kandev data access is limited to the current workspace while the canvas stays
placed in its creating task. Imported packages and later permission increases
need human approval. Keep `network_origins` as exact HTTPS origins. Do not use
wildcards, paths, credentials, query strings, or fragments.
For example, a page can read task data with the browser Fetch API:
@@ -137,9 +138,12 @@ if (!response.ok) {
const tasks = await response.json();
```
Use `./_kandev/v1/events` for the event stream. Keep all protocol paths
relative so the same package works in task and workspace scope. Do not copy a
capability URL from the host into the app.
Use `./_kandev/v1/events` for the event stream. Read both `scope_kind` and
`data_scope_kind` from `./_kandev/v1/context`: the first describes placement,
and the second describes the Kandev data boundary. Keep all protocol paths
relative so the same package works in task and workspace placement. For task
lists, follow `page_info.next_cursor` to load every page. Do not set
`workspace_id` to another workspace or copy a capability URL from the host.
For recorded workflow movement, the browser can GET
`./_kandev/v1/data/tasks/{task_id}/step-transitions` with
+5 -2
View File
@@ -10,8 +10,8 @@ last_updated: 2026-09-10
# Canvases
Canvases own agent-authored task applications and their promotion to workspace
applications. The system owns canvas scope, source lineage, release selection,
editing sessions, discovery, and portable canvas distribution.
applications. The system owns canvas placement and data scope, source lineage,
release selection, editing sessions, discovery, and portable canvas distribution.
The Plugins system owns the web-application runtime, permissions,
Kandev data access, state, events, and package validation. The task system
@@ -20,18 +20,21 @@ remains authoritative for task data and permissions.
## Requirements
- [Agent-authored web-app canvases](requirements/agent-authored-web-apps.md)
- [Task canvas workspace data preview](requirements/task-canvas-workspace-preview.md)
- [Canvas marketplace and sharing](requirements/marketplace-sharing.md)
- [Deprecated collaborative canvases](requirements/collaborative-canvases.md)
## System design
- [Agent-authored web-app canvases](system-design/agent-authored-web-apps.md)
- [Task canvas workspace data preview](system-design/task-canvas-workspace-preview.md)
- [Canvas marketplace and sharing](system-design/marketplace-sharing.md)
- [Superseded collaborative canvases](system-design/collaborative-canvases.md)
## Related context
- [Runtime and permission fix plan](../../plans/canvas-runtime-permission-fixes/plan.md)
- [Task canvas workspace data preview plan](../../plans/task-canvas-workspace-preview/plan.md)
- [Agent MCP discovery guidance](../agents/system-design/mcp-tool-discovery-guidance.md)
- [MCP discovery and canvas prompt plan](../../plans/mcp-discovery-canvas-prompts/plan.md)
- [GitHub Copilot App Canvas reference](../../copilot-canvas-reference.md)
@@ -6,7 +6,7 @@ system: canvases
owners:
- canvases
created: 2026-08-26
last_updated: 2026-09-21
last_updated: 2026-09-23
---
# Agent-authored web-app canvases Requirements
@@ -15,7 +15,8 @@ last_updated: 2026-09-21
A canvas is a custom web application that an agent creates for one task. A
user can promote a useful task canvas to its workspace. A workspace canvas
appears in workspace navigation and can use workspace-scoped data.
appears in workspace navigation. An owner-authorized task canvas can already
use its workspace's data while the user reviews it in the originating task.
The Canvases system owns the canvas scope, source lineage, release selection,
promotion, editing flow, and discovery. The Plugins system owns the web-application
@@ -24,13 +25,13 @@ runtime and its data contract.
## Terminology
- **Task canvas:** A canvas that belongs to one task and appears only in that
task.
task. Its placement does not determine its approved data scope.
- **Workspace canvas:** A canvas that belongs to one workspace and appears in
workspace navigation. Agent-authored canvases reach this scope by promotion;
[distribution](marketplace-sharing.md) also defines reviewed package installs.
- **Draft:** Editable canvas source in an authorized agent workspace.
- **Release:** An immutable package that passed validation.
- **Promotion:** A user action that changes a task canvas to workspace scope.
- **Promotion:** A user action that changes a task canvas to workspace placement.
## Requirements
@@ -120,8 +121,8 @@ browser session end.
### REQ-CANVASES-AGENT-WEB-APPS-003: User-controlled promotion
**Intent:** A useful task canvas becomes a workspace application only after a
user reviews its scope and permissions.
**Intent:** A useful task canvas becomes available in workspace navigation only
after a user reviews its placement and permissions.
**User story:** As a user, I want to promote a useful task canvas, so that I
can open it from the workspace sidebar.
@@ -132,7 +133,8 @@ can open it from the workspace sidebar.
system shall show the requested data, write, event, state, and network
permissions before confirmation.
- **AC-CANVASES-AGENT-WEB-APPS-003.2:** When the user confirms promotion, the
same canvas identity and active release shall change to workspace scope.
same canvas identity and active release shall change to workspace placement.
A release that already has workspace data access shall keep that access.
- **AC-CANVASES-AGENT-WEB-APPS-003.3:** When promotion completes, the canvas
shall appear in navigation for that workspace only.
- **AC-CANVASES-AGENT-WEB-APPS-003.4:** An agent shall not promote, demote, or
@@ -342,6 +344,7 @@ including missing references, lookup failures, and passthrough exclusions.
- [Canvas runtime and task-entry recovery](../../../plans/canvas-runtime-entry-recovery/plan.md)
- [Direct canvas creation and saved prompt](../../../plans/canvas-direct-creation/plan.md)
- [Task canvas workspace data preview](../../../plans/task-canvas-workspace-preview/plan.md)
## Out of scope
@@ -6,7 +6,7 @@ system: canvases
owners:
- canvases
created: 2026-09-10
last_updated: 2026-09-10
last_updated: 2026-09-23
---
# Owner-authorized canvas creation
@@ -39,10 +39,11 @@ imported code and later changes cannot claim that creation authority.
- **AC-CANVASES-LOCAL-CREATION-001.1:** The first valid release of an
owner-authorized task canvas shall activate without a separate permission
approval. Its grants shall contain only its declared, supported permissions.
- **AC-CANVASES-LOCAL-CREATION-001.2:** Initial grants shall remain within the
task scope and current owner access. They can cover supported data reads,
writes, events, instance state, and exact HTTPS external origins. They shall
not enable remote scripts, managed backend execution, or workspace access.
- **AC-CANVASES-LOCAL-CREATION-001.2:** Initial grants shall contain only the
declared supported data reads, writes, events, instance state, and exact HTTPS
external origins. For a new owner-authorized canvas, those grants shall cover
the current workspace while the canvas remains in its task. They shall not
enable another workspace, remote scripts, or managed backend execution.
- **AC-CANVASES-LOCAL-CREATION-001.3:** Agent fields, package metadata, display
titles, and ownership of an imported package shall not establish local
creation authority. Missing or mismatched trusted identity shall deny it.
@@ -71,3 +72,4 @@ a marketplace, import UI, collaborator role, or ongoing blanket approval.
## Implementation plans
- [Canvas runtime and permission fixes](../../../plans/canvas-runtime-permission-fixes/plan.md)
- [Task canvas workspace data preview](../../../plans/task-canvas-workspace-preview/plan.md)
@@ -0,0 +1,88 @@
---
id: canvases-task-canvas-workspace-preview
title: Task canvas workspace data preview
status: draft
system: canvases
owners:
- canvases
created: 2026-09-23
last_updated: 2026-09-23
---
# Task canvas workspace data preview Requirements
## Overview
A user creates a canvas from a task and reviews the live application there
before deciding whether to add it to workspace navigation. Its task placement
must not reduce the data available to an owner-authorized first release.
Canvases owns the creation and promotion lifecycle; the Plugins system owns the
runtime data contract and grant enforcement.
## Terminology
- **Placement scope:** Where Kandev presents a canvas and which task owns its
unpromoted lifecycle.
- **Data scope:** The largest Kandev data boundary admitted by a release's
declared and granted capabilities. Data scope never overrides the viewing
user's current authorization.
## Requirements
### REQ-CANVASES-WORKSPACE-PREVIEW-001: Representative task canvas preview
**Intent:** A locally requested canvas works with the current workspace's live
data before the user chooses to promote it.
**User story:** As a user creating a canvas from a task, I want to see all tasks
in my current workspace, so that I can judge the canvas before promotion.
#### Acceptance criteria
- **AC-CANVASES-WORKSPACE-PREVIEW-001.1:** After the first valid release of an
owner-authorized task canvas activates, its declared task read capability
shall list and read all currently authorized tasks in the canvas's workspace,
including tasks added after publication. Refresh and pagination shall reach
the full result set. A task in another workspace shall remain unavailable.
- **AC-CANVASES-WORKSPACE-PREVIEW-001.2:** Before promotion, every supported
capability declared by that first release shall operate across the same
workspace where the capability has a workspace data meaning. Undeclared or
unsupported capabilities shall remain unavailable, and every operation shall
obey current user authorization.
- **AC-CANVASES-WORKSPACE-PREVIEW-001.3:** The canvas shall remain discoverable
only in its originating task until a user promotes it. Task removal shall
retain its existing cleanup behavior. Promotion shall still require user
confirmation, but it shall not be required to preview workspace data.
- **AC-CANVASES-WORKSPACE-PREVIEW-001.4:** The canvas context and host review
shall distinguish task placement from workspace data access. Promotion review
shall identify whether it changes data access or only placement.
- **AC-CANVASES-WORKSPACE-PREVIEW-001.5:** An existing task canvas with
task-only data access shall keep that access after upgrade until a current
workspace owner explicitly enables workspace data access. The review shall
name the active release and its declared permissions. Confirmation shall
widen only those declared grants without promoting or republishing the
canvas; cancellation shall change nothing.
- **AC-CANVASES-WORKSPACE-PREVIEW-001.6:** A stale review, changed owner,
revoked grant, missing task or workspace, or failed permission check shall
deny the access change without widening data exposure. A new release that
adds a capability after first publication shall still await permission
review.
- **AC-CANVASES-WORKSPACE-PREVIEW-001.7:** Desktop and phone users shall be
able to inspect the data scope and complete the existing-canvas access review
from the task canvas host. The phone flow shall remain usable with one
vertical scroll region, safe-area clearance, and touch controls.
- **AC-CANVASES-WORKSPACE-PREVIEW-001.8:** A canvas built under this contract
shall receive only workspace data authorized for its own workspace. Its
runtime token, manifest, or agent input shall not select a different
workspace or expand its capabilities.
## Out of scope
- Data from other workspaces or installation-wide grants.
- Blanket grants for capabilities a release does not declare.
- New canvas plugin capability types or arbitrary backend execution.
- Automatic widening of existing published releases.
## Implementation plans
- [Task canvas workspace data preview](../../../plans/task-canvas-workspace-preview/plan.md)
@@ -6,7 +6,7 @@ system: canvases
owners:
- canvases
created: 2026-08-26
last_updated: 2026-09-21
last_updated: 2026-09-23
requirements:
- REQ-CANVASES-AGENT-WEB-APPS-001
- REQ-CANVASES-AGENT-WEB-APPS-002
@@ -110,9 +110,11 @@ Use a small lifecycle record instead of declarative canvas blocks.
- nullable `archived_at`
- `created_at` and `updated_at`
The plugin instance owns `scope_kind`, active release, status, and grants. The
canvas service is the only service that changes the task or workspace scope of
a canvas instance.
The plugin instance owns placement `scope_kind`, effective data scope, active
release, status, and grants. The canvas service is the only service that
changes task or workspace placement or authorizes a canvas data-scope change.
The [workspace preview design](task-canvas-workspace-preview.md) separates
these scopes for locally requested task canvases.
The canvas and plugin instance have a one-to-one relationship. Canvas removal
removes the plugin instance, runtime tokens, grants, state, pending releases,
@@ -366,13 +368,14 @@ The promotion dialog shows:
- each event subject
- shared state access
- each exact external network origin
- the change from task scope to workspace scope
- the change from task placement to workspace placement, with any data-scope
difference identified separately
- the new workspace navigation placement
The user can cancel without a state change. Confirmation creates the approved
workspace grants and changes the plugin instance scope in one transaction. The
canvas keeps its ID, plugin instance, active release, state, and release
history.
The user can cancel without a state change. Confirmation creates any needed
workspace grants and changes the plugin instance placement scope in one
transaction. The canvas keeps its ID, plugin instance, active release, state,
and release history.
Promotion publishes one lifecycle event after commit. The task and workspace
navigation projections then refresh.
@@ -641,8 +644,10 @@ connection. An edit Quick Chat session also verifies its trusted target canvas
metadata.
Task canvases cannot appear in another task. Workspace canvases can serve task
surfaces only inside their workspace. Promotion does not grant access to tasks,
repositories, sessions, or external services by itself.
surfaces only inside their workspace. A task canvas can use approved workspace
data before promotion under the [workspace preview contract](task-canvas-workspace-preview.md).
Promotion does not grant undeclared access to tasks, repositories, sessions,
or external services.
The plugin runtime repeats resource authorization for each request. Canvas
authorization does not replace task or workspace authorization.
@@ -152,7 +152,8 @@ The definition in `config/prompts/create-canvas.md` contains this guidance:
> Call `publish_canvas_kandev` and address any validation errors.
> Report the canvas identity and whether its release is active, awaits permission review, or was unsuccessful.
> If publication is unsuccessful, report the failure and do not claim that the canvas is published.
> If workspace access requires promotion, explain the user action that is still required.
> A new owner-authorized task canvas can use its declared supported permissions across the current workspace before promotion.
> Promotion adds workspace navigation. Do not claim that promotion is required to preview workspace task data.
> A local build alone does not publish a canvas inside Kandev.
> If the tools remain unavailable, report the limitation instead of claiming that workspace files are a Kandev canvas.
@@ -6,7 +6,7 @@ system: canvases
owners:
- canvases
created: 2026-09-10
last_updated: 2026-09-10
last_updated: 2026-09-23
requirements:
- REQ-CANVASES-LOCAL-CREATION-001
---
@@ -20,7 +20,8 @@ owns grant storage, release activation, and runtime enforcement. This design
implements `REQ-CANVASES-LOCAL-CREATION-001`; the authority, transaction, and
compatibility sections map to criteria .1-.3, .4-.5, and .6-.7 respectively.
See [the creation authority decision](../../../decisions/2026-09-10-canvas-creation-authority.md)
See [the creation authority decision](../../../decisions/2026-09-10-canvas-creation-authority.md),
[its workspace-data amendment](../../../decisions/2026-09-23-task-canvas-workspace-data.md),
and [plugin grants](../../plugins/system-design/isolated-web-app-contributions.md#instance-grants).
## Trusted creation authority
@@ -40,7 +41,7 @@ Add a canvas-owned `canvas_creation_authority` table through
| `canvas_id` | Primary key, references the canvas lifecycle identity |
| `owner_user_id` | Trusted workspace owner at creation |
| `creating_session_id` | Trusted source session |
| `policy_version` | Integer 1 for the initial-publication policy |
| `policy_version` | Integer 1 for historical task-data grants; version 2 for new workspace-data grants |
| `consumed_at` | Empty until the first release transaction consumes it |
Create the row in the canvas/instance creation transaction. No agent-facing
@@ -52,7 +53,9 @@ Existing databases acquire the empty table; do not backfill authority.
At publication require every predicate: a nonzero captured `PublishAuthority`,
local-canvas instance source, task scope, matching task and workspace, matching
creating session, unchanged current owner, pending instance, no active or
persisted release, no previous grant changes, and unconsumed policy version 1.
persisted release, no previous grant changes, and an unconsumed supported
policy version. New authority uses version 2; historical version-1 authority
keeps its task data ceiling and is never upgraded by publication alone.
Check the full instance snapshot again inside the transaction. Re-read the
current task/workspace ownership through the same transaction and serialize
against ownership changes; the adapter's earlier lookup alone is insufficient.
@@ -64,10 +67,12 @@ The trusted adapter supplies the freshly resolved owner; caller-controlled
## Grant derivation and transaction
Derive grants from `ManifestPermissions` and the existing static web-app
capability vocabulary. Restrict Kandev resource access to the recorded task,
using normal runtime authorization. Normalize each declared external origin
through `NormalizeNetworkOrigins`; initial external grants count as delegated
owner approval, with that owner as `ApprovedBy`. This is deliberate: a locally
capability vocabulary. Version-2 authority binds the approved data scope to
the recorded workspace while the canvas remains task-placed. Historical
version-1 authority retains task data scope. See the
[workspace preview design](task-canvas-workspace-preview.md). Normalize each
declared external origin through `NormalizeNetworkOrigins`; initial external
grants count as delegated owner approval, with that owner as `ApprovedBy`. A locally
requested app can contact its declared HTTPS service on its first run.
Unsupported capabilities and backend/native contributions cannot gain access
through this path. Do not add a generic manifest-controlled auto-approve flag.
@@ -96,8 +101,9 @@ schema replay and backup enumeration must include this table.
## API and compatibility
Return an additive `initial_permission_policy` field in the create response:
version 1, eligibility, scope `task`, supported permission kinds, and the exact
HTTPS-origin constraint. This is descriptive output, never a publish input.
the policy version, eligibility, placement `task`, data scope, supported
permission kinds, and exact HTTPS-origin constraint. This is descriptive
output, never a publish input.
It must not claim a permission ceiling that the backend does not enforce.
Keep the existing `activated` and `permission_required` publish result fields.
@@ -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)
@@ -0,0 +1,72 @@
---
id: plugins-canvas-workspace-data-scope-design
title: Canvas placement and data scope in the web-app runtime
status: draft
system: plugins
owners:
- kandev
created: 2026-09-23
last_updated: 2026-09-23
requirements: []
---
# Canvas placement and data scope in the web-app runtime
## Boundary
This is the Plugins runtime implementation contract for the
[Canvas workspace preview requirement](../../canvases/requirements/task-canvas-workspace-preview.md).
Canvases decides when an owner-authorized local app may use workspace data.
Plugins persists and enforces that decision; it does not infer authority from
the manifest or browser request. The existing
[isolated web-app design](isolated-web-app-contributions.md) remains the general
runtime contract.
## Instance model and grants
Add nullable `plugin_instances.data_scope_kind`. A null value resolves to
`scope_kind` for retained rows and non-canvas instances. A non-null workspace
data scope is valid only for a `local_canvas` instance placed in a task or
workspace with a trusted `workspace_id`. Reject any attempt to use an
installation-wide data scope for a canvas. Creation, reviewed upgrade, and
promotion update the field and grants through transactions owned by the
canvas lifecycle service.
Grant fit, release activation, and runtime validation compare each declared
permission with the effective data scope. An exact task grant cannot cover
workspace data. A workspace grant authorizes only the bound workspace and is
still intersected with current user and resource access. Revocation and scope
changes increment the existing grant generation.
## Runtime binding and protocol
Add effective `DataScopeKind` to `webapp.CapabilityBinding`, sourced from the
persisted instance and checked against it on every request. Keep `ScopeKind`
for placement and task lifecycle. The relative context response exposes both
`scope_kind` and `data_scope_kind`; empty historical data scope resolves to
placement scope.
Task lists, single-task reads, task writes, messages, workflow reads, task
dependency projections, and events use data scope. Workspace-data task
canvases use the paginated workspace path, bounded by the trusted workspace
ID, rather than the task-only shortcut. Explicit foreign `workspace_id`
filters fail. Non-canvas instances retain current behavior.
## Compatibility and failure
The schema migration does not widen old rows. Historical runtime bindings
and grants remain task-scoped until a reviewed update changes them. A stale
binding, missing workspace/task, revoked grant, or mismatched data scope fails
closed through existing safe errors. Current plugin manifests and immutable
canvas packages need no rewrite.
## Verification
Test SQLite and PostgreSQL mapping, legacy null fallback, invalid scope
combinations, runtime token invalidation, exact grants, all workspace task
pages, task read/write and message paths, workflow and event scope, dependency
redaction, and foreign-workspace denial.
## Related decision
- [Task canvas workspace data](../../../decisions/2026-09-23-task-canvas-workspace-data.md)