# Live Artifacts Implementation Checklist ## Phase 0 — Contracts and fixtures - [ ] Define `html_template_v1` rendering contract. - [ ] Decide MVP binding syntax: Mustache-style `{{data.path}}`, `data-od-*` attributes, or both. - [ ] Specify that interpolation HTML-escapes by default. - [ ] Explicitly disallow raw / unescaped interpolation in MVP. - [ ] Specify allowed structural directives, if any. - [ ] Define shared bounded JSON constraints. - [ ] Max object depth. - [ ] Max array length. - [ ] Max string length. - [ ] Max serialized payload size. - [ ] Define shared contract DTOs for core types. - [ ] Add shared DTOs under `packages/contracts/src/api/live-artifacts.ts`. - [ ] Add connector DTOs under `packages/contracts/src/api/connectors.ts`. - [ ] Export new contract modules from `packages/contracts/src/index.ts`. - [ ] `BoundedJsonValue` / `BoundedJsonObject`. - [ ] `LiveArtifact`. - [ ] `LiveArtifactDocument`. - [ ] `LiveArtifactSource`. - [ ] `LiveArtifactProvenance`. - [ ] `ConnectorDetail`. - [ ] `ConnectorToolSafety`. - [ ] Implement daemon runtime validation schemas in `apps/daemon/src/live-artifacts/schema.ts`. - [ ] Consume or mirror shared contract DTOs without adding daemon internals to `packages/contracts`. - [ ] Validate persisted artifact files and create/update inputs. - [ ] Define create/update input schemas. - [ ] `LiveArtifactCreateInput`. - [ ] `LiveArtifactUpdateInput`. - [ ] Reject daemon-owned fields from agent input: `id`, `projectId`, `createdAt`, `createdByRunId`, `schemaVersion`, `refreshStatus`. - [ ] Extend the shared API error envelope for live artifact and connector failures. - [ ] Add live artifact / connector `ApiErrorCode` values in `packages/contracts/src/errors.ts`. - [ ] Use `ApiErrorResponse` for agent-facing tool endpoint failures. - [ ] Put validation field details in the existing error `details` field. - [ ] Add fixture artifacts under `specs/2026-04-29-live-artifacts/examples/`. - [ ] Minimal static `html_template_v1` artifact. - [ ] Invalid fixture containing forbidden raw provider fields. - [ ] Invalid fixture containing credential-like fields. - [ ] Add schema validation tests. - [ ] Reject `raw`, `rawResponse`, `payload`, `body`, `headers`, `cookie`, `authorization`, `token`, `secret`, `credential`, `password` keys. - [ ] Reject path traversal. - [ ] Reject oversized JSON. - [ ] Accept valid fixture artifacts. ## Phase 1A — Static live artifact registration - [ ] Create daemon live artifact module structure. - [ ] `apps/daemon/src/live-artifacts/schema.ts`. - [ ] `apps/daemon/src/live-artifacts/store.ts`. - [ ] `apps/daemon/src/live-artifacts/render.ts`. - [ ] Implement project-scoped storage layout. - [ ] `/projects//.live-artifacts//artifact.json`. - [ ] `/projects//.live-artifacts//template.html`. - [ ] `/projects//.live-artifacts//data.json`. - [ ] `/projects//.live-artifacts//provenance.json`. - [ ] `/projects//.live-artifacts//refreshes.jsonl`. - [ ] `/projects//.live-artifacts//snapshots/`. - [ ] Support `OD_DATA_DIR` override through existing daemon runtime data-dir conventions. - [ ] Implement artifact ID and slug generation. - [ ] Implement safe path resolution. - [ ] Ensure all reads/writes stay inside project workspace. - [ ] Reject absolute paths from agent payloads. - [ ] Reject `..` traversal. - [ ] Implement `createLiveArtifact` service. - [ ] Validate create input. - [ ] Assign daemon-owned fields. - [ ] Persist files atomically where practical. - [ ] Generate initial `index.html` as derived preview output. - [ ] Implement `listLiveArtifacts` service. - [ ] Read project live artifact directories. - [ ] Return compact summaries. - [ ] Hide snapshots and implementation files. - [ ] Implement `getLiveArtifact` service. - [ ] Add daemon routes for UI reads. - [ ] `GET /api/live-artifacts?projectId=...`. - [ ] `GET /api/live-artifacts/:artifactId`. - [ ] Add daemon tool routes for agent registration. - [ ] `POST /api/tools/live-artifacts/create`. - [ ] `GET /api/tools/live-artifacts/list`. - [ ] Implement run-scoped tool token infrastructure. - [ ] Define run as one `/api/chat` invocation. - [ ] Mint `OD_TOOL_TOKEN` per run. - [ ] Bind token to `runId`, `projectId`, allowed endpoints, allowed operations, and expiry. - [ ] Revoke token when child process exits. - [ ] Revoke token when SSE stream ends. - [ ] Revoke token when TTL expires. - [ ] Isolate concurrent runs under the same project. - [ ] Inject runtime tool environment into agent session. - [ ] `OD_DAEMON_URL`. - [ ] `OD_TOOL_TOKEN`. - [ ] Enforce `/api/tools/*` auth. - [ ] Require bearer token. - [ ] Derive project scope from token. - [ ] Reject request-supplied project overrides. - [ ] Enforce endpoint allowlist. - [ ] Enforce operation allowlist. ## Phase 1B — Preview and UI integration - [ ] Implement preview renderer. - [ ] Load `template.html`. - [ ] Load `data.json` as source of truth. - [ ] Apply `html_template_v1` bindings. - [ ] HTML-escape interpolated values. - [ ] Regenerate derived `index.html` when needed. - [ ] Add preview route. - [ ] `GET /api/live-artifacts/:artifactId/preview`. - [ ] Serve with iframe-compatible response. - [ ] Apply restrictive CSP. - [ ] Apply iframe sandbox assumptions. - [ ] Apply local daemon security to preview routes. - [ ] Host header validation. - [ ] Origin validation. - [ ] CORS restrictions. - [ ] CSRF protection where relevant. - [ ] DNS rebinding protection. - [ ] Add live artifact type definitions to frontend. - [ ] Keep live artifacts distinct from the static artifact model. - [ ] Do not add live artifacts as a static `ArtifactKind`. - [ ] Model workspace items as a discriminated `kind: 'live-artifact'` entry. - [ ] Use namespaced tab IDs such as `live:`. - [ ] Extend frontend provider/registry methods. - [ ] List live artifacts. - [ ] Fetch live artifact detail. - [ ] Build preview URL. - [ ] Add entry-header connector surface. - [ ] Add `Connectors` tab in `apps/web/src/components/EntryView.tsx`. - [ ] In Phase 1B, show stubbed or local-only connector cards until Phase 3 connector APIs are implemented. - [ ] Display connector name, category/provider, status, account label, and connect/configure actions as available. - [ ] Add new project live artifact entry. - [ ] Add `New live artifact` to new project tabs in `apps/web/src/components/NewProjectPanel.tsx`. - [ ] Start normal project creation with live-artifact intent / skill path. - [ ] List live artifacts in the `Designs` tab. - [ ] Show live artifacts as first-class selectable entries associated with their parent project/design. - [ ] Visually distinguish entries with `Live` / `Refreshable` status. - [ ] Open directly into the parent project workspace with the live artifact selected. - [ ] Optionally show live-artifact count/status on parent design cards. - [ ] Show live artifacts as virtual nodes in the artifact tree. - [ ] One node per live artifact. - [ ] Hide `snapshots/` by default. - [ ] Render under a virtual group in `FileWorkspace.tsx`. - [ ] Add badges. - [ ] `Live`. - [ ] `Refreshable`. - [ ] `Refreshing...`. - [ ] `Refresh failed`. - [ ] `Archived`. - [ ] Add preview panel support. - [ ] Load preview route in iframe. - [ ] Add `LiveArtifactViewer` path in `apps/web/src/components/FileViewer.tsx`. - [ ] Reuse existing `HtmlViewer` toolbar / iframe / sandbox patterns. - [ ] Add `Preview` tab. - [ ] Add `Source` tab. - [ ] Add `Data` tab. - [ ] Add `Provenance` tab. - [ ] Add `Refresh history` tab. - [ ] Ensure `data.json` is source of truth. - [ ] Treat any API `dataJson` as derived cache only. - [ ] On divergence, prefer `data.json`. ## Phase 1C — Built-in skill and wrapper CLI - [ ] Add built-in skill directory. - [ ] `skills/live-artifact/SKILL.md`. - [ ] `skills/live-artifact/references/artifact-schema.md`. - [ ] `skills/live-artifact/references/connector-policy.md`. - [ ] `skills/live-artifact/references/refresh-contract.md`. - [ ] Write skill frontmatter. - [ ] `name: live-artifact`. - [ ] Trigger keywords for live dashboards/reports. - [ ] `od.mode: prototype`. - [ ] `od.preview.type: html`. - [ ] `od.outputs.primary: index.html`. - [ ] Required capabilities: `shell`, `file_write`. - [ ] Write skill workflow instructions. - [ ] Determine if user wants live vs static artifact. - [ ] Use daemon wrappers instead of raw curl. - [ ] Write `template.html`, `data.json`, `artifact.json`, `provenance.json`. - [ ] Include `template.html` in declared skill outputs. - [ ] Treat `index.html` as derived preview output. - [ ] Never store credentials or raw provider responses. - [ ] Keep `data.json` compact and preview-oriented. - [ ] Implement wrapper CLI. - [ ] `od tools live-artifacts create --input artifact.json`. - [ ] `od tools live-artifacts list --format compact`. - [ ] `od tools live-artifacts update --artifact-id --input artifact.json`. - [ ] `od tools live-artifacts refresh --artifact-id `. - [ ] Implement project-owned command code as TypeScript under `apps/daemon/src`. - [ ] Ensure wrapper reads injected environment. - [ ] `OD_DAEMON_URL`. - [ ] `OD_TOOL_TOKEN`. - [ ] Ensure wrapper returns agent-friendly output. - [ ] Compact success JSON. - [ ] Compact validation errors. - [ ] Non-zero exit code on failure. - [ ] Update system prompt / skill preamble injection. - [ ] Include daemon URL. - [ ] Include token availability without exposing unnecessary internals. - [ ] Verify skill discovery. - [ ] Skill appears in catalog. - [ ] Skill body includes root preamble for references/assets. - [ ] Active agent receives live artifact workflow instructions. ## Phase 2 — Refresh runner - [ ] Implement refresh storage. - [ ] Append-only `refreshes.jsonl`. - [ ] Refresh step status. - [ ] Refresh duration. - [ ] Connector/tool metadata. - [ ] Compact error records. - [ ] Implement refresh lock. - [ ] One active refresh per artifact. - [ ] Reject or queue concurrent refreshes. - [ ] Implement monotonic refresh IDs. - [ ] Prevent stale refresh from overwriting newer committed data. - [ ] Implement timeout and cancellation. - [ ] Per-source timeout. - [ ] Total refresh timeout. - [ ] User cancellation path. - [ ] Implement crash recovery. - [ ] Detect stale `running` refreshes on daemon startup. - [ ] Mark timed-out stale runs as failed. - [ ] Preserve last valid preview. - [ ] Implement local daemon refresh sources. - [ ] `project_files.search`. - [ ] `project_files.read_json`. - [ ] `git.summary`. - [ ] Implement declarative output mapping. - [ ] `outputMapping.dataPaths`. - [ ] `identity` transform. - [ ] `compact_table` transform. - [ ] `metric_summary` transform. - [ ] Implement all-or-nothing refresh commit. - [ ] Build candidate `data.json`. - [ ] Validate all candidates. - [ ] Commit only if all refreshable sources succeed. - [ ] Keep previous data/preview if any source fails. - [ ] Implement snapshot behavior. - [ ] Successful snapshots under `snapshots//`. - [ ] Failed attempts summarized in `refreshes.jsonl`. - [ ] Decide whether failed payloads are retained under hidden failed snapshot directory. - [ ] Add refresh UI. - [ ] Refresh button. - [ ] Running state. - [ ] Success state. - [ ] Failure state with actionable error. - [ ] Implement refresh permission flow. - [ ] Initial state `refreshPermission: none`. - [ ] First manual refresh confirmation. - [ ] Persist `manual_refresh_granted_for_read_only` after approval. - [ ] Allow revoke from Source tab. - [ ] Emit refresh events. - [ ] Extend `packages/contracts/src/sse/chat.ts` for live artifact create/update/refresh events. - [ ] Translate live artifact SSE payloads in `apps/web/src/providers/daemon.ts`. - [ ] Auto-open created/updated live artifacts via the existing project open-request flow. - [ ] Update viewer refresh loading/failure state. ## Phase 3 — Connector catalog and read-only connector tools - [ ] Create connector module structure. - [ ] `apps/daemon/src/connectors/catalog.ts`. - [ ] `apps/daemon/src/connectors/service.ts`. - [ ] `apps/daemon/src/connectors/routes.ts`. - [ ] `apps/daemon/src/tools/connectors.ts`. - [ ] Implement connector catalog. - [ ] Static connector definitions. - [ ] Featured tools. - [ ] Allowed tools. - [ ] Minimum approval policy. - [ ] Implement connector status service. - [ ] `available`. - [ ] `connected`. - [ ] `error`. - [ ] `disabled`. - [ ] `accountLabel`. - [ ] Add connector UI/API endpoints. - [ ] `GET /api/connectors`. - [ ] `GET /api/connectors/:connectorId`. - [ ] `POST /api/connectors/:connectorId/connect`. - [ ] `DELETE /api/connectors/:connectorId/connection`. - [ ] Defer OAuth callback routes until OAuth-backed connectors are implemented. - [ ] Implement connector tool endpoints. - [ ] `GET /api/tools/connectors/list`. - [ ] `POST /api/tools/connectors/execute`. - [ ] Implement connector wrapper CLI. - [ ] `od tools connectors list --format compact`. - [ ] `od tools connectors execute --connector --tool --input input.json`. - [ ] Implement project-owned command code as TypeScript under `apps/daemon/src`. - [ ] Implement read-only safety classification. - [ ] Scope/name contains write/create/update/delete/admin/send/post/manage → write/confirm. - [ ] Destructive hints → destructive/disabled for refresh. - [ ] Explicit read-only hints → read/auto. - [ ] Unknown → write/confirm. - [ ] Enforce policy at execution time. - [ ] Re-check allowlist. - [ ] Re-check current scopes. - [ ] Re-check tool safety. - [ ] Re-check connector status. - [ ] Fail closed if read-only tool becomes write-capable. - [ ] Never make write/destructive/unknown tools refreshable. - [ ] Implement connector output protections. - [ ] Max serialized output size, e.g. 256KB. - [ ] Per-run rate limit, e.g. 10 calls/minute. - [ ] Per-run total call limit, e.g. 60 calls/run. - [ ] Redact credentials and provider envelope fields. - [ ] Return compact summaries where possible. - [ ] Implement credential storage policy. - [ ] Store OAuth credentials outside project artifacts. - [ ] Use daemon-controlled global store or app database. - [ ] Persist only connector references in artifacts. - [ ] Never write tokens/headers/cookies/OAuth state under live artifact directories. - [ ] Add first connector or public/local provider. - [ ] Prefer local/public source before OAuth-backed provider. - [ ] Validate read-only refresh end-to-end. - [ ] Update skill references. - [ ] Document connector listing. - [ ] Document connector execution. - [ ] Document read-only refresh rules. - [ ] Document credential handling constraints. ## Phase 4 — Optional MCP wrapper - [x] Confirm need for MCP after skill + wrapper path works. - [x] Design MCP server as wrapper over existing daemon services. - [ ] Do not make MCP required. - [ ] Do not mutate user global MCP config automatically. - [ ] Keep skill + CLI path unchanged. - [ ] Add MCP discovery only for agents with mature MCP support. - [x] Verify Claude Code or another MCP-capable agent can discover equivalent tools. ## Cross-cutting verification - [ ] Run schema tests. - [ ] Run daemon route tests. - [ ] Run storage/path traversal tests. - [ ] Run preview renderer tests. - [ ] Run token auth tests. - [ ] Run refresh failure fallback tests. - [ ] Run connector policy tests. - [ ] Run frontend build/typecheck. - [ ] Run an end-to-end local artifact create flow with one supported agent. - [ ] Run an end-to-end refresh flow using a local read-only source. - [ ] Verify no fixture or generated artifact contains raw credentials, headers, cookies, or full provider payloads.