Files
suaveplan/openspec/changes/enterprise-browser-clipboard/tasks.md
2026-05-27 23:29:53 +01:00

4.9 KiB

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<T> 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/.