feat: Worker portal Stage 6 — Studio live-mode composer
Description
Land the Studio live-mode composer. Jurisdiction admins edit composition surfaces (worker / supervisor / analyst dashboards, case-detail) in a real-time editor; changes write to the live-override layer via Stage-3 live override APIs (#491 (closed)). The composition loader picks up edits on next jurisdiction-wide render thanks to ADR-021's invalidate-on-write cache.
v1 scope note: the promote modal (originally part of this issue's scope) was descoped when ADR-023 was reframed and deferred to #507 (unified canopy config backend). In v1, admins promote live overrides to baseline via their jurisdiction's existing baseline-edit workflow (PR / Salt / manual edit) external to canopy — no POST /v1/composition/{surface}/promote endpoint in v1, no Studio-driven PR generation. When #507 ratifies a write-capable backend, the promote modal returns as a follow-up MR. Issue weight reduced 5 → 3 to reflect this scope cut.
Acceptance Criteria
- Template at
services/canopy-web/templates/studio/live_mode.html - Live composer:
- Picker for surface (worker-dashboard / supervisor-dashboard / analyst-dashboard / case-detail)
- Visual editor that mirrors the live surface (drag to reorder; hide/show; resize span within
allowed_spans; change shell strategy per role for case-detail per ADR-021) - Save persists via Stage-3
PUT /v1/composition/{surface}/live(full patch-op list replace) orPATCH(append ops) - Composition loader picks up edits on next render via ADR-021's invalidate-on-write cache
- "Live override matches baseline" hint per ADR-022 lifecycle: when a baseline refresh detects the patched composition equals the post-refresh baseline, Studio prompts "Archive this live override?" with explicit "Archive" / "Keep" buttons. Archive calls
POST /v1/composition/{surface}/live/archive(#491 (closed)). - Gated to
studio_adminrole - Audit emitted on every live edit + archive per ADR-014
- Playwright E2E: edit → save → live render reflects; archive prompt fires when live matches baseline; Archive button moves row to
composition_documents_archive - axe-core WCAG 2.1 AA clean
- CHANGELOG entry under
=== Added
Out of v1 (deferred to #507)
- Promote modal (Studio-driven PR generation against jurisdiction baseline)
POST /v1/composition/{surface}/promoteendpoint- Diff view of live overrides vs current baseline (TOML or JSON-merge-patch) — currently only exists implicitly via the "live matches baseline" hint; an explicit diff view returns with the promote modal when #507 lands
Blocked by
- Stage 6 Studio onboarding issue merged (#499 (closed))
- Stage 3 live override APIs merged (#491 (closed))
Context & References
- Tracking issue: #460
- Epic: &51
- Plan: worker-portal-redesign.adoc, Stage 6
- ADR-021: composability runtime + plugin model (cache invalidation contract)
- ADR-022: composition override storage layering (Archive lifecycle, RFC 6902 patch ops)
- #507: deferred promote modal pending unified config backend
Labels
type::feature, priority::medium, program::infrastructure, service::web, workflow::needs-spec, compliance::wcag-21-aa