@cookiemunch/sdk 0.1.1 → 0.2.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 CHANGED
@@ -114,6 +114,38 @@ interface DsarRequest {
114
114
  /** A test request: off the SLA board, labelled, and deletable with `dsar.delete`. A closed request can be marked one with `dsar.markTest`. */
115
115
  test?: boolean;
116
116
  }
117
+ /**
118
+ * How a rights-page requester was verified — on every answer of the public intake
119
+ * (`POST /api/v1/public/dsar`, `/verify`, `/resend`) and so in the `dsar.created` webhook payload.
120
+ * `email_code` on a 202: a code was mailed through your own provider; on a 201: the code matched.
121
+ * `none` with a `reason`: filed without verification — confirm the requester yourself. `none`
122
+ * without one: an opt-out, which needs no verification.
123
+ */
124
+ type PublicVerification = {
125
+ method: 'session' | 'email_code' | 'account_link';
126
+ } | {
127
+ method: 'none';
128
+ reason?: 'no_verification_configured' | 'mail_failed' | 'recipient_rejected';
129
+ };
130
+ /** A public intake that filed a request (201): also the `dsar.created` payload for one. */
131
+ interface PublicDsarFiled {
132
+ id: string;
133
+ status: 'received' | 'verifying';
134
+ /** Epoch ms the statutory response is due. */
135
+ deadline: number;
136
+ /** Only when filed without verification; the same as `verification.method` `none` with a `reason`. */
137
+ unverified?: true;
138
+ verification: PublicVerification;
139
+ }
140
+ /** A public intake waiting for its email code (202). */
141
+ interface PublicDsarPending {
142
+ pendingId: string;
143
+ expiresAt: number;
144
+ resendAfter?: number;
145
+ verification: {
146
+ method: 'email_code';
147
+ };
148
+ }
117
149
  interface DsarCreate {
118
150
  type: DsarType;
119
151
  subjectEmail: string;
@@ -220,13 +252,13 @@ declare function verifyWebhookSignature(input: VerifyWebhookInput): boolean;
220
252
  * from the key, so callers never pass an orgId. `fetch` is injectable for testing
221
253
  * and non-browser/non-Node runtimes; it defaults to the global fetch.
222
254
  *
223
- * const fc = createCookieMunch({ apiKey: 'fck_…', baseUrl: 'https://cmp.example.com' });
255
+ * const fc = createCookieMunch({ apiKey: 'fck_…', baseUrl: 'https://api.cookiemunch.net' });
224
256
  * const sites = await fc.sites.list();
225
257
  */
226
258
 
227
259
  interface CookieMunchOptions {
228
260
  apiKey: string;
229
- /** e.g. "https://cmp.example.com" — the /v1 prefix is appended automatically. */
261
+ /** "https://api.cookiemunch.net" — the /v1 prefix is appended automatically. */
230
262
  baseUrl: string;
231
263
  /** Injectable for tests / custom runtimes. Defaults to the global fetch. */
232
264
  fetch?: typeof fetch;
@@ -240,7 +272,9 @@ interface CookieMunchOptions {
240
272
  declare class CookieMunchApiError extends Error {
241
273
  readonly status: number;
242
274
  readonly code?: string;
243
- constructor(status: number, message: string, code?: string);
275
+ /** The parsed JSON error body, when there was one (e.g. `issues` on a 422). */
276
+ readonly body?: unknown;
277
+ constructor(status: number, message: string, code?: string, body?: unknown);
244
278
  }
245
279
  /** A cookie discovered on a site, classified into a consent category (wire shape of the
246
280
  * cookie-declaration feed). Matches the server's CategorizedCookie schema. */
@@ -250,6 +284,11 @@ interface CategorizedCookie {
250
284
  domain?: string;
251
285
  provider?: string;
252
286
  purpose?: string;
287
+ /**
288
+ * The purpose by language (lowercase BCP-47 tag). On a declared row, the owner's; on a
289
+ * row the cookie database classified, the database's (empty: none yet).
290
+ */
291
+ purposes?: Record<string, string>;
253
292
  expiry?: string;
254
293
  /** Page URLs (multi-page scan) that set this cookie, earliest first. */
255
294
  foundOnPages?: string[];
@@ -273,8 +312,14 @@ interface CookieDeclaration {
273
312
  interface DeclaredCookieInput {
274
313
  /** A standard category or one of the site's `categories.custom` ids. Not `unclassified`. */
275
314
  category: string;
276
- /** Shown to visitors. */
315
+ /** Shown to visitors, and the fallback for any language `purposes` lacks. */
277
316
  purpose: string;
317
+ /**
318
+ * The purpose in other languages: `{ es: '…', 'pt-BR': '…' }` (BCP-47 language or
319
+ * language-region tags, stored lowercased; ≤50 languages, ≤1000 characters each).
320
+ * The banner, `data-cc="declaration"` and /cookie-declaration.js draw the visitor's.
321
+ */
322
+ purposes?: Record<string, string> | null;
278
323
  provider?: string;
279
324
  expiry?: string;
280
325
  domain?: string;
@@ -286,6 +331,23 @@ interface DeclaredCookie extends DeclaredCookieInput {
286
331
  name: string;
287
332
  updatedAt: number;
288
333
  }
334
+ /** What a declaration write would change (`dryRun`). */
335
+ interface DeclarationDiff {
336
+ added: DeclaredCookie[];
337
+ removed: DeclaredCookie[];
338
+ changed: Array<{
339
+ name: string;
340
+ before: DeclaredCookie;
341
+ after: DeclaredCookie;
342
+ }>;
343
+ }
344
+ /** The answer to a `dryRun` declaration write: nothing was stored. */
345
+ interface DeclarationDryRun {
346
+ dryRun: true;
347
+ /** Every declaration the site would have. */
348
+ declared: DeclaredCookie[];
349
+ diff: DeclarationDiff;
350
+ }
289
351
  /** A warning about a write: e.g. the category is switched off for the site. */
290
352
  interface DeclarationWarning {
291
353
  field: string;
@@ -315,6 +377,27 @@ interface ScanStatus {
315
377
  status: 'idle' | 'scanning';
316
378
  /** Epoch-ms of the last completed scan, or null. */
317
379
  lastScannedAt: number | null;
380
+ /** What the last scan saw of the live banner's Accept all / Reject all. Absent until measured. */
381
+ buttonParity?: ButtonParityScan;
382
+ }
383
+ /** Consent-button parity of the banner a real browser saw on the site (see ScanStatus). */
384
+ interface ButtonParityScan {
385
+ url: string;
386
+ /** False when no visible consent accept control was found in a recognisable banner. */
387
+ bannerFound: boolean;
388
+ /**
389
+ * True when the checks ran: our embed, or a recognised banner with both Accept and Reject.
390
+ * False = not measured — no findings, `score` null. Absent on scans stored before it existed.
391
+ */
392
+ measured?: boolean;
393
+ /** `cookiemunch` = our embed; `other` = found by its button text. */
394
+ cmp: 'cookiemunch' | 'other' | null;
395
+ acceptFound: boolean;
396
+ rejectFound: boolean;
397
+ designWarnings: ButtonParityFinding[];
398
+ /** 0–100; null when no banner was found. */
399
+ score: number | null;
400
+ checkedAt?: number;
318
401
  }
319
402
  /** @deprecated The server returns {@link ScanStatus}; kept only for back-compat. */
320
403
  interface ScanResult {
@@ -388,6 +471,182 @@ interface ConfigDryRun {
388
471
  /** Every leaf that would change. */
389
472
  diff: ConfigChange[];
390
473
  warnings?: ConfigWarning[];
474
+ /** Consent-button parity of the would-be config (see {@link ButtonParityFinding}). */
475
+ designWarnings: ButtonParityFinding[];
476
+ }
477
+ /** The effective style of an Accept all / Reject all control. */
478
+ interface ParityControlSummary {
479
+ id?: string;
480
+ label: string;
481
+ element: 'button' | 'link';
482
+ background?: string;
483
+ color?: string;
484
+ borderColor?: string;
485
+ borderWidth?: number;
486
+ fontSize?: number;
487
+ fontWeight?: number;
488
+ width?: number;
489
+ height?: number;
490
+ }
491
+ /**
492
+ * One way Accept all is pushed harder than Reject all (colour, size, placement, copy, custom
493
+ * CSS). Returned as `designWarnings` on every config read and write, and by `lintConfig`.
494
+ * A warning, never an error — the config is saved regardless. See /docs/fair-consent-buttons.
495
+ */
496
+ interface ButtonParityFinding {
497
+ 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';
498
+ severity: 'warning' | 'notice';
499
+ layer: 'banner' | 'preferences' | 'modal' | 'popup' | 'bar' | 'inline' | 'custom';
500
+ accept: ParityControlSummary | null;
501
+ reject: ParityControlSummary | null;
502
+ metric: {
503
+ name: string;
504
+ accept?: number;
505
+ reject?: number;
506
+ value: number;
507
+ threshold: number;
508
+ };
509
+ detail: string;
510
+ fix: string;
511
+ where: {
512
+ view?: string;
513
+ variant?: string;
514
+ theme?: 'light' | 'dark';
515
+ breakpoint?: 'desktop' | 'mobile';
516
+ language?: string;
517
+ url?: string;
518
+ };
519
+ }
520
+ /** Reject all style values that would match the Accept all on the same layer. */
521
+ interface SuggestedRejectStyle {
522
+ layer: string;
523
+ view?: string;
524
+ background?: string;
525
+ color?: string;
526
+ borderColor?: string;
527
+ borderWidth?: number;
528
+ fontSize?: number;
529
+ fontWeight?: number;
530
+ width?: number;
531
+ height?: number;
532
+ }
533
+ /** `POST /v1/sites/:cbid/config/lint` — nothing is saved. */
534
+ interface ButtonParityLint {
535
+ /** `merged` = what PATCH would store (merged over the stored config); `replaced` = what PUT would store (`replace: true`). */
536
+ mode: 'merged' | 'replaced';
537
+ designWarnings: ButtonParityFinding[];
538
+ /** 100 minus 20 per warning and 5 per notice, floored at 0. */
539
+ score: number;
540
+ suggestedReject: SuggestedRejectStyle[];
541
+ }
542
+ /** The hosted rights page document. See docs/rights-page for each section type's props. */
543
+ interface RightsPageDocument {
544
+ v: 1;
545
+ theme: {
546
+ preset: 'brand' | 'light' | 'dark' | 'custom';
547
+ width: 'narrow' | 'normal' | 'wide' | 'full';
548
+ density: 'compact' | 'comfortable' | 'spacious';
549
+ colorScheme: 'light' | 'dark' | 'auto';
550
+ [k: string]: unknown;
551
+ };
552
+ sections: Array<{
553
+ id: string;
554
+ type: string;
555
+ props: Record<string, unknown>;
556
+ hidden?: {
557
+ phone?: boolean;
558
+ desktop?: boolean;
559
+ };
560
+ style?: Record<string, unknown>;
561
+ }>;
562
+ form: {
563
+ requestTypes: Array<Record<string, unknown>>;
564
+ fields: Array<Record<string, unknown>>;
565
+ jurisdiction: 'auto' | 'ask' | 'hidden';
566
+ consentIdField: 'hidden' | 'optional' | 'required';
567
+ success: {
568
+ title?: string;
569
+ body?: string;
570
+ };
571
+ submitLabel?: string;
572
+ };
573
+ i18n: {
574
+ defaultLocale: string;
575
+ autoDetect: boolean;
576
+ overrides: Record<string, unknown>;
577
+ };
578
+ seo: {
579
+ title?: string;
580
+ description?: string;
581
+ favicon?: string;
582
+ image?: string;
583
+ index: boolean;
584
+ };
585
+ customCss?: string;
586
+ }
587
+ /** `message` is English; `code` (+ `params`) is stable, for your own wording or language. */
588
+ interface RightsPageIssue {
589
+ path: string;
590
+ message: string;
591
+ code?: string;
592
+ params?: Record<string, string | number>;
593
+ }
594
+ interface RightsPageDraft {
595
+ cbid: string;
596
+ draft: RightsPageDocument;
597
+ version: number;
598
+ publishedAt: number | null;
599
+ updatedAt: number | null;
600
+ warnings: RightsPageIssue[];
601
+ }
602
+ interface RightsPageDryRun {
603
+ dryRun: true;
604
+ cbid: string;
605
+ draft: RightsPageDocument;
606
+ warnings: RightsPageIssue[];
607
+ }
608
+ /** Who published a version: `publishedBy` is an actor id; `publishedByEmail` names a dashboard user (null for an API key). */
609
+ interface RightsPagePublisher {
610
+ publishedBy: string;
611
+ publishedByEmail: string | null;
612
+ publishedVia: 'dashboard' | 'api_key';
613
+ }
614
+ interface RightsPagePublished {
615
+ cbid: string;
616
+ page: RightsPageDocument;
617
+ version: number;
618
+ publishedAt: number;
619
+ publishedBy?: string | null;
620
+ publishedByEmail?: string | null;
621
+ publishedVia?: 'dashboard' | 'api_key' | null;
622
+ }
623
+ /**
624
+ * Optimistic concurrency for a draft write: the draft's `updatedAt` as you last read it (epoch ms or
625
+ * an ISO date; null = you saw no saved draft). A mismatch rejects with a 409 CookieMunchApiError whose
626
+ * body is RightsPageDraftConflict. Omitted: a full write (put) is last-write-wins; a patch merges onto the draft
627
+ * as it is when written, so a concurrent edit is not lost.
628
+ */
629
+ interface RightsPageWriteOptions {
630
+ baseUpdatedAt?: number | string | null;
631
+ }
632
+ interface RightsPageDraftConflict {
633
+ error: 'draft_conflict';
634
+ draft: RightsPageDraft;
635
+ }
636
+ /** `draftUpdatedAt`: the draft's updatedAt after the call — pass it as the next `baseUpdatedAt`. */
637
+ interface RightsPagePublishResult {
638
+ cbid: string;
639
+ version: number;
640
+ publishedAt: number;
641
+ draftUpdatedAt: number;
642
+ rolledBackTo?: number;
643
+ }
644
+ interface RightsPageVersions {
645
+ cbid: string;
646
+ versions: Array<{
647
+ version: number;
648
+ publishedAt: number;
649
+ } & RightsPagePublisher>;
391
650
  }
392
651
  /** Options for POST /v1/sites/:cbid/preview-token. All optional. */
393
652
  interface PreviewTokenOptions {
@@ -411,6 +670,70 @@ interface PreviewToken {
411
670
  /** The page with `cm_preview` / `cm_region` / `cm_lang` added. */
412
671
  previewUrl?: string;
413
672
  }
673
+ /** A right a rights link may file (the hosted rights page's request-type kinds). */
674
+ type RightKind = 'access' | 'erasure' | 'rectification' | 'portability' | 'restriction' | 'objection' | 'opt_out_sale' | 'opt_out_targeted' | 'limit_sensitive';
675
+ /** Input for POST /v1/sites/:cbid/rights-links. */
676
+ interface RightsLinkInput {
677
+ /** The signed-in person. `email` must be an address you have verified. */
678
+ subject: {
679
+ email: string;
680
+ userId?: string;
681
+ };
682
+ /** Limit the link to these rights. Default: every right the page offers. */
683
+ rights?: RightKind[];
684
+ /** Lifetime in seconds, 60..3600. Default 900. */
685
+ ttlSeconds?: number;
686
+ }
687
+ /** A signed, single-use link to the hosted rights page for one signed-in person. */
688
+ interface RightsLink {
689
+ url: string;
690
+ /** Epoch milliseconds. */
691
+ expiresAt: number;
692
+ }
693
+ /** One DNS record to create, exactly as written. */
694
+ interface DnsRecordInstruction {
695
+ type: 'CNAME' | 'TXT';
696
+ name: string;
697
+ value: string;
698
+ }
699
+ /** A custom hostname serving a site's rights page. */
700
+ interface RightsPageDomain {
701
+ /** Lowercase ASCII form (punycode for an internationalised name). */
702
+ hostname: string;
703
+ /** As a person reads it. */
704
+ unicodeHostname: string;
705
+ cbid: string;
706
+ /** pending_dns → verifying → issuing → active, or error (see lastError). */
707
+ status: 'pending_dns' | 'verifying' | 'issuing' | 'active' | 'error';
708
+ certStatus: 'none' | 'pending' | 'issued' | 'failed';
709
+ createdAt: number;
710
+ verifiedAt?: number;
711
+ activatedAt?: number;
712
+ lastCheckedAt?: number;
713
+ /** dns_not_found | wrong_target | hostname_in_use | router_write_failed | certificate_not_issued | dns_changed | probe_failed */
714
+ lastError?: string;
715
+ url: string;
716
+ /** The records to create: the CNAME, or (apex / flattened / proxied) the TXT plus an ALIAS to the same target. */
717
+ /** `cname.value` is this domain's own `<token>.cname.cookiemunch.net` — unique to the claim; a CNAME to anything else does not verify it. */
718
+ dns: {
719
+ recommended: 'cname' | 'flattened';
720
+ cname: DnsRecordInstruction;
721
+ txt: DnsRecordInstruction;
722
+ };
723
+ /** Only on a verify that found no proof: what DNS answered. */
724
+ dnsSeen?: {
725
+ cnames: string[];
726
+ addresses: string[];
727
+ txt: string[];
728
+ };
729
+ }
730
+ /** The site's custom hostnames, the plan allowance (null = unlimited) and the org's usage. */
731
+ interface RightsPageDomainList {
732
+ domains: RightsPageDomain[];
733
+ limit: number | null;
734
+ used: number;
735
+ target: string;
736
+ }
414
737
  /** Options for the snippet endpoint. */
415
738
  interface SnippetOptions {
416
739
  /** Override the site's configured `blocking.mode`. Default: the config's. */
@@ -469,7 +792,8 @@ type FlowOp = {
469
792
  */
470
793
  type FlowOpResponse = {
471
794
  ok: true;
472
- flow: Record<string, unknown>;
795
+ flow: Record<string, unknown>; /** Consent-button parity of the saved design. */
796
+ designWarnings?: ButtonParityFinding[];
473
797
  } | {
474
798
  ok: false;
475
799
  failedAt?: number;
@@ -625,6 +949,150 @@ interface Org {
625
949
  plan: string;
626
950
  logoUrl: string | null;
627
951
  }
952
+ type MailProviderKind = 'brevo' | 'sendgrid' | 'postmark' | 'resend' | 'ses' | 'smtp';
953
+ /**
954
+ * The org's own mail provider for rights-request mail. The credential is never returned —
955
+ * `secretLast4` only. `sender` says whether verification codes go through it right now
956
+ * (`own`) or are not mailed at all (`none`): there is no shared sender for rights mail.
957
+ */
958
+ interface MailProvider {
959
+ configured: boolean;
960
+ sender: 'own' | 'none';
961
+ provider?: MailProviderKind;
962
+ fromEmail?: string;
963
+ fromName?: string;
964
+ replyTo?: string;
965
+ ses?: {
966
+ region: string;
967
+ accessKeyId: string;
968
+ };
969
+ smtp?: {
970
+ host: string;
971
+ port: number;
972
+ security: 'tls' | 'starttls';
973
+ username: string;
974
+ };
975
+ secretLast4?: string;
976
+ status?: 'untested' | 'verified' | 'failing';
977
+ verifiedAt?: number | null;
978
+ lastTest?: {
979
+ ok: boolean;
980
+ at: number;
981
+ error?: string;
982
+ } | null;
983
+ updatedAt?: number;
984
+ /** Only on `set`: no verification codes are mailed until a test succeeds. */
985
+ note?: string;
986
+ }
987
+ /** Save a provider. `secret` is write-only; omit it to keep the stored one (same provider only). */
988
+ interface MailProviderInput {
989
+ provider: MailProviderKind;
990
+ fromEmail: string;
991
+ fromName?: string | null;
992
+ replyTo?: string | null;
993
+ secret?: string;
994
+ ses?: {
995
+ region: string;
996
+ accessKeyId: string;
997
+ };
998
+ smtp?: {
999
+ host: string;
1000
+ port: 25 | 465 | 587 | 2525;
1001
+ security: 'tls' | 'starttls';
1002
+ username: string;
1003
+ };
1004
+ }
1005
+ type RightsCaptchaProvider = 'turnstile' | 'hcaptcha' | 'recaptcha_v2' | 'recaptcha_v3';
1006
+ /**
1007
+ * The rights page's captcha in force: your own keys (`own`, recommended) or none (`off`, the default).
1008
+ * Cookie Munch's own captcha is never used on rights pages. The secret is never returned.
1009
+ */
1010
+ interface RightsCaptcha {
1011
+ /** `site`: the site's own setting; `org`: the organisation default; `default`: neither (off). */
1012
+ source: 'site' | 'org' | 'default';
1013
+ mode: 'own' | 'off';
1014
+ provider?: RightsCaptchaProvider;
1015
+ siteKey?: string;
1016
+ /** reCAPTCHA v3 only. */
1017
+ minScore?: number;
1018
+ secretSet: boolean;
1019
+ secretLast4?: string;
1020
+ status: 'verified' | 'disabled';
1021
+ verifiedAt: number | null;
1022
+ updatedAt: number | null;
1023
+ /** Only when a `set` turned the captcha off: what that costs. */
1024
+ warning?: string;
1025
+ }
1026
+ /**
1027
+ * `own` needs provider, siteKey and (the first time) secret; the provider is asked to accept the secret before
1028
+ * anything is saved (422 captcha_secret_invalid / 502 captcha_unreachable). `off` removes spam protection beyond
1029
+ * the hidden spam-trap field, the rate limits and the email code.
1030
+ */
1031
+ interface RightsCaptchaInput {
1032
+ mode: 'own' | 'off';
1033
+ provider?: RightsCaptchaProvider;
1034
+ siteKey?: string;
1035
+ /** Write-only. Omit to keep the stored one (same provider, same place). */
1036
+ secret?: string;
1037
+ /** reCAPTCHA v3 only: 0.1–0.9, default 0.5. */
1038
+ minScore?: number;
1039
+ }
1040
+ type RightsIdentityType = 'clerk' | 'atlas' | 'oidc_jwt';
1041
+ /**
1042
+ * The sign-in provider rights requests are verified with: a visitor signed in to your site is
1043
+ * verified by their session, with no code mail. Nothing here is secret.
1044
+ */
1045
+ interface RightsIdentity {
1046
+ /** `site`: the site's own setting; `org`: the organisation default; `default`: neither (none). */
1047
+ source: 'site' | 'org' | 'default';
1048
+ configured: boolean;
1049
+ type?: RightsIdentityType;
1050
+ issuer?: string;
1051
+ jwksUrl?: string;
1052
+ audience?: string;
1053
+ authorizedParties?: string[];
1054
+ emailClaim?: string;
1055
+ emailVerifiedClaim?: string;
1056
+ sessionCookieName?: string;
1057
+ /** Present (true) only when set: clerk/atlas tokens without the verified claim are accepted. */
1058
+ trustEmailClaim?: true;
1059
+ status: 'verified' | 'not_configured';
1060
+ verifiedAt: number | null;
1061
+ updatedAt: number | null;
1062
+ }
1063
+ /**
1064
+ * The JWKS is fetched and checked before anything is saved (502 identity_jwks_unreachable /
1065
+ * 422 identity_jwks_invalid). `authorizedParties` (your own origins) is required for clerk and atlas;
1066
+ * oidc_jwt needs an `audience` or `authorizedParties`. Issuer and JWKS URL are https on a host name,
1067
+ * never an IP address. The token must carry the email and a verified-email claim set to `true`
1068
+ * (clerk/atlas with `trustEmailClaim`: the verified claim may be absent).
1069
+ */
1070
+ interface RightsIdentityInput {
1071
+ type: RightsIdentityType;
1072
+ /** Exactly the token's `iss` (Clerk: your Frontend API URL). */
1073
+ issuer: string;
1074
+ /** Required for oidc_jwt; clerk/atlas default to `<issuer>/.well-known/jwks.json`. */
1075
+ jwksUrl?: string;
1076
+ audience?: string;
1077
+ authorizedParties?: string[];
1078
+ /** Default `email`. */
1079
+ emailClaim?: string;
1080
+ /** Default `email_verified`. */
1081
+ emailVerifiedClaim?: string;
1082
+ /** Default `__session`: the cookie the hosted page on your custom domain reads. */
1083
+ sessionCookieName?: string;
1084
+ /**
1085
+ * clerk/atlas only, default false. True when your provider has no verified-email claim and every
1086
+ * address it puts in the email claim is verified: a token without the verified claim is accepted.
1087
+ */
1088
+ trustEmailClaim?: boolean;
1089
+ }
1090
+ interface MailProviderTestResult {
1091
+ ok: boolean;
1092
+ sentTo: string;
1093
+ error?: string;
1094
+ mailProvider: MailProvider;
1095
+ }
628
1096
  /** Change an org's name or logo. `logoUrl: null` removes the logo. */
629
1097
  interface OrgUpdate {
630
1098
  name?: string;
@@ -708,6 +1176,8 @@ interface BannerSummary {
708
1176
  name: string;
709
1177
  updatedAt: number;
710
1178
  assignedCbids: string[];
1179
+ /** How many warning-severity consent-button parity findings the design has (0 = fair). */
1180
+ designWarningCount: number;
711
1181
  }
712
1182
  /** A full account-level banner record, including its config JSON. */
713
1183
  interface BannerRecord {
@@ -717,6 +1187,8 @@ interface BannerRecord {
717
1187
  json: SiteConfig;
718
1188
  createdAt: number;
719
1189
  updatedAt: number;
1190
+ /** Consent-button parity findings in the design. Never blocks a save. */
1191
+ designWarnings?: ButtonParityFinding[];
720
1192
  }
721
1193
  /**
722
1194
  * Input for the public consent-log ingest endpoint (POST /api/v1/consent) — the
@@ -1002,6 +1474,48 @@ interface DsarExecutor {
1002
1474
  /** Open a sub-task automatically when a request reaches fulfilment. */
1003
1475
  auto: boolean;
1004
1476
  createdAt: number;
1477
+ /** Where that system should send its completion webhooks. On every connection, secret or not. */
1478
+ webhookUrl: string;
1479
+ }
1480
+ /** What a connection write would do (`?dryRun=1`). Nothing was stored. */
1481
+ interface DsarExecutorDryRun {
1482
+ dryRun: true;
1483
+ /** The connection as it would be, credentials excluded. A create has no `id` or `webhookUrl` yet. */
1484
+ executor: Partial<DsarExecutor> & Record<string, unknown>;
1485
+ /** Each field that would change. */
1486
+ diff: ConfigChange[];
1487
+ warnings?: Array<{
1488
+ field: string;
1489
+ reason: string;
1490
+ }>;
1491
+ }
1492
+ /** Where a webhook check stopped. */
1493
+ type WebhookStage = 'configuration' | 'headers' | 'timestamp' | 'prefix' | 'signature';
1494
+ /** Which key a verified delivery matched: a `whsec_` secret's base64-decoded remainder, or the secret as typed. */
1495
+ type WebhookKeyForm = 'decoded' | 'raw';
1496
+ /** Whether a supplied delivery verified (`stage` and `reason` are null when it did). */
1497
+ interface ExecutorWebhookTestResult {
1498
+ verified: boolean;
1499
+ stage: WebhookStage | null;
1500
+ reason: string | null;
1501
+ /** Which key form matched; null when refused. */
1502
+ keyForm: WebhookKeyForm | null;
1503
+ }
1504
+ /** One delivery to a connection's webhook. Never the secret, the signature or the body. */
1505
+ interface ExecutorWebhookDelivery {
1506
+ id: string;
1507
+ executorId: string;
1508
+ at: number;
1509
+ verified: boolean;
1510
+ stage: WebhookStage | null;
1511
+ reason: string | null;
1512
+ /** The HTTP status we answered with. */
1513
+ status: number;
1514
+ /** The first 16 hex characters of SHA-256 over the raw body. */
1515
+ bodySha256: string;
1516
+ bodyBytes: number;
1517
+ /** Which key form matched; null when refused (or logged before this was kept). Never the key. */
1518
+ keyForm: WebhookKeyForm | null;
1005
1519
  }
1006
1520
  interface DsarExecutorInput {
1007
1521
  /** The name this connection answers to in a plan, e.g. `identity` or `crm`. */
@@ -1010,15 +1524,24 @@ interface DsarExecutorInput {
1010
1524
  baseUrl: string;
1011
1525
  /** Its API key. Stored encrypted; never returned. */
1012
1526
  secretKey: string;
1013
- /** The signing secret of its webhook endpoint. Optional — polling closes tasks without it. */
1527
+ /**
1528
+ * The signing secret of its webhook endpoint. Optional — polling closes tasks without it.
1529
+ * A `whsec_<base64>` secret verifies a delivery signed with either the base64-decoded bytes
1530
+ * or the literal string; anything else only with its UTF-8 bytes.
1531
+ */
1014
1532
  webhookSecret?: string;
1015
1533
  auto?: boolean;
1016
1534
  /** How to drive it. */
1017
1535
  profile: ExecutorProfile;
1018
1536
  }
1019
- interface DsarExecutorCreated extends DsarExecutor {
1020
- /** Point the connected system's webhook endpoint here. */
1021
- webhookUrl: string;
1537
+ type DsarExecutorCreated = DsarExecutor;
1538
+ /** The fields `updateExecutor` may change. */
1539
+ interface DsarExecutorPatch {
1540
+ profile?: unknown;
1541
+ baseUrl?: string;
1542
+ secretKey?: string;
1543
+ webhookSecret?: string | null;
1544
+ auto?: boolean;
1022
1545
  }
1023
1546
  /** One entry in a fulfilment task's status history. */
1024
1547
  interface DsarTaskEvent {
@@ -1182,6 +1705,14 @@ interface CookieMunchClient {
1182
1705
  dryRunConfig(cbid: string, config: Partial<SiteConfig>, opts?: {
1183
1706
  mode?: 'patch' | 'put';
1184
1707
  } & PutConfigOptions): Promise<ConfigDryRun>;
1708
+ /**
1709
+ * Check a proposed config for consent-button parity — an Accept all pushed harder than
1710
+ * Reject all — without saving it. A partial v1 config is merged over the stored one (like
1711
+ * PATCH); a v2 design, or `replace: true`, is linted as sent. Needs only `sites:read`.
1712
+ */
1713
+ lintConfig(cbid: string, config: Partial<SiteConfig>, opts?: {
1714
+ replace?: boolean;
1715
+ }): Promise<ButtonParityLint>;
1185
1716
  cookies(cbid: string): Promise<CookieDeclaration>;
1186
1717
  scan(cbid: string): Promise<ScanStatus>;
1187
1718
  scanStatus(cbid: string): Promise<ScanStatus>;
@@ -1221,24 +1752,37 @@ interface CookieMunchClient {
1221
1752
  /**
1222
1753
  * Declare what one cookie is. Overrides scanned, observed and database classification
1223
1754
  * in the API, the preference modal and `data-cc="declaration"`. A name ending in `*`
1224
- * declares a prefix wildcard.
1755
+ * declares a prefix wildcard. `dryRun` validates and returns the would-be list and a
1756
+ * diff without storing anything.
1225
1757
  */
1226
- declareCookie(cbid: string, name: string, input: DeclaredCookieInput): Promise<{
1758
+ declareCookie(cbid: string, name: string, input: DeclaredCookieInput, opts?: {
1759
+ dryRun?: boolean;
1760
+ }): Promise<{
1227
1761
  cookie: DeclaredCookie;
1228
1762
  warnings?: DeclarationWarning[];
1229
- }>;
1763
+ } & Partial<DeclarationDryRun>>;
1230
1764
  /** Remove a declaration; the scanned classification applies again. */
1231
1765
  undeclareCookie(cbid: string, name: string): Promise<void>;
1232
- /** Declare many at once (all-or-nothing). `replace` also removes declarations not listed. */
1766
+ /** What removing a declaration would leave; nothing is removed. */
1767
+ undeclareCookie(cbid: string, name: string, opts: {
1768
+ dryRun: true;
1769
+ }): Promise<DeclarationDryRun>;
1770
+ /**
1771
+ * Declare many at once (all-or-nothing). `replace` also removes declarations not listed;
1772
+ * `dryRun` answers with what would be stored and a diff, storing nothing.
1773
+ */
1233
1774
  declareCookies(cbid: string, cookies: Array<DeclaredCookieInput & {
1234
1775
  name: string;
1235
1776
  }>, opts?: {
1236
1777
  replace?: boolean;
1778
+ dryRun?: boolean;
1237
1779
  }): Promise<{
1238
1780
  declared: DeclaredCookie[];
1239
1781
  saved: number;
1240
1782
  removed: number;
1241
1783
  warnings?: DeclarationWarning[];
1784
+ dryRun?: true;
1785
+ diff?: DeclarationDiff;
1242
1786
  }>;
1243
1787
  snippet(cbid: string, opts?: SnippetOptions): Promise<InstallSnippet>;
1244
1788
  /**
@@ -1352,6 +1896,38 @@ interface CookieMunchClient {
1352
1896
  }>;
1353
1897
  delete(id: string): Promise<void>;
1354
1898
  };
1899
+ /** The hosted rights page (cookiemunch.net/r/<cbid> or the site's own domain). */
1900
+ rightsPage: {
1901
+ get(cbid: string): Promise<RightsPageDraft>;
1902
+ /** Replace the draft. Nothing is live until publish(). `opts.baseUpdatedAt` refuses to overwrite a newer save (409 draft_conflict). */
1903
+ put(cbid: string, page: RightsPageDocument, opts?: RightsPageWriteOptions): Promise<RightsPageDraft>;
1904
+ /** Merge into the draft: objects merge, arrays replace, null removes. `opts.baseUpdatedAt` as on put(). */
1905
+ patch(cbid: string, patch: Record<string, unknown>, opts?: RightsPageWriteOptions): Promise<RightsPageDraft>;
1906
+ /** Validate a write without saving it. */
1907
+ dryRun(cbid: string, page: Record<string, unknown>, opts?: {
1908
+ mode?: 'patch' | 'put';
1909
+ }): Promise<RightsPageDryRun>;
1910
+ getPublished(cbid: string): Promise<RightsPagePublished>;
1911
+ /**
1912
+ * Publish the draft; it goes live at once. Pass `opts.baseUpdatedAt` (the draft's updatedAt
1913
+ * as you read it) so only the draft you saw goes live: 409 draft_conflict otherwise.
1914
+ */
1915
+ publish(cbid: string, opts?: RightsPageWriteOptions): Promise<RightsPagePublishResult>;
1916
+ versions(cbid: string): Promise<RightsPageVersions>;
1917
+ /**
1918
+ * Publish an earlier version again; it goes live at once and REPLACES the current draft
1919
+ * (unpublished edits are lost). `opts.baseUpdatedAt` refuses with 409 if the draft moved.
1920
+ */
1921
+ rollback(cbid: string, version: number, opts?: RightsPageWriteOptions): Promise<RightsPagePublishResult>;
1922
+ /** Custom hostnames serving the rights page, with the plan allowance. */
1923
+ listDomains(cbid: string): Promise<RightsPageDomainList>;
1924
+ /** Add a custom hostname (e.g. privacy.example.com); the answer carries the DNS records to create. */
1925
+ addDomain(cbid: string, hostname: string): Promise<RightsPageDomain>;
1926
+ /** Check it now: DNS while pending, the HTTPS answer once routed. Always the domain as it stands. */
1927
+ verifyDomain(cbid: string, hostname: string): Promise<RightsPageDomain>;
1928
+ /** Remove it: it stops being served and its certificate is not renewed. */
1929
+ removeDomain(cbid: string, hostname: string): Promise<void>;
1930
+ };
1355
1931
  /**
1356
1932
  * Identity resolution. Reads are POSTs on purpose: a person's identifiers travel in the
1357
1933
  * body, never a URL where they would land in access logs.
@@ -1546,13 +2122,21 @@ interface CookieMunchClient {
1546
2122
  * is kept unless you pass a new `secretKey` — so adding a field to a profile does not
1547
2123
  * cost you the connection or its id.
1548
2124
  */
1549
- updateExecutor(id: string, patch: {
1550
- profile?: unknown;
1551
- baseUrl?: string;
1552
- secretKey?: string;
1553
- webhookSecret?: string | null;
1554
- auto?: boolean;
1555
- }): Promise<DsarExecutor>;
2125
+ updateExecutor(id: string, patch: DsarExecutorPatch): Promise<DsarExecutor>;
2126
+ /** What `connectExecutor` would create, validated in full; nothing is stored (`?dryRun=1`). */
2127
+ dryRunConnectExecutor(input: DsarExecutorInput): Promise<DsarExecutorDryRun>;
2128
+ /** What `updateExecutor` would change, with a diff; the stored connection is untouched (`?dryRun=1`). */
2129
+ dryRunUpdateExecutor(id: string, patch: DsarExecutorPatch): Promise<DsarExecutorDryRun>;
2130
+ /**
2131
+ * Would this webhook delivery verify? Runs the receiver's exact check on headers and a raw
2132
+ * body you supply, acts on nothing, and names the stage that failed.
2133
+ */
2134
+ testExecutorWebhook(id: string, delivery: {
2135
+ headers: Record<string, string>;
2136
+ body: string;
2137
+ }): Promise<ExecutorWebhookTestResult>;
2138
+ /** The last 50 deliveries to a connection's webhook, newest first, each with its reason. */
2139
+ executorWebhookDeliveries(id: string): Promise<ExecutorWebhookDelivery[]>;
1556
2140
  /** Disconnect a system; its open sub-tasks stop being driven. */
1557
2141
  disconnectExecutor(id: string): Promise<void>;
1558
2142
  /** The export bundle a connected system produced, fetched from it on demand. */
@@ -1619,6 +2203,35 @@ interface CookieMunchClient {
1619
2203
  get(): Promise<Org>;
1620
2204
  /** Rename the org or set its logo. Deleting the org is not available through the API. */
1621
2205
  update(patch: OrgUpdate): Promise<Org>;
2206
+ /**
2207
+ * Your own mail provider for rights-request mail. It carries verification codes once
2208
+ * `test` succeeds; every `set` clears that. There is no shared sender: without one, requests
2209
+ * are verified by your sign-in provider (`rightsIdentity`) or filed unverified for you to confirm.
2210
+ */
2211
+ mailProvider: {
2212
+ get(): Promise<MailProvider>;
2213
+ set(input: MailProviderInput): Promise<MailProvider>;
2214
+ remove(): Promise<void>;
2215
+ /** Send a test through your provider. `to` defaults to the reply-to, else the from address. */
2216
+ test(to?: string): Promise<MailProviderTestResult>;
2217
+ };
2218
+ /**
2219
+ * The default captcha for your rights pages, for every site without its own (`rightsCaptcha`): your own
2220
+ * keys (recommended) or off. Without one, rights pages have no captcha.
2221
+ */
2222
+ rightsCaptcha: {
2223
+ get(): Promise<RightsCaptcha>;
2224
+ set(input: RightsCaptchaInput): Promise<RightsCaptcha>;
2225
+ /** Remove the default; answers the setting now in force (off). */
2226
+ remove(): Promise<RightsCaptcha>;
2227
+ };
2228
+ /** The default sign-in provider rights requests are verified with, for every site without its own. */
2229
+ rightsIdentity: {
2230
+ get(): Promise<RightsIdentity>;
2231
+ set(input: RightsIdentityInput): Promise<RightsIdentity>;
2232
+ /** Remove the default; answers the setting now in force. */
2233
+ remove(): Promise<RightsIdentity>;
2234
+ };
1622
2235
  };
1623
2236
  /** The org's audit log, newest first. API actions appear as `apikey:<prefix>`. */
1624
2237
  audit(limit?: number): Promise<{
@@ -1676,6 +2289,34 @@ interface CookieMunchClient {
1676
2289
  /** Deliver a dead letter again, to the subscription as it is now. */
1677
2290
  replayDeadLetter(id: string): Promise<unknown>;
1678
2291
  };
2292
+ /**
2293
+ * Account-linked rights requests: a single-use link to the hosted rights page for a person your
2294
+ * backend knows is signed in. The page locks their email and skips the code step. Requires dsar:write.
2295
+ */
2296
+ rightsLinks: {
2297
+ create(cbid: string, input: RightsLinkInput): Promise<RightsLink>;
2298
+ };
2299
+ /**
2300
+ * A site's rights-page captcha: your own Turnstile, hCaptcha or reCAPTCHA keys (recommended), or off. A site
2301
+ * without its own setting uses the organisation default (`org.rightsCaptcha`), else off. Requires sites:read / sites:write.
2302
+ */
2303
+ rightsCaptcha: {
2304
+ get(cbid: string): Promise<RightsCaptcha>;
2305
+ set(cbid: string, input: RightsCaptchaInput): Promise<RightsCaptcha>;
2306
+ /** Remove the site's own setting: it inherits the organisation default again. Answers the setting now in force. */
2307
+ remove(cbid: string): Promise<RightsCaptcha>;
2308
+ };
2309
+ /**
2310
+ * A site's sign-in provider (Clerk, Atlas or any JWKS issuer): a visitor signed in to your site
2311
+ * is verified by their session, with no code mail. A site without its own setting uses the
2312
+ * organisation default (`org.rightsIdentity`). Requires sites:read / sites:write.
2313
+ */
2314
+ rightsIdentity: {
2315
+ get(cbid: string): Promise<RightsIdentity>;
2316
+ set(cbid: string, input: RightsIdentityInput): Promise<RightsIdentity>;
2317
+ /** Remove the site's own setting: it inherits the organisation default again. */
2318
+ remove(cbid: string): Promise<RightsIdentity>;
2319
+ };
1679
2320
  /** One person's consent across every site in the org, by the subjectId your apps attach. */
1680
2321
  subjects: {
1681
2322
  /** Requires consent:read; not available to property-locked keys. */
@@ -1711,4 +2352,4 @@ interface CookieMunchClient {
1711
2352
  }
1712
2353
  declare function createCookieMunch(opts: CookieMunchOptions): CookieMunchClient;
1713
2354
 
1714
- export { type AbResult, type AccountOrg, type AccountOrgs, type AdPersonalizationInput, type AiInspectInput, type AiInspectResult, type ApiKey, type ApiKeyIssueInput, type ApiKeyIssued, type ApiKeyPrefix, type ApiKeyUpdate, type AppliedImport, type AssetUpload, type AuditEntry, type BannerRecord, type BannerSummary, type BlockedReport, type BrandExtractionResult, type BrandKit, type BrandKitCreate, type BrandSuggestion, type BulkSiteInput, type BulkSiteResult, type CategorizedCookie, type ChildKeyInput, type ConfigChange, type ConfigDryRun, type ConfigWarning, type ConsentDay, type ConsentDecisionInput, type ConsentIngestInput, type ConsentLogRow, type CookieDeclaration, CookieMunchApiError, type CookieMunchClient, type CookieMunchOptions, type CspSources, type DeclarationWarning, type DeclaredCookie, type DeclaredCookieInput, type DsarCreate, type DsarEraseResult, type DsarExecutor, type DsarExecutorCreated, type DsarExecutorInput, type DsarExportResult, type DsarRequest, type DsarStatus, type DsarTask, type DsarTaskEvent, type DsarTaskExport, type DsarTaskLogEntry, type DsarTaskOutcome, type DsarType, type EnforcementRuleInput, type ExecutorProfile, type ExecutorTestInput, type ExecutorTestResult, type FlowIssue, type FlowOp, type FlowOpResponse, type FulfillmentOp, type Identifier, type Identity, type ImportedCookie, type ImportedDeclaration, type InstallSnippet, type LegalBasis, type LogQuery, type Member, type OptInMethod, type Org, type OrgUpdate, type PlanSource, type PolicyOptions, type PreferenceItem, type PreferenceRecord, type PreviewToken, type PreviewTokenOptions, type ProfileAttributeInput, type PutConfigOptions, type RangeQuery, type Regulation, type RegulationSummary, type RegulatoryFeedResult, type ResellerChild, type ResellerChildCreate, type ResellerChildList, type ResellerChildPatch, type RiskScore, type RopaEntry, type RopaInput, type ScanResult, type ScanStatus, type ScoredVendor, type SessionAnalysisInput, type SignedReceipt, type Site, type SiteConfig, type SiteCookie, type SiteCreate, type SiteFlow, type SnippetOptions, type SubscriptionTopicInput, type SupportedLanguage, type Usage, type VendorInput, type VendorRecord, type VerifyResult, type VerifyWebhookInput, type WebhookCreate, type WebhookDeadLetter, type WebhookSubscription, type WebhookTestResult, type WebhookUpdate, createCookieMunch, verifyWebhookSignature };
2355
+ export { type AbResult, type AccountOrg, type AccountOrgs, type AdPersonalizationInput, type AiInspectInput, type AiInspectResult, type ApiKey, type ApiKeyIssueInput, type ApiKeyIssued, type ApiKeyPrefix, type ApiKeyUpdate, type AppliedImport, type AssetUpload, type AuditEntry, type BannerRecord, type BannerSummary, type BlockedReport, type BrandExtractionResult, type BrandKit, type BrandKitCreate, type BrandSuggestion, type BulkSiteInput, type BulkSiteResult, type ButtonParityFinding, type ButtonParityLint, type ButtonParityScan, type CategorizedCookie, type ChildKeyInput, type ConfigChange, type ConfigDryRun, type ConfigWarning, type ConsentDay, type ConsentDecisionInput, type ConsentIngestInput, type ConsentLogRow, type CookieDeclaration, CookieMunchApiError, type CookieMunchClient, type CookieMunchOptions, type CspSources, type DeclarationDiff, type DeclarationDryRun, type DeclarationWarning, type DeclaredCookie, type DeclaredCookieInput, type DnsRecordInstruction, type DsarCreate, type DsarEraseResult, type DsarExecutor, type DsarExecutorCreated, type DsarExecutorDryRun, type DsarExecutorInput, type DsarExecutorPatch, type DsarExportResult, type DsarRequest, type DsarStatus, type DsarTask, type DsarTaskEvent, type DsarTaskExport, type DsarTaskLogEntry, type DsarTaskOutcome, type DsarType, type EnforcementRuleInput, type ExecutorProfile, type ExecutorTestInput, type ExecutorTestResult, type ExecutorWebhookDelivery, type ExecutorWebhookTestResult, type FlowIssue, type FlowOp, type FlowOpResponse, type FulfillmentOp, type Identifier, type Identity, type ImportedCookie, type ImportedDeclaration, type InstallSnippet, type LegalBasis, type LogQuery, type MailProvider, type MailProviderInput, type MailProviderKind, type MailProviderTestResult, type Member, type OptInMethod, type Org, type OrgUpdate, type ParityControlSummary, type PlanSource, type PolicyOptions, type PreferenceItem, type PreferenceRecord, type PreviewToken, type PreviewTokenOptions, type ProfileAttributeInput, 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 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, type ScanResult, type ScanStatus, type ScoredVendor, type SessionAnalysisInput, type SignedReceipt, type Site, type SiteConfig, type SiteCookie, type SiteCreate, type SiteFlow, type SnippetOptions, type SubscriptionTopicInput, type SuggestedRejectStyle, type SupportedLanguage, type Usage, type VendorInput, type VendorRecord, type VerifyResult, type VerifyWebhookInput, type WebhookCreate, type WebhookDeadLetter, type WebhookKeyForm, type WebhookStage, type WebhookSubscription, type WebhookTestResult, type WebhookUpdate, createCookieMunch, verifyWebhookSignature };