type Locale = "es" | "en"; interface SnapshotConfig { /** allowlist of localStorage keys to include (never a wholesale dump) */ localStorage?: string[]; /** include non-HttpOnly document.cookie (default false) */ cookies?: boolean; } /** * The closed sets the server accepts. Mirrored here so a host app gets * autocomplete and a compile error for a typo; the server still normalizes * anything it doesn't know, so this staying slightly behind is harmless. * Source of truth: GET /api/v1/reports/taxonomy. */ type ReportCategory = "bug" | "ui" | "performance" | "data" | "other"; type ReportPriority = "low" | "medium" | "high" | "urgent"; interface WidgetConfig { /** public write-only ingest key (pk_…) */ projectKey: string; /** UI language (default 'es') */ locale?: Locale; /** ingest base URL, e.g. https://cac.guz-studio.dev */ endpoint?: string; /** curated extra context attached to every report */ context?: () => Record; /** * Identity of the reporter, taken from the host app's session (not asked in * the form). Populates who-reported in the console and scopes the future * "my reports" view. e.g. () => ({ id: session.user.id, name: session.user.name }) */ reporter?: () => { id?: string; name?: string; email?: string; }; /** * Area applied to every report this widget files, when the form doesn't ask. * Per-app rather than global: "Sala de Operaciones" means something in one * tenant and nothing in another. */ defaultArea?: string; /** opt-in localStorage/cookie snapshot (server redacts/encrypts) */ snapshot?: SnapshotConfig; /** * allowlist of URL path globs whose request bodies are captured on FAILURE * only (e.g. ['/api/checkout', '/api/forms/*']). Payment/auth hosts are * always excluded regardless of this list. */ captureBodies?: string[]; /** extra field names to scrub from captured bodies (merged with defaults) */ scrubFields?: string[]; /** theme for the launcher button */ theme?: { color?: string; position?: "bottom-right" | "bottom-left"; }; } interface ReporterImage { id: string; fileName: string; url: string; } interface ReporterComment { author: "you" | "team" | "system"; body: string; images?: ReporterImage[]; createdAt: string; } interface ReporterReport { id: string; folio: string; title: string; description: string; status: "pending" | "in_progress" | "resolved" | "closed"; createdAt: string; updatedAt: string; images: ReporterImage[]; comments: ReporterComment[]; } interface ErrorBreadcrumb { ts: number; message: string; stack?: string; source?: string; kind: "error" | "unhandledrejection"; } interface ConsoleBreadcrumb { ts: number; level: "error" | "warn"; text: string; } interface NetworkBreadcrumb { ts: number; method: string; url: string; status: number; durationMs: number; body?: string; } interface NavBreadcrumb { ts: number; from: string; to: string; } interface Telemetry { errors: ErrorBreadcrumb[]; console: ConsoleBreadcrumb[]; network: NetworkBreadcrumb[]; nav: NavBreadcrumb[]; } export type { ConsoleBreadcrumb as C, ErrorBreadcrumb as E, Locale as L, NavBreadcrumb as N, ReportCategory as R, SnapshotConfig as S, Telemetry as T, WidgetConfig as W, ReportPriority as a, ReporterReport as b, NetworkBreadcrumb as c, ReporterComment as d, ReporterImage as e };