@cookiemunch/sdk 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts DELETED
@@ -1,4267 +0,0 @@
1
- export { CONSENT_COOKIE_NAME, ConsentCategory, ConsentSource, ConsentTokenClaims, DEFAULT_JWKS_URL, JsonWebKeySet, KeySetOptions, ReadConsentOptions, ReadSignedConsentOptions, ServerConsent, SignableDecision, VerifyTokenOptions, consentSignaturePayload, getConsent, isAllowed, parseConsentValue, readConsent, verifyDecisionSignature, verifyToken } from './consent.cjs';
2
-
3
- /**
4
- * Request/response shapes for the Cookie Munch Developer API (/v1). These mirror the
5
- * server's dev-api surface; they are defined here (rather than imported) so the SDK
6
- * has no runtime/workspace dependency on the server package.
7
- */
8
- interface Identity {
9
- orgId: string;
10
- orgName?: string | null;
11
- /** The EFFECTIVE plan — the one every feature gate and limit uses. */
12
- plan: string;
13
- /**
14
- * Why: `org` = this org's own subscription (or free, or a reseller-managed `child` plan);
15
- * `account` = another org with the same owner pays for a higher plan that covers this one.
16
- */
17
- planSource: PlanSource;
18
- /** What this org subscribes to itself (`free` = no subscription of its own). */
19
- subscribedPlan: string;
20
- /** Features the effective plan unlocks (e.g. `whiteLabel`, `tcf`, `sso`, `abTesting`). */
21
- features: string[];
22
- keyPrefix: string;
23
- /** null = full access. */
24
- scopes?: string[] | null;
25
- unscoped?: boolean;
26
- propertyLocked?: boolean;
27
- cbids?: string[];
28
- reseller?: boolean;
29
- /** This organisation is a sandbox (`sandbox.create()`): test keys, test rights requests, never billed. */
30
- sandbox?: boolean;
31
- /** For a sandbox: the live organisation it belongs to. */
32
- sandboxOf?: string;
33
- }
34
- type PlanSource = 'org' | 'account';
35
- /** One organisation on an account (GET /v1/orgs, and the `org_limit` refusal). */
36
- interface AccountOrg {
37
- id: string;
38
- name: string;
39
- /** The effective plan. */
40
- plan: string;
41
- planSource: PlanSource;
42
- subscribedPlan: string;
43
- /** Present on a reseller-managed child organisation. */
44
- parentOrgId?: string;
45
- createdAt: number;
46
- /** True for the organisation the calling key belongs to. */
47
- current: boolean;
48
- }
49
- interface AccountOrgs {
50
- orgs: AccountOrg[];
51
- /** The per-account org cap: `max` (null = unlimited), the `plan` that sets it, and `used`. */
52
- orgLimit: {
53
- max: number | null;
54
- plan: string;
55
- used: number;
56
- };
57
- /** The dashboard billing page, where a plan is chosen. */
58
- upgradeUrl: string;
59
- }
60
- interface Site {
61
- cbid: string;
62
- orgId: string;
63
- domain: string;
64
- /** The business name data subjects see on the rights page, in notices and the policy. Absent: the domain is shown. */
65
- name?: string;
66
- /** Other hosts serving the site: accepted consent-ingest origins, never verified claims. */
67
- aliases?: string[];
68
- verified?: boolean;
69
- }
70
- /** PATCH /v1/sites/{cbid} — rename or move a site. `name: null` clears the name; `aliases: []` clears them. */
71
- interface SiteUpdate {
72
- domain?: string;
73
- name?: string | null;
74
- aliases?: string[];
75
- }
76
- interface SiteUpdateResult {
77
- dryRun?: true;
78
- site: Site;
79
- diff: Array<{
80
- field: 'domain' | 'name' | 'aliases' | 'verified';
81
- before: unknown;
82
- after: unknown;
83
- }>;
84
- effects: {
85
- /** `reset`: the domain moved; verify the new one. */
86
- verification: 'kept' | 'reset';
87
- scanTarget: string;
88
- previewDefaultUrl: string;
89
- displayName: string;
90
- /** Custom rights-page hostnames no longer under the domain or an alias (left in place). */
91
- staleRightsDomains: string[];
92
- };
93
- warnings?: Array<{
94
- field: string;
95
- reason: string;
96
- }>;
97
- }
98
- /** One row of GET /v1/integration-health. `ok: null` = the check could not run (see `detail`). */
99
- interface HealthRow {
100
- /** The suite shape's name for `check` (always equal). */
101
- id: string;
102
- check: string;
103
- /** The generic check this row is an instance of (`forumulate.webhook` → `webhook.delivery`); otherwise `check`. */
104
- kind: string;
105
- /** The vendor a vendor-specific instance is about. */
106
- vendor?: string;
107
- ok: boolean | null;
108
- severity: 'error' | 'warning' | 'info';
109
- subject: string;
110
- fixHint?: string;
111
- /** The same as fixHint (suite shape). */
112
- fix?: string;
113
- /** Where the check and its fix are explained. */
114
- docs: string;
115
- detail?: string;
116
- /** Network checks: the hop that failed (or, on success, the last one reached). */
117
- hop?: 'dns' | 'tls' | 'http' | 'challenge' | 'auth';
118
- status?: number;
119
- elapsedMs?: number;
120
- /** Failed network checks: a stable code (ENOTFOUND, timeout, challenge, http_503, …). */
121
- error?: string;
122
- /** A waiver covers this failing row; `ok` is then null. */
123
- waived?: {
124
- reason: string;
125
- by: string;
126
- until: number | null;
127
- };
128
- lastCheckedAt: number;
129
- }
130
- interface IntegrationHealthReport {
131
- cbid: string;
132
- checkedAt: number;
133
- generatedAt: string;
134
- ok: boolean;
135
- counts: {
136
- error: number;
137
- warning: number;
138
- notChecked: number;
139
- waived: number;
140
- };
141
- checks: HealthRow[];
142
- }
143
- /** PUT /v1/integration-health/waivers. */
144
- interface HealthWaiverInput {
145
- /** Optional when the organisation has one site. */
146
- cbid?: string;
147
- /** A row's `check` or `kind`. */
148
- check: string;
149
- /** A row's `subject`; omitted: every subject of the check (`*`). */
150
- subject?: string;
151
- /** Why this is deliberate (1–500 characters). */
152
- reason: string;
153
- /** ISO date or epoch ms, future, within a year; omitted or null: never expires. */
154
- until?: string | number | null;
155
- }
156
- interface HealthWaiver {
157
- cbid: string;
158
- check: string;
159
- subject: string;
160
- reason: string;
161
- by: string;
162
- until: number | null;
163
- createdAt: number;
164
- expired?: boolean;
165
- }
166
- /** POST /v1/provision. Secrets are used for the request only and never returned. */
167
- interface ProvisionRequest {
168
- product: string;
169
- domain: string;
170
- name?: string;
171
- aliases?: string[];
172
- cbid?: string;
173
- /** `frontendApiHost` (e.g. auth.example.com) lets provision declare Atlas's sign-in cookies on the site. */
174
- /** `rightsIdentity` (default true) makes Atlas the site's rights sign-in (step `rights.identity`). */
175
- atlas?: {
176
- secretKey: string;
177
- cookieConsent?: boolean;
178
- dsrWebhook?: boolean;
179
- rightsIdentity?: boolean;
180
- frontendApiHost?: string;
181
- };
182
- forumulate?: {
183
- token: string;
184
- orgId: string;
185
- consent?: boolean;
186
- executorKey?: boolean;
187
- label?: string;
188
- };
189
- rightsApi?: {
190
- baseUrl: string;
191
- secretKey: string;
192
- profilePreset?: string;
193
- };
194
- }
195
- interface ProvisionStep {
196
- /** v2 answers: the stable step id (`fromStep` takes it). */
197
- id?: string;
198
- step: string;
199
- status: 'created' | 'updated' | 'unchanged' | 'would_create' | 'would_update' | 'skipped' | 'waiting' | 'waiting_on' | 'failed' | 'passed';
200
- detail?: string;
201
- diff?: Array<{
202
- field: string;
203
- before: unknown;
204
- after: unknown;
205
- }>;
206
- /** A string in v1 answers; `{ platform, items }` in v2 answers. */
207
- waitingOn?: string | {
208
- platform: string;
209
- items: string[];
210
- };
211
- }
212
- interface ProvisionResult {
213
- dryRun: boolean;
214
- product: string;
215
- cbid: string | null;
216
- steps: ProvisionStep[];
217
- summary: {
218
- changed: number;
219
- unchanged: number;
220
- waiting: number;
221
- failed: number;
222
- };
223
- /** v2 answers only. */
224
- version?: 2;
225
- ids?: {
226
- orgId: string;
227
- cbid: string | null;
228
- executors: Record<string, string>;
229
- webhooks: string[];
230
- };
231
- sealedSecrets?: Array<Record<string, unknown>>;
232
- checklist?: string[];
233
- }
234
- /** A partner the deployment knows: built in (forumulate, atlas, chatly, referalli) or any other registered on it. */
235
- type PartnerId = 'forumulate' | 'atlas' | 'chatly' | 'referalli' | (string & {});
236
- interface PartnerLinkCreate {
237
- partner: PartnerId;
238
- /** The partner's id for the receiving account (a Forumulate organisation id, an Atlas instance id). */
239
- externalId: string;
240
- label?: string;
241
- events?: Array<'consent.recorded' | 'consent.withdrawn'>;
242
- }
243
- interface PartnerLink {
244
- id: string;
245
- cbid: string;
246
- partner: PartnerId;
247
- externalId: string;
248
- label?: string;
249
- events: string[];
250
- status: 'active' | 'waiting_on_partner' | 'revoked';
251
- /** e.g. "Forumulate (docs) — receiving consent events". */
252
- summary: string;
253
- waitingOn?: string;
254
- createdAt: number;
255
- createdBy?: string;
256
- revokedAt?: number;
257
- revokedBy?: string | null;
258
- lastDeliveryAt: number | null;
259
- lastError: string | null;
260
- }
261
- interface PartnerCatalogEntry {
262
- id: PartnerId;
263
- label: string;
264
- externalIdLabel: string;
265
- events: string[];
266
- available: boolean;
267
- waitingOn?: string;
268
- }
269
- interface SiteCreate {
270
- domain: string;
271
- /** Optional; the server auto-generates a cbid when omitted. */
272
- cbid?: string;
273
- }
274
- /** Site config is an open, deeply-nested object owned by @cookiemunch/core. */
275
- type SiteConfig = Record<string, unknown>;
276
- interface ConsentDay {
277
- Date: string;
278
- OptIn: number;
279
- OptOut: number;
280
- OptInImplied: number;
281
- OptInStrict: number;
282
- TypeOptInPref: number;
283
- TypeOptInStat: number;
284
- TypeOptInMark: number;
285
- Impressions: number;
286
- Countries: Record<string, number>;
287
- }
288
- interface ConsentLogRow {
289
- stamp: string;
290
- receivedAt: number;
291
- region: string;
292
- method: string;
293
- choices: {
294
- preferences: boolean;
295
- statistics: boolean;
296
- marketing: boolean;
297
- };
298
- anonIp: string;
299
- url: string;
300
- }
301
- interface RangeQuery {
302
- from?: number;
303
- to?: number;
304
- }
305
- interface LogQuery extends RangeQuery {
306
- limit?: number;
307
- }
308
- type DsarType = 'access' | 'deletion' | 'rectification' | 'portability' | 'opt-out' | 'closure' | 'restriction';
309
- /** A type word as sent: the canonical words, or an alias (`erasure`/`erase` → deletion, `export` → access). */
310
- type DsarTypeWord = DsarType | 'erasure' | 'erase' | 'export';
311
- type Regulation = 'gdpr' | 'ccpa';
312
- type DsarStatus = 'received' | 'verifying' | 'in_progress' | 'completed' | 'rejected' | 'cancelled';
313
- interface DsarRequest {
314
- id: string;
315
- type: DsarType;
316
- subjectEmail: string;
317
- regulation: Regulation;
318
- status: DsarStatus;
319
- createdAt: number;
320
- dueAt: number;
321
- /** Where the subject said they are, when the intake captured it. */
322
- jurisdiction?: string;
323
- /** INTERNAL: intake note plus the audit lines `/erase` and `/export` append. Never shown to the subject. */
324
- note?: string;
325
- /** The line the subject reads in the response notice. */
326
- messageToSubject?: string;
327
- /** A test request: off the SLA board, labelled, and deletable with `dsar.delete`. A closed request can be marked one with `dsar.markTest`. */
328
- test?: boolean;
329
- /** Its type in the suite vocabulary (`erasure` was stored as `deletion`). */
330
- canonicalType?: string;
331
- /** The case's X-ForgeDeck-Trace, when it has one. */
332
- trace?: string;
333
- }
334
- /** A signed-in identity from any OIDC issuer the site trusts. `(iss, sub)` is the key. */
335
- interface SubjectIdentity {
336
- iss: string;
337
- sub: string;
338
- ext?: string;
339
- principal?: string;
340
- }
341
- /** Who a case is about. `atlas` is accepted as an alias of `identity`. */
342
- interface DsarSubject {
343
- emails: string[];
344
- identity?: SubjectIdentity;
345
- atlas?: SubjectIdentity;
346
- }
347
- /** POST /v1/dsar/requests. */
348
- interface DsarCaseCreate {
349
- cbid: string;
350
- type: DsarTypeWord;
351
- subject?: DsarSubject;
352
- /** The person's own token from the site's sign-in issuer (aud `cookiemunch:<cbid>`). */
353
- subjectToken?: string;
354
- /** product and atlas need dsar:write and attest the person; admin (default) files it received. */
355
- source?: 'product' | 'atlas' | 'admin';
356
- reason?: string;
357
- /** Connections not to ask: system names, connection ids, or `self`. */
358
- skipSystems?: string[];
359
- /** Default true. */
360
- fulfill?: boolean;
361
- regulation?: 'gdpr' | 'ccpa' | 'lgpd' | 'pipeda' | 'vcdpa';
362
- jurisdiction?: string;
363
- test?: boolean;
364
- }
365
- type DsarCaseStatus = 'pending' | 'scheduled' | 'processing' | 'completed' | 'completed_with_retention' | 'rejected' | 'cancelled';
366
- interface RetentionLine {
367
- category: string;
368
- basis: 'legal_obligation' | 'legal_claims' | 'contract' | 'public_interest';
369
- until?: string;
370
- }
371
- interface DsarCaseTask {
372
- system: string;
373
- executorId: string | null;
374
- taskId: string;
375
- status: DsarCaseStatus | 'no_match';
376
- requestId: string | null;
377
- eta: string | null;
378
- completedAt: string | null;
379
- detail: string | null;
380
- retention?: RetentionLine[];
381
- }
382
- /** A case across every connected system. */
383
- interface DsarCase {
384
- id: string;
385
- type: DsarType;
386
- canonicalType: string;
387
- status: DsarCaseStatus;
388
- requestStatus: DsarStatus;
389
- cbid?: string;
390
- source: 'product' | 'atlas' | 'rights_page' | 'admin' | null;
391
- reason: string | null;
392
- openedAt: string;
393
- /** Nothing is erased anywhere before this. */
394
- executeAfter: string | null;
395
- graceDays: number | null;
396
- closedAt: string | null;
397
- /** False for a closure: no statutory clock. */
398
- statutory: boolean;
399
- dueAt: string | null;
400
- verification: string | null;
401
- trace: string | null;
402
- subject: {
403
- emails: string[];
404
- identity: SubjectIdentity | null;
405
- };
406
- skipSystems: string[];
407
- fulfill: boolean | null;
408
- cancelRequestedAt: string | null;
409
- test: boolean;
410
- tasks: DsarCaseTask[];
411
- receiptUrl: string;
412
- /** Lets the person who asked read this case through POST /api/v1/public/dsar/status. */
413
- statusToken?: string;
414
- }
415
- /** One signed receipt for a case (Ed25519; verify with GET /v1/partner/jwks.json). */
416
- interface DsarCaseReceipt {
417
- receiptVersion: number;
418
- caseId: string;
419
- type: DsarType;
420
- canonicalType: string;
421
- status: DsarCaseStatus;
422
- openedAt: string;
423
- executeAfter: string | null;
424
- closedAt: string | null;
425
- verification: string | null;
426
- trace: string | null;
427
- subject: {
428
- emailHashes: string[];
429
- identityHash?: string;
430
- atlasSubHash?: string;
431
- };
432
- systems: Array<{
433
- system: string;
434
- executorId: string | null;
435
- requestId: string | null;
436
- status: string;
437
- completedAt: string | null;
438
- trace: string | null;
439
- retention?: RetentionLine[];
440
- }>;
441
- issuedAt: string;
442
- signature: {
443
- alg: 'Ed25519';
444
- kid: string;
445
- value: string;
446
- covers?: string;
447
- };
448
- }
449
- /** A site's rights-request settings. */
450
- interface DsarSettings {
451
- cbid: string;
452
- /** Days an erasure or account closure waits before any system acts (0–30). 7 for a new site; 0 for one that existed before (opt-in). */
453
- graceDays: number;
454
- /** site: set explicitly; default: a new site's 7 days; legacy: an existing site, 0 until set. */
455
- source: 'site' | 'default' | 'legacy';
456
- updatedAt: number | null;
457
- }
458
- /** GET /v1/integrations/{app}/card. */
459
- interface SubjectCard {
460
- app: string;
461
- openCases: Array<{
462
- id: string;
463
- type: string;
464
- status: string;
465
- executeAfter: string | null;
466
- openedAt: string;
467
- receiptUrl: string;
468
- }>;
469
- consent: null;
470
- }
471
- /**
472
- * How a rights-page requester was verified — on every answer of the public intake
473
- * (`POST /api/v1/public/dsar`, `/verify`, `/resend`) and so in the `dsar.created` webhook payload.
474
- * `email_code` on a 202: a code was mailed through your own provider; on a 201: the code matched.
475
- * `none` with a `reason`: filed without verification — confirm the requester yourself. `none`
476
- * without one: an opt-out, which needs no verification.
477
- */
478
- type PublicVerification = {
479
- method: 'session' | 'email_code' | 'account_link';
480
- } | {
481
- method: 'none';
482
- reason?: 'no_verification_configured' | 'mail_failed' | 'recipient_rejected';
483
- };
484
- /** A public intake that filed a request (201): also the `dsar.created` payload for one. */
485
- interface PublicDsarFiled {
486
- id: string;
487
- status: 'received' | 'verifying';
488
- /** Epoch ms the statutory response is due. */
489
- deadline: number;
490
- /** Only when filed without verification; the same as `verification.method` `none` with a `reason`. */
491
- unverified?: true;
492
- verification: PublicVerification;
493
- }
494
- /** A public intake waiting for its email code (202). */
495
- interface PublicDsarPending {
496
- pendingId: string;
497
- expiresAt: number;
498
- resendAfter?: number;
499
- verification: {
500
- method: 'email_code';
501
- };
502
- }
503
- interface DsarCreate {
504
- type: DsarType;
505
- subjectEmail: string;
506
- /** Picks the statutory response window. */
507
- regulation: Regulation;
508
- /**
509
- * Where the subject says they are (ISO 3166 country or country-subdivision, e.g.
510
- * `US-TX`). The response notice names the statute that governs there — without it a
511
- * Texan is told their request was handled under a Virginia law, since every US state
512
- * shares one `regulation` for the deadline.
513
- */
514
- jurisdiction?: string;
515
- /** INTERNAL: kept on the request, never shown to the subject. */
516
- note?: string;
517
- /** The one free-text line the subject reads in the notice (≤2000 chars; an API key or key prefix is refused). */
518
- messageToSubject?: string;
519
- /** The property this request belongs to; decides which connected systems answer it. */
520
- cbid?: string;
521
- /** The subject's consent-receipt id. */
522
- stamp?: string;
523
- /**
524
- * Mark it as a test: left out of SLA metrics and the deadline board, labelled as a test,
525
- * and deletable with `dsar.delete(id)`. For end-to-end checks of a rights flow.
526
- */
527
- test?: boolean;
528
- }
529
- interface VendorInput {
530
- name: string;
531
- category: string;
532
- dataShared: string[];
533
- dpaSigned: boolean;
534
- subprocessors: number;
535
- certifications: string[];
536
- region: string;
537
- }
538
- interface RiskScore {
539
- score: number;
540
- band: 'low' | 'medium' | 'high';
541
- }
542
- /** A stored vendor record (no computed risk; see {@link ScoredVendor}). Returned as the
543
- * `vendor` field of POST /v1/vendors. */
544
- interface VendorRecord extends VendorInput {
545
- id: string;
546
- }
547
- /** A vendor as listed, with its computed risk flattened in. */
548
- interface ScoredVendor extends VendorRecord {
549
- risk: RiskScore;
550
- }
551
- type LegalBasis = 'consent' | 'contract' | 'legal-obligation' | 'vital-interests' | 'public-task' | 'legitimate-interests';
552
- interface RopaInput {
553
- name: string;
554
- purpose: string;
555
- legalBasis: LegalBasis;
556
- dataCategories: string[];
557
- recipients: string[];
558
- retentionDays: number;
559
- crossBorderTransfer: boolean;
560
- }
561
- interface RopaEntry extends RopaInput {
562
- id: string;
563
- }
564
- /** A signed consent receipt (shape owned by @cookiemunch/receipts). */
565
- type SignedReceipt = Record<string, unknown>;
566
- /** How a preference-center opt-in was captured. Mirrors @cookiemunch/preferences OptInMethod. */
567
- type OptInMethod = 'single-opt-in' | 'double-opt-in';
568
- /**
569
- * A subject's saved preference-center record (identity-keyed named purposes, distinct
570
- * from the org-level {@link PreferenceItem} catalog). Matches @cookiemunch/preferences
571
- * PreferenceRecord (mirrored here per this package's no-server-dependency convention).
572
- * Returned wrapped as `{ record }` by POST /v1/preferences.
573
- */
574
- interface PreferenceRecord {
575
- subjectId: string;
576
- purposes: Record<string, boolean>;
577
- method: OptInMethod;
578
- confirmed: boolean;
579
- updatedAt: number;
580
- version: number;
581
- }
582
- /** GET /v1/categories/registry — the reserved category templates (CMU-X15). */
583
- interface CategoryRegistry {
584
- version: 1;
585
- standard: string[];
586
- suite: Array<{
587
- id: 'support_chat' | 'referrals';
588
- stance: 'necessary_on_request' | 'opt_in_eu_uk';
589
- fallback: 'preferences' | 'marketing';
590
- /** By banner language. */
591
- labels: Record<string, string>;
592
- descriptions: Record<string, string>;
593
- basis?: string[];
594
- vendors?: Array<{
595
- product: string;
596
- storage: string[];
597
- }>;
598
- }>;
599
- }
600
-
601
- interface VerifyWebhookInput {
602
- /** The raw request body, exactly as received. Do NOT re-stringify parsed JSON. */
603
- payload: string;
604
- /** The `X-CookieMunch-Signature` header value. */
605
- signature: string | undefined | null;
606
- /** The `X-CookieMunch-Timestamp` header value (unix seconds). */
607
- timestamp: string | number | undefined | null;
608
- /** The subscription secret (`whsec_…`), shown once when the webhook was created. */
609
- secret: string;
610
- /**
611
- * Maximum age (in seconds) of a delivery before it is rejected as stale/replayed.
612
- * Defaults to 300 (5 minutes). Pass 0 to disable the freshness check entirely.
613
- */
614
- toleranceSeconds?: number;
615
- /** Current time in ms (injectable for tests); defaults to `Date.now()`. */
616
- now?: number;
617
- }
618
- /**
619
- * Returns true only when the signature is valid AND (unless disabled) the timestamp is fresh.
620
- * Fail-closed: any missing/malformed input returns false rather than throwing.
621
- */
622
- declare function verifyWebhookSignature(input: VerifyWebhookInput): boolean;
623
-
624
- interface MintConsentSyncTokenInput {
625
- /** The site's consent-sync secret (`cmss_…`). */
626
- secret: string;
627
- /** The site the token is for. A token for one site is refused by every other. */
628
- cbid: string;
629
- /** Who is signed in: 1–128 of `A-Z a-z 0-9 . _ : @ + / = ~ -`. Use an opaque id. */
630
- subject: string;
631
- /** Lifetime in seconds. Default 3600; at most 86400 (Cookie Munch refuses longer). */
632
- ttlSeconds?: number;
633
- /** Current time in ms (injectable for tests). */
634
- now?: number;
635
- }
636
- declare function mintConsentSyncToken(input: MintConsentSyncTokenInput): string;
637
-
638
- /**
639
- * The cm-standard-v2 executor conformance kit (CMU-X20).
640
- *
641
- * cm-standard-v2 is an open contract: any system that holds personal data can implement it and
642
- * be driven by Cookie Munch with no code on our side (docs: cookiemunch.net/docs/executor-contract-v2).
643
- * This kit checks an implementation rule by rule, and names the rule that fails. It is the same
644
- * suite Cookie Munch runs on `POST /v1/dsar/executors/{id}/test {conformance: true}`, and the
645
- * `cookiemunch executors conformance <baseUrl>` command runs it from a terminal or CI.
646
- *
647
- * It only ever touches the CANARY subject — an address no real person has. The contract asks every
648
- * implementation to treat the canary as an existing synthetic person: it is found by its email and
649
- * by its identity, requests on it move through the full state machine, and nothing real is ever
650
- * erased. So the kit can check that an erasure waits for `executeAfter`, that a cancel leaves the
651
- * person in place, and that an identity is never matched to someone else through a shared email —
652
- * without a real person's data being anywhere near it.
653
- *
654
- * No dependencies: `fetch` only, so it runs in Node 18+, a browser, or an edge runtime.
655
- */
656
- type ConformanceStatus = 'pass' | 'fail' | 'skip';
657
- interface ConformanceRuleResult {
658
- /** A stable id, e.g. `requests.execute_after.scheduled`. */
659
- id: string;
660
- /** What the rule says, in one sentence. */
661
- title: string;
662
- status: ConformanceStatus;
663
- /** What was seen, when it failed or was skipped. */
664
- detail?: string;
665
- }
666
- interface ConformanceReport {
667
- /** True when no rule failed. */
668
- ok: boolean;
669
- passed: number;
670
- failed: number;
671
- skipped: number;
672
- rules: ConformanceRuleResult[];
673
- /** The `X-Version` the executor answered with, when it sent one. */
674
- version?: string;
675
- }
676
- interface ConformanceOptions {
677
- /** The executor's base: the contract paths are `{baseUrl}/privacy/lookup` and so on. https (http only for localhost). */
678
- baseUrl: string;
679
- /** The credential Cookie Munch would send. */
680
- secret: string;
681
- /**
682
- * The canary address: `canary-<16 hex>@canary.cookiemunch.net`, per organisation
683
- * (`GET /v1/dsar/executors/presets` → `canaryEmail`).
684
- */
685
- canaryEmail: string;
686
- /** How the secret is sent. Default `Authorization: Bearer {secret}`. */
687
- auth?: {
688
- header: string;
689
- format: string;
690
- };
691
- /** Path prefix under baseUrl. Default `/privacy`. */
692
- prefix?: string;
693
- fetch?: typeof fetch;
694
- now?: () => number;
695
- /** A per-run tag for idempotency keys and case ids. Default random. */
696
- runId?: string;
697
- }
698
- /** The issuer the canary identity carries. */
699
- declare const CANARY_ISSUER = "https://canary.cookiemunch.net";
700
- /** The canary subject's identity, derived from its address. */
701
- declare function canaryIdentityFor(canaryEmail: string): {
702
- iss: string;
703
- sub: string;
704
- ext: string;
705
- };
706
- /** Every rule, in the order they run. */
707
- declare const CONFORMANCE_RULES: ReadonlyArray<{
708
- id: string;
709
- title: string;
710
- }>;
711
- /** Run every rule against one executor. Never throws for an executor's answer; only for bad options. */
712
- declare function runExecutorConformance(o: ConformanceOptions): Promise<ConformanceReport>;
713
-
714
- /**
715
- * Operator token exchange (RFC 8693, CMU-X33): swap your identity provider's token for a short-lived,
716
- * scoped Cookie Munch API key, so no long-lived key has to live in a file.
717
- *
718
- * import { exchangeOperatorToken, createCookieMunch } from '@cookiemunch/sdk';
719
- * const { accessToken } = await exchangeOperatorToken({
720
- * subjectToken: process.env.STAFF_ACCESS_TOKEN!, // from the sign-in your organisation trusts
721
- * scope: ['sites:read', 'dsar:read'],
722
- * resource: 'org:2f1c…', // or 'site:<cbid>' to lock the key to one site
723
- * });
724
- * const client = createCookieMunch({ apiKey: accessToken, baseUrl: 'https://api.cookiemunch.net' });
725
- *
726
- * No API key is needed for the exchange itself. The key it returns expires on its own (at most an hour).
727
- */
728
- interface OperatorTokenExchangeInput {
729
- /** The access or ID token from an OIDC issuer the deployment trusts. */
730
- subjectToken: string;
731
- /** Which kind of token `subjectToken` is. Default `access_token`. */
732
- subjectTokenType?: 'access_token' | 'jwt' | 'id_token';
733
- /** The API scopes the key should carry. Required: an exchanged key is never full access. */
734
- scope: string[];
735
- /** `org:<id>`, or `site:<cbid>` to lock the key to one site. */
736
- resource: `org:${string}` | `site:${string}`;
737
- /** Seconds, 60 to 3600. Default 3600. */
738
- expiresIn?: number;
739
- /** Default `https://api.cookiemunch.net`. */
740
- baseUrl?: string;
741
- fetch?: typeof fetch;
742
- }
743
- interface OperatorTokenExchangeResult {
744
- /** A scoped Cookie Munch API key. */
745
- accessToken: string;
746
- expiresIn: number;
747
- scope: string[];
748
- }
749
- /** Thrown with the RFC 6749 `error` and `error_description` the server answered. */
750
- declare class TokenExchangeError extends Error {
751
- readonly error: string;
752
- readonly status: number;
753
- constructor(error: string, status: number, description?: string);
754
- }
755
- declare function exchangeOperatorToken(input: OperatorTokenExchangeInput): Promise<OperatorTokenExchangeResult>;
756
-
757
- /**
758
- * Types for `window.__fdConsent`, the shared consent API any embed can code against — a chat
759
- * widget, a referral snippet, an analytics tag — whatever CMP the page runs. Cookie Munch sets
760
- * it natively; `fd-consent-shim.js` sets the same object over Cookiebot, OneTrust or no CMP.
761
- * Type-only: importing this module adds nothing to a bundle.
762
- *
763
- * import type { FdConsent, FdConsentQueue } from '@cookiemunch/sdk';
764
- * const fd = (window.__fdConsent ??= { q: [] });
765
- * if ('version' in fd) fd.on('change', (s) => …); else fd.q.push(['on', 'change', (s) => …]);
766
- *
767
- * `version` changes only with a breaking change; new members do not bump it.
768
- */
769
- /** What caused a change. The same causes Cookie Munch's ledger records. */
770
- type FdCause = 'replay' | 'accept' | 'decline' | 'selection' | 'withdraw' | 'implied' | 'sync' | 'request' | 'migrated';
771
- interface FdSnapshot {
772
- /** False until the visitor has answered. */
773
- decided: boolean;
774
- /** False when this visitor's region and the site's rules need no answer (a default applies). */
775
- required: boolean;
776
- /** Every category the site offers (standard, custom, reserved) and its answer. */
777
- categories: Record<string, boolean>;
778
- /** The decision's stamp (`CookieMunch.consentId()`), or null. */
779
- stamp: string | null;
780
- region: string;
781
- /** A Global Privacy Control signal was seen. */
782
- gpc: boolean;
783
- /** ISO 8601, or null before a decision. */
784
- decidedAt: string | null;
785
- }
786
- interface FdRequestOptions {
787
- /** One sentence in the page's language: what will be stored and why. Shown as the prompt's text. */
788
- reason: string;
789
- /** Who is asking: your vendor id. Recorded with the answer. */
790
- vendor: string;
791
- }
792
- interface FdConsent {
793
- readonly version: 1;
794
- /** `cookiemunch`, or `shim:cookiebot` / `shim:onetrust` / `shim:none`. */
795
- readonly provider: string;
796
- /** Resolves once a decision exists, or at once where the region needs none. */
797
- ready(): Promise<FdSnapshot>;
798
- /** true / false, or null while a required decision is pending. Never false for "not decided". */
799
- has(category: string): boolean | null;
800
- /** Fires once per decision (a returning visitor's as `replay`); a withdrawal synchronously. Returns unsubscribe. */
801
- on(event: 'change', cb: (snapshot: FdSnapshot, cause: FdCause) => void): () => void;
802
- /** Ask for one category at the moment you need it. Never re-asks a refusal; one prompt per category per page view. */
803
- request(category: string, opts: FdRequestOptions): Promise<boolean>;
804
- /** Not available yet: warns once and does nothing. */
805
- identify(token: string): void;
806
- layout: {
807
- bottomInset(): number;
808
- on(cb: (insetPx: number) => void): () => void;
809
- };
810
- /** Calls made on the queue before this existed ran in order; later pushes run at once. */
811
- q: {
812
- push(...calls: FdQueuedCall[]): number;
813
- };
814
- }
815
- /** A call queued before the real object exists. */
816
- type FdQueuedCall = ['on', 'change', (snapshot: FdSnapshot, cause: FdCause) => void] | ['ready', (snapshot: FdSnapshot) => void] | ['request', string, FdRequestOptions, (granted: boolean) => void] | ['identify', string];
817
- /** What an embed that loads first creates: `window.__fdConsent = window.__fdConsent || { q: [] }`. */
818
- interface FdConsentQueue {
819
- q: FdQueuedCall[];
820
- }
821
- declare global {
822
- interface Window {
823
- __fdConsent?: FdConsent | FdConsentQueue;
824
- }
825
- }
826
-
827
- /**
828
- * @cookiemunch/sdk — a small, typed REST client for the Cookie Munch Developer API
829
- * (the /v1 surface). Construct it with an API key; the org is derived server-side
830
- * from the key, so callers never pass an orgId. `fetch` is injectable for testing
831
- * and non-browser/non-Node runtimes; it defaults to the global fetch.
832
- *
833
- * const fc = createCookieMunch({ apiKey: 'fck_…', baseUrl: 'https://api.cookiemunch.net' });
834
- * const sites = await fc.sites.list();
835
- */
836
-
837
- /**
838
- * This package's version, sent in the default User-Agent. Cloudflare answers a request with
839
- * no recognisable User-Agent with `403 error code: 1010`; a test pins this to package.json.
840
- */
841
- declare const SDK_VERSION = "0.7.1";
842
- interface CookieMunchOptions {
843
- apiKey: string;
844
- /** "https://api.cookiemunch.net" — the /v1 prefix is appended automatically. */
845
- baseUrl: string;
846
- /** Injectable for tests / custom runtimes. Defaults to the global fetch. */
847
- fetch?: typeof fetch;
848
- /**
849
- * Send `Prefer: strict-unknown-fields` on every write: a body field the operation does not
850
- * declare is refused (`400 unknown_field`, with `field`) instead of ignored. Catches typos.
851
- */
852
- strictUnknownFields?: boolean;
853
- /** The `User-Agent` sent on every request. Default `cookiemunch-js/<version>`. */
854
- userAgent?: string;
855
- /**
856
- * Serve every request under this dated API version (`CookieMunch-Version`, e.g. `'2026-10-24'`) instead of the
857
- * one your key is pinned to. `versions()` lists them; `keys.updateSelf({ apiVersion })` re-pins the key.
858
- */
859
- apiVersion?: string;
860
- /**
861
- * Seal every once-shown secret to this X25519 public key (`x25519:<base64>`): answers carry `sealed_secret`
862
- * (a libsodium sealed box) and `sealed_field` instead of the plaintext. Sent as `X-Secret-Recipient` on writes.
863
- */
864
- secretRecipient?: string;
865
- /**
866
- * Extra headers on every request, e.g. `{ 'Idempotency-Key': '<forgedeck ref>:<run>' }` on a client made for
867
- * one create: a retry with the same key replays the first answer (secrets included) for 24 hours.
868
- */
869
- headers?: Record<string, string>;
870
- }
871
- /** Tags on a created resource (CMU-X29). `forgedeck_sandbox: true` can only be set at creation. */
872
- type ResourceMetadata = Record<string, string | number | boolean>;
873
- /** Keep only resources whose tags match, e.g. `{ forgedeck_product: 'referalli' }`. */
874
- interface MetadataFilter {
875
- metadata?: Record<string, string>;
876
- }
877
- /** externalRef and metadata, accepted by every create (orgs, sites, webhooks, executors, DSARs, partner links). */
878
- interface ResourceTagsInput {
879
- /** Your own name for it, unique per org and type: a repeat create with the same body returns the existing one. */
880
- externalRef?: string;
881
- metadata?: ResourceMetadata;
882
- }
883
- type TaggedType = 'org' | 'site' | 'webhook' | 'executor' | 'dsar' | 'partner_link';
884
- interface ResourceTags {
885
- type: TaggedType;
886
- id: string;
887
- metadata: ResourceMetadata;
888
- externalRef: string | null;
889
- sandbox: boolean;
890
- }
891
- interface ResourceTagsUpdate {
892
- dryRun?: true;
893
- type: TaggedType;
894
- id: string;
895
- metadata: ResourceMetadata;
896
- diff: Array<{
897
- field: string;
898
- before: unknown;
899
- after: unknown;
900
- }>;
901
- }
902
- /** What a sandbox hard delete removed. */
903
- interface SandboxPurge {
904
- deleted: true;
905
- cbid?: string;
906
- orgId?: string;
907
- counts: Record<string, number>;
908
- }
909
- /** A partner link in the suite-standard shape (CMU-X34). */
910
- interface StandardPartnerLink {
911
- id: string;
912
- partner: string;
913
- resource: string;
914
- scopes: string[];
915
- created_at: string | null;
916
- expires_at: string | null;
917
- last_used_at: string | null;
918
- calls_30d: number;
919
- status: 'active' | 'waiting_on_partner' | 'revoked' | 'expired';
920
- externalId?: string;
921
- label?: string;
922
- }
923
- interface StandardPartnerLinkCreate extends ResourceTagsInput {
924
- partner: string;
925
- /** `site:<cbid>` or `org:<org id>`. */
926
- resource: string;
927
- scopes: Array<'consent:read' | 'receipt:read' | 'dsar:read' | 'dsar:write' | 'dsar:rights-links' | 'sites:read'>;
928
- expires_at?: string;
929
- externalId?: string;
930
- label?: string;
931
- }
932
- /** POST /v1/provision v2: the `cookiemunch` block of a forgedeck.yaml (see the forgedeck API map page). */
933
- interface ProvisionRequestV2 {
934
- forgedeck: {
935
- ref?: string;
936
- product: string;
937
- env?: string;
938
- sandbox?: boolean;
939
- };
940
- site: {
941
- domain: string;
942
- name?: string;
943
- aliases?: string[];
944
- locales?: string[];
945
- preset?: string;
946
- devOrigins?: string[];
947
- };
948
- cbid?: string;
949
- categories?: string[];
950
- rightsIdentity?: Record<string, unknown>;
951
- dsar?: {
952
- graceDays?: number;
953
- };
954
- atlas?: {
955
- instanceId?: string;
956
- secretKey?: string;
957
- cookieConsent?: boolean;
958
- executor?: boolean;
959
- frontendApiHost?: string;
960
- };
961
- forumulate?: {
962
- org?: string;
963
- orgId?: string;
964
- token?: string;
965
- consent?: boolean;
966
- executor?: boolean;
967
- label?: string;
968
- };
969
- chatly?: {
970
- workspace?: string;
971
- publicId?: string;
972
- vendorHook?: boolean;
973
- executor?: boolean;
974
- };
975
- self?: {
976
- baseUrl: string;
977
- contract?: string;
978
- secret: string;
979
- };
980
- referalli?: {
981
- orgId?: string;
982
- trackingToken?: string;
983
- preset?: boolean;
984
- partner?: boolean;
985
- executor?: string | boolean;
986
- };
987
- embedManifests?: string | string[];
988
- brand?: {
989
- url?: string;
990
- };
991
- }
992
- /** GET /v1/provision/env: names, non-secret values, and references for secrets. */
993
- interface ProvisionEnv {
994
- ref: string;
995
- cbid: string;
996
- env: Array<{
997
- name: string;
998
- value?: string;
999
- secretRef?: string;
1000
- }>;
1001
- }
1002
- /** A vended short-lived key, shown once. */
1003
- interface ApiKeyVended {
1004
- key: string;
1005
- prefix: string;
1006
- expiresAt: number;
1007
- scopes: string[];
1008
- cbids: string[] | null;
1009
- }
1010
- /** The suite-standard key listing (GET /v1/keys?shape=standard). */
1011
- interface StandardKeyList {
1012
- keys: Array<{
1013
- id: string;
1014
- prefix: string;
1015
- name: string | null;
1016
- owner: string | null;
1017
- kind: string | null;
1018
- env: string | null;
1019
- format: string | null;
1020
- scopes: string[] | null;
1021
- resources: string[] | null;
1022
- created_at: string | null;
1023
- expires_at: string | null;
1024
- last_used_at: string | null;
1025
- last_used_ip: string | null;
1026
- status: 'active' | 'expired';
1027
- }>;
1028
- }
1029
- /** A leaked secret to revoke (POST /v1/keys/revoke_leaked, no authentication needed). */
1030
- type LeakReport = {
1031
- key: string;
1032
- source?: string;
1033
- } | {
1034
- keys: string[];
1035
- source?: string;
1036
- };
1037
- /**
1038
- * Thrown for any non-2xx response. `message` is the server's `error` field when present;
1039
- * `code` is populated from the server's `code` field whenever the error body carries one
1040
- * (e.g. `forbidden` on a scope failure, whose `message` is `insufficient_scope`,
1041
- * or `banner_in_use` on a banner-library conflict). It's `undefined` when the body has no `code`.
1042
- */
1043
- declare class CookieMunchApiError extends Error {
1044
- readonly status: number;
1045
- readonly code?: string;
1046
- /** The parsed JSON error body, when there was one (e.g. `issues` on a 422). */
1047
- readonly body?: unknown;
1048
- constructor(status: number, message: string, code?: string, body?: unknown);
1049
- }
1050
- /** A cookie discovered on a site, classified into a consent category (wire shape of the
1051
- * cookie-declaration feed). Matches the server's CategorizedCookie schema. */
1052
- interface CategorizedCookie {
1053
- name: string;
1054
- category: 'necessary' | 'preferences' | 'statistics' | 'marketing' | 'unclassified' | (string & {});
1055
- domain?: string;
1056
- provider?: string;
1057
- purpose?: string;
1058
- /**
1059
- * The purpose by language (lowercase BCP-47 tag). On a declared row, the owner's; on a
1060
- * row the cookie database classified, the database's (empty: none yet).
1061
- */
1062
- purposes?: Record<string, string>;
1063
- expiry?: string;
1064
- /** Page URLs (multi-page scan) that set this cookie, earliest first. */
1065
- foundOnPages?: string[];
1066
- /** The site owner declared this cookie; it overrides the scan. */
1067
- declared?: boolean;
1068
- /** A declared `prefix*` wildcard row that no observed cookie matched yet. */
1069
- pattern?: boolean;
1070
- /**
1071
- * Why a person should look at it. Visitors see unclassified and category ones under
1072
- * "Unclassified"; `retired_but_seen` = retired, but a crawl or a visit saw it since, so the
1073
- * site still sets it and it is listed again. `awaiting_corroboration` / `suspicious_report` =
1074
- * only visitors reported it (not enough of them yet, or in one injection-shaped report), owner
1075
- * views only; `foreign_cmp` = another consent platform's cookie, filed unclassified;
1076
- * `not_seen_recently` = unseen for the site's `staleAfterDays`, owner views only.
1077
- */
1078
- review?: 'unclassified' | 'category_disabled' | 'category_unknown' | 'retired_but_seen' | 'awaiting_corroboration' | 'suspicious_report' | 'foreign_cmp' | 'not_seen_recently';
1079
- /** Epoch-ms a crawl or a real visit last saw it. Absent on older rows. */
1080
- lastSeenAt?: number;
1081
- /** Owner views only: the site owner retired this cookie (see `sites.retireCookie`). */
1082
- retired?: {
1083
- at: number;
1084
- renamedTo?: string;
1085
- note?: string;
1086
- by?: string;
1087
- pattern?: string;
1088
- };
1089
- /** A cookie (default, also when absent) or a key in browser storage. */
1090
- type?: StorageType;
1091
- /** Where the row came from: a real visit, a crawl, the owner (`api`) or a vendor preset (`import`). */
1092
- source?: 'embed' | 'scan' | 'api' | 'import';
1093
- /** Epoch-ms it was first stored. Absent on rows from before provenance was recorded. */
1094
- firstSeen?: number;
1095
- /** Distinct visits that reported it. */
1096
- visits?: number;
1097
- /** Owner views only: reported by a real visit, but not yet by enough distinct visits to be listed publicly. */
1098
- quarantined?: boolean;
1099
- /** "Declared by <vendor>": the vendor preset that declared it. */
1100
- vendor?: string;
1101
- }
1102
- /** What a declaration row describes. */
1103
- type StorageType = 'cookie' | 'localStorage' | 'sessionStorage' | 'indexedDB';
1104
- /** A cookie the site owner retired: the site renamed or stopped setting it. */
1105
- interface RetiredCookie {
1106
- /** Exact name, or a `prefix*` wildcard. */
1107
- name: string;
1108
- /** Epoch-ms it was retired; anything seen after this brings it back. */
1109
- at: number;
1110
- renamedTo?: string;
1111
- note?: string;
1112
- /** `apikey:<prefix>` or a dashboard user id. */
1113
- by?: string;
1114
- pattern?: boolean;
1115
- }
1116
- /** A site's cookie declaration: the latest scan and observed visits with the site's own
1117
- * declarations on top. This is what GET /v1/sites/:cbid/cookies returns. */
1118
- interface CookieDeclaration {
1119
- /** Epoch-ms of the latest scan or declaration change, or 0 if none. */
1120
- updatedAt: number;
1121
- cookies: CategorizedCookie[];
1122
- /** The site owner's declarations, as stored. */
1123
- declared?: DeclaredCookie[];
1124
- /** The site's retirements, as stored (owner views only). */
1125
- retired?: RetiredCookie[];
1126
- }
1127
- /** What the site owner says a cookie is (PUT /v1/sites/:cbid/cookies/:name). */
1128
- interface DeclaredCookieInput {
1129
- /** A standard category or one of the site's `categories.custom` ids. Not `unclassified`. */
1130
- category: string;
1131
- /** Shown to visitors, and the fallback for any language `purposes` lacks. */
1132
- purpose: string;
1133
- /**
1134
- * The purpose in other languages: `{ es: '…', 'pt-BR': '…' }` (BCP-47 language or
1135
- * language-region tags, stored lowercased; ≤50 languages, ≤1000 characters each).
1136
- * The banner, `data-cc="declaration"` and /cookie-declaration.js draw the visitor's.
1137
- */
1138
- purposes?: Record<string, string> | null;
1139
- provider?: string;
1140
- expiry?: string;
1141
- domain?: string;
1142
- /** Treat the name as a prefix wildcard (a trailing `*` does the same). */
1143
- pattern?: boolean;
1144
- /** A cookie (default) or a key in localStorage, sessionStorage or IndexedDB. */
1145
- type?: StorageType;
1146
- }
1147
- /** A stored declaration. */
1148
- interface DeclaredCookie extends DeclaredCookieInput {
1149
- name: string;
1150
- updatedAt: number;
1151
- /** `import` when a vendor preset wrote it. */
1152
- source?: 'import';
1153
- /** The vendor whose preset declared it. */
1154
- vendor?: string;
1155
- }
1156
- /** A platform whose cookies and storage a preset declares. */
1157
- type CookiePresetVendor = 'atlas' | 'forumulate' | 'chatly' | 'cookiemunch' | 'referalli' | 'firstpromoter' | 'partnerstack' | 'tapfiliate' | 'impact'
1158
- /** @deprecated the old name of `referalli`, accepted until 2027-10-23. */
1159
- | 'referally';
1160
- /** Where a vendor's live manifest will come from, and whether it exists yet. */
1161
- interface CookiePresetManifest {
1162
- /** `live`/`stale`/`invalid`: the vendor's embed manifest feeds the preset; `waiting_on_vendor`: built-in rows. */
1163
- status: 'builtin' | 'live' | 'stale' | 'invalid' | 'waiting_on_vendor';
1164
- waitingOn?: string;
1165
- item?: string;
1166
- contract?: string;
1167
- /** Where the manifest is read from, or `upload`. */
1168
- source?: string;
1169
- /** The `updated` of the copy in effect. */
1170
- updated?: string;
1171
- fetchedAt?: number;
1172
- /** Why the latest read was not accepted, by rule (1–6). */
1173
- errors?: Array<{
1174
- rule?: number;
1175
- path?: string;
1176
- code?: string;
1177
- message: string;
1178
- }>;
1179
- warnings?: Array<{
1180
- rule?: number;
1181
- path?: string;
1182
- code?: string;
1183
- message: string;
1184
- }>;
1185
- }
1186
- /** PUT /v1/sites/:cbid/cookies/presets/custom — any vendor's embed manifest, by URL or as a body. */
1187
- type CustomPresetInput = ({
1188
- url: string;
1189
- manifest?: never;
1190
- } | {
1191
- manifest: EmbedManifest;
1192
- url?: never;
1193
- }) & {
1194
- /** Values for the manifest's `{placeholders}`. */
1195
- params?: Record<string, string>;
1196
- };
1197
- /** One suggestion in GET /v1/sites/:cbid/cookies/suggestions. */
1198
- interface CookieSuggestion {
1199
- name: string;
1200
- storage: 'cookie' | 'localStorage' | 'sessionStorage' | 'indexedDB';
1201
- foundOnPages: string[];
1202
- /** `denied`: a crawl saw it before any consent; `granted`: after accepting all. */
1203
- consentStates?: Array<'denied' | 'granted'>;
1204
- suggestedPreset?: string;
1205
- suggestedCategory: string;
1206
- confidence: 'high' | 'medium' | 'low';
1207
- purpose?: string;
1208
- reason: string;
1209
- }
1210
- /** GET /v1/sites/:cbid/cookies/suggestions */
1211
- interface CookieSuggestions {
1212
- suggestions: CookieSuggestion[];
1213
- vendors: Array<{
1214
- vendor: string;
1215
- display: string;
1216
- preset: string | null;
1217
- applied: boolean;
1218
- needsParams: boolean;
1219
- evidence: Array<{
1220
- kind: 'script' | 'storage' | 'manifest';
1221
- value: string;
1222
- pages?: string[];
1223
- }>;
1224
- }>;
1225
- }
1226
- /** POST /v1/sites/:cbid/cookies/suggestions/declare */
1227
- interface CookieSuggestionsDeclared {
1228
- presetsApplied: string[];
1229
- declaredCount: number;
1230
- skipped?: Array<{
1231
- name: string;
1232
- reason: string;
1233
- }>;
1234
- dryRun?: true;
1235
- declared?: DeclaredCookie[];
1236
- diff?: DeclarationDiff;
1237
- }
1238
- /** Preset parameters: Atlas `frontendApiHost`/`crossSubdomainCookies`; Chatly `publicId`/`dragging`/`category`; referral and affiliate presets (referalli, firstpromoter, partnerstack, tapfiliate, impact) `cookieDomain`/`cookieDays`/`category`, referalli `legacyName`, impact `campaignId`. */
1239
- interface CookiePresetParams {
1240
- frontendApiHost?: string;
1241
- crossSubdomainCookies?: boolean;
1242
- publicId?: string;
1243
- dragging?: boolean;
1244
- category?: string;
1245
- cookieDomain?: string;
1246
- cookieDays?: number;
1247
- /** referalli: default true, also declare referally_ctx (the pre-rename copy aff.js still writes). */
1248
- legacyName?: boolean;
1249
- /** impact: your program id; declares IR_<campaignId> too. */
1250
- campaignId?: string;
1251
- }
1252
- /** One browser key a surface writes, in an embed manifest. */
1253
- interface EmbedManifestStorage {
1254
- name: string;
1255
- type: 'cookie' | 'localStorage' | 'sessionStorage' | 'indexedDB';
1256
- category: string;
1257
- /** `session`, `persistent` or a duration such as `365d`. */
1258
- lifetime?: string;
1259
- /** By language; `en` is always there. */
1260
- purpose: Record<string, string>;
1261
- domain?: string;
1262
- sentTo?: string;
1263
- }
1264
- /** One embeddable surface in an embed manifest: its origins by CSP directive and its storage. */
1265
- interface EmbedManifestSurface {
1266
- /** Origins by CSP directive (`script-src`, `connect-src`, …). */
1267
- csp?: Record<string, string[]>;
1268
- /** Non-origin sources the surface needs (`'unsafe-inline'`, `data:`). */
1269
- requires?: Record<string, string[]>;
1270
- trustedTypes?: string[];
1271
- consentCategory?: string;
1272
- storage?: EmbedManifestStorage[];
1273
- sri?: Record<string, string>;
1274
- }
1275
- /** The shared embed/origins manifest (https://cookiemunch.net/schemas/embed-v1.json). */
1276
- interface EmbedManifest {
1277
- schema: string;
1278
- product: string;
1279
- updated: string;
1280
- openapi?: string;
1281
- llms?: string;
1282
- status?: string;
1283
- changelog?: string;
1284
- docs?: string;
1285
- checkers?: {
1286
- userAgent?: string;
1287
- egress?: string[];
1288
- agents?: Array<{
1289
- role: string;
1290
- userAgent?: string;
1291
- userAgentContains?: string;
1292
- description?: string;
1293
- }>;
1294
- };
1295
- surfaces: Record<string, EmbedManifestSurface>;
1296
- changes?: Array<{
1297
- effective: string;
1298
- surface: string;
1299
- add?: Record<string, string[]>;
1300
- remove?: Record<string, string[]>;
1301
- note?: string;
1302
- }>;
1303
- /** The tenant variant only: the site and its hosts. */
1304
- tenant?: {
1305
- cbid: string;
1306
- siteHosts: string[];
1307
- rightsPage: string;
1308
- preferenceCentre: string;
1309
- };
1310
- }
1311
- /** One preset in GET /v1/sites/:cbid/cookies/presets. */
1312
- interface CookiePreset {
1313
- /** A first-class preset, or a custom preset's product id. */
1314
- vendor: CookiePresetVendor | (string & {});
1315
- /** A custom preset (importCookieManifest). */
1316
- custom?: boolean;
1317
- url?: string;
1318
- params: Array<{
1319
- name: string;
1320
- type: string;
1321
- required: boolean;
1322
- description?: string;
1323
- }>;
1324
- applied: boolean;
1325
- declared: string[];
1326
- manifest: CookiePresetManifest;
1327
- }
1328
- /** What applying a preset declared. */
1329
- interface CookiePresetResult {
1330
- vendor: CookiePresetVendor | (string & {});
1331
- /** `manifest` when the rows came from the vendor's embed manifest. */
1332
- source?: 'manifest';
1333
- cookies: DeclaredCookie[];
1334
- removed: string[];
1335
- skipped?: Array<{
1336
- name: string;
1337
- reason: string;
1338
- }>;
1339
- note?: string;
1340
- /** Rows filed under a category this site has switched off (`cookies[<name>].category`). */
1341
- warnings?: Array<{
1342
- field: string;
1343
- reason: string;
1344
- }>;
1345
- /** With `warnings`: a body for `sites.patchConfig` that fixes them; apply the preset again after. */
1346
- suggestedConfigPatch?: Record<string, unknown>;
1347
- /** True when called with the deprecated name `referally`. */
1348
- deprecated?: true;
1349
- deprecatedAlias?: string;
1350
- manifest: CookiePresetManifest;
1351
- dryRun?: true;
1352
- declared?: DeclaredCookie[];
1353
- diff?: DeclarationDiff;
1354
- }
1355
- /** What removing observed rows removed (or, with `dryRun`, would). */
1356
- interface ObservedPurgeResult {
1357
- removed: string[];
1358
- count: number;
1359
- since?: number;
1360
- until?: number;
1361
- dryRun?: true;
1362
- }
1363
- /** What a declaration write would change (`dryRun`). */
1364
- interface DeclarationDiff {
1365
- added: DeclaredCookie[];
1366
- removed: DeclaredCookie[];
1367
- changed: Array<{
1368
- name: string;
1369
- before: DeclaredCookie;
1370
- after: DeclaredCookie;
1371
- }>;
1372
- }
1373
- /** The answer to a `dryRun` declaration write: nothing was stored. */
1374
- interface DeclarationDryRun {
1375
- dryRun: true;
1376
- /** Every declaration the site would have. */
1377
- declared: DeclaredCookie[];
1378
- diff: DeclarationDiff;
1379
- }
1380
- /** A warning about a write: e.g. the category is switched off for the site. */
1381
- interface DeclarationWarning {
1382
- field: string;
1383
- reason: string;
1384
- }
1385
- /** What an import with `apply` declared, on top of what it read. */
1386
- interface AppliedImport extends ImportedDeclaration {
1387
- applied: number;
1388
- skipped: Array<{
1389
- name: string;
1390
- reason: string;
1391
- }>;
1392
- warnings?: DeclarationWarning[];
1393
- }
1394
- /** @deprecated The server returns {@link CookieDeclaration}; kept only for back-compat. */
1395
- interface SiteCookie {
1396
- name: string;
1397
- domain: string;
1398
- category: string;
1399
- provider?: string;
1400
- purpose?: string;
1401
- expiry?: string;
1402
- firstSeen?: number;
1403
- }
1404
- /** Cookie-scan status, from GET /v1/sites/:cbid/scan. */
1405
- interface ScanStatus {
1406
- /** `scanning` while the last scan is queued or crawling. Kept for older clients; read `state`. */
1407
- status: 'idle' | 'scanning';
1408
- /** Epoch-ms of the last completed scan, or null. */
1409
- lastScannedAt: number | null;
1410
- /** What the last scan saw of the live banner's Accept all / Reject all. Absent until measured. */
1411
- buttonParity?: ButtonParityScan;
1412
- /** Where the last scan is: `idle` when the site was never scanned (older servers left it out). */
1413
- state?: 'idle' | 'queued' | 'scanning' | 'done' | 'failed';
1414
- scanId?: string;
1415
- startedAt?: number;
1416
- finishedAt?: number;
1417
- durationMs?: number;
1418
- /** Cookies this crawl saw (the stored list also keeps earlier finds: `keptFromEarlier`). */
1419
- cookieCount?: number;
1420
- keptFromEarlier?: number;
1421
- pagesVisited?: number;
1422
- /** Where the site's address redirected to (its canonical host), when it did. */
1423
- finalUrl?: string;
1424
- /** Why it failed. */
1425
- error?: string;
1426
- }
1427
- /** Consent-button parity of the banner a real browser saw on the site (see ScanStatus). */
1428
- interface ButtonParityScan {
1429
- url: string;
1430
- /** False when no visible consent accept control was found in a recognisable banner. */
1431
- bannerFound: boolean;
1432
- /**
1433
- * True when the checks ran: our embed, or a recognised banner with both Accept and Reject.
1434
- * False = not measured — no findings, `score` null. Absent on scans stored before it existed.
1435
- */
1436
- measured?: boolean;
1437
- /** `cookiemunch` = our embed; `other` = found by its button text. */
1438
- cmp: 'cookiemunch' | 'other' | null;
1439
- acceptFound: boolean;
1440
- rejectFound: boolean;
1441
- designWarnings: ButtonParityFinding[];
1442
- /** 0–100; null when no banner was found. */
1443
- score: number | null;
1444
- checkedAt?: number;
1445
- }
1446
- /** @deprecated The server returns {@link ScanStatus}; kept only for back-compat. */
1447
- interface ScanResult {
1448
- scanId: string;
1449
- status: 'queued' | 'running' | 'complete' | 'failed';
1450
- startedAt?: number;
1451
- finishedAt?: number;
1452
- pagesScanned?: number;
1453
- cookiesFound?: number;
1454
- }
1455
- /** A/B banner experiment results for a single variant. */
1456
- interface AbResult {
1457
- variant: string;
1458
- impressions: number;
1459
- optIns: number;
1460
- optInRate: number;
1461
- }
1462
- /** The response shape of GET /v1/sites/:cbid/snippet. */
1463
- interface InstallSnippet {
1464
- /** The exact `<script>` tag to paste into `<head>`. */
1465
- snippet: string;
1466
- /** URL of the consent.js embed file (the embed/CDN origin). */
1467
- src: string;
1468
- /** The API origin (beacons + consent-tcf.js). Present when the server reports it. */
1469
- api?: string;
1470
- /** The site identifier. */
1471
- cbid: string;
1472
- /** The blocking mode on the tag — the site's `blocking.mode` unless overridden. */
1473
- blockingMode: string;
1474
- /** Where `blockingMode` came from: the site's config, or the `blockingMode` option. */
1475
- blockingModeSource?: 'config' | 'query';
1476
- /** The tag's data-culture, when it has one. */
1477
- culture?: string;
1478
- /** CSP sources this site needs, by directive, plus a paste-able `policy`. */
1479
- csp?: CspSources;
1480
- /** Present when an override disagrees with the stored config. */
1481
- warnings?: ConfigWarning[];
1482
- }
1483
- /** Content Security Policy sources the embed needs. */
1484
- interface CspSources {
1485
- script: string[];
1486
- connect: string[];
1487
- img: string[];
1488
- /** Always includes 'unsafe-inline' (the banner's shadow-root <style>), unless you use a nonce. */
1489
- style: string[];
1490
- font: string[];
1491
- frame: string[];
1492
- /** The same as one policy fragment. */
1493
- policy: string;
1494
- }
1495
- /** Something a config write did not store as sent. */
1496
- interface ConfigWarning {
1497
- field: string;
1498
- reason: string;
1499
- }
1500
- /** One leaf a config write would change. */
1501
- interface ConfigChange {
1502
- path: string;
1503
- from?: unknown;
1504
- to?: unknown;
1505
- }
1506
- /** `PUT …/config` options. `keep: 'unspecified'` keeps the stored value of every top-level field the body omits. */
1507
- interface PutConfigOptions {
1508
- keep?: 'unspecified';
1509
- }
1510
- /** What a config write would do (`?dryRun=1`) — nothing is saved. */
1511
- interface ConfigDryRun {
1512
- dryRun: true;
1513
- /** The config as it would be saved. */
1514
- config: SiteConfig;
1515
- /** Every leaf that would change. */
1516
- diff: ConfigChange[];
1517
- warnings?: ConfigWarning[];
1518
- /** Consent-button parity of the would-be config (see {@link ButtonParityFinding}). */
1519
- designWarnings: ButtonParityFinding[];
1520
- }
1521
- /** The effective style of an Accept all / Reject all control. */
1522
- interface ParityControlSummary {
1523
- id?: string;
1524
- label: string;
1525
- element: 'button' | 'link';
1526
- background?: string;
1527
- color?: string;
1528
- borderColor?: string;
1529
- borderWidth?: number;
1530
- fontSize?: number;
1531
- fontWeight?: number;
1532
- width?: number;
1533
- height?: number;
1534
- }
1535
- /**
1536
- * One way Accept all is pushed harder than Reject all (colour, size, placement, copy, custom
1537
- * CSS). Returned as `designWarnings` on every config read and write, and by `lintConfig`.
1538
- * A warning, never an error — the config is saved regardless. See /docs/fair-consent-buttons.
1539
- */
1540
- interface ButtonParityFinding {
1541
- code: 'reject_missing_first_layer' | 'reject_missing_same_layer' | 'reject_hidden' | 'reject_below_fold' | 'reject_isolated' | 'reject_low_emphasis' | 'saturation_gap' | 'color_mismatch' | 'reject_text_low_contrast' | 'reject_styled_as_link' | 'font_size_gap' | 'font_weight_gap' | 'size_gap' | 'padding_gap' | 'border_mismatch' | 'reject_label_missing' | 'reject_label_long' | 'confirmshaming' | 'custom_css_asymmetric' | 'text_low_contrast' | 'link_low_contrast' | 'button_text_low_contrast' | 'focus_ring_low_contrast' | 'toggle_low_contrast' | 'control_boundary_low_contrast';
1542
- severity: 'warning' | 'notice';
1543
- layer: 'banner' | 'preferences' | 'modal' | 'popup' | 'bar' | 'inline' | 'custom';
1544
- accept: ParityControlSummary | null;
1545
- reject: ParityControlSummary | null;
1546
- metric: {
1547
- name: string;
1548
- accept?: number;
1549
- reject?: number;
1550
- value: number;
1551
- threshold: number;
1552
- };
1553
- detail: string;
1554
- fix: string;
1555
- where: {
1556
- view?: string;
1557
- variant?: string;
1558
- theme?: 'light' | 'dark';
1559
- breakpoint?: 'desktop' | 'mobile';
1560
- language?: string;
1561
- url?: string;
1562
- };
1563
- /** On a contrast finding: the WCAG success criterion (1.4.3 text, 1.4.11 non-text). */
1564
- wcag?: '1.4.3' | '1.4.11';
1565
- }
1566
- /** Reject all style values that would match the Accept all on the same layer. */
1567
- interface SuggestedRejectStyle {
1568
- layer: string;
1569
- view?: string;
1570
- background?: string;
1571
- color?: string;
1572
- borderColor?: string;
1573
- borderWidth?: number;
1574
- fontSize?: number;
1575
- fontWeight?: number;
1576
- width?: number;
1577
- height?: number;
1578
- }
1579
- /** `POST /v1/sites/:cbid/config/lint` — nothing is saved. */
1580
- interface ButtonParityLint {
1581
- /** `merged` = what PATCH would store (merged over the stored config); `replaced` = what PUT would store (`replace: true`). */
1582
- mode: 'merged' | 'replaced';
1583
- designWarnings: ButtonParityFinding[];
1584
- /** 100 minus 20 per warning and 5 per notice, floored at 0. */
1585
- score: number;
1586
- suggestedReject: SuggestedRejectStyle[];
1587
- }
1588
- /**
1589
- * Scrollbars on the surfaces Cookie Munch renders — the same shape on the banner theme (`theme.scrollbar`)
1590
- * and the rights-page theme. Colours are #hex, rgb() or hsl(); width is clamped to 4–16, radius to 0–999.
1591
- */
1592
- interface ScrollbarTheme {
1593
- style: 'themed' | 'thin' | 'native' | 'hidden';
1594
- thumb?: string;
1595
- thumbHover?: string;
1596
- track?: string;
1597
- width?: number;
1598
- radius?: number;
1599
- }
1600
- /** The hosted rights page document. See docs/rights-page for each section type's props. */
1601
- interface RightsPageDocument {
1602
- v: 1;
1603
- theme: {
1604
- preset: 'brand' | 'light' | 'dark' | 'custom';
1605
- width: 'narrow' | 'normal' | 'wide' | 'full';
1606
- density: 'compact' | 'comfortable' | 'spacious';
1607
- colorScheme: 'light' | 'dark' | 'auto';
1608
- scrollbar?: ScrollbarTheme;
1609
- [k: string]: unknown;
1610
- };
1611
- sections: Array<{
1612
- id: string;
1613
- type: string;
1614
- props: Record<string, unknown>;
1615
- hidden?: {
1616
- phone?: boolean;
1617
- desktop?: boolean;
1618
- };
1619
- style?: Record<string, unknown>;
1620
- }>;
1621
- form: {
1622
- requestTypes: Array<Record<string, unknown>>;
1623
- fields: Array<Record<string, unknown>>;
1624
- jurisdiction: 'auto' | 'ask' | 'hidden';
1625
- consentIdField: 'hidden' | 'optional' | 'required';
1626
- success: {
1627
- title?: string;
1628
- body?: string;
1629
- };
1630
- submitLabel?: string;
1631
- };
1632
- i18n: {
1633
- defaultLocale: string;
1634
- autoDetect: boolean;
1635
- overrides: Record<string, unknown>;
1636
- };
1637
- seo: {
1638
- title?: string;
1639
- description?: string;
1640
- favicon?: string;
1641
- image?: string;
1642
- index: boolean;
1643
- };
1644
- customCss?: string;
1645
- }
1646
- /** `message` is English; `code` (+ `params`) is stable, for your own wording or language. */
1647
- interface RightsPageIssue {
1648
- path: string;
1649
- message: string;
1650
- code?: string;
1651
- params?: Record<string, string | number>;
1652
- }
1653
- interface RightsPageDraft {
1654
- cbid: string;
1655
- draft: RightsPageDocument;
1656
- version: number;
1657
- publishedAt: number | null;
1658
- updatedAt: number | null;
1659
- warnings: RightsPageIssue[];
1660
- }
1661
- interface RightsPageDryRun {
1662
- dryRun: true;
1663
- cbid: string;
1664
- draft: RightsPageDocument;
1665
- warnings: RightsPageIssue[];
1666
- }
1667
- /** Who published a version: `publishedBy` is an actor id; `publishedByEmail` names a dashboard user (null for an API key). */
1668
- interface RightsPagePublisher {
1669
- publishedBy: string;
1670
- publishedByEmail: string | null;
1671
- publishedVia: 'dashboard' | 'api_key';
1672
- }
1673
- interface RightsPagePublished {
1674
- cbid: string;
1675
- page: RightsPageDocument;
1676
- version: number;
1677
- publishedAt: number;
1678
- publishedBy?: string | null;
1679
- publishedByEmail?: string | null;
1680
- publishedVia?: 'dashboard' | 'api_key' | null;
1681
- }
1682
- /**
1683
- * Optimistic concurrency for a draft write: the draft's `updatedAt` as you last read it (epoch ms or
1684
- * an ISO date; null = you saw no saved draft). A mismatch rejects with a 409 CookieMunchApiError whose
1685
- * body is RightsPageDraftConflict. Omitted: a full write (put) is last-write-wins; a patch merges onto the draft
1686
- * as it is when written, so a concurrent edit is not lost.
1687
- */
1688
- interface RightsPageWriteOptions {
1689
- baseUpdatedAt?: number | string | null;
1690
- }
1691
- interface RightsPageDraftConflict {
1692
- error: 'draft_conflict';
1693
- draft: RightsPageDraft;
1694
- }
1695
- /** `draftUpdatedAt`: the draft's updatedAt after the call — pass it as the next `baseUpdatedAt`. */
1696
- interface RightsPagePublishResult {
1697
- cbid: string;
1698
- version: number;
1699
- publishedAt: number;
1700
- draftUpdatedAt: number;
1701
- rolledBackTo?: number;
1702
- }
1703
- interface RightsPageVersions {
1704
- cbid: string;
1705
- versions: Array<{
1706
- version: number;
1707
- publishedAt: number;
1708
- } & RightsPagePublisher>;
1709
- }
1710
- /** Options for POST /v1/sites/:cbid/preview-token. All optional. */
1711
- interface PreviewTokenOptions {
1712
- /** Lifetime in seconds, 1..3600. Default 900. */
1713
- ttlSeconds?: number;
1714
- /** The page to preview. Default: the site's registered domain. */
1715
- url?: string;
1716
- /** Region to force: a country or subdivision code (`de`, `us-ca`) or `eu`. */
1717
- region?: string;
1718
- /** Language to force, as a BCP 47 tag (`de`, `pt-BR`). */
1719
- lang?: string;
1720
- }
1721
- /** A banner preview token, and the page URL that opens the preview. */
1722
- interface PreviewToken {
1723
- cbid: string;
1724
- token: string;
1725
- /** Epoch milliseconds. */
1726
- expiresAt: number;
1727
- region?: string;
1728
- lang?: string;
1729
- /** The page with `cm_preview` / `cm_region` / `cm_lang` added. */
1730
- previewUrl?: string;
1731
- }
1732
- /** A right a rights link may file (the hosted rights page's request-type kinds). */
1733
- type RightKind = 'access' | 'erasure' | 'rectification' | 'portability' | 'restriction' | 'objection' | 'opt_out_sale' | 'opt_out_targeted' | 'limit_sensitive';
1734
- /** Input for POST /v1/sites/:cbid/rights-links. */
1735
- interface RightsLinkInput {
1736
- /** The signed-in person. `email` must be an address you have verified. */
1737
- subject: {
1738
- email: string;
1739
- userId?: string;
1740
- };
1741
- /** Limit the link to these rights. Default: every right the page offers. */
1742
- rights?: RightKind[];
1743
- /** Lifetime in seconds, 60..3600. Default 900. */
1744
- ttlSeconds?: number;
1745
- }
1746
- /** A signed, single-use link to the hosted rights page for one signed-in person. */
1747
- interface RightsLink {
1748
- /** `https://<customDomain>/?t=…`, or `https://cookiemunch.net/r/<cbid>?t=…` when `customDomain` is null. */
1749
- url: string;
1750
- /** Epoch milliseconds. */
1751
- expiresAt: number;
1752
- /** The site's active custom rights-page host the link opens on, or null. */
1753
- customDomain: string | null;
1754
- }
1755
- /** One DNS record to create, exactly as written. */
1756
- interface DnsRecordInstruction {
1757
- type: 'CNAME' | 'TXT';
1758
- name: string;
1759
- value: string;
1760
- }
1761
- /** A custom hostname serving a site's rights page. */
1762
- interface RightsPageDomain {
1763
- /** Lowercase ASCII form (punycode for an internationalised name). */
1764
- hostname: string;
1765
- /** As a person reads it. */
1766
- unicodeHostname: string;
1767
- cbid: string;
1768
- /** pending_dns → verifying → issuing → active, or error (see lastError). */
1769
- status: 'pending_dns' | 'verifying' | 'issuing' | 'active' | 'error';
1770
- certStatus: 'none' | 'pending' | 'issued' | 'failed';
1771
- createdAt: number;
1772
- verifiedAt?: number;
1773
- activatedAt?: number;
1774
- lastCheckedAt?: number;
1775
- /** dns_not_found | wrong_target | hostname_in_use | router_write_failed | certificate_not_issued | dns_changed | probe_failed */
1776
- lastError?: string;
1777
- url: string;
1778
- /** The records to create: the CNAME, or (apex / flattened / proxied) the TXT plus an ALIAS to the same target. */
1779
- /** `cname.value` is this domain's own `<token>.cname.cookiemunch.net` — unique to the claim; a CNAME to anything else does not verify it. */
1780
- dns: {
1781
- recommended: 'cname' | 'flattened';
1782
- cname: DnsRecordInstruction;
1783
- txt: DnsRecordInstruction;
1784
- };
1785
- /** Only on a verify that found no proof: what DNS answered. */
1786
- dnsSeen?: {
1787
- cnames: string[];
1788
- addresses: string[];
1789
- txt: string[];
1790
- };
1791
- }
1792
- /** The site's custom hostnames, the plan allowance (null = unlimited) and the org's usage. */
1793
- interface RightsPageDomainList {
1794
- domains: RightsPageDomain[];
1795
- limit: number | null;
1796
- used: number;
1797
- target: string;
1798
- }
1799
- /** Options for the snippet endpoint. */
1800
- interface SnippetOptions {
1801
- /** Override the site's configured `blocking.mode`. Default: the config's. */
1802
- blockingMode?: 'auto' | 'manual';
1803
- /** Language culture override, e.g. "en" or "fr". */
1804
- culture?: string;
1805
- }
1806
- /**
1807
- * The result of domain verification.
1808
- * Keep in sync with the POST /v1/sites/:cbid/verify response in
1809
- * packages/server/src/dev-api.ts (~L267) — note the server adds `method` on success,
1810
- * so this wire shape is wider than domain-verify.ts's internal VerifyResult.
1811
- */
1812
- interface VerifyResult {
1813
- verified: boolean;
1814
- method?: 'dns' | 'meta' | 'file';
1815
- reason?: string;
1816
- }
1817
- /** A site brand suggestion ("Match my site"). Keep in sync with packages/server/src/brand-extract.ts BrandSuggestion. */
1818
- interface BrandSuggestion {
1819
- background?: string;
1820
- text?: string;
1821
- highlight?: string;
1822
- fontFamily?: string;
1823
- fontUrl?: string;
1824
- palette?: string[];
1825
- }
1826
- /** The response shape of POST /v1/sites/:cbid/brand. */
1827
- interface BrandExtractionResult {
1828
- suggestion: BrandSuggestion;
1829
- }
1830
- /** PUT /v1/sites/{cbid}/brand: `{url}` alone (fetched once, https only), or a DTCG brand.json document. */
1831
- type BrandImportInput = {
1832
- url: string;
1833
- } | Record<string, unknown>;
1834
- /** One brand.json role and what it became. */
1835
- interface BrandMappingRow {
1836
- role: string;
1837
- /** The site-config path it sets, e.g. `banner.theme.highlight`. */
1838
- target: string;
1839
- value: string | number;
1840
- /** The rights-page theme token the same value feeds. */
1841
- rightsPage?: string;
1842
- /** `site` when the site's own banner theme value wins over brand.json. */
1843
- source: 'brand.json' | 'site';
1844
- inForce?: string | number;
1845
- /** Variants that override it for some visitors. */
1846
- variants?: string[];
1847
- }
1848
- /** The read-back of a brand.json import. Precedence: brand.json < site banner theme < per-banner variant. */
1849
- interface BrandReadBack {
1850
- cbid: string;
1851
- dryRun?: boolean;
1852
- source: {
1853
- type: 'url';
1854
- url: string;
1855
- } | {
1856
- type: 'body';
1857
- };
1858
- importedAt: number;
1859
- precedence: string;
1860
- mapping: BrandMappingRow[];
1861
- ignored: Array<{
1862
- role: string;
1863
- reason: string;
1864
- }>;
1865
- warnings: Array<{
1866
- role: string;
1867
- code: 'third_party_font_host';
1868
- message: string;
1869
- }>;
1870
- configWarnings?: Array<{
1871
- field: string;
1872
- reason: string;
1873
- }>;
1874
- }
1875
- /** A validation/lint issue on a v2 banner flow. */
1876
- interface FlowIssue {
1877
- code: string;
1878
- message: string;
1879
- path?: string;
1880
- }
1881
- /** A site's v2 banner flow + lint issues, from GET /v1/sites/:cbid/flow. */
1882
- interface SiteFlow {
1883
- v: 2;
1884
- flow: Record<string, unknown>;
1885
- categories: Record<string, unknown>;
1886
- customCss?: string;
1887
- lint: FlowIssue[];
1888
- }
1889
- /**
1890
- * A single structured flow edit operation. `op` selects the kind; remaining fields are
1891
- * that op's args (e.g. { op: 'addView', id, surface, layoutMode }).
1892
- */
1893
- type FlowOp = {
1894
- op: string;
1895
- } & Record<string, unknown>;
1896
- /**
1897
- * Result of editFlow/setFlow. On success the new flow is persisted and returned;
1898
- * on a validation/lint failure the config is NOT saved and `issues` says why.
1899
- */
1900
- type FlowOpResponse = {
1901
- ok: true;
1902
- flow: Record<string, unknown>; /** Consent-button parity of the saved design. */
1903
- designWarnings?: ButtonParityFinding[];
1904
- } | {
1905
- ok: false;
1906
- failedAt?: number;
1907
- op?: unknown;
1908
- issues: FlowIssue[];
1909
- };
1910
- /** A reusable brand kit (colors/logo/typography) for banner theming. */
1911
- interface BrandKit {
1912
- id: string;
1913
- orgId: string;
1914
- name: string;
1915
- /** Banner theme tokens (opaque design object). */
1916
- theme: Record<string, unknown>;
1917
- /** Optional banner content overrides (opaque). */
1918
- content?: Record<string, unknown>;
1919
- logoUrl?: string;
1920
- customCss?: string;
1921
- }
1922
- /** A configurable consent preference/purpose item. */
1923
- interface PreferenceItem {
1924
- id: string;
1925
- orgId: string;
1926
- cbid?: string;
1927
- label: string;
1928
- description?: string;
1929
- category?: string;
1930
- }
1931
- /** An organization member. */
1932
- interface Member {
1933
- userId: string;
1934
- email: string;
1935
- role: 'owner' | 'admin' | 'member' | 'viewer' | (string & {});
1936
- }
1937
- /** Display metadata for an issued key — never the secret. Returned by keys.list(). */
1938
- interface ApiKeyPrefix {
1939
- prefix: string;
1940
- createdAt?: number;
1941
- /** Epoch ms the key stops working; null = never. */
1942
- expiresAt?: number | null;
1943
- name?: string | null;
1944
- /** null = full access. */
1945
- scopes?: string[] | null;
1946
- cbids?: string[] | null;
1947
- /** Epoch ms it last authenticated a request (recorded at most hourly); null = not since recording began. */
1948
- lastUsedAt?: number | null;
1949
- /** The address of that request. */
1950
- lastUsedIp?: string | null;
1951
- /** `user:<id>`, `service:<name>` or `apikey:<prefix>`. */
1952
- owner?: string | null;
1953
- kind?: 'org' | 'site' | null;
1954
- env?: 'live' | 'test' | null;
1955
- format?: 'cookiemunch' | 'legacy';
1956
- strictUnknownFields?: boolean;
1957
- /** The dated API version this key is pinned to. */
1958
- apiVersion?: string;
1959
- }
1960
- /** A live organisation's sandbox (GET /v1/sandbox). */
1961
- interface SandboxOrg {
1962
- orgId: string;
1963
- name: string;
1964
- sandboxOf: string;
1965
- createdAt: string;
1966
- }
1967
- /** POST /v1/sandbox: the sandbox and a test key for it, shown once. */
1968
- interface SandboxCreated {
1969
- sandbox: SandboxOrg;
1970
- created: boolean;
1971
- key: string;
1972
- keyPrefix: string;
1973
- keyExpiresAt: string;
1974
- }
1975
- /** GET /v1/versions. */
1976
- interface ApiVersions {
1977
- latest: string;
1978
- base: string;
1979
- /** With a key: the version it is pinned to. */
1980
- yours?: string;
1981
- versions: Array<{
1982
- version: string;
1983
- summary: string;
1984
- changes: Array<{
1985
- id: string;
1986
- summary: string;
1987
- docs: string;
1988
- }>;
1989
- }>;
1990
- }
1991
- /** A revoked key in the report: when, by whom, why; never the secret. */
1992
- interface ApiKeyRevoked {
1993
- prefix: string;
1994
- name: string | null;
1995
- owner: string | null;
1996
- scopes: string[] | null;
1997
- cbids: string[] | null;
1998
- createdAt: number;
1999
- expiresAt: number | null;
2000
- lastUsedAt: number | null;
2001
- lastUsedIp: string | null;
2002
- revokedAt: number;
2003
- revokedBy: string;
2004
- reason: 'revoked' | 'rolled' | 'leaked';
2005
- leakSource: string | null;
2006
- }
2007
- /** GET /v1/keys/report — key hygiene. */
2008
- interface ApiKeyReport {
2009
- generatedAt: number;
2010
- unusedDays: number;
2011
- expiringDays: number;
2012
- unused: Array<ApiKeyPrefix & {
2013
- reason: string;
2014
- }>;
2015
- broad: Array<ApiKeyPrefix & {
2016
- reason: string;
2017
- }>;
2018
- expiringSoon: Array<ApiKeyPrefix & {
2019
- reason: string;
2020
- }>;
2021
- noExpiry: number;
2022
- total: number;
2023
- /** Revoked, rolled and leak-revoked keys, newest first. */
2024
- revoked?: ApiKeyRevoked[];
2025
- }
2026
- /** A newly issued key. `key` is returned ONCE and never again (or, with `secretRecipient`, sealed). */
2027
- interface ApiKeyIssued {
2028
- key: string;
2029
- prefix: string;
2030
- expiresAt?: number | null;
2031
- scopes?: string[] | null;
2032
- cbids?: string[] | null;
2033
- /** No expiry, or one over 365 days. */
2034
- warnings?: string[];
2035
- /** With `secretRecipient`: the key, sealed (and `key` absent). */
2036
- sealed_secret?: string;
2037
- sealed_field?: string;
2038
- }
2039
- /** @deprecated No endpoint returns this shape; use {@link ApiKeyPrefix} / {@link ApiKeyIssued}. */
2040
- interface ApiKey {
2041
- id: string;
2042
- orgId: string;
2043
- prefix: string;
2044
- name?: string;
2045
- createdAt: number;
2046
- lastUsedAt?: number;
2047
- secret?: string;
2048
- }
2049
- /**
2050
- * Input for issuing a new API key (POST /v1/keys). Every field is honoured: `scopes`, `cbids`,
2051
- * `expiresInDays` / `expiresAt`, `name`, `owner` and `strictUnknownFields`.
2052
- */
2053
- interface ApiKeyIssueInput {
2054
- /** `user:<id>`, `service:<name>` or `apikey:<prefix>`. Default: the calling key. */
2055
- owner?: string;
2056
- /** Writes with the new key refuse unknown body fields unless they send `Prefer: lenient-unknown-fields`. */
2057
- strictUnknownFields?: boolean;
2058
- name?: string;
2059
- /** Least privilege: grant only these scopes. Omit for a full-access key. */
2060
- scopes?: string[];
2061
- /**
2062
- * Lock the key to these properties. A locked key works only on those sites and on no
2063
- * org-wide endpoint — see "Keys locked to properties" in the client reference.
2064
- */
2065
- cbids?: string[];
2066
- /** Expire the key after this many days (1–3650). */
2067
- expiresInDays?: number;
2068
- /** Or when it expires: epoch ms or an ISO date-time (not with expiresInDays). Omit both: never. */
2069
- expiresAt?: number | string;
2070
- }
2071
- /** One entitlement (suite-standard shape). A feature is `{key, enabled}`; a limit is `limits.<name>`. */
2072
- interface Entitlement {
2073
- key: string;
2074
- enabled: boolean;
2075
- /** Limits only. null = unlimited, 0 = not on this plan. */
2076
- limit?: number | null;
2077
- /** Limits the server meters, when metering is wired. */
2078
- used?: number;
2079
- source: 'plan';
2080
- }
2081
- /** GET /v1/entitlements: what the org may use, from its effective plan. */
2082
- interface Entitlements {
2083
- orgId: string;
2084
- plan: string;
2085
- planSource: 'org' | 'account';
2086
- subscribedPlan: string;
2087
- entitlements: Entitlement[];
2088
- generatedAt: string;
2089
- }
2090
- /** Org usage/quota summary. Matches the server's Usage schema. */
2091
- interface Usage {
2092
- domains: number;
2093
- seats: number;
2094
- monthlyEvents: number;
2095
- }
2096
- /** A webhook subscription. `secret` is present only in the create response. */
2097
- interface WebhookSubscription {
2098
- id: string;
2099
- orgId: string;
2100
- url: string;
2101
- secret?: string;
2102
- events: string[];
2103
- cbid: string | null;
2104
- active: boolean;
2105
- createdAt: number;
2106
- /** The endpoint lifecycle: `failing` from the first event that failed every retry, `disabled` after 72 hours. */
2107
- state?: 'healthy' | 'failing' | 'disabled' | 'paused';
2108
- failingSince?: number | null;
2109
- disabledAt?: number | null;
2110
- lastSuccessAt?: number | null;
2111
- lastFailure?: {
2112
- at: number;
2113
- status: number | null;
2114
- error: string | null;
2115
- } | null;
2116
- lastDeliveryAt?: number | null;
2117
- lastStatus?: number | null;
2118
- consecutiveFailures?: number;
2119
- /** Who is emailed when it fails; null: the organisation's owners. */
2120
- alertContacts?: string[] | null;
2121
- /** On an update that re-enabled a disabled endpoint: how to send what it missed. */
2122
- replay?: {
2123
- since: number;
2124
- path: string;
2125
- };
2126
- }
2127
- /** POST /v1/webhooks/{id}/replay. */
2128
- interface WebhookReplayResult {
2129
- ok: boolean;
2130
- replayed: number;
2131
- failed: number;
2132
- remaining: number;
2133
- stoppedAt?: string;
2134
- status?: number;
2135
- error?: string;
2136
- }
2137
- /** The audit-log export (GET/PUT /v1/audit/sink). Never the secret. */
2138
- interface AuditSink {
2139
- type: 'webhook';
2140
- url: string;
2141
- secretSet: true;
2142
- createdAt: number;
2143
- updatedAt: number;
2144
- lastDeliveryAt: number | null;
2145
- lastStatus: number | null;
2146
- lastError: string | null;
2147
- }
2148
- interface AuditSinkInput {
2149
- type: 'webhook';
2150
- url: string;
2151
- /** 16–256 characters; omitted: one is generated and returned once. */
2152
- secret?: string;
2153
- }
2154
- /** GET /v1/sites/{cbid}/consent/insights. */
2155
- interface ConsentInsights {
2156
- cbid: string;
2157
- from: number;
2158
- to: number;
2159
- totals: {
2160
- impressions: number | null;
2161
- decisions: number;
2162
- optIns: number;
2163
- optOuts: number;
2164
- optInRate: number | null;
2165
- decisionRate: number | null;
2166
- };
2167
- byRegion: Array<{
2168
- region: string;
2169
- decisions: number;
2170
- optIns: number;
2171
- optInRate: number | null;
2172
- }>;
2173
- byVariant: Array<{
2174
- variant: string;
2175
- impressions: number;
2176
- optIns: number;
2177
- optInRate: number | null;
2178
- }>;
2179
- byVariantWindow: 'all_time';
2180
- /** Decisions made on a banner, by the language it was shown in; null when none in the window. */
2181
- byLanguage: Array<{
2182
- language: string;
2183
- decisions: number;
2184
- optIns: number;
2185
- optInRate: number | null;
2186
- }> | null;
2187
- /** How long after the banner appeared visitors decided, as a histogram; null when none in the window. */
2188
- timeToDecision: {
2189
- decisions: number;
2190
- buckets: Array<{
2191
- upToSeconds: number | null;
2192
- count: number;
2193
- }>;
2194
- median: {
2195
- fromSeconds: number;
2196
- upToSeconds: number | null;
2197
- } | null;
2198
- } | null;
2199
- /** Present for a figure with nothing recorded in the window, saying why. */
2200
- notRecorded?: {
2201
- byLanguage?: string;
2202
- timeToDecision?: string;
2203
- };
2204
- }
2205
- /** One cookie read from another CMP's export. */
2206
- interface ImportedCookie {
2207
- name: string;
2208
- domain: string;
2209
- /** Ours, or `unclassified` when their category did not map to one. */
2210
- category: 'necessary' | 'preferences' | 'statistics' | 'marketing' | 'unclassified';
2211
- /** What the previous vendor called it, kept for review. */
2212
- sourceCategory: string;
2213
- purpose: string;
2214
- provider: string;
2215
- expiry: string;
2216
- }
2217
- /** What a competitor's cookie-declaration export contained, in our vocabulary. */
2218
- interface ImportedDeclaration {
2219
- source: 'onetrust' | 'cookiebot' | 'cookieyes' | 'unknown';
2220
- cookies: ImportedCookie[];
2221
- /** Rows whose category could not be placed — review these first. */
2222
- unmapped: Array<{
2223
- name: string;
2224
- category: string;
2225
- }>;
2226
- }
2227
- /**
2228
- * A page that refused to load the banner renderer. The site is live and configured, so
2229
- * every other signal looks healthy; this is the one that says nobody can be asked.
2230
- */
2231
- interface BlockedReport {
2232
- cbid: string;
2233
- /** Origin of the page the embed was running on. */
2234
- page: string;
2235
- /** The bundle URL that page refused. */
2236
- url: string;
2237
- reason: string;
2238
- firstSeen: number;
2239
- lastSeen: number;
2240
- /** How many times this page has reported. Repeats are counted, not stored. */
2241
- count: number;
2242
- }
2243
- /** A webhook delivery that failed every retry. Replay it by `id`. */
2244
- interface WebhookDeadLetter {
2245
- id: string;
2246
- orgId: string;
2247
- subscriptionId: string;
2248
- url: string;
2249
- eventType: string;
2250
- cbid: string | null;
2251
- payload: unknown;
2252
- attempts: number;
2253
- lastStatus?: number;
2254
- lastError?: string;
2255
- failedAt: number;
2256
- }
2257
- /** What a test delivery's endpoint answered. */
2258
- interface WebhookTestResult {
2259
- ok: boolean;
2260
- status?: number;
2261
- error?: string;
2262
- }
2263
- /** The key's organisation. */
2264
- interface Org {
2265
- id: string;
2266
- name: string;
2267
- plan: string;
2268
- logoUrl: string | null;
2269
- }
2270
- type MailProviderKind = 'brevo' | 'sendgrid' | 'postmark' | 'resend' | 'ses' | 'smtp';
2271
- /**
2272
- * The org's own mail provider for rights-request mail. The credential is never returned —
2273
- * `secretLast4` only. `sender` says whether verification codes go through it right now
2274
- * (`own`) or are not mailed at all (`none`): there is no shared sender for rights mail.
2275
- */
2276
- interface MailProvider {
2277
- configured: boolean;
2278
- sender: 'own' | 'none';
2279
- provider?: MailProviderKind;
2280
- fromEmail?: string;
2281
- fromName?: string;
2282
- replyTo?: string;
2283
- ses?: {
2284
- region: string;
2285
- accessKeyId: string;
2286
- };
2287
- smtp?: {
2288
- host: string;
2289
- port: number;
2290
- security: 'tls' | 'starttls';
2291
- username: string;
2292
- };
2293
- secretLast4?: string;
2294
- status?: 'untested' | 'verified' | 'failing';
2295
- verifiedAt?: number | null;
2296
- lastTest?: {
2297
- ok: boolean;
2298
- at: number;
2299
- error?: string;
2300
- } | null;
2301
- updatedAt?: number;
2302
- /** Only on `set`: no verification codes are mailed until a test succeeds. */
2303
- note?: string;
2304
- }
2305
- /** Save a provider. `secret` is write-only; omit it to keep the stored one (same provider only). */
2306
- interface MailProviderInput {
2307
- provider: MailProviderKind;
2308
- fromEmail: string;
2309
- fromName?: string | null;
2310
- replyTo?: string | null;
2311
- secret?: string;
2312
- ses?: {
2313
- region: string;
2314
- accessKeyId: string;
2315
- };
2316
- smtp?: {
2317
- host: string;
2318
- port: 25 | 465 | 587 | 2525;
2319
- security: 'tls' | 'starttls';
2320
- username: string;
2321
- };
2322
- }
2323
- type RightsCaptchaProvider = 'turnstile' | 'hcaptcha' | 'recaptcha_v2' | 'recaptcha_v3';
2324
- /**
2325
- * The rights page's captcha in force: your own keys (`own`, recommended) or none (`off`, the default).
2326
- * Cookie Munch's own captcha is never used on rights pages. The secret is never returned.
2327
- */
2328
- /** Whether hosted consent sync is set up for a site. The secret itself is never read back. */
2329
- interface ConsentSyncSecret {
2330
- cbid: string;
2331
- configured: boolean;
2332
- secretLast4: string | null;
2333
- /** Epoch ms the current secret was minted. */
2334
- createdAt: number | null;
2335
- }
2336
- /**
2337
- * Who a preference-centre token is for: a site of your organisation and exactly one of `email`
2338
- * (resolved as the emailed preference link resolves it) or `subjectId`.
2339
- */
2340
- type CenterTokenInput = {
2341
- cbid: string;
2342
- ttlSeconds?: number;
2343
- } & ({
2344
- email: string;
2345
- subjectId?: never;
2346
- } | {
2347
- subjectId: string;
2348
- email?: never;
2349
- });
2350
- /** A preference-centre token. A credential: hand it to `CookieMunch.setSubjectToken`, never put it in a shared URL or a log. */
2351
- interface CenterToken {
2352
- token: string;
2353
- /** ISO 8601. */
2354
- expiresAt: string;
2355
- }
2356
- /** A freshly minted or rotated consent-sync secret: `secret` is shown this once. */
2357
- interface ConsentSyncSecretMinted extends ConsentSyncSecret {
2358
- secret: string;
2359
- }
2360
- interface RightsCaptcha {
2361
- /** `site`: the site's own setting; `org`: the organisation default; `default`: neither (off). */
2362
- source: 'site' | 'org' | 'default';
2363
- mode: 'own' | 'off';
2364
- provider?: RightsCaptchaProvider;
2365
- siteKey?: string;
2366
- /** reCAPTCHA v3 only. */
2367
- minScore?: number;
2368
- secretSet: boolean;
2369
- secretLast4?: string;
2370
- status: 'verified' | 'disabled';
2371
- verifiedAt: number | null;
2372
- updatedAt: number | null;
2373
- /** Only when a `set` turned the captcha off: what that costs. */
2374
- warning?: string;
2375
- }
2376
- /**
2377
- * `own` needs provider, siteKey and (the first time) secret; the provider is asked to accept the secret before
2378
- * anything is saved (422 captcha_secret_invalid / 502 captcha_unreachable). `off` removes spam protection beyond
2379
- * the hidden spam-trap field, the rate limits and the email code.
2380
- */
2381
- interface RightsCaptchaInput {
2382
- mode: 'own' | 'off';
2383
- provider?: RightsCaptchaProvider;
2384
- siteKey?: string;
2385
- /** Write-only. Omit to keep the stored one (same provider, same place). */
2386
- secret?: string;
2387
- /** reCAPTCHA v3 only: 0.1–0.9, default 0.5. */
2388
- minScore?: number;
2389
- }
2390
- type RightsIdentityType = 'clerk' | 'atlas' | 'oidc_jwt';
2391
- /**
2392
- * The sign-in provider rights requests are verified with: a visitor signed in to your site is
2393
- * verified by their session, with no code mail. Nothing here is secret.
2394
- */
2395
- interface RightsIdentity {
2396
- /** `site`: the site's own setting; `org`: the organisation default; `default`: neither (none). */
2397
- source: 'site' | 'org' | 'default';
2398
- configured: boolean;
2399
- type?: RightsIdentityType;
2400
- issuer?: string;
2401
- jwksUrl?: string;
2402
- audience?: string;
2403
- authorizedParties?: string[];
2404
- emailClaim?: string;
2405
- emailVerifiedClaim?: string;
2406
- sessionCookieName?: string;
2407
- /** Present (true) only when set: clerk/atlas tokens without the verified claim are accepted. */
2408
- trustEmailClaim?: true;
2409
- status: 'verified' | 'not_configured';
2410
- verifiedAt: number | null;
2411
- updatedAt: number | null;
2412
- }
2413
- /**
2414
- * The JWKS is fetched and checked before anything is saved (502 identity_jwks_unreachable /
2415
- * 422 identity_jwks_invalid). `authorizedParties` (your own origins) is required for clerk and atlas;
2416
- * oidc_jwt needs an `audience` or `authorizedParties`. Issuer and JWKS URL are https on a host name,
2417
- * never an IP address. The token must carry the email and a verified-email claim set to `true`
2418
- * (clerk/atlas with `trustEmailClaim`: the verified claim may be absent).
2419
- */
2420
- interface RightsIdentityInput {
2421
- type: RightsIdentityType;
2422
- /** Exactly the token's `iss` (Clerk: your Frontend API URL). */
2423
- issuer: string;
2424
- /** Required for oidc_jwt; clerk/atlas default to `<issuer>/.well-known/jwks.json`. */
2425
- jwksUrl?: string;
2426
- audience?: string;
2427
- authorizedParties?: string[];
2428
- /** Default `email`. */
2429
- emailClaim?: string;
2430
- /** Default `email_verified`. */
2431
- emailVerifiedClaim?: string;
2432
- /** Default `__session`: the cookie the hosted page on your custom domain reads. */
2433
- sessionCookieName?: string;
2434
- /**
2435
- * clerk/atlas only, default false. True when your provider has no verified-email claim and every
2436
- * address it puts in the email claim is verified: a token without the verified claim is accepted.
2437
- */
2438
- trustEmailClaim?: boolean;
2439
- }
2440
- /** The organisation's own data-controller identity (GET /v1/org/controller). */
2441
- interface OrgControllerIdentity {
2442
- /** False when none is set; then only `updatedAt` (null) is present. */
2443
- set: boolean;
2444
- legalName?: string;
2445
- contactEmail?: string;
2446
- address?: string;
2447
- /** The Data Protection Officer: a name, an email address, or both. */
2448
- dpoContact?: string;
2449
- updatedAt: number | null;
2450
- }
2451
- /** Replaces the identity: a field left out is removed. `legalName` is required. */
2452
- interface OrgControllerInput {
2453
- legalName: string;
2454
- contactEmail?: string;
2455
- address?: string;
2456
- dpoContact?: string;
2457
- }
2458
- interface MailProviderTestResult {
2459
- ok: boolean;
2460
- sentTo: string;
2461
- error?: string;
2462
- mailProvider: MailProvider;
2463
- }
2464
- /** Change an org's name or logo. `logoUrl: null` removes the logo. */
2465
- interface OrgUpdate {
2466
- name?: string;
2467
- logoUrl?: string | null;
2468
- }
2469
- /** One entry in the org's audit log. */
2470
- interface AuditEntry {
2471
- id: string;
2472
- orgId: string;
2473
- actorUserId: string;
2474
- actorEmail?: string;
2475
- action: string;
2476
- target?: string;
2477
- meta?: Record<string, unknown>;
2478
- at: number;
2479
- }
2480
- /** Rename a key, or replace its scopes or the properties it is locked to. */
2481
- interface ApiKeyUpdate {
2482
- owner?: string;
2483
- strictUnknownFields?: boolean;
2484
- name?: string;
2485
- scopes?: string[];
2486
- cbids?: string[];
2487
- /** A new expiry (epoch ms or ISO date-time), or null to remove it. */
2488
- expiresAt?: number | string | null;
2489
- }
2490
- /** An image to upload: base64 (or a `data:` URL) plus its type. */
2491
- interface AssetUpload {
2492
- data: string;
2493
- contentType: 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif' | 'image/svg+xml';
2494
- }
2495
- /** Result of erasing a subject's consent for a deletion request. */
2496
- interface DsarEraseResult {
2497
- erased: number;
2498
- encryptionEnabled: boolean;
2499
- /** Present when no KEK is configured, so nothing was cryptographically erased. */
2500
- warning?: string;
2501
- request: DsarRequest;
2502
- }
2503
- /** Result of exporting a subject's consent for an access or portability request. */
2504
- interface DsarExportResult {
2505
- records: unknown[];
2506
- count: number;
2507
- request: DsarRequest;
2508
- }
2509
- /** Input for creating a webhook subscription. */
2510
- interface WebhookCreate {
2511
- url: string;
2512
- events: string[];
2513
- cbid?: string;
2514
- }
2515
- /** Fields to change on a webhook subscription. Only those present are sent. */
2516
- interface WebhookUpdate {
2517
- url?: string;
2518
- events?: string[];
2519
- /** One property, or null for every property in the org. */
2520
- cbid?: string | null;
2521
- /** false pauses delivery without deleting the subscription; true re-enables a disabled one. */
2522
- active?: boolean;
2523
- /** 1–10 addresses emailed when it fails; null: back to the organisation's owners. */
2524
- alertContacts?: string[] | null;
2525
- }
2526
- /** One site to create in a bulk call. */
2527
- interface BulkSiteInput {
2528
- domain: string;
2529
- cbid?: string;
2530
- platform?: string;
2531
- }
2532
- /** Per-item outcome of a bulk create, in input order. */
2533
- interface BulkSiteResult {
2534
- ok: boolean;
2535
- cbid?: string;
2536
- domain?: string;
2537
- error?: string;
2538
- }
2539
- /** Input for creating a brand kit. */
2540
- interface BrandKitCreate {
2541
- name: string;
2542
- theme: unknown;
2543
- content?: unknown;
2544
- logoUrl?: string;
2545
- customCss?: string;
2546
- }
2547
- /** A lightweight summary of an account-level banner, as returned by GET /v1/banners. */
2548
- interface BannerSummary {
2549
- id: string;
2550
- name: string;
2551
- updatedAt: number;
2552
- assignedCbids: string[];
2553
- /** How many warning-severity consent-button parity findings the design has (0 = fair). */
2554
- designWarningCount: number;
2555
- }
2556
- /** A full account-level banner record, including its config JSON. */
2557
- interface BannerRecord {
2558
- id: string;
2559
- orgId: string;
2560
- name: string;
2561
- json: SiteConfig;
2562
- createdAt: number;
2563
- updatedAt: number;
2564
- /** Consent-button parity findings in the design. Never blocks a save. */
2565
- designWarnings?: ButtonParityFinding[];
2566
- }
2567
- /**
2568
- * Input for the public consent-log ingest endpoint (POST /api/v1/consent) — the
2569
- * tamper-evident, hash-chained ledger write the browser embed makes. Mirrors the
2570
- * server's ConsentPayload; optional fields are sent only when set. Records are
2571
- * anonymised (IP truncated) and hash-chained server-side.
2572
- */
2573
- interface ConsentIngestInput {
2574
- /** The registered site id the consent belongs to. */
2575
- cbid: string;
2576
- /** Stable per-subject consent-receipt id (used for erase/export). */
2577
- stamp: string;
2578
- /** The subject's cookie-category choices. */
2579
- choices: {
2580
- preferences: boolean;
2581
- statistics: boolean;
2582
- marketing: boolean;
2583
- };
2584
- /** How consent was captured. */
2585
- method: 'explicit' | 'implied';
2586
- /** Consent/notice version number. */
2587
- ver: number;
2588
- /** Epoch-ms the decision was made. */
2589
- utc: number;
2590
- /** The URL / screen where consent was captured. */
2591
- url: string;
2592
- /** Optional IAB TCF consent string (TCF mode only). */
2593
- tcString?: string;
2594
- /** Optional GPP string (GPP mode only). */
2595
- gppString?: string;
2596
- /** Optional named-purpose map beyond the standard categories. */
2597
- purposes?: Record<string, boolean>;
2598
- /** Optional opaque digest of the exact notice text shown to the subject. */
2599
- subjectPolicyHash?: string;
2600
- /** Optional map: named purpose → RoPA entry id. */
2601
- purposeRopa?: Record<string, string>;
2602
- /** Optional A/B variant id. */
2603
- variant?: string;
2604
- /**
2605
- * Optional, app-supplied STABLE cross-surface subject id. Lets an org retrieve one
2606
- * subject's consent history across ALL its sites/surfaces (web + mobile + desktop).
2607
- * Opaque — stored and bound into the record hash server-side, never interpreted.
2608
- */
2609
- subjectId?: string;
2610
- }
2611
- /** One of a person's identifiers: an identity-space code plus the normalised value. */
2612
- interface Identifier {
2613
- space: string;
2614
- value: string;
2615
- }
2616
- interface ConsentDecisionInput {
2617
- purpose: string;
2618
- allowed: boolean;
2619
- legalBasis?: string;
2620
- jurisdiction?: string;
2621
- provenance?: string;
2622
- collectedAt?: number;
2623
- }
2624
- interface ProfileAttributeInput {
2625
- value: string;
2626
- purpose?: string;
2627
- collectedAt?: number;
2628
- }
2629
- interface SubscriptionTopicInput {
2630
- code: string;
2631
- name?: string;
2632
- channels: string[];
2633
- downstream?: Record<string, string>;
2634
- }
2635
- /** A warehouse-native enforcement rule. See POST /v1/discovery/enforcement. */
2636
- interface EnforcementRuleInput {
2637
- id: string;
2638
- action: 'mask' | 'restrict';
2639
- /** Select columns at or above this sensitivity. */
2640
- minSensitivity?: 'personal' | 'sensitive';
2641
- /** Select columns in any of these categories. */
2642
- categories?: string[];
2643
- /** mask: roles that still see the raw value. */
2644
- allowRoles?: string[];
2645
- /** restrict: the purpose a subject must have consented to. */
2646
- purpose?: string;
2647
- /** restrict: the column holding the subject id. Default SUBJECT_ID. */
2648
- subjectColumn?: string;
2649
- }
2650
- interface RegulationSummary {
2651
- id: string;
2652
- jurisdiction: string;
2653
- name: string;
2654
- /** ISO date the law takes (or took) effect. */
2655
- effective: string;
2656
- model: 'opt-in' | 'opt-out';
2657
- obligations: string[];
2658
- /** Primary source — the statute or the regulator. */
2659
- source: string;
2660
- }
2661
- interface RegulatoryFeedResult {
2662
- /** When a human last checked the dataset against its sources. */
2663
- reviewedAt: string;
2664
- /** Days since that review. */
2665
- ageDays: number;
2666
- /** How long a review is considered good for. */
2667
- reviewAfterDays: number;
2668
- /** True once the review interval has passed — treat the answer with caution. */
2669
- stale: boolean;
2670
- regulations: RegulationSummary[];
2671
- }
2672
- interface AiInspectInput {
2673
- prompt: string;
2674
- purpose: string;
2675
- model?: string;
2676
- actor?: string;
2677
- direction?: 'prompt' | 'response';
2678
- /** The subject's current permits, when the call concerns an identified person. */
2679
- consent?: Record<string, boolean>;
2680
- }
2681
- interface AiInspectResult {
2682
- action: 'allow' | 'redact' | 'block';
2683
- /** The text to forward: redacted when `redact`, empty when `block`. */
2684
- prompt: string;
2685
- findings: unknown[];
2686
- reasons: string[];
2687
- policyIds: string[];
2688
- blocked: boolean;
2689
- direction: 'prompt' | 'response';
2690
- }
2691
- type FulfillmentOp = 'locate' | 'export' | 'erase' | 'optOut';
2692
- /** A child org provisioned by a reseller. */
2693
- interface ResellerChild {
2694
- id: string;
2695
- name: string;
2696
- status: 'active' | 'suspended';
2697
- delegatedAccess?: boolean;
2698
- /** Per-child DSAR routing override; unset defers to the reseller's policy. */
2699
- dsarRouting?: 'reseller' | 'child';
2700
- createdAt?: number;
2701
- usage?: unknown;
2702
- }
2703
- interface ResellerChildList {
2704
- children: ResellerChild[];
2705
- /** Pooled usage across the reseller and all its children, when metering is wired. */
2706
- aggregate?: {
2707
- childOrgs: number;
2708
- sites: number;
2709
- monthlyEvents: number;
2710
- monthlyEventsCap: number | null;
2711
- overCap: boolean;
2712
- };
2713
- }
2714
- interface ResellerChildCreate {
2715
- name: string;
2716
- ownerEmail?: string;
2717
- /** legalName, contactEmail, address, dpoContact. */
2718
- controller?: Record<string, unknown>;
2719
- /** Branding overrides, merged onto the reseller's white-label defaults. */
2720
- whiteLabel?: Record<string, unknown>;
2721
- delegatedAccess?: boolean;
2722
- /** Also issue an API key for the new child; it is returned once, as `apiKey`. */
2723
- mintKey?: boolean;
2724
- /** Scopes for that key. Defaults to ["sites:read"]. */
2725
- keyScopes?: string[];
2726
- }
2727
- interface ResellerChildPatch {
2728
- status?: 'active' | 'suspended';
2729
- delegatedAccess?: boolean;
2730
- /** Pin this child's DSAR routing; null clears the override. */
2731
- dsarRouting?: 'reseller' | 'child' | null;
2732
- controller?: Record<string, unknown>;
2733
- }
2734
- interface ChildKeyInput {
2735
- name?: string;
2736
- scopes?: string[];
2737
- /** Lock the key to these properties of the child org. */
2738
- cbids?: string[];
2739
- }
2740
- interface PolicyOptions {
2741
- /** Contact email shown in the policy. Falls back to the org controller's, then the owner's. */
2742
- contactEmail?: string;
2743
- /** YYYY-MM-DD. Defaults to today. */
2744
- effectiveDate?: string;
2745
- /** Override the jurisdictions the policy addresses. */
2746
- jurisdictions?: string[];
2747
- }
2748
- interface AdPersonalizationInput {
2749
- enabled: boolean;
2750
- /** Whether personalised ads start on before the visitor chooses. */
2751
- default?: boolean;
2752
- label?: string;
2753
- }
2754
- interface SessionAnalysisInput {
2755
- /** A HAR export of the captured session. */
2756
- har?: unknown;
2757
- /** Or the requests directly. */
2758
- requests?: unknown[];
2759
- /** The consent state the session ran under. */
2760
- consent?: Record<string, boolean>;
2761
- /** Whether Global Privacy Control was set. */
2762
- gpc?: boolean;
2763
- }
2764
- /**
2765
- * How to drive one system's rights API, as data. This is what makes a connection specific to
2766
- * a platform — Cookie Munch names none of them, so connecting a new system is a profile
2767
- * rather than a release. Paths are relative to `baseUrl`; placeholders are `{email}`,
2768
- * `{subject}`, `{operation}`, `{correlation}` and `{id}`.
2769
- */
2770
- interface ExecutorProfile {
2771
- /** How requests carry the credential. Defaults to `Authorization: Bearer {secret}`. */
2772
- auth?: {
2773
- header: string;
2774
- format: string;
2775
- };
2776
- /**
2777
- * Optional first step: turn the subject's email into the id this system uses. `noMatch`
2778
- * names how the system says "no record of that person" in its body — a sentinel id is
2779
- * never read as a person when it is set.
2780
- */
2781
- subjectLookup?: {
2782
- method: 'GET' | 'POST';
2783
- path: string;
2784
- body?: unknown;
2785
- idPath: string;
2786
- noMatch?: {
2787
- statusPath: string;
2788
- values: string[];
2789
- };
2790
- /** How this system says the person was already removed; closes the task as `already_erased`. Checked before `noMatch`. */
2791
- alreadyErased?: {
2792
- statusPath: string;
2793
- values: string[];
2794
- };
2795
- };
2796
- /** Response header carrying the system's version, recorded in the task log. Default `X-Version`. */
2797
- versionHeader?: string;
2798
- /** How to open a request. An operation left out of `operations` is one this system does not run. */
2799
- open: {
2800
- method: 'POST' | 'PUT';
2801
- path: string;
2802
- body?: unknown;
2803
- operations: {
2804
- export?: string;
2805
- erase?: string;
2806
- };
2807
- idPath: string;
2808
- statusPath?: string;
2809
- };
2810
- /** How to ask how it is going. Polling is the truth; a webhook only prompts a check. */
2811
- poll: {
2812
- method?: 'GET';
2813
- path: string;
2814
- statusPath: string;
2815
- resultPath?: string;
2816
- /** Whether `resultPath` holds the bundle itself or a URL to fetch it from. */
2817
- resultIs?: 'inline' | 'url';
2818
- /** Where a date the work is waiting for lives (an erasure in a grace period). */
2819
- scheduledPath?: string;
2820
- };
2821
- /** That system's status words → the three answers a sub-task can have. */
2822
- statuses: {
2823
- running: string[];
2824
- done: string[];
2825
- failed: string[];
2826
- };
2827
- idempotencyHeader?: string;
2828
- /**
2829
- * An identity platform's app grant, revoked on erasure before anything else: look it up by
2830
- * `{email}`, then end it with `{grant}`. A test looks it up but never revokes it.
2831
- */
2832
- grantRevoke?: {
2833
- lookup: {
2834
- method: 'GET' | 'POST';
2835
- path: string;
2836
- body?: unknown;
2837
- grantIdPath: string;
2838
- };
2839
- revoke: {
2840
- method: 'POST' | 'DELETE';
2841
- path: string;
2842
- body?: unknown;
2843
- };
2844
- };
2845
- /** How that system signs its webhooks, if it sends any. */
2846
- webhook?: {
2847
- algorithm: 'hmac-sha256';
2848
- /** Must include `{body}`, or the signature proves nothing about it. */
2849
- signedPayload: string;
2850
- headers: {
2851
- signature: string;
2852
- timestamp?: string;
2853
- id?: string;
2854
- };
2855
- encoding?: 'base64' | 'hex';
2856
- prefix?: string;
2857
- toleranceSeconds?: number;
2858
- timestampUnit?: 'seconds' | 'milliseconds' | 'auto';
2859
- };
2860
- }
2861
- /** A system connected to run part of a rights request. Credentials are never included. */
2862
- interface DsarExecutor {
2863
- id: string;
2864
- /** The name it answers to in a fulfillment plan, e.g. `identity` or `crm`. */
2865
- system: string;
2866
- profile: ExecutorProfile;
2867
- baseUrl: string;
2868
- keyPrefix: string;
2869
- hasWebhookSecret: boolean;
2870
- /** Open a sub-task automatically when a request reaches fulfilment. */
2871
- auto: boolean;
2872
- /** What the subject reads on this system's notice line when it holds nothing about them. */
2873
- subjectNote?: string;
2874
- createdAt: number;
2875
- /** Where that system should send its completion webhooks. On every connection, secret or not. */
2876
- webhookUrl: string;
2877
- /**
2878
- * The last canary health check (hourly, and on `testExecutor(id, { canary: true })`). null
2879
- * until the first; cleared when the address, profile or key changes.
2880
- */
2881
- health: ExecutorHealth | null;
2882
- /** The preset it was built from; absent when hand-written. */
2883
- preset?: ExecutorPresetName;
2884
- presetVersion?: number;
2885
- /** Newer than `presetVersion`: `upgradeExecutorPreset` applies it. */
2886
- presetLatestVersion?: number;
2887
- /** The non-secret params it was built with, e.g. `{ orgId }`. */
2888
- presetParams?: Record<string, string>;
2889
- /** How the stored address and profile differ from what its preset version builds. Empty: unmodified. */
2890
- presetDiff?: ConfigChange[];
2891
- /** Preset-built: profile fields you removed or changed by hand; `upgradeExecutorPreset` keeps them. */
2892
- profileOverrides?: Array<{
2893
- path: string;
2894
- kind: 'removed' | 'changed';
2895
- at: number;
2896
- }>;
2897
- /** Preset-built: true when it must not follow its preset. */
2898
- presetPinned?: boolean;
2899
- /** Your name for the credential. */
2900
- label?: string;
2901
- /** 2: orchestrator v2 headers on every call; 1: the v1 adapter every connection made before v2 has. */
2902
- orchestrator?: 1 | 2;
2903
- hasCompletionSecret?: boolean;
2904
- completionSecretPrefix?: string;
2905
- /** When a signed completion last verified; running work is then polled every 6 hours. */
2906
- lastSignedCompletionAt?: number | null;
2907
- /** Where signed cm-standard-v2 completions go. */
2908
- completionsUrl?: string;
2909
- /** On create only: the completion secret, shown this once. */
2910
- completionSecret?: string;
2911
- }
2912
- /** POST …/completion-secret/roll. */
2913
- interface CompletionSecretRolled {
2914
- id: string;
2915
- completionSecret: string;
2916
- completionSecretPrefix: string;
2917
- previousRetiresAt: string | null;
2918
- completionsUrl?: string;
2919
- }
2920
- /** POST …/test {conformance: true}: the conformance kit's report. */
2921
- interface ExecutorConformanceResult extends ConformanceReport {
2922
- conformance: true;
2923
- canary: true;
2924
- email: string;
2925
- }
2926
- /** A connection's last health check. */
2927
- interface ExecutorHealth {
2928
- lastCheckedAt: number;
2929
- ok: boolean;
2930
- verdict: string;
2931
- /** e.g. `base_url_redirects`, `credential_unavailable`. */
2932
- code?: string;
2933
- /** When a check last passed. */
2934
- lastSuccessAt?: number;
2935
- /** On reads: true when the last check is more than an hour old, with the command that re-checks it in `hint`. */
2936
- stale?: boolean;
2937
- hint?: string;
2938
- }
2939
- /** A preset's name, as `executorPresets()` lists them. Not enumerated here: presets are data. */
2940
- type ExecutorPresetName = string;
2941
- /**
2942
- * Connect a system from a versioned preset instead of a hand-written profile. Each preset
2943
- * lists the params it takes (`executorPresets()`); a preset waiting on another platform is
2944
- * refused with `preset_waiting_on_platform`.
2945
- */
2946
- interface DsarExecutorPresetInput {
2947
- preset: ExecutorPresetName;
2948
- presetVersion?: number;
2949
- secretKey: string;
2950
- system?: string;
2951
- baseUrl?: string;
2952
- orgId?: string;
2953
- atlasIdAppId?: string;
2954
- /** A preset param, when the preset lists it: default false. True adds an optional step revoking the person's app grant on erasure. */
2955
- revokeAtlasIdGrant?: boolean;
2956
- webhookSecret?: string;
2957
- auto?: boolean;
2958
- cbid?: string;
2959
- /** Your name for the credential, shown beside `keyPrefix`. */
2960
- label?: string;
2961
- /** Default 2. */
2962
- orchestrator?: 1 | 2;
2963
- }
2964
- /** What `upgradeExecutorPreset` takes: a version, a preset to adopt, or params to add. */
2965
- interface ExecutorPresetUpgrade {
2966
- preset?: ExecutorPresetName;
2967
- presetVersion?: number;
2968
- orgId?: string;
2969
- atlasIdAppId?: string;
2970
- revokeAtlasIdGrant?: boolean;
2971
- /** Overridden paths (`profileOverrides`) that take the preset's value again; every other override is kept. */
2972
- acceptPreset?: string | string[];
2973
- }
2974
- /** One step a preset builds, and whether it can run now (CMU-B01). */
2975
- interface ExecutorPresetStep {
2976
- name: 'subjectLookup' | 'open' | 'poll' | 'webhook' | 'grantRevoke';
2977
- available: boolean;
2978
- /** Never fails a connection: a credential without the scope reports `skipped: insufficient_scope`. */
2979
- optional?: boolean;
2980
- /** False: added only with `param`. */
2981
- defaultOn: boolean;
2982
- param?: string;
2983
- note?: string;
2984
- waitingOn?: {
2985
- platform: string;
2986
- items: string[];
2987
- operations: string[];
2988
- };
2989
- }
2990
- /** The presets, which are usable now, and this org's canary address. */
2991
- interface ExecutorPresets {
2992
- canaryEmail: string;
2993
- presets: Array<{
2994
- name: ExecutorPresetName;
2995
- title: string;
2996
- latestVersion: number;
2997
- defaultSystem?: string;
2998
- params: Array<{
2999
- name: string;
3000
- required: boolean;
3001
- description: string;
3002
- type?: 'string' | 'boolean';
3003
- }>;
3004
- available: boolean;
3005
- waitingOn?: {
3006
- platform: string;
3007
- items: string[];
3008
- operations: string[];
3009
- };
3010
- steps: ExecutorPresetStep[];
3011
- }>;
3012
- }
3013
- /** What a connection write would do (`?dryRun=1`). Nothing was stored. */
3014
- interface DsarExecutorDryRun {
3015
- dryRun: true;
3016
- /** The connection as it would be, credentials excluded. A create has no `id` or `webhookUrl` yet. */
3017
- executor: Partial<DsarExecutor> & Record<string, unknown>;
3018
- /** Each field that would change. */
3019
- diff: ConfigChange[];
3020
- warnings?: Array<{
3021
- field: string;
3022
- reason: string;
3023
- }>;
3024
- }
3025
- /** Where a webhook check stopped. */
3026
- type WebhookStage = 'configuration' | 'headers' | 'timestamp' | 'prefix' | 'signature';
3027
- /** Which key a verified delivery matched: a `whsec_` secret's base64-decoded remainder, or the secret as typed. */
3028
- type WebhookKeyForm = 'decoded' | 'raw';
3029
- /** Whether a supplied delivery verified (`stage` and `reason` are null when it did). */
3030
- interface ExecutorWebhookTestResult {
3031
- verified: boolean;
3032
- stage: WebhookStage | null;
3033
- reason: string | null;
3034
- /** Which key form matched; null when refused. */
3035
- keyForm: WebhookKeyForm | null;
3036
- }
3037
- /** One delivery to a connection's webhook. Never the secret, the signature or the body. */
3038
- interface ExecutorWebhookDelivery {
3039
- id: string;
3040
- executorId: string;
3041
- at: number;
3042
- verified: boolean;
3043
- stage: WebhookStage | null;
3044
- reason: string | null;
3045
- /** The HTTP status we answered with. */
3046
- status: number;
3047
- /** The first 16 hex characters of SHA-256 over the raw body. */
3048
- bodySha256: string;
3049
- bodyBytes: number;
3050
- /** Which key form matched; null when refused (or logged before this was kept). Never the key. */
3051
- keyForm: WebhookKeyForm | null;
3052
- }
3053
- interface DsarExecutorInput {
3054
- /** The name this connection answers to in a plan, e.g. `identity` or `crm`. */
3055
- system: string;
3056
- /** The system's public https origin. */
3057
- baseUrl: string;
3058
- /** Its API key. Stored encrypted; never returned. */
3059
- secretKey: string;
3060
- /**
3061
- * The signing secret of its webhook endpoint. Optional — polling closes tasks without it.
3062
- * A `whsec_<base64>` secret (standard base64 or base64url, padded or not) verifies a delivery
3063
- * signed with either the base64-decoded bytes or the literal string; anything else only with
3064
- * its UTF-8 bytes.
3065
- */
3066
- webhookSecret?: string;
3067
- auto?: boolean;
3068
- /** What the subject reads when this system holds nothing about them (≤500 chars, never a key). */
3069
- subjectNote?: string;
3070
- /** How to drive it. */
3071
- profile: ExecutorProfile;
3072
- /** Default 2. */
3073
- orchestrator?: 1 | 2;
3074
- }
3075
- type DsarExecutorCreated = DsarExecutor;
3076
- /** The fields `updateExecutor` may change. */
3077
- interface DsarExecutorPatch {
3078
- profile?: unknown;
3079
- baseUrl?: string;
3080
- secretKey?: string;
3081
- webhookSecret?: string | null;
3082
- auto?: boolean;
3083
- /** null removes it. */
3084
- subjectNote?: string | null;
3085
- /** Your name for the credential; null removes it. */
3086
- label?: string | null;
3087
- /** Preset-built only: true stops `upgradeExecutorPreset` changing it. */
3088
- presetPinned?: boolean;
3089
- /** Opt in to (2) or out of (1) orchestrator v2. */
3090
- orchestrator?: 1 | 2;
3091
- }
3092
- /** One entry in a fulfilment task's status history. */
3093
- interface DsarTaskEvent {
3094
- at: number;
3095
- kind: 'created' | 'changed' | 'version_changed';
3096
- status: 'pending' | 'running' | 'done' | 'failed' | 'cancelled';
3097
- detail?: string;
3098
- outcome?: DsarTaskOutcome;
3099
- scheduledFor?: number;
3100
- externalRef?: string;
3101
- }
3102
- /** What a task's answer means for the person. `exported` only once the export was fetched. */
3103
- type DsarTaskOutcome = 'located' | 'exported' | 'erased' | 'no_record' | 'done_without_artifact' | 'not_applicable' | 'already_erased' | 'external_identity';
3104
- /** One request made to a connected system on a task's behalf, credentials removed. Kept 30 days. */
3105
- interface DsarTaskLogEntry {
3106
- id?: string;
3107
- system?: string;
3108
- step: 'lookup' | 'open' | 'poll' | 'export' | 'grant';
3109
- method: string;
3110
- path: string;
3111
- /** Absent when the system never answered. */
3112
- status?: number;
3113
- latencyMs: number;
3114
- requestHeaders?: Record<string, string>;
3115
- /** The first ~2 KB of what was sent. */
3116
- request?: string;
3117
- /** The first ~2 KB of what came back. */
3118
- response?: string;
3119
- error?: string;
3120
- /** The system's version header on this answer. */
3121
- version?: string;
3122
- /** This answer was a redirect (origin and path; never the query). Only same-origin, method-keeping ones are followed. */
3123
- redirect?: {
3124
- status: number;
3125
- location: string;
3126
- };
3127
- at: number;
3128
- }
3129
- /** One fulfilment task with its history and its upstream request log. */
3130
- interface DsarTask {
3131
- id: string;
3132
- requestId: string;
3133
- system: string;
3134
- operation: FulfillmentOp;
3135
- status: 'pending' | 'running' | 'done' | 'failed' | 'cancelled';
3136
- detail?: string;
3137
- outcome?: DsarTaskOutcome;
3138
- attempts: number;
3139
- executor?: string;
3140
- externalRef?: string;
3141
- scheduledFor?: number;
3142
- artifacts?: Array<{
3143
- kind: string;
3144
- system: string;
3145
- ref: string;
3146
- }>;
3147
- createdAt: number;
3148
- updatedAt: number;
3149
- events: DsarTaskEvent[];
3150
- log: DsarTaskLogEntry[];
3151
- /** Versions the system reported while working on this task, in order of change. */
3152
- upstreamVersions?: string[];
3153
- /** The system was redeployed while this task was in flight. */
3154
- versionChanged: boolean;
3155
- }
3156
- /** What testing a connection found. Nothing was filed. */
3157
- interface ExecutorTestResult {
3158
- system: string;
3159
- /** Did the lookup find the person; null when there is no lookup step or it failed. */
3160
- matched: boolean | null;
3161
- subject?: string;
3162
- operationWord?: string;
3163
- /** The open request a real request would send, when it was not sent. */
3164
- wouldSend?: {
3165
- method: string;
3166
- path: string;
3167
- body: unknown;
3168
- };
3169
- /** One sentence: what a real request would have done. */
3170
- verdict: string;
3171
- ok: boolean;
3172
- /** Why not, when there is a code: `base_url_redirects` — the baseUrl redirected; the verdict names the status and target. */
3173
- code?: string;
3174
- /** The subject's app grant at an identity platform, when the profile has a grant step. Never revoked by a test. */
3175
- grant?: string;
3176
- /** Optional steps this credential may not run: reported, never a failure. */
3177
- skipped?: Array<{
3178
- step: string;
3179
- reason: 'insufficient_scope';
3180
- }>;
3181
- /** Present when the test used the org canary address, with the address in `email`. */
3182
- canary?: boolean;
3183
- email?: string;
3184
- /** Every upstream answer, as the system gave it (credentials removed). */
3185
- exchanges: DsarTaskLogEntry[];
3186
- }
3187
- interface ExecutorTestInput {
3188
- /** The address to look up. Required unless `canary` is true. */
3189
- email?: string;
3190
- /** Use this org's canary address — no real person. A canary `locate` also updates `health`. */
3191
- canary?: boolean;
3192
- /** Default `locate`. */
3193
- operation?: 'locate' | 'export' | 'erase';
3194
- /** For `export` only: open a real export and poll it once. An erasure is never sent. */
3195
- open?: boolean;
3196
- }
3197
- interface DsarTaskExport {
3198
- system: string;
3199
- ref: string;
3200
- /** The bundle as that system returned it. Not stored here. */
3201
- bundle: unknown;
3202
- }
3203
- /** A language the banner already has copy for. */
3204
- interface SupportedLanguage {
3205
- /** BCP-47 tag, lowercase. Matched exactly, then by language prefix. */
3206
- code: string;
3207
- /** English name. */
3208
- name: string;
3209
- /** The language's name in itself. */
3210
- endonym: string;
3211
- /** Written right to left; the banner flips for these. */
3212
- rtl: boolean;
3213
- /** `bundled` ships in consent.js; `extended` ships in the renderer, fetched when a banner is first drawn. */
3214
- source: 'bundled' | 'extended';
3215
- }
3216
- interface CookieMunchClient {
3217
- me(): Promise<Identity>;
3218
- /**
3219
- * Languages the banner already speaks. Diff this against the locales your visitors
3220
- * use to see which ones you still need to write copy for in `banner.i18n`.
3221
- */
3222
- languages(): Promise<SupportedLanguage[]>;
3223
- orgs: {
3224
- /**
3225
- * Every organisation on this key's account, each with its effective plan and where that
3226
- * comes from, plus the per-account org cap and the upgrade URL. Needs an unscoped key that
3227
- * is not locked to properties.
3228
- */
3229
- list(opts?: MetadataFilter): Promise<AccountOrgs>;
3230
- /**
3231
- * Create a sibling organisation owned by the same account — for a separate business of
3232
- * your own. Needs an unscoped key. Not reseller provisioning, which is for your customers.
3233
- */
3234
- create(name: string, opts?: {
3235
- mintKey?: boolean;
3236
- keyScopes?: string[];
3237
- keyExpiresInDays?: number;
3238
- keyOwner?: string;
3239
- } & ResourceTagsInput): Promise<{
3240
- org: {
3241
- id: string;
3242
- name: string;
3243
- role: string;
3244
- };
3245
- apiKey?: string;
3246
- keyError?: string;
3247
- }>;
3248
- /** Hard-delete a SANDBOX organisation of this account (created with metadata.forgedeck_sandbox). Anything else: 403 not_a_sandbox. */
3249
- deleteSandbox(id: string): Promise<SandboxPurge>;
3250
- };
3251
- /** Tags on any created resource (CMU-X29). */
3252
- metadata: {
3253
- get(type: TaggedType, id: string): Promise<ResourceTags>;
3254
- /** Merge tags (null removes one). `forgedeck_sandbox` cannot be set here. `{ dryRun: true }` answers with the diff. */
3255
- update(type: TaggedType, id: string, metadata: Record<string, string | number | boolean | null>, opts?: {
3256
- dryRun?: boolean;
3257
- }): Promise<ResourceTagsUpdate>;
3258
- };
3259
- /** Partner links in the suite-standard shape (CMU-X34). */
3260
- partnerLinks: {
3261
- list(opts?: MetadataFilter): Promise<StandardPartnerLink[]>;
3262
- create(input: StandardPartnerLinkCreate): Promise<StandardPartnerLink>;
3263
- revoke(id: string): Promise<StandardPartnerLink>;
3264
- };
3265
- /** What `forgedeck env` writes for a product provisioned with this forgedeck ref: names, values, secret references. */
3266
- provisionEnv(ref: string): Promise<ProvisionEnv>;
3267
- sites: {
3268
- list(opts?: MetadataFilter): Promise<Site[]>;
3269
- create(input: SiteCreate & ResourceTagsInput): Promise<Site>;
3270
- get(cbid: string): Promise<Site>;
3271
- /**
3272
- * Rename or move a site: domain, display name, aliases. The cbid and the consent ledger stay; a domain
3273
- * move clears verification. `{ dryRun: true }` answers with the diff and stores nothing.
3274
- */
3275
- update(cbid: string, patch: SiteUpdate, opts?: {
3276
- dryRun?: boolean;
3277
- }): Promise<SiteUpdateResult>;
3278
- delete(cbid: string): Promise<void>;
3279
- /** Purge a SANDBOX site: its consent ledger, declarations and test rights requests too. Anything else: 403 not_a_sandbox. */
3280
- deleteSandbox(cbid: string): Promise<SandboxPurge>;
3281
- /** Partner platforms granted this site's consent events, and the partners on offer. */
3282
- listPartners(cbid: string): Promise<{
3283
- links: PartnerLink[];
3284
- partners: PartnerCatalogEntry[];
3285
- }>;
3286
- /** Grant a partner (Forumulate, Atlas) the site's consent events — no secret is created. Idempotent. */
3287
- linkPartner(cbid: string, input: PartnerLinkCreate, opts?: {
3288
- dryRun?: boolean;
3289
- }): Promise<{
3290
- change: 'created' | 'updated' | 'unchanged';
3291
- link: PartnerLink;
3292
- dryRun?: true;
3293
- }>;
3294
- /** Revoke a partner link: deliveries stop at once. */
3295
- unlinkPartner(cbid: string, linkId: string): Promise<{
3296
- link: PartnerLink;
3297
- }>;
3298
- getConfig(cbid: string): Promise<SiteConfig>;
3299
- /**
3300
- * Replaces the whole config — a top-level field you omit reverts to its default. With
3301
- * `{ keep: 'unspecified' }` (`?keep=unspecified`) an omitted top-level field keeps its
3302
- * stored value instead; each field you send is still replaced whole, and one sent as
3303
- * `null` reverts to its default.
3304
- */
3305
- putConfig(cbid: string, config: SiteConfig, opts?: PutConfigOptions): Promise<SiteConfig>;
3306
- /**
3307
- * Changes some of the config — a JSON Merge Patch (RFC 7386): omitted fields keep their
3308
- * stored value, nested objects merge, and `null` removes a field (it takes its default):
3309
- * `{ banner: { i18n: { es: null } } }` drops the Spanish override. Arrays replace whole.
3310
- */
3311
- patchConfig(cbid: string, config: Partial<SiteConfig>): Promise<SiteConfig>;
3312
- /**
3313
- * Preview a config write without saving it: the merged result and a diff. `mode: 'put'`
3314
- * previews a replace (the diff then lists everything that would revert to its default);
3315
- * add `keep: 'unspecified'` to preview a replace that keeps omitted fields.
3316
- */
3317
- dryRunConfig(cbid: string, config: Partial<SiteConfig>, opts?: {
3318
- mode?: 'patch' | 'put';
3319
- } & PutConfigOptions): Promise<ConfigDryRun>;
3320
- /**
3321
- * Check a proposed config for consent-button parity — an Accept all pushed harder than
3322
- * Reject all — without saving it. A partial v1 config is merged over the stored one (like
3323
- * PATCH); a v2 design, or `replace: true`, is linted as sent. Needs only `sites:read`.
3324
- */
3325
- lintConfig(cbid: string, config: Partial<SiteConfig>, opts?: {
3326
- replace?: boolean;
3327
- }): Promise<ButtonParityLint>;
3328
- cookies(cbid: string): Promise<CookieDeclaration>;
3329
- /**
3330
- * Start a cookie crawl. Answers at once with `scanId` and `state: 'queued'`; `wait`
3331
- * (seconds, ≤60) holds the request until the scan is done or failed.
3332
- */
3333
- scan(cbid: string, opts?: {
3334
- wait?: number;
3335
- }): Promise<ScanStatus>;
3336
- /** The last scan's state. `wait` (seconds, ≤60) holds the request until a running scan settles. */
3337
- scanStatus(cbid: string, opts?: {
3338
- wait?: number;
3339
- }): Promise<ScanStatus>;
3340
- /**
3341
- * Resolve once the site's scan is done or failed (read `state` and `error`), long-polling
3342
- * the server. At `timeoutMs` (default 120 000) it resolves with the still-running state.
3343
- */
3344
- waitForScan(cbid: string, opts?: {
3345
- timeoutMs?: number;
3346
- }): Promise<ScanStatus>;
3347
- ab(cbid: string): Promise<AbResult[]>;
3348
- /** Generate the site's privacy and cookie policy, as Markdown. */
3349
- policy(cbid: string, opts?: PolicyOptions): Promise<string>;
3350
- /** Turn on the personalised-ads split on whichever banner form the site uses. */
3351
- setAdPersonalization(cbid: string, input: AdPersonalizationInput): Promise<unknown>;
3352
- /** Analyse a captured session: trackers that fired after opt-out, personal data leaving the page. */
3353
- analyzeSession(cbid: string, input: SessionAnalysisInput): Promise<unknown>;
3354
- /** Which banner design this site uses, or null when none is assigned. */
3355
- banner(cbid: string): Promise<{
3356
- bannerId: string | null;
3357
- }>;
3358
- /**
3359
- * Pages where the embed could not load its banner renderer — the host page's CSP or
3360
- * Trusted Types policy refused it, so nobody on that page can be asked. An empty list
3361
- * is the healthy answer.
3362
- */
3363
- blocked(cbid: string): Promise<{
3364
- reports: BlockedReport[];
3365
- }>;
3366
- /**
3367
- * Read a cookie declaration exported from another CMP and translate its categories
3368
- * into ours. Nothing is applied: their vocabulary is not ours, and a cookie in the
3369
- * wrong category is a tag firing against a refusal, so the result is for review.
3370
- */
3371
- importDeclaration(cbid: string, data: string): Promise<ImportedDeclaration>;
3372
- /**
3373
- * Import AND declare: every row that mapped to one of our categories and has a purpose
3374
- * is declared; the rest come back in `skipped`. Already-declared cookies are kept
3375
- * unless `overwrite`.
3376
- */
3377
- applyImport(cbid: string, data: string, opts?: {
3378
- overwrite?: boolean;
3379
- }): Promise<AppliedImport>;
3380
- /**
3381
- * Declare what one cookie is. Overrides scanned, observed and database classification
3382
- * in the API, the preference modal and `data-cc="declaration"`. A name ending in `*`
3383
- * declares a prefix wildcard. `dryRun` validates and returns the would-be list and a
3384
- * diff without storing anything.
3385
- */
3386
- declareCookie(cbid: string, name: string, input: DeclaredCookieInput, opts?: {
3387
- dryRun?: boolean;
3388
- }): Promise<{
3389
- cookie: DeclaredCookie;
3390
- warnings?: DeclarationWarning[];
3391
- } & Partial<DeclarationDryRun>>;
3392
- /**
3393
- * Retire a cookie the site renamed or stopped setting: it leaves the banner's list,
3394
- * `data-cc="declaration"` and the public feed, and stays listed for you with `retired`.
3395
- * A name ending in `*` retires every cookie with that prefix. If a crawl or a visit sees
3396
- * it again afterwards it is listed again, flagged `review: 'retired_but_seen'`.
3397
- */
3398
- retireCookie(cbid: string, name: string, input?: {
3399
- renamedTo?: string;
3400
- note?: string;
3401
- }, opts?: {
3402
- dryRun?: boolean;
3403
- }): Promise<{
3404
- cookie: RetiredCookie;
3405
- matched: string[];
3406
- dryRun?: true;
3407
- retired?: RetiredCookie[];
3408
- }>;
3409
- /** Un-retire a cookie: it is listed again everywhere. */
3410
- unretireCookie(cbid: string, name: string): Promise<void>;
3411
- /** What un-retiring would leave; nothing is removed. */
3412
- unretireCookie(cbid: string, name: string, opts: {
3413
- dryRun: true;
3414
- }): Promise<{
3415
- dryRun: true;
3416
- retired: RetiredCookie[];
3417
- }>;
3418
- /** Every declaration preset (atlas, forumulate, chatly, cookiemunch, referalli, firstpromoter, partnerstack, tapfiliate, impact): params, what it declared here, manifest status. */
3419
- cookiePresets(cbid: string): Promise<{
3420
- presets: CookiePreset[];
3421
- aliases?: Record<string, string>;
3422
- }>;
3423
- /**
3424
- * Apply (or re-sync) a vendor preset: declares what that platform writes, marked
3425
- * `vendor`. Names you declared yourself are kept (`skipped`). `dryRun` stores nothing.
3426
- */
3427
- applyCookiePreset(cbid: string, vendor: CookiePresetVendor, params?: CookiePresetParams, opts?: {
3428
- dryRun?: boolean;
3429
- }): Promise<CookiePresetResult>;
3430
- /**
3431
- * Declare ANY vendor's cookies and storage from its embed manifest (`url`, re-read hourly, or
3432
- * the `manifest` itself). The vendor id is the manifest's `product`; remove it with
3433
- * removeCookiePreset(cbid, product). `dryRun` stores nothing.
3434
- */
3435
- importCookieManifest(cbid: string, input: CustomPresetInput, opts?: {
3436
- dryRun?: boolean;
3437
- }): Promise<CookiePresetResult>;
3438
- /** What to declare: detected vendors (script, storage, manifest) and one suggestion per undeclared row. */
3439
- cookieSuggestions(cbid: string): Promise<CookieSuggestions>;
3440
- /** Declare the suggestions: detected vendors' presets, then every other suggestion with a purpose. Try `dryRun` first. */
3441
- declareCookieSuggestions(cbid: string, input?: {
3442
- names?: string[];
3443
- presets?: boolean;
3444
- }, opts?: {
3445
- dryRun?: boolean;
3446
- }): Promise<CookieSuggestionsDeclared>;
3447
- /** Remove every declaration a vendor preset made. */
3448
- removeCookiePreset(cbid: string, vendor: CookiePresetVendor | (string & {}), opts?: {
3449
- dryRun?: boolean;
3450
- }): Promise<{
3451
- vendor: string;
3452
- removed: string[];
3453
- dryRun?: true;
3454
- declared?: DeclaredCookie[];
3455
- diff?: DeclarationDiff;
3456
- }>;
3457
- /** Remove every stored (scanned or observed) row of this name. A declaration of it stays. */
3458
- deleteObservedCookie(cbid: string, name: string): Promise<void>;
3459
- /** What deleting it would remove; nothing is removed. */
3460
- deleteObservedCookie(cbid: string, name: string, opts: {
3461
- dryRun: true;
3462
- }): Promise<ObservedPurgeResult>;
3463
- /**
3464
- * Purge observed since T: remove every row a real visit first reported at or after
3465
- * `since` (and before `until`). Crawled rows and declarations stay. ISO-8601 or epoch ms.
3466
- */
3467
- purgeObservedCookies(cbid: string, input: {
3468
- since: string | number;
3469
- until?: string | number;
3470
- }, opts?: {
3471
- dryRun?: boolean;
3472
- }): Promise<ObservedPurgeResult>;
3473
- /** Remove a declaration; the scanned classification applies again. */
3474
- undeclareCookie(cbid: string, name: string): Promise<void>;
3475
- /** What removing a declaration would leave; nothing is removed. */
3476
- undeclareCookie(cbid: string, name: string, opts: {
3477
- dryRun: true;
3478
- }): Promise<DeclarationDryRun>;
3479
- /**
3480
- * Declare many at once (all-or-nothing). `replace` also removes declarations not listed;
3481
- * `dryRun` answers with what would be stored and a diff, storing nothing.
3482
- */
3483
- declareCookies(cbid: string, cookies: Array<DeclaredCookieInput & {
3484
- name: string;
3485
- }>, opts?: {
3486
- replace?: boolean;
3487
- dryRun?: boolean;
3488
- }): Promise<{
3489
- declared: DeclaredCookie[];
3490
- saved: number;
3491
- removed: number;
3492
- warnings?: DeclarationWarning[];
3493
- dryRun?: true;
3494
- diff?: DeclarationDiff;
3495
- }>;
3496
- snippet(cbid: string, opts?: SnippetOptions): Promise<InstallSnippet>;
3497
- /**
3498
- * Mint a short-lived signed token to see the banner as a visitor in a given region and
3499
- * language sees it — even from a headless browser, and without recording anything.
3500
- */
3501
- previewToken(cbid: string, opts?: PreviewTokenOptions): Promise<PreviewToken>;
3502
- verify(cbid: string, method: 'dns' | 'meta' | 'file' | 'embed'): Promise<VerifyResult>;
3503
- /** Exactly what to publish to prove control of the domain, for each verification method. */
3504
- verifyChallenge(cbid: string): Promise<unknown>;
3505
- /** Create up to 100 sites. Partial success: a bad or duplicate item fails only itself. */
3506
- createBulk(sites: BulkSiteInput[]): Promise<{
3507
- results: BulkSiteResult[];
3508
- }>;
3509
- brand(cbid: string): Promise<BrandExtractionResult>;
3510
- /** Read back the brand.json last imported: each role, its source (brand.json or site), ignored[] and warnings[]. 404 when none. */
3511
- getBrand(cbid: string): Promise<BrandReadBack>;
3512
- /** Import a brand.json (`{url}` or the document) into the banner theme and the rights page. `dryRun` saves nothing. */
3513
- setBrand(cbid: string, input: BrandImportInput, opts?: {
3514
- dryRun?: boolean;
3515
- }): Promise<BrandReadBack>;
3516
- /** Read a site's v2 banner flow (views, categories) plus any lint issues. */
3517
- getFlow(cbid: string): Promise<SiteFlow>;
3518
- /** Apply an ordered batch of structured edit ops; validated + persisted if lint-clean. */
3519
- editFlow(cbid: string, operations: FlowOp[]): Promise<FlowOpResponse>;
3520
- /** Wholesale-replace the flow with a full v2 config; validated + persisted if valid. */
3521
- setFlow(cbid: string, config: Record<string, unknown>): Promise<FlowOpResponse>;
3522
- };
3523
- consent: {
3524
- /**
3525
- * Verify the consent log's tamper-evident hash chain. Each record carries the hash of the
3526
- * one before it, so an edited, reordered or removed record answers `false`. This is the
3527
- * evidence behind the log: proof that what it says today is what it said when written.
3528
- */
3529
- verify(cbid: string): Promise<{
3530
- valid: boolean;
3531
- }>;
3532
- stats(cbid: string, query?: RangeQuery): Promise<ConsentDay[]>;
3533
- /** Opt-in by region and A/B variant, and the decision rate. Language and time-to-decision are not recorded (null). */
3534
- insights(cbid: string, query?: RangeQuery): Promise<ConsentInsights>;
3535
- log(cbid: string, query?: LogQuery): Promise<ConsentLogRow[]>;
3536
- export(cbid: string, query?: RangeQuery): Promise<string>;
3537
- receipt(cbid: string, stamp: string): Promise<SignedReceipt>;
3538
- /** Crypto-erase a subject's consent records by their consent-receipt stamp. Irreversible. */
3539
- eraseSubject(cbid: string, stamp: string): Promise<{
3540
- erased: number;
3541
- }>;
3542
- /** Export a data subject's consent records by their consent-receipt stamp (GDPR access/portability). */
3543
- exportSubject(cbid: string, stamp: string): Promise<{
3544
- cbid: string;
3545
- stamp: string;
3546
- records: unknown[];
3547
- count: number;
3548
- }>;
3549
- /** Record a consent decision via the PUBLIC ingest endpoint (POST /api/v1/consent). No `/v1`
3550
- * prefix and no auth is required by the server (the cbid must be a registered site); for
3551
- * server-side / non-browser consent flows. Pass `subjectId` to correlate a subject cross-surface. */
3552
- ingest(input: ConsentIngestInput): Promise<void>;
3553
- /**
3554
- * The reserved categories any site can switch on with `categories.suite` (`support_chat`,
3555
- * `referrals`): stance, fallback, regulatory basis, wording in every banner language, and
3556
- * known vendors. Public — `GET /v1/categories/registry` needs no key.
3557
- */
3558
- categoryRegistry(): Promise<CategoryRegistry>;
3559
- };
3560
- dsar: {
3561
- list(): Promise<DsarRequest[]>;
3562
- /**
3563
- * One request, in the same shape `list` returns — note that `create` answers with it
3564
- * wrapped as `{ request }`, so `create(...).request.id` is what you pass here.
3565
- */
3566
- get(id: string): Promise<DsarRequest>;
3567
- create(input: DsarCreate & ResourceTagsInput): Promise<{
3568
- request: DsarRequest;
3569
- }>;
3570
- /** `opts.messageToSubject` replaces the line the subject reads in the notice — for a rejection, why. */
3571
- advance(id: string, toStatus: DsarStatus, opts?: {
3572
- messageToSubject?: string;
3573
- }): Promise<{
3574
- request: DsarRequest;
3575
- }>;
3576
- /** The subject-facing response notice for a request, as plain text. */
3577
- response(id: string): Promise<string>;
3578
- /**
3579
- * Erase a subject's consent records on one site, for a deletion request past identity
3580
- * verification. Noted on the request. Requires dsar:write and consent:write.
3581
- */
3582
- erase(id: string, cbid: string, stamp: string): Promise<DsarEraseResult>;
3583
- /**
3584
- * A subject's consent records on one site, for an access or portability request past
3585
- * identity verification. Noted on the request. Requires dsar:write and consent:read.
3586
- */
3587
- export(id: string, cbid: string, stamp: string): Promise<DsarExportResult>;
3588
- /**
3589
- * Delete a TEST request (created with `test: true`), with its tasks and their log. A
3590
- * real request cannot be deleted (409 `not_a_test_request`); the deletion is audited.
3591
- */
3592
- delete(id: string): Promise<void>;
3593
- /**
3594
- * Mark a CLOSED request (completed or rejected) as a test, after the fact — for trials
3595
- * filed before `test` existed. An open one is refused (409 `request_not_closed`). Audited
3596
- * as `dsar.marked_test`; afterwards `delete` works on it. `changed` is false on a repeat.
3597
- */
3598
- markTest(id: string): Promise<{
3599
- request: DsarRequest;
3600
- changed: boolean;
3601
- }>;
3602
- /** Requests carrying one X-ForgeDeck-Trace (`GET /v1/dsar?trace=`). */
3603
- listByTrace(trace: string): Promise<DsarRequest[]>;
3604
- /**
3605
- * Open a case fanned out to every connected system (POST /v1/dsar/requests). `opts.idempotencyKey`
3606
- * (16–128 chars) makes a retry answer the same case; `opts.trace` passes your X-ForgeDeck-Trace on.
3607
- */
3608
- openCase(input: DsarCaseCreate, opts?: {
3609
- idempotencyKey?: string;
3610
- trace?: string;
3611
- }): Promise<DsarCase>;
3612
- /** One case across every system. */
3613
- getCase(id: string): Promise<DsarCase>;
3614
- /** Cancel a case before executeAfter; status `cancelled` once every system confirmed. */
3615
- cancelCase(id: string): Promise<DsarCase>;
3616
- /** The signed receipt for a case. */
3617
- caseReceipt(id: string): Promise<DsarCaseReceipt>;
3618
- /** The signed receipt as a PDF. */
3619
- caseReceiptPdf(id: string): Promise<ArrayBuffer>;
3620
- };
3621
- vendors: {
3622
- list(): Promise<ScoredVendor[]>;
3623
- create(input: VendorInput): Promise<{
3624
- vendor: VendorRecord;
3625
- risk: RiskScore;
3626
- }>;
3627
- };
3628
- ropa: {
3629
- list(): Promise<RopaEntry[]>;
3630
- create(input: RopaInput): Promise<{
3631
- entry: RopaEntry;
3632
- }>;
3633
- /** The org's RoPA (GDPR Art. 30) as CSV. */
3634
- exportCsv(): Promise<string>;
3635
- };
3636
- brandKits: {
3637
- list(): Promise<BrandKit[]>;
3638
- create(input: BrandKitCreate): Promise<{
3639
- kit: BrandKit;
3640
- }>;
3641
- delete(id: string): Promise<void>;
3642
- };
3643
- /** The hosted rights page (cookiemunch.net/r/<cbid> or the site's own domain). */
3644
- rightsPage: {
3645
- get(cbid: string): Promise<RightsPageDraft>;
3646
- /** Replace the draft. Nothing is live until publish(). `opts.baseUpdatedAt` refuses to overwrite a newer save (409 draft_conflict). */
3647
- put(cbid: string, page: RightsPageDocument, opts?: RightsPageWriteOptions): Promise<RightsPageDraft>;
3648
- /** Merge into the draft: objects merge, arrays replace, null removes. `opts.baseUpdatedAt` as on put(). */
3649
- patch(cbid: string, patch: Record<string, unknown>, opts?: RightsPageWriteOptions): Promise<RightsPageDraft>;
3650
- /** Validate a write without saving it. */
3651
- dryRun(cbid: string, page: Record<string, unknown>, opts?: {
3652
- mode?: 'patch' | 'put';
3653
- }): Promise<RightsPageDryRun>;
3654
- getPublished(cbid: string): Promise<RightsPagePublished>;
3655
- /**
3656
- * Publish the draft; it goes live at once. Pass `opts.baseUpdatedAt` (the draft's updatedAt
3657
- * as you read it) so only the draft you saw goes live: 409 draft_conflict otherwise.
3658
- */
3659
- publish(cbid: string, opts?: RightsPageWriteOptions): Promise<RightsPagePublishResult>;
3660
- versions(cbid: string): Promise<RightsPageVersions>;
3661
- /**
3662
- * Publish an earlier version again; it goes live at once and REPLACES the current draft
3663
- * (unpublished edits are lost). `opts.baseUpdatedAt` refuses with 409 if the draft moved.
3664
- */
3665
- rollback(cbid: string, version: number, opts?: RightsPageWriteOptions): Promise<RightsPagePublishResult>;
3666
- /** Custom hostnames serving the rights page, with the plan allowance. */
3667
- listDomains(cbid: string): Promise<RightsPageDomainList>;
3668
- /** Add a custom hostname (e.g. privacy.example.com); the answer carries the DNS records to create. */
3669
- addDomain(cbid: string, hostname: string): Promise<RightsPageDomain>;
3670
- /** Check it now: DNS while pending, the HTTPS answer once routed. Always the domain as it stands. */
3671
- verifyDomain(cbid: string, hostname: string): Promise<RightsPageDomain>;
3672
- /** Remove it: it stops being served and its certificate is not renewed. */
3673
- removeDomain(cbid: string, hostname: string): Promise<void>;
3674
- };
3675
- /**
3676
- * Identity resolution. Reads are POSTs on purpose: a person's identifiers travel in the
3677
- * body, never a URL where they would land in access logs.
3678
- */
3679
- identity: {
3680
- /** Canonical subject id for any known identifier, else null. */
3681
- resolve(identifiers: Identifier[]): Promise<{
3682
- subjectId: string | null;
3683
- }>;
3684
- /** Stitch identifiers into one subject (merging clusters when a link bridges them). */
3685
- link(identifiers: Identifier[]): Promise<{
3686
- subjectId: string;
3687
- }>;
3688
- cluster(subjectId: string): Promise<{
3689
- subjectId: string;
3690
- identifiers: Identifier[];
3691
- }>;
3692
- };
3693
- /** The Permission Vault: a resolved person's current consent state. */
3694
- vault: {
3695
- record(identifiers: Identifier[], decisions: ConsentDecisionInput[]): Promise<{
3696
- subjectId: string;
3697
- permits: unknown[];
3698
- }>;
3699
- current(identifiers: Identifier[]): Promise<{
3700
- purposes: Record<string, boolean>;
3701
- }>;
3702
- permits(identifiers: Identifier[]): Promise<{
3703
- permits: unknown[];
3704
- }>;
3705
- };
3706
- /** The unified profile, with consent enforced at ACTIVATION time. */
3707
- profile: {
3708
- get(identifiers: Identifier[]): Promise<unknown>;
3709
- setAttributes(identifiers: Identifier[], attributes: Record<string, ProfileAttributeInput>): Promise<{
3710
- subjectId: string;
3711
- }>;
3712
- /** Attribute values usable for `purpose` — {} when the person hasn't consented to it. */
3713
- activate(identifiers: Identifier[], purpose: string): Promise<{
3714
- attributes: Record<string, string>;
3715
- }>;
3716
- };
3717
- /** Marketing preferences as topics x channels. */
3718
- subscriptions: {
3719
- /** The org's topic catalog — what a subject can subscribe TO. */
3720
- topics(): Promise<{
3721
- topics: SubscriptionTopicInput[];
3722
- }>;
3723
- /** Replace the catalog. It is authored whole, not patched. */
3724
- setTopics(topics: SubscriptionTopicInput[]): Promise<{
3725
- topics: SubscriptionTopicInput[];
3726
- }>;
3727
- get(subjectId: string): Promise<unknown>;
3728
- set(subjectId: string, topic: string, channel: string, optedIn: boolean): Promise<unknown>;
3729
- unsubscribeAll(subjectId: string): Promise<unknown>;
3730
- resubscribe(subjectId: string): Promise<unknown>;
3731
- activation(subjectId: string, topics: SubscriptionTopicInput[]): Promise<{
3732
- entries: unknown[];
3733
- }>;
3734
- };
3735
- /** DPIA / PIA / LIA / TIA / AI-impact / vendor assessments. */
3736
- assessments: {
3737
- templates(): Promise<{
3738
- templates: unknown[];
3739
- }>;
3740
- list(): Promise<{
3741
- assessments: unknown[];
3742
- }>;
3743
- start(template: string, subject: string): Promise<unknown>;
3744
- /** The record plus its derived score, completeness and SME routing. */
3745
- get(id: string): Promise<unknown>;
3746
- answer(id: string, questionId: string, value: string | number | boolean): Promise<unknown>;
3747
- /** Fill from the org's latest data map; never overwrites a human answer. */
3748
- autoPopulateFromMap(id: string): Promise<{
3749
- assessment: unknown;
3750
- applied: string[];
3751
- }>;
3752
- /** Fill from evidence you supply. Never overwrites a human answer; records `source` as provenance. */
3753
- autoPopulate(id: string, evidence: Record<string, unknown>, source?: string): Promise<{
3754
- assessment: unknown;
3755
- applied: string[];
3756
- }>;
3757
- submit(id: string): Promise<unknown>;
3758
- approve(id: string, by: string): Promise<unknown>;
3759
- reject(id: string, by: string, reason: string): Promise<unknown>;
3760
- };
3761
- /** The data map produced by an in-environment scan (metadata only). */
3762
- discovery: {
3763
- ingestMap(map: unknown): Promise<{
3764
- scannedAt: number;
3765
- systems: number;
3766
- }>;
3767
- getMap(): Promise<unknown>;
3768
- ropaDrafts(): Promise<{
3769
- drafts: unknown[];
3770
- }>;
3771
- evidence(): Promise<{
3772
- evidence: Record<string, unknown>;
3773
- }>;
3774
- /** What changed since the last scan, and where the RoPA disagrees with reality. */
3775
- drift(): Promise<{
3776
- comparedTo: number | null;
3777
- sinceLastScan: unknown[];
3778
- againstRecord: unknown[];
3779
- }>;
3780
- /**
3781
- * Plan warehouse-native policy from the latest map. Returns a PLAN with its own
3782
- * revert — nothing is applied to your warehouse by calling this.
3783
- */
3784
- planEnforcement(dialect: 'postgres' | 'mysql' | 'snowflake', rules: EnforcementRuleInput[], opts?: {
3785
- permitsTable?: string;
3786
- policyPrefix?: string;
3787
- }): Promise<{
3788
- plan: {
3789
- statements: unknown[];
3790
- revert: unknown[];
3791
- skipped: unknown[];
3792
- };
3793
- }>;
3794
- };
3795
- /**
3796
- * Regulatory intelligence: the curated privacy-law dataset. Every response carries
3797
- * `reviewedAt` — the dataset ships with the product and is only as current as its
3798
- * last review. Not legal advice.
3799
- */
3800
- regulatory: {
3801
- /** The dataset, optionally narrowed to the jurisdictions you operate in. */
3802
- feed(jurisdictions?: string[]): Promise<RegulatoryFeedResult>;
3803
- /** What takes effect within `days` (default 180), soonest first. */
3804
- upcoming(days?: number): Promise<RegulatoryFeedResult>;
3805
- };
3806
- /** AI governance: policy, the inline gateway, inventory and lineage. */
3807
- ai: {
3808
- getPolicy(): Promise<{
3809
- policy: unknown;
3810
- configured: boolean;
3811
- }>;
3812
- setPolicy(policy: unknown): Promise<{
3813
- policy: unknown;
3814
- }>;
3815
- /** Enforce consent + policy on a prompt or response. Requires the ai:inspect scope. */
3816
- inspect(input: AiInspectInput): Promise<AiInspectResult>;
3817
- inventory(): Promise<{
3818
- systems: unknown[];
3819
- shadow: unknown[];
3820
- }>;
3821
- lineage(): Promise<{
3822
- lineage: Record<string, string[]>;
3823
- }>;
3824
- registerSystem(input: {
3825
- id: string;
3826
- name: string;
3827
- provider?: string;
3828
- purpose?: string;
3829
- }): Promise<unknown>;
3830
- /** The AI systems declared with registerSystem. */
3831
- systems(): Promise<unknown>;
3832
- audit(limit?: number): Promise<{
3833
- entries: unknown[];
3834
- }>;
3835
- };
3836
- /** DSR fulfillment: plan work per system, poll it from an in-VPC agent, report outcomes. */
3837
- fulfillment: {
3838
- sla(): Promise<unknown>;
3839
- plan(requestId: string, systems: Array<{
3840
- system: string;
3841
- operation: FulfillmentOp;
3842
- }>, includeHistorical?: boolean): Promise<{
3843
- requestId: string;
3844
- tasks: unknown[];
3845
- }>;
3846
- status(requestId: string): Promise<unknown>;
3847
- /** In-VPC agent: poll pending tasks. */
3848
- pendingTasks(limit?: number): Promise<{
3849
- tasks: unknown[];
3850
- }>;
3851
- /** In-VPC agent: report an outcome. Only the outcome crosses the boundary. */
3852
- reportTask(taskId: string, ok: boolean, error?: string): Promise<unknown>;
3853
- /**
3854
- * Systems you have connected that run part of a request themselves — an identity
3855
- * platform holding your users' accounts, for instance. The in-VPC agent covers the
3856
- * systems we cannot reach; these are the ones we can.
3857
- */
3858
- executors(opts?: MetadataFilter): Promise<DsarExecutor[]>;
3859
- /** One connection with its full profile, never the credentials. Read it before changing `profile`: `updateExecutor` replaces the whole profile. */
3860
- executor(id: string): Promise<DsarExecutor>;
3861
- /**
3862
- * Connect one. The secret is stored encrypted and never returned; the response carries
3863
- * the URL to point that system's webhook at.
3864
- */
3865
- connectExecutor(input: (DsarExecutorInput | DsarExecutorPresetInput) & ResourceTagsInput): Promise<DsarExecutorCreated>;
3866
- /**
3867
- * Change a connection in place. Only what you send changes, and the stored credential
3868
- * is kept unless you pass a new `secretKey` — so adding a field to a profile does not
3869
- * cost you the connection or its id.
3870
- */
3871
- updateExecutor(id: string, patch: DsarExecutorPatch): Promise<DsarExecutor>;
3872
- /** What `connectExecutor` would create, validated in full; nothing is stored (`?dryRun=1`). */
3873
- dryRunConnectExecutor(input: DsarExecutorInput | DsarExecutorPresetInput): Promise<DsarExecutorDryRun>;
3874
- /** The versioned presets, whether each is usable now (or waits on another platform), and the org canary address. */
3875
- executorPresets(): Promise<ExecutorPresets>;
3876
- /**
3877
- * Rebuild a connection from its preset's latest version (or `presetVersion`), keeping its id
3878
- * and credentials; or adopt a preset on a hand-written one by naming it. Answers with `diff`.
3879
- */
3880
- upgradeExecutorPreset(id: string, input?: ExecutorPresetUpgrade): Promise<DsarExecutor & {
3881
- diff: ConfigChange[];
3882
- warnings?: Array<{
3883
- field: string;
3884
- reason: string;
3885
- }>;
3886
- }>;
3887
- /** What `upgradeExecutorPreset` would change; nothing is stored (`?dryRun=1`). */
3888
- dryRunUpgradeExecutorPreset(id: string, input?: ExecutorPresetUpgrade): Promise<DsarExecutorDryRun>;
3889
- /** What `updateExecutor` would change, with a diff; the stored connection is untouched (`?dryRun=1`). */
3890
- dryRunUpdateExecutor(id: string, patch: DsarExecutorPatch): Promise<DsarExecutorDryRun>;
3891
- /**
3892
- * Would this webhook delivery verify? Runs the receiver's exact check on headers and a raw
3893
- * body you supply, acts on nothing, and names the stage that failed.
3894
- */
3895
- testExecutorWebhook(id: string, delivery: {
3896
- headers: Record<string, string>;
3897
- body: string;
3898
- }): Promise<ExecutorWebhookTestResult>;
3899
- /** The last 50 deliveries to a connection's webhook, newest first, each with its reason. */
3900
- executorWebhookDeliveries(id: string): Promise<ExecutorWebhookDelivery[]>;
3901
- /** Disconnect a system; its open sub-tasks stop being driven. */
3902
- disconnectExecutor(id: string): Promise<void>;
3903
- /** The export bundle a connected system produced, fetched from it on demand. */
3904
- taskExport(requestId: string, taskId: string): Promise<DsarTaskExport>;
3905
- /**
3906
- * One task: its status history (`events`), every request made to a connected system on
3907
- * its behalf (`log`, redacted, 30 days) and whether that system's version changed mid-way.
3908
- */
3909
- task(requestId: string, taskId: string): Promise<DsarTask>;
3910
- /**
3911
- * Try a connection against one email without filing anything: runs the lookup, returns
3912
- * the raw (redacted) upstream answers and what a real request would have sent.
3913
- */
3914
- testExecutor(id: string, input: ExecutorTestInput): Promise<ExecutorTestResult>;
3915
- /** Re-check a connection now (a canary test that records its health); for a deploy pipeline. */
3916
- recheckExecutor(id: string): Promise<ExecutorTestResult>;
3917
- /** A connection's last health checks, newest first (`limit` 1 to 50, default 50). */
3918
- executorHealthHistory(id: string, opts?: {
3919
- limit?: number;
3920
- }): Promise<ExecutorHealth[]>;
3921
- /** Run the cm-standard-v2 conformance kit against a connection, on the canary subject only. */
3922
- executorConformance(id: string): Promise<ExecutorConformanceResult>;
3923
- /** A new completion secret, shown once; the old one keeps verifying for 24 hours. */
3924
- rollExecutorCompletionSecret(id: string): Promise<CompletionSecretRolled>;
3925
- };
3926
- preferences: {
3927
- list(): Promise<PreferenceItem[]>;
3928
- /** Save/update a subject's named-purpose opt-ins. Returns the persisted record. */
3929
- save(subjectId: string, purposes: Record<string, boolean>): Promise<{
3930
- record: PreferenceRecord;
3931
- }>;
3932
- /** One subject's record. A subject with none has empty `purposes`. */
3933
- get(subjectId: string): Promise<PreferenceRecord>;
3934
- };
3935
- /** The hosted preference centre, opened for a visitor your server has signed in. */
3936
- preferenceCenter: {
3937
- /**
3938
- * Mint a preference-centre token (POST /v1/preference-center/tokens) for the page to pass to
3939
- * `CookieMunch.setSubjectToken`. Server-side only: the token opens that subject's subscriptions
3940
- * and profile until `expiresAt`. `ttlSeconds` defaults to 3600, at most 86400. Needs
3941
- * subscriptions:write and profile:write, plus identity:read when minting by email.
3942
- */
3943
- mintToken(input: CenterTokenInput): Promise<CenterToken>;
3944
- };
3945
- members: {
3946
- list(): Promise<Member[]>;
3947
- invite(email: string, role: string): Promise<{
3948
- member: {
3949
- userId: string;
3950
- email: string;
3951
- role: string;
3952
- };
3953
- }>;
3954
- setRole(userId: string, role: string): Promise<{
3955
- member: {
3956
- userId: string;
3957
- email: string;
3958
- role: string;
3959
- };
3960
- }>;
3961
- remove(userId: string): Promise<{
3962
- ok: true;
3963
- }>;
3964
- };
3965
- keys: {
3966
- list(): Promise<ApiKeyPrefix[]>;
3967
- /**
3968
- * Issue a new API key; the secret is returned once. Pass `scopes` and/or `cbids` for a
3969
- * least-privilege key — omit both for full access to the whole org.
3970
- */
3971
- issue(input?: ApiKeyIssueInput): Promise<ApiKeyIssued>;
3972
- /** Revoke a key by its prefix. Immediate. */
3973
- revoke(prefix: string): Promise<void>;
3974
- /** Rotate a key: a new secret, returned once, with the same scopes, lock and expiry. The old one stops working. */
3975
- roll(prefix: string): Promise<ApiKeyIssued>;
3976
- /** Rename a key, or replace its scopes or property lock. Only the fields sent change. */
3977
- update(prefix: string, patch: ApiKeyUpdate): Promise<{
3978
- ok: true;
3979
- }>;
3980
- /** Key hygiene: keys unused for `unusedDays` (default 90), broad keys, keys expiring within `expiringDays` (default 14). */
3981
- report(opts?: {
3982
- unusedDays?: number;
3983
- expiringDays?: number;
3984
- }): Promise<ApiKeyReport>;
3985
- /** The suite-standard listing (`?shape=standard`). */
3986
- listStandard(): Promise<StandardKeyList>;
3987
- /** The calling key itself, whatever its scopes: check its own expiry. */
3988
- self(): Promise<ApiKeyPrefix>;
3989
- /** Re-pin the calling key to another dated API version. Any key may, for itself. */
3990
- updateSelf(input: {
3991
- apiVersion: string;
3992
- }): Promise<ApiKeyPrefix>;
3993
- /** The calling key rotates itself; the old secret stops at once. Use a client with an Idempotency-Key header. */
3994
- rollSelf(): Promise<ApiKeyIssued>;
3995
- /** A short-lived key (ttlSeconds at most 43200) within this key's own scopes and properties. Needs keys:write or full access. */
3996
- vend(input: {
3997
- scopes: string[];
3998
- ttlSeconds: number;
3999
- cbids?: string[];
4000
- name?: string;
4001
- }): Promise<ApiKeyVended>;
4002
- /** Revoke a leaked secret (works without a valid key; always answers { received }). */
4003
- revokeLeaked(report: LeakReport): Promise<{
4004
- received: number;
4005
- }>;
4006
- };
4007
- usage(): Promise<Usage>;
4008
- /** The dated API versions, what each changed, and the one this key is pinned to (`yours`). */
4009
- versions(): Promise<ApiVersions>;
4010
- /** What the org may use: every plan feature (`whiteLabel`, `tcf`, …) and limit, in the suite-standard shape. Any key may read it. */
4011
- entitlements(): Promise<Entitlements>;
4012
- /**
4013
- * The organisation's sandbox: a separate test organisation with the same people and plan features, never billed.
4014
- * Its keys are test-format keys and its rights requests are all tests. `create` and `delete` need an unscoped key or `orgs:create`.
4015
- */
4016
- sandbox: {
4017
- /** The sandbox, or null. From a sandbox key, the sandbox itself. */
4018
- get(): Promise<SandboxOrg | null>;
4019
- /** Make the sandbox (or return the existing one, `created: false`) with a new test key for it. */
4020
- create(input?: {
4021
- keyName?: string;
4022
- }): Promise<SandboxCreated>;
4023
- /** Erase the sandbox entirely. Cannot be undone; the live organisation is not touched. */
4024
- delete(): Promise<SandboxPurge>;
4025
- };
4026
- /** Every link a site's privacy wiring depends on, one row each with `ok` and a fix hint. `cbid` may be omitted with one site. */
4027
- integrationHealth(cbid?: string): Promise<IntegrationHealthReport>;
4028
- /** Waive a health check you chose not to meet: the row reports `ok: null` with `waived`. Audited. */
4029
- healthWaivers: {
4030
- list(cbid?: string): Promise<{
4031
- cbid: string;
4032
- waivers: HealthWaiver[];
4033
- }>;
4034
- set(input: HealthWaiverInput): Promise<{
4035
- waiver: HealthWaiver;
4036
- }>;
4037
- remove(check: string, opts?: {
4038
- cbid?: string;
4039
- subject?: string;
4040
- }): Promise<void>;
4041
- };
4042
- /**
4043
- * The site's embed manifest: the tenant variant of `/.well-known/forgedeck-embed.json` — every
4044
- * origin by CSP directive and every browser key the embed writes for this site's config. Public.
4045
- */
4046
- embedManifest(cbid: string): Promise<EmbedManifest>;
4047
- /**
4048
- * Wire a product's privacy in one call: the site, connected systems, Atlas and Forumulate. Idempotent;
4049
- * `{ dryRun: true }` writes nothing anywhere. No secret appears in the answer.
4050
- */
4051
- provision(input: ProvisionRequest | ProvisionRequestV2, opts?: {
4052
- dryRun?: boolean;
4053
- fromStep?: string;
4054
- }): Promise<ProvisionResult>;
4055
- /** The key's organisation. Requires an unscoped key that is not property-locked. */
4056
- org: {
4057
- get(): Promise<Org>;
4058
- /** Rename the org or set its logo. Deleting the org is not available through the API. */
4059
- update(patch: OrgUpdate): Promise<Org>;
4060
- /**
4061
- * Your own mail provider for rights-request mail. It carries verification codes once
4062
- * `test` succeeds; every `set` clears that. There is no shared sender: without one, requests
4063
- * are verified by your sign-in provider (`rightsIdentity`) or filed unverified for you to confirm.
4064
- */
4065
- mailProvider: {
4066
- get(): Promise<MailProvider>;
4067
- set(input: MailProviderInput): Promise<MailProvider>;
4068
- remove(): Promise<void>;
4069
- /** Send a test through your provider. `to` defaults to the reply-to, else the from address. */
4070
- test(to?: string): Promise<MailProviderTestResult>;
4071
- };
4072
- /**
4073
- * Your organisation's own data-controller identity: who every rights notice names, before any site config
4074
- * `controller` block. Needed for a notice on a request filed without a cbid when you have several sites.
4075
- * An unscoped key, or `rights:write`.
4076
- */
4077
- controller: {
4078
- get(): Promise<OrgControllerIdentity>;
4079
- /** Replace it: a field left out is removed. */
4080
- set(input: OrgControllerInput): Promise<OrgControllerIdentity>;
4081
- remove(): Promise<void>;
4082
- };
4083
- /**
4084
- * The default captcha for your rights pages, for every site without its own (`rightsCaptcha`): your own
4085
- * keys (recommended) or off. Without one, rights pages have no captcha.
4086
- */
4087
- rightsCaptcha: {
4088
- get(): Promise<RightsCaptcha>;
4089
- set(input: RightsCaptchaInput): Promise<RightsCaptcha>;
4090
- /** Remove the default; answers the setting now in force (off). */
4091
- remove(): Promise<RightsCaptcha>;
4092
- };
4093
- /** The default sign-in provider rights requests are verified with, for every site without its own. */
4094
- rightsIdentity: {
4095
- get(): Promise<RightsIdentity>;
4096
- set(input: RightsIdentityInput): Promise<RightsIdentity>;
4097
- /** Remove the default; answers the setting now in force. */
4098
- remove(): Promise<RightsIdentity>;
4099
- };
4100
- };
4101
- /** The org's audit log, newest first. API actions appear as `apikey:<prefix>`. */
4102
- /** `{ actor: 'self' }` reads the calling key's own rows, the one form a scoped key may call. */
4103
- audit(limit?: number, opts?: {
4104
- actor?: string;
4105
- }): Promise<{
4106
- entries: AuditEntry[];
4107
- }>;
4108
- /** Stream the audit log to an HTTPS endpoint as CloudEvents 1.0. Unscoped keys. */
4109
- auditSink: {
4110
- get(): Promise<{
4111
- sink: AuditSink;
4112
- }>;
4113
- set(input: AuditSinkInput): Promise<{
4114
- sink: AuditSink;
4115
- secret?: string;
4116
- }>;
4117
- remove(): Promise<void>;
4118
- };
4119
- assets: {
4120
- /** Upload a banner image (≤ 1,000,000 bytes) and get its public URL. Requires sites:write. */
4121
- upload(input: AssetUpload): Promise<{
4122
- url: string;
4123
- }>;
4124
- /**
4125
- * Delete a stored image. Takes the URL `upload` returned, or just its file name. Only
4126
- * your own org's images are reachable — the folder comes from your API key.
4127
- */
4128
- delete(urlOrFileName: string): Promise<void>;
4129
- };
4130
- /** Provision and manage child orgs. Requires a key with the reseller:* scopes. */
4131
- reseller: {
4132
- list(): Promise<ResellerChildList>;
4133
- /** Provision a child org. With `mintKey`, its first API key is returned once, as `apiKey`. */
4134
- create(input: ResellerChildCreate): Promise<{
4135
- child: ResellerChild;
4136
- apiKey?: string;
4137
- }>;
4138
- get(id: string): Promise<unknown>;
4139
- update(id: string, patch: ResellerChildPatch): Promise<unknown>;
4140
- /**
4141
- * Deprovision a child. Suspends it by default, which is reversible; `{ purge: true }`
4142
- * hard-deletes it and its data, which is not.
4143
- */
4144
- deprovision(id: string, opts?: {
4145
- purge?: boolean;
4146
- }): Promise<void>;
4147
- listKeys(id: string): Promise<ApiKeyPrefix[]>;
4148
- /** Mint an API key for a child. The secret is returned once. */
4149
- mintKey(id: string, input?: ChildKeyInput): Promise<ApiKeyIssued>;
4150
- revokeKey(id: string, prefix: string): Promise<void>;
4151
- };
4152
- webhooks: {
4153
- list(opts?: MetadataFilter): Promise<WebhookSubscription[]>;
4154
- create(input: WebhookCreate & ResourceTagsInput): Promise<WebhookSubscription>;
4155
- /** Change or pause a subscription. `{ active: false }` pauses without deleting it. */
4156
- update(id: string, patch: WebhookUpdate): Promise<WebhookSubscription>;
4157
- delete(id: string): Promise<void>;
4158
- /** Rotate the signing secret. The new secret is returned once. */
4159
- rollSecret(id: string): Promise<{
4160
- secret: string;
4161
- }>;
4162
- /** Send a signed test event now and report what the endpoint answered. */
4163
- test(id: string): Promise<WebhookTestResult>;
4164
- /** Deliveries that failed every retry, newest first. */
4165
- deadLetters(): Promise<{
4166
- deadLetters: WebhookDeadLetter[];
4167
- }>;
4168
- /** Deliver a dead letter again, to the subscription as it is now. */
4169
- replayDeadLetter(id: string): Promise<unknown>;
4170
- /** Send what a failing or disabled endpoint missed since `since` (epoch ms or ISO), oldest first, stopping at the first failure. */
4171
- replay(id: string, since: number | string, opts?: {
4172
- limit?: number;
4173
- }): Promise<WebhookReplayResult>;
4174
- };
4175
- /**
4176
- * Account-linked rights requests: a single-use link to the hosted rights page for a person your
4177
- * backend knows is signed in. The page locks their email and skips the code step. Requires dsar:write.
4178
- */
4179
- rightsLinks: {
4180
- create(cbid: string, input: RightsLinkInput): Promise<RightsLink>;
4181
- };
4182
- /**
4183
- * A site's consent-sync signing secret: your server signs consent-sync tokens with it
4184
- * (`mintConsentSyncToken`) so a visitor's decision syncs across their browsers. `rotate` mints the
4185
- * first one or replaces it (the old one stops at once) and is the only time the secret is returned.
4186
- * Reading needs sites:read; rotate and remove need sites:write and consent:write.
4187
- */
4188
- consentSyncSecret: {
4189
- get(cbid: string): Promise<ConsentSyncSecret>;
4190
- rotate(cbid: string): Promise<ConsentSyncSecretMinted>;
4191
- /** Turn hosted consent sync off for the site. */
4192
- remove(cbid: string): Promise<ConsentSyncSecret>;
4193
- };
4194
- /**
4195
- * A site's rights-page captcha: your own Turnstile, hCaptcha or reCAPTCHA keys (recommended), or off. A site
4196
- * without its own setting uses the organisation default (`org.rightsCaptcha`), else off. Requires sites:read / sites:write.
4197
- */
4198
- rightsCaptcha: {
4199
- get(cbid: string): Promise<RightsCaptcha>;
4200
- set(cbid: string, input: RightsCaptchaInput): Promise<RightsCaptcha>;
4201
- /** Remove the site's own setting: it inherits the organisation default again. Answers the setting now in force. */
4202
- remove(cbid: string): Promise<RightsCaptcha>;
4203
- };
4204
- /**
4205
- * A site's sign-in provider (Clerk, Atlas or any JWKS issuer): a visitor signed in to your site
4206
- * is verified by their session, with no code mail. A site without its own setting uses the
4207
- * organisation default (`org.rightsIdentity`). Requires sites:read / sites:write.
4208
- */
4209
- rightsIdentity: {
4210
- get(cbid: string): Promise<RightsIdentity>;
4211
- set(cbid: string, input: RightsIdentityInput): Promise<RightsIdentity>;
4212
- /** Remove the site's own setting: it inherits the organisation default again. */
4213
- remove(cbid: string): Promise<RightsIdentity>;
4214
- };
4215
- /** A site's rights-request settings: graceDays (0–30; 7 for a new site, 0 until set for one that existed before). Requires dsar:read / dsar:write. */
4216
- dsarSettings: {
4217
- get(cbid: string): Promise<DsarSettings>;
4218
- set(cbid: string, input: {
4219
- graceDays: number;
4220
- }): Promise<DsarSettings>;
4221
- };
4222
- /** Cards for support, CRM and helpdesk sidebars. Requires dsar:read. */
4223
- integrations: {
4224
- /** Open rights requests for one person, by identity (preferred) or email. */
4225
- subjectCard(app: string, person: {
4226
- iss: string;
4227
- sub: string;
4228
- } | {
4229
- email: string;
4230
- }): Promise<SubjectCard>;
4231
- };
4232
- /** One person's consent across every site in the org, by the subjectId your apps attach. */
4233
- subjects: {
4234
- /** Requires consent:read; not available to property-locked keys. */
4235
- consent(subjectId: string): Promise<{
4236
- subjectId: string;
4237
- records: unknown[];
4238
- count: number;
4239
- sites: string[];
4240
- }>;
4241
- };
4242
- banners: {
4243
- list(): Promise<BannerSummary[]>;
4244
- create(input: {
4245
- name: string;
4246
- json: SiteConfig;
4247
- }): Promise<BannerRecord>;
4248
- get(id: string): Promise<BannerRecord>;
4249
- update(id: string, patch: {
4250
- name?: string;
4251
- json?: SiteConfig;
4252
- }): Promise<BannerRecord>;
4253
- delete(id: string): Promise<void>;
4254
- assignments(id: string): Promise<{
4255
- cbids: string[];
4256
- }>;
4257
- setAssignments(id: string, cbids: string[]): Promise<{
4258
- cbids: string[];
4259
- }>;
4260
- publish(id: string): Promise<{
4261
- publishedCbids: string[];
4262
- }>;
4263
- };
4264
- }
4265
- declare function createCookieMunch(opts: CookieMunchOptions): CookieMunchClient;
4266
-
4267
- export { type AbResult, type AccountOrg, type AccountOrgs, type AdPersonalizationInput, type AiInspectInput, type AiInspectResult, type ApiKey, type ApiKeyIssueInput, type ApiKeyIssued, type ApiKeyPrefix, type ApiKeyReport, type ApiKeyRevoked, type ApiKeyUpdate, type ApiKeyVended, type ApiVersions, type AppliedImport, type AssetUpload, type AuditEntry, type AuditSink, type AuditSinkInput, type BannerRecord, type BannerSummary, type BlockedReport, type BrandExtractionResult, type BrandImportInput, type BrandKit, type BrandKitCreate, type BrandMappingRow, type BrandReadBack, type BrandSuggestion, type BulkSiteInput, type BulkSiteResult, type ButtonParityFinding, type ButtonParityLint, type ButtonParityScan, CANARY_ISSUER, CONFORMANCE_RULES, type CategorizedCookie, type CategoryRegistry, type CenterToken, type CenterTokenInput, type ChildKeyInput, type CompletionSecretRolled, type ConfigChange, type ConfigDryRun, type ConfigWarning, type ConformanceOptions, type ConformanceReport, type ConformanceRuleResult, type ConformanceStatus, type ConsentDay, type ConsentDecisionInput, type ConsentIngestInput, type ConsentInsights, type ConsentLogRow, type ConsentSyncSecret, type ConsentSyncSecretMinted, type CookieDeclaration, CookieMunchApiError, type CookieMunchClient, type CookieMunchOptions, type CookiePreset, type CookiePresetManifest, type CookiePresetParams, type CookiePresetResult, type CookiePresetVendor, type CookieSuggestion, type CookieSuggestions, type CookieSuggestionsDeclared, type CspSources, type CustomPresetInput, type DeclarationDiff, type DeclarationDryRun, type DeclarationWarning, type DeclaredCookie, type DeclaredCookieInput, type DnsRecordInstruction, type DsarCase, type DsarCaseCreate, type DsarCaseReceipt, type DsarCaseStatus, type DsarCaseTask, type DsarCreate, type DsarEraseResult, type DsarExecutor, type DsarExecutorCreated, type DsarExecutorDryRun, type DsarExecutorInput, type DsarExecutorPatch, type DsarExecutorPresetInput, type DsarExportResult, type DsarRequest, type DsarSettings, type DsarStatus, type DsarSubject, type DsarTask, type DsarTaskEvent, type DsarTaskExport, type DsarTaskLogEntry, type DsarTaskOutcome, type DsarType, type DsarTypeWord, type EmbedManifest, type EmbedManifestStorage, type EmbedManifestSurface, type EnforcementRuleInput, type Entitlement, type Entitlements, type ExecutorConformanceResult, type ExecutorHealth, type ExecutorPresetName, type ExecutorPresetStep, type ExecutorPresetUpgrade, type ExecutorPresets, type ExecutorProfile, type ExecutorTestInput, type ExecutorTestResult, type ExecutorWebhookDelivery, type ExecutorWebhookTestResult, type FdCause, type FdConsent, type FdConsentQueue, type FdQueuedCall, type FdRequestOptions, type FdSnapshot, type FlowIssue, type FlowOp, type FlowOpResponse, type FulfillmentOp, type HealthRow, type HealthWaiver, type HealthWaiverInput, type Identifier, type Identity, type ImportedCookie, type ImportedDeclaration, type InstallSnippet, type IntegrationHealthReport, type LeakReport, type LegalBasis, type LogQuery, type MailProvider, type MailProviderInput, type MailProviderKind, type MailProviderTestResult, type Member, type MetadataFilter, type MintConsentSyncTokenInput, type ObservedPurgeResult, type OperatorTokenExchangeInput, type OperatorTokenExchangeResult, type OptInMethod, type Org, type OrgControllerIdentity, type OrgControllerInput, type OrgUpdate, type ParityControlSummary, type PartnerCatalogEntry, type PartnerId, type PartnerLink, type PartnerLinkCreate, type PlanSource, type PolicyOptions, type PreferenceItem, type PreferenceRecord, type PreviewToken, type PreviewTokenOptions, type ProfileAttributeInput, type ProvisionEnv, type ProvisionRequest, type ProvisionRequestV2, type ProvisionResult, type ProvisionStep, type PublicDsarFiled, type PublicDsarPending, type PublicVerification, type PutConfigOptions, type RangeQuery, type Regulation, type RegulationSummary, type RegulatoryFeedResult, type ResellerChild, type ResellerChildCreate, type ResellerChildList, type ResellerChildPatch, type ResourceMetadata, type ResourceTags, type ResourceTagsInput, type ResourceTagsUpdate, type RetentionLine, type RetiredCookie, type RightKind, type RightsCaptcha, type RightsCaptchaInput, type RightsCaptchaProvider, type RightsIdentity, type RightsIdentityInput, type RightsIdentityType, type RightsLink, type RightsLinkInput, type RightsPageDocument, type RightsPageDomain, type RightsPageDomainList, type RightsPageDraft, type RightsPageDraftConflict, type RightsPageDryRun, type RightsPageIssue, type RightsPagePublishResult, type RightsPagePublished, type RightsPagePublisher, type RightsPageVersions, type RightsPageWriteOptions, type RiskScore, type RopaEntry, type RopaInput, SDK_VERSION, type SandboxCreated, type SandboxOrg, type SandboxPurge, type ScanResult, type ScanStatus, type ScoredVendor, type ScrollbarTheme, type SessionAnalysisInput, type SignedReceipt, type Site, type SiteConfig, type SiteCookie, type SiteCreate, type SiteFlow, type SiteUpdate, type SiteUpdateResult, type SnippetOptions, type StandardKeyList, type StandardPartnerLink, type StandardPartnerLinkCreate, type StorageType, type SubjectCard, type SubjectIdentity, type SubscriptionTopicInput, type SuggestedRejectStyle, type SupportedLanguage, type TaggedType, TokenExchangeError, type Usage, type VendorInput, type VendorRecord, type VerifyResult, type VerifyWebhookInput, type WebhookCreate, type WebhookDeadLetter, type WebhookKeyForm, type WebhookReplayResult, type WebhookStage, type WebhookSubscription, type WebhookTestResult, type WebhookUpdate, canaryIdentityFor, createCookieMunch, exchangeOperatorToken, mintConsentSyncToken, runExecutorConformance, verifyWebhookSignature };