# Design — enterprise-clipboard > Non-normative rationale, algorithms, and file layout for the > `@suaveplan/clipboard` enterprise migration. Normative requirements live in > [`./specs/clipboard/spec.md`](./specs/clipboard/spec.md). ## Layout ```text packages/foundation/data/clipboard/ README.md package.json vite.config.ts vitest.config.ts tsconfig.lib.json src/ index.ts # explicit named re-exports types/ clipboard.types.ts # shared types: ClipboardData/Result/Options/... errors/ index.ts errors.ts # CLIPBOARD_CODES + ClipboardError errors.md errors.test.ts observability/ index.ts observability.ts # createClipboardObservability observability.md observability.test.ts observability.types.ts security/ index.ts security.ts # requireSecureContext + isSecure security.md security.test.ts queue/ index.ts queue.ts # AsyncQueue with FIFO ordering queue.md queue.test.ts sanitizer/ index.ts sanitizer.ts # default identity + Sanitizer interface sanitizer.md sanitizer.test.ts permissions/ index.ts permissions.ts # checkPermissions + onPermissionChange permissions.md permissions.test.ts fallback/ index.ts fallback.ts # textarea+execCommand + paste-event capture fallback.md fallback.test.ts manager/ index.ts manager.ts # ClipboardManager — orchestrates all features manager.md manager.test.ts ``` ## Public API ```ts // CLIPBOARD_CODES export const CLIPBOARD_CODES = defineCodes("CLIPBOARD", [ "API_UNAVAILABLE", // navigator.clipboard absent "PERMISSION_DENIED", // PermissionState === "denied" "FALLBACK_FAILED", // execCommand returned false or threw "INSECURE_CONTEXT", // window.isSecureContext === false "NO_CONTENT", // copyRichContent called with empty data "READ_FAILED", // read* threw "DOCUMENT_UNAVAILABLE", // document undefined (SSR) "QUEUE_DRAINED", // queued op cancelled because Manager was disposed ] as const); // Errors export class ClipboardError extends SuaveplanError {} // Manager export class ClipboardManager { constructor(opts?: Partial, nav?: ClipboardNavigator); copyText(text: string): Promise>; copyRichContent(data: ClipboardData): Promise>; readText(): Promise>; readRichContent(): Promise>; checkPermissions(): Promise; onPermissionChange(cb: PermissionChangeListener): () => void; isSupported(): boolean; isSecure(): boolean; dispose(): void; } ``` ## Async queue `AsyncQueue` holds a tail `Promise` and every `enqueue(fn)` call chains: ```ts class AsyncQueue { private tail: Promise = Promise.resolve(); enqueue(fn: () => Promise): Promise { const result = this.tail.then(() => fn(), () => fn()); this.tail = result.catch(() => undefined); return result; } drain(): Promise { return this.tail.then(() => undefined, () => undefined); } } ``` When `serialize: false` is passed, the manager calls `fn()` directly. ## Fallback flow `copyTextFallback(text)` creates a hidden `