5.9 KiB
Editor CMS Connection Implementation Plan
For agentic workers: Use superpowers:executing-plans inline. The user requests direct execution; do not pause for another execution-mode choice.
Goal: Let the web app load the real editor Skill and authenticate its own CMS session, then read genuine drama inventory and subtitles without exposing credentials.
Architecture: First implement the CMS/auth boundary as a separately testable milestone. It does not claim render readiness; the subsequent media milestone requires an authenticated source and explicit model/footage authorization. Original Skill and CMS code remain unchanged.
Tech Stack: Existing Fastify, React, Pi, Zod, pinned official Supabase JS client.
Spec: docs/superpowers/specs/2026-09-10-short-drama-web-design.md.
2026-09-14 execution checkpoint: Auth/API/UI/read-only tools are implemented. Full suite: 146 passed, lint/typecheck/build passed. Real login, 30-item catalog, Skill + CMS contract reads and status tool passed through the Vite/API/real-Qwen chain. Browser login/catalog also passed. Detailed evidence and remaining limitations: docs/editor-cms-web.md. Checklists below retain unverified cases (including explicit expiry, busy API mutation and browser content approval); do not interpret this milestone as full video acceptance.
Global Constraints
- localhost single-user app; no CMS writes, RLS changes, service_role, arbitrary shell or uploads.
- Authentication is a separate UI form; no password/token in chat, model tools, SSE or disk. Session reset clears only this app's CMS connection.
- Fixed Supabase project and CMS origin; reject redirects. Only verified app_metadata.role=admin is accepted, matching actual backend checks.
- Skill source is read-only; copy only explicitly enumerated references and script dependencies.
- Do not equate readable Skill/catalog with a finished video pipeline.
Task 1: Authenticated CMS boundary
Files: packages/harness/src/cms/cms-connection.ts, packages/harness/tests/cms-connection.test.ts.
Interface: CmsConnection({publishableKey,fetch?}): login(email,password), status(), clear(), listDramas(query,offset), inventory(dramaId), subtitle(dramaId,episodeId,locale).
- RED: create real service tests with injected external HTTP responses. Assert no data query before login; fail non-admin even with user_metadata.admin; status omits passwords/tokens; subtitle rejects an episode not in the requested drama; inventory completeness preserves missing sources. Example:
await expect(cms.listDramas('',0)).rejects.toMatchObject({code:'CMS_LOGIN_REQUIRED'}). - Run
../../node_modules/.bin/vitest run tests/cms-connection.test.tsin harness and observe missing implementation failure. - GREEN: use official
createClient(url,key,{auth:{persistSession:false,autoRefreshToken:false,detectSessionInUrl:false}}). CallsignInWithPasswordthengetUserand verify role. Fetch only known tables/selects, validate all returns with Zod; fixed CMS subtitle route and bounded responses. Never return raw SDK errors. - Verify tests and TypeScript, including expiry and disconnect; review credential lifecycle and request destinations.
Task 2: Session API and login UI
Files: apps/server/src/routes/cms.ts, apps/server/src/app.ts, apps/server/src/index.ts, apps/web/src/components/cms/CmsPanel.tsx, apps/web/src/App.tsx, corresponding route/component tests.
Interface: GET/POST/DELETE /api/sessions/:sessionId/cms/connection; GET /api/sessions/:sessionId/cms/dramas?q=&offset=. All authenticated CMS objects are mapped by Session; dispose clears them.
- RED: API rejects unknown Session, cross-origin mutation, concurrent login, busy mutation; private fields never appear in status. UI password empties on submission/failure/close; authenticated catalog selection fills an exact drama ID in Chat.
- Run test files and observe failures before implementation.
- GREEN: fixed-origin backend API, JSON-only login body, same-origin/fetch metadata guard, bounded login attempts, no-store. Status communicates
connectedandexpiresAt; no user email or credentials to model. UI accessible labels, pending/error states and an explicit notice of the destination receiving credentials. - Verify route and UI tests; unchanged report flow passes.
Task 3: Real Skill and read-only tools
Files: packages/harness/src/cms/editor-tools.ts, apps/server/src/index.ts, tool policy, Skill and web tests.
Interfaces: cms_connection_status, cms_list_dramas, cms_drama_inventory, cms_read_subtitle. Model never calls login or changes the connection. Inventory and subtitle access require page approval because they can disclose licensed/nonpublic content to the configured model.
- RED: Skill snapshot reads full reference hierarchy; tools reject data access before login; policy asks for content reads; discovery alone does not claim rendering ready.
- GREEN: enumerate trusted Skill resources, register tools only with that Skill, strict tool argument schemas, inject runtime instruction to report missing media/vision/research capability honestly and never use demo data.
- Run all tests, lint, typecheck, build, then restart only the local Agent Studio service with secrets via hidden stdin.
- Browser verify Skill entry, original instructions, login form and capability/status tools; request the user to authenticate through the form for the real CMS flow. Stop at a genuine missing login instead of inventing an admin session.
Remaining full-workflow milestones (not claimed by this plan)
After real CMS login is available: approved bounded HLS download; vision evidence and analysis v2 gate; configured reference research and scoring; immutable plan approval; fixed Python/FFmpeg worker with cancellation/quota; machine QA; human sound/viewing review; versioned downloads/export. Each requires its own test-first plan against the full spec. The task remains incomplete until these are verified on user-selected licensed footage.