# Tasks: enterprise-browser-clipboard **Change ID**: enterprise-browser-clipboard **Package**: `@suaveplan/clipboard` **Target path**: `browser/platform/clipboard` **Prerequisite packages on Verdaccio**: `@suaveplan/error`, `@suaveplan/logger` --- ## 0. Pre-flight (non-negotiable) - [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each) - [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Scaffold - [ ] Create directory tree per `proposal.md`. - [ ] `package.json` v0.0.0, `"sideEffects": false`. - `dependencies`: `@suaveplan/error workspace:^`, `@suaveplan/logger workspace:^`, `@suaveplan/schema-registry workspace:^`, `zod catalog:forms`, `@opentelemetry/api catalog:observability`, `tslib catalog:build` - `devDependencies`: `vitest catalog:testing`, `@vitest/coverage-istanbul catalog:testing`, `happy-dom catalog:testing`, `@playwright/test catalog:testing`, `@suaveplan/testing workspace:^` - Subpath exports: `"."`, `"./types"` - [ ] `tsconfig.json`, `vitest.config.ts` (pool: forks, happy-dom environment). --- ## 2. Error codes - [ ] `CLIPBOARD_API_UNAVAILABLE`, `CLIPBOARD_PERMISSION_DENIED`, `CLIPBOARD_FALLBACK_FAILED`, `CLIPBOARD_INSECURE_CONTEXT`. - [ ] `registerClipboardErrorCodes()` — call eagerly. --- ## 3. Types (`src/types/types/`) - [ ] `ClipboardData` (text, html, image, blobs), `ClipboardOptions`, `ClipboardResult`, `PermissionResult`, `ClipboardNavigator`. - [ ] Write `types.md`. --- ## 4. ClipboardOptions schema (`src/schema/clipboard-schema/`) - [ ] Zod schema for `ClipboardOptions`; `registerClipboardSchema()`. - [ ] Write `clipboard-schema.md`. --- ## 5. Async queue (`src/clipboard/queue/`) - [ ] `queue.ts` — `OperationQueue` serializes concurrent async operations; rejects queued calls after configurable timeout. - [ ] Write `queue.test.ts` (sequential execution, timeout rejection). Write `queue.md`. --- ## 6. Fallback module (`src/clipboard/fallback/`) - [ ] `fallback.ts` — `execCommandFallback(text)` for copy; `pasteEventFallback()` for read (focus + paste event capture). - [ ] `requireSecureContext()` — throws `CLIPBOARD_INSECURE_CONTEXT` on HTTP. - [ ] Focus-aware retry: on `Document is not focused`, wait for focus, retry once. - [ ] Write `fallback.test.ts` (execCommand success, paste capture, insecure context). Write `fallback.md`. --- ## 7. OTel metrics (`src/telemetry/metrics/`) - [ ] `metrics.ts` — counter `clipboard.copy_total{method}`, counter `clipboard.read_total{method}`, counter `clipboard.fallback_used_total`, counter `clipboard.error_total{code}`, histogram `clipboard.op_latency_ms`. - [ ] Write `metrics.md`. --- ## 8. `ClipboardManager` (`src/clipboard/clipboard/`) - [ ] `clipboard.ts` — `ClipboardManager` composing queue + fallback + metrics. - [ ] `copyText` / `readText` with secure-context guard + API → fallback path. - [ ] `copyRichContent` / `readRichContent` — `text/plain`, `text/html`, `image/png`, arbitrary MIME via `ClipboardItem`. - [ ] `checkPermission`, `onPermissionChange` via `PermissionStatus.onchange`. - [ ] Log deprecation metric when `execCommand` path fires. - [ ] Write `clipboard.test.ts` (all paths, image copy, permission change, queue serialization, insecure context). Write `clipboard.md`. --- ## 9. Integration test (`tests/integration.test.ts`) - [ ] Plain text copy + read round-trip. - [ ] Rich content (text + html) round-trip. - [ ] Queue serializes 3 concurrent copy calls. - [ ] Insecure-context throws `CLIPBOARD_INSECURE_CONTEXT`. --- ## 10. Playwright E2E (`e2e/clipboard.spec.ts`) - [ ] Chromium, WebKit, Firefox. - [ ] Copy and read plain text with real `clipboard-write` / `clipboard-read` permissions. - [ ] Copy and read PNG image in Chromium. - [ ] Permission-denied path returns `CLIPBOARD_PERMISSION_DENIED`. - [ ] `onPermissionChange` subscription fires on deny → grant transition. --- ## 11. Docs + verify - [ ] Write `.md` per module (≥200 words, API reference, examples). - [ ] Write `README.md` with browser-matrix table, API guide, permission guide. - [ ] `bunx turbo lint typecheck test --filter=@suaveplan/clipboard` — green. - [ ] `bunx turbo test:coverage` — 100%. - [ ] No `@ts-expect-error` in `src/` or tests. No `vi.stubGlobal`. - [ ] Playwright E2E green on Chromium, WebKit, Firefox. - [ ] `bun scripts/publish.ts --package @suaveplan/clipboard`. - [ ] Archive to `openspec/archive/2026-04-24-enterprise-browser-clipboard/`.