@cookiemunch/sdk 0.0.0-stage → 0.1.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/README.md +59 -2
- package/dist/chunk-G7ORTXTK.js +104 -0
- package/dist/chunk-G7ORTXTK.js.map +1 -0
- package/dist/consent.cjs +132 -0
- package/dist/consent.cjs.map +1 -0
- package/dist/consent.d.cts +88 -0
- package/dist/consent.d.ts +88 -0
- package/dist/consent.js +15 -0
- package/dist/consent.js.map +1 -0
- package/dist/index.cjs +464 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1620 -0
- package/dist/index.d.ts +1620 -0
- package/dist/index.js +342 -0
- package/dist/index.js.map +1 -0
- package/package.json +34 -3
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1620 @@
|
|
|
1
|
+
export { CONSENT_COOKIE_NAME, ConsentCategory, ConsentSource, ReadConsentOptions, ServerConsent, getConsent, isAllowed, parseConsentValue, readConsent } from './consent.js';
|
|
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
|
+
}
|
|
30
|
+
type PlanSource = 'org' | 'account';
|
|
31
|
+
/** One organisation on an account (GET /v1/orgs, and the `org_limit` refusal). */
|
|
32
|
+
interface AccountOrg {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
/** The effective plan. */
|
|
36
|
+
plan: string;
|
|
37
|
+
planSource: PlanSource;
|
|
38
|
+
subscribedPlan: string;
|
|
39
|
+
/** Present on a reseller-managed child organisation. */
|
|
40
|
+
parentOrgId?: string;
|
|
41
|
+
createdAt: number;
|
|
42
|
+
/** True for the organisation the calling key belongs to. */
|
|
43
|
+
current: boolean;
|
|
44
|
+
}
|
|
45
|
+
interface AccountOrgs {
|
|
46
|
+
orgs: AccountOrg[];
|
|
47
|
+
/** The per-account org cap: `max` (null = unlimited), the `plan` that sets it, and `used`. */
|
|
48
|
+
orgLimit: {
|
|
49
|
+
max: number | null;
|
|
50
|
+
plan: string;
|
|
51
|
+
used: number;
|
|
52
|
+
};
|
|
53
|
+
/** The dashboard billing page, where a plan is chosen. */
|
|
54
|
+
upgradeUrl: string;
|
|
55
|
+
}
|
|
56
|
+
interface Site {
|
|
57
|
+
cbid: string;
|
|
58
|
+
orgId: string;
|
|
59
|
+
domain: string;
|
|
60
|
+
}
|
|
61
|
+
interface SiteCreate {
|
|
62
|
+
domain: string;
|
|
63
|
+
/** Optional; the server auto-generates a cbid when omitted. */
|
|
64
|
+
cbid?: string;
|
|
65
|
+
}
|
|
66
|
+
/** Site config is an open, deeply-nested object owned by @cookiemunch/core. */
|
|
67
|
+
type SiteConfig = Record<string, unknown>;
|
|
68
|
+
interface ConsentDay {
|
|
69
|
+
Date: string;
|
|
70
|
+
OptIn: number;
|
|
71
|
+
OptOut: number;
|
|
72
|
+
OptInImplied: number;
|
|
73
|
+
OptInStrict: number;
|
|
74
|
+
TypeOptInPref: number;
|
|
75
|
+
TypeOptInStat: number;
|
|
76
|
+
TypeOptInMark: number;
|
|
77
|
+
Impressions: number;
|
|
78
|
+
Countries: Record<string, number>;
|
|
79
|
+
}
|
|
80
|
+
interface ConsentLogRow {
|
|
81
|
+
stamp: string;
|
|
82
|
+
receivedAt: number;
|
|
83
|
+
region: string;
|
|
84
|
+
method: string;
|
|
85
|
+
choices: {
|
|
86
|
+
preferences: boolean;
|
|
87
|
+
statistics: boolean;
|
|
88
|
+
marketing: boolean;
|
|
89
|
+
};
|
|
90
|
+
anonIp: string;
|
|
91
|
+
url: string;
|
|
92
|
+
}
|
|
93
|
+
interface RangeQuery {
|
|
94
|
+
from?: number;
|
|
95
|
+
to?: number;
|
|
96
|
+
}
|
|
97
|
+
interface LogQuery extends RangeQuery {
|
|
98
|
+
limit?: number;
|
|
99
|
+
}
|
|
100
|
+
type DsarType = 'access' | 'deletion' | 'rectification' | 'portability' | 'opt-out';
|
|
101
|
+
type Regulation = 'gdpr' | 'ccpa';
|
|
102
|
+
type DsarStatus = 'received' | 'verifying' | 'in_progress' | 'completed' | 'rejected';
|
|
103
|
+
interface DsarRequest {
|
|
104
|
+
id: string;
|
|
105
|
+
type: DsarType;
|
|
106
|
+
subjectEmail: string;
|
|
107
|
+
regulation: Regulation;
|
|
108
|
+
status: DsarStatus;
|
|
109
|
+
createdAt: number;
|
|
110
|
+
dueAt: number;
|
|
111
|
+
/** Where the subject said they are, when the intake captured it. */
|
|
112
|
+
jurisdiction?: string;
|
|
113
|
+
note?: string;
|
|
114
|
+
/** A test request: off the SLA board, labelled, and deletable with `dsar.delete`. */
|
|
115
|
+
test?: boolean;
|
|
116
|
+
}
|
|
117
|
+
interface DsarCreate {
|
|
118
|
+
type: DsarType;
|
|
119
|
+
subjectEmail: string;
|
|
120
|
+
/** Picks the statutory response window. */
|
|
121
|
+
regulation: Regulation;
|
|
122
|
+
/**
|
|
123
|
+
* Where the subject says they are (ISO 3166 country or country-subdivision, e.g.
|
|
124
|
+
* `US-TX`). The response notice names the statute that governs there — without it a
|
|
125
|
+
* Texan is told their request was handled under a Virginia law, since every US state
|
|
126
|
+
* shares one `regulation` for the deadline.
|
|
127
|
+
*/
|
|
128
|
+
jurisdiction?: string;
|
|
129
|
+
note?: string;
|
|
130
|
+
/** The property this request belongs to; decides which connected systems answer it. */
|
|
131
|
+
cbid?: string;
|
|
132
|
+
/** The subject's consent-receipt id. */
|
|
133
|
+
stamp?: string;
|
|
134
|
+
/**
|
|
135
|
+
* Mark it as a test: left out of SLA metrics and the deadline board, labelled as a test,
|
|
136
|
+
* and deletable with `dsar.delete(id)`. For end-to-end checks of a rights flow.
|
|
137
|
+
*/
|
|
138
|
+
test?: boolean;
|
|
139
|
+
}
|
|
140
|
+
interface VendorInput {
|
|
141
|
+
name: string;
|
|
142
|
+
category: string;
|
|
143
|
+
dataShared: string[];
|
|
144
|
+
dpaSigned: boolean;
|
|
145
|
+
subprocessors: number;
|
|
146
|
+
certifications: string[];
|
|
147
|
+
region: string;
|
|
148
|
+
}
|
|
149
|
+
interface RiskScore {
|
|
150
|
+
score: number;
|
|
151
|
+
band: 'low' | 'medium' | 'high';
|
|
152
|
+
}
|
|
153
|
+
/** A stored vendor record (no computed risk; see {@link ScoredVendor}). Returned as the
|
|
154
|
+
* `vendor` field of POST /v1/vendors. */
|
|
155
|
+
interface VendorRecord extends VendorInput {
|
|
156
|
+
id: string;
|
|
157
|
+
}
|
|
158
|
+
/** A vendor as listed, with its computed risk flattened in. */
|
|
159
|
+
interface ScoredVendor extends VendorRecord {
|
|
160
|
+
risk: RiskScore;
|
|
161
|
+
}
|
|
162
|
+
type LegalBasis = 'consent' | 'contract' | 'legal-obligation' | 'vital-interests' | 'public-task' | 'legitimate-interests';
|
|
163
|
+
interface RopaInput {
|
|
164
|
+
name: string;
|
|
165
|
+
purpose: string;
|
|
166
|
+
legalBasis: LegalBasis;
|
|
167
|
+
dataCategories: string[];
|
|
168
|
+
recipients: string[];
|
|
169
|
+
retentionDays: number;
|
|
170
|
+
crossBorderTransfer: boolean;
|
|
171
|
+
}
|
|
172
|
+
interface RopaEntry extends RopaInput {
|
|
173
|
+
id: string;
|
|
174
|
+
}
|
|
175
|
+
/** A signed consent receipt (shape owned by @cookiemunch/receipts). */
|
|
176
|
+
type SignedReceipt = Record<string, unknown>;
|
|
177
|
+
/** How a preference-center opt-in was captured. Mirrors @cookiemunch/preferences OptInMethod. */
|
|
178
|
+
type OptInMethod = 'single-opt-in' | 'double-opt-in';
|
|
179
|
+
/**
|
|
180
|
+
* A subject's saved preference-center record (identity-keyed named purposes, distinct
|
|
181
|
+
* from the org-level {@link PreferenceItem} catalog). Matches @cookiemunch/preferences
|
|
182
|
+
* PreferenceRecord (mirrored here per this package's no-server-dependency convention).
|
|
183
|
+
* Returned wrapped as `{ record }` by POST /v1/preferences.
|
|
184
|
+
*/
|
|
185
|
+
interface PreferenceRecord {
|
|
186
|
+
subjectId: string;
|
|
187
|
+
purposes: Record<string, boolean>;
|
|
188
|
+
method: OptInMethod;
|
|
189
|
+
confirmed: boolean;
|
|
190
|
+
updatedAt: number;
|
|
191
|
+
version: number;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
interface VerifyWebhookInput {
|
|
195
|
+
/** The raw request body, exactly as received. Do NOT re-stringify parsed JSON. */
|
|
196
|
+
payload: string;
|
|
197
|
+
/** The `X-CookieMunch-Signature` header value. */
|
|
198
|
+
signature: string | undefined | null;
|
|
199
|
+
/** The `X-CookieMunch-Timestamp` header value (unix seconds). */
|
|
200
|
+
timestamp: string | number | undefined | null;
|
|
201
|
+
/** The subscription secret (`whsec_…`), shown once when the webhook was created. */
|
|
202
|
+
secret: string;
|
|
203
|
+
/**
|
|
204
|
+
* Maximum age (in seconds) of a delivery before it is rejected as stale/replayed.
|
|
205
|
+
* Defaults to 300 (5 minutes). Pass 0 to disable the freshness check entirely.
|
|
206
|
+
*/
|
|
207
|
+
toleranceSeconds?: number;
|
|
208
|
+
/** Current time in ms (injectable for tests); defaults to `Date.now()`. */
|
|
209
|
+
now?: number;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Returns true only when the signature is valid AND (unless disabled) the timestamp is fresh.
|
|
213
|
+
* Fail-closed: any missing/malformed input returns false rather than throwing.
|
|
214
|
+
*/
|
|
215
|
+
declare function verifyWebhookSignature(input: VerifyWebhookInput): boolean;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* @cookiemunch/sdk — a small, typed REST client for the Cookie Munch Developer API
|
|
219
|
+
* (the /v1 surface). Construct it with an API key; the org is derived server-side
|
|
220
|
+
* from the key, so callers never pass an orgId. `fetch` is injectable for testing
|
|
221
|
+
* and non-browser/non-Node runtimes; it defaults to the global fetch.
|
|
222
|
+
*
|
|
223
|
+
* const fc = createCookieMunch({ apiKey: 'fck_…', baseUrl: 'https://cmp.example.com' });
|
|
224
|
+
* const sites = await fc.sites.list();
|
|
225
|
+
*/
|
|
226
|
+
|
|
227
|
+
interface CookieMunchOptions {
|
|
228
|
+
apiKey: string;
|
|
229
|
+
/** e.g. "https://cmp.example.com" — the /v1 prefix is appended automatically. */
|
|
230
|
+
baseUrl: string;
|
|
231
|
+
/** Injectable for tests / custom runtimes. Defaults to the global fetch. */
|
|
232
|
+
fetch?: typeof fetch;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Thrown for any non-2xx response. `message` is the server's `error` field when present;
|
|
236
|
+
* `code` is populated from the server's `code` field whenever the error body carries one
|
|
237
|
+
* (e.g. banner-library conflicts, docs-admin checks) — not only for scoped-key
|
|
238
|
+
* (`insufficient_scope`) responses. It's `undefined` when the body has no `code`.
|
|
239
|
+
*/
|
|
240
|
+
declare class CookieMunchApiError extends Error {
|
|
241
|
+
readonly status: number;
|
|
242
|
+
readonly code?: string;
|
|
243
|
+
constructor(status: number, message: string, code?: string);
|
|
244
|
+
}
|
|
245
|
+
/** A cookie discovered on a site, classified into a consent category (wire shape of the
|
|
246
|
+
* cookie-declaration feed). Matches the server's CategorizedCookie schema. */
|
|
247
|
+
interface CategorizedCookie {
|
|
248
|
+
name: string;
|
|
249
|
+
category: 'necessary' | 'preferences' | 'statistics' | 'marketing' | 'unclassified' | (string & {});
|
|
250
|
+
domain?: string;
|
|
251
|
+
provider?: string;
|
|
252
|
+
purpose?: string;
|
|
253
|
+
expiry?: string;
|
|
254
|
+
}
|
|
255
|
+
/** A site's cookie declaration: the latest scan's categorized cookies. This is what
|
|
256
|
+
* GET /v1/sites/:cbid/cookies actually returns (a wrapper, not a bare array). */
|
|
257
|
+
interface CookieDeclaration {
|
|
258
|
+
/** Epoch-ms of the latest scan, or 0 if none. */
|
|
259
|
+
updatedAt: number;
|
|
260
|
+
cookies: CategorizedCookie[];
|
|
261
|
+
}
|
|
262
|
+
/** @deprecated The server returns {@link CookieDeclaration}; kept only for back-compat. */
|
|
263
|
+
interface SiteCookie {
|
|
264
|
+
name: string;
|
|
265
|
+
domain: string;
|
|
266
|
+
category: string;
|
|
267
|
+
provider?: string;
|
|
268
|
+
purpose?: string;
|
|
269
|
+
expiry?: string;
|
|
270
|
+
firstSeen?: number;
|
|
271
|
+
}
|
|
272
|
+
/** Cookie-scan status, from GET /v1/sites/:cbid/scan. */
|
|
273
|
+
interface ScanStatus {
|
|
274
|
+
status: 'idle' | 'scanning';
|
|
275
|
+
/** Epoch-ms of the last completed scan, or null. */
|
|
276
|
+
lastScannedAt: number | null;
|
|
277
|
+
}
|
|
278
|
+
/** @deprecated The server returns {@link ScanStatus}; kept only for back-compat. */
|
|
279
|
+
interface ScanResult {
|
|
280
|
+
scanId: string;
|
|
281
|
+
status: 'queued' | 'running' | 'complete' | 'failed';
|
|
282
|
+
startedAt?: number;
|
|
283
|
+
finishedAt?: number;
|
|
284
|
+
pagesScanned?: number;
|
|
285
|
+
cookiesFound?: number;
|
|
286
|
+
}
|
|
287
|
+
/** A/B banner experiment results for a single variant. */
|
|
288
|
+
interface AbResult {
|
|
289
|
+
variant: string;
|
|
290
|
+
impressions: number;
|
|
291
|
+
optIns: number;
|
|
292
|
+
optInRate: number;
|
|
293
|
+
}
|
|
294
|
+
/** The response shape of GET /v1/sites/:cbid/snippet. */
|
|
295
|
+
interface InstallSnippet {
|
|
296
|
+
/** The exact `<script>` tag to paste into `<head>`. */
|
|
297
|
+
snippet: string;
|
|
298
|
+
/** URL of the consent.js embed file (the embed/CDN origin). */
|
|
299
|
+
src: string;
|
|
300
|
+
/** The API origin (beacons + consent-tcf.js). Present when the server reports it. */
|
|
301
|
+
api?: string;
|
|
302
|
+
/** The site identifier. */
|
|
303
|
+
cbid: string;
|
|
304
|
+
/** The blocking mode on the tag — the site's `blocking.mode` unless overridden. */
|
|
305
|
+
blockingMode: string;
|
|
306
|
+
/** Where `blockingMode` came from: the site's config, or the `blockingMode` option. */
|
|
307
|
+
blockingModeSource?: 'config' | 'query';
|
|
308
|
+
/** The tag's data-culture, when it has one. */
|
|
309
|
+
culture?: string;
|
|
310
|
+
/** CSP sources this site needs, by directive, plus a paste-able `policy`. */
|
|
311
|
+
csp?: CspSources;
|
|
312
|
+
/** Present when an override disagrees with the stored config. */
|
|
313
|
+
warnings?: ConfigWarning[];
|
|
314
|
+
}
|
|
315
|
+
/** Content Security Policy sources the embed needs. */
|
|
316
|
+
interface CspSources {
|
|
317
|
+
script: string[];
|
|
318
|
+
connect: string[];
|
|
319
|
+
img: string[];
|
|
320
|
+
/** Always includes 'unsafe-inline' (the banner's shadow-root <style>), unless you use a nonce. */
|
|
321
|
+
style: string[];
|
|
322
|
+
font: string[];
|
|
323
|
+
frame: string[];
|
|
324
|
+
/** The same as one policy fragment. */
|
|
325
|
+
policy: string;
|
|
326
|
+
}
|
|
327
|
+
/** Something a config write did not store as sent. */
|
|
328
|
+
interface ConfigWarning {
|
|
329
|
+
field: string;
|
|
330
|
+
reason: string;
|
|
331
|
+
}
|
|
332
|
+
/** One leaf a config write would change. */
|
|
333
|
+
interface ConfigChange {
|
|
334
|
+
path: string;
|
|
335
|
+
from?: unknown;
|
|
336
|
+
to?: unknown;
|
|
337
|
+
}
|
|
338
|
+
/** What a config write would do (`?dryRun=1`) — nothing is saved. */
|
|
339
|
+
interface ConfigDryRun {
|
|
340
|
+
dryRun: true;
|
|
341
|
+
/** The config as it would be saved. */
|
|
342
|
+
config: SiteConfig;
|
|
343
|
+
/** Every leaf that would change. */
|
|
344
|
+
diff: ConfigChange[];
|
|
345
|
+
warnings?: ConfigWarning[];
|
|
346
|
+
}
|
|
347
|
+
/** Options for POST /v1/sites/:cbid/preview-token. All optional. */
|
|
348
|
+
interface PreviewTokenOptions {
|
|
349
|
+
/** Lifetime in seconds, 1..3600. Default 900. */
|
|
350
|
+
ttlSeconds?: number;
|
|
351
|
+
/** The page to preview. Default: the site's registered domain. */
|
|
352
|
+
url?: string;
|
|
353
|
+
/** Region to force: a country or subdivision code (`de`, `us-ca`) or `eu`. */
|
|
354
|
+
region?: string;
|
|
355
|
+
/** Language to force, as a BCP 47 tag (`de`, `pt-BR`). */
|
|
356
|
+
lang?: string;
|
|
357
|
+
}
|
|
358
|
+
/** A banner preview token, and the page URL that opens the preview. */
|
|
359
|
+
interface PreviewToken {
|
|
360
|
+
cbid: string;
|
|
361
|
+
token: string;
|
|
362
|
+
/** Epoch milliseconds. */
|
|
363
|
+
expiresAt: number;
|
|
364
|
+
region?: string;
|
|
365
|
+
lang?: string;
|
|
366
|
+
/** The page with `cm_preview` / `cm_region` / `cm_lang` added. */
|
|
367
|
+
previewUrl?: string;
|
|
368
|
+
}
|
|
369
|
+
/** Options for the snippet endpoint. */
|
|
370
|
+
interface SnippetOptions {
|
|
371
|
+
/** Override the site's configured `blocking.mode`. Default: the config's. */
|
|
372
|
+
blockingMode?: 'auto' | 'manual';
|
|
373
|
+
/** Language culture override, e.g. "en" or "fr". */
|
|
374
|
+
culture?: string;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* The result of domain verification.
|
|
378
|
+
* Keep in sync with the POST /v1/sites/:cbid/verify response in
|
|
379
|
+
* packages/server/src/dev-api.ts (~L267) — note the server adds `method` on success,
|
|
380
|
+
* so this wire shape is wider than domain-verify.ts's internal VerifyResult.
|
|
381
|
+
*/
|
|
382
|
+
interface VerifyResult {
|
|
383
|
+
verified: boolean;
|
|
384
|
+
method?: 'dns' | 'meta' | 'file';
|
|
385
|
+
reason?: string;
|
|
386
|
+
}
|
|
387
|
+
/** A site brand suggestion ("Match my site"). Keep in sync with packages/server/src/brand-extract.ts BrandSuggestion. */
|
|
388
|
+
interface BrandSuggestion {
|
|
389
|
+
background?: string;
|
|
390
|
+
text?: string;
|
|
391
|
+
highlight?: string;
|
|
392
|
+
fontFamily?: string;
|
|
393
|
+
fontUrl?: string;
|
|
394
|
+
palette?: string[];
|
|
395
|
+
}
|
|
396
|
+
/** The response shape of POST /v1/sites/:cbid/brand. */
|
|
397
|
+
interface BrandExtractionResult {
|
|
398
|
+
suggestion: BrandSuggestion;
|
|
399
|
+
}
|
|
400
|
+
/** A validation/lint issue on a v2 banner flow. */
|
|
401
|
+
interface FlowIssue {
|
|
402
|
+
code: string;
|
|
403
|
+
message: string;
|
|
404
|
+
path?: string;
|
|
405
|
+
}
|
|
406
|
+
/** A site's v2 banner flow + lint issues, from GET /v1/sites/:cbid/flow. */
|
|
407
|
+
interface SiteFlow {
|
|
408
|
+
v: 2;
|
|
409
|
+
flow: Record<string, unknown>;
|
|
410
|
+
categories: Record<string, unknown>;
|
|
411
|
+
customCss?: string;
|
|
412
|
+
lint: FlowIssue[];
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* A single structured flow edit operation. `op` selects the kind; remaining fields are
|
|
416
|
+
* that op's args (e.g. { op: 'addView', id, surface, layoutMode }).
|
|
417
|
+
*/
|
|
418
|
+
type FlowOp = {
|
|
419
|
+
op: string;
|
|
420
|
+
} & Record<string, unknown>;
|
|
421
|
+
/**
|
|
422
|
+
* Result of editFlow/setFlow. On success the new flow is persisted and returned;
|
|
423
|
+
* on a validation/lint failure the config is NOT saved and `issues` says why.
|
|
424
|
+
*/
|
|
425
|
+
type FlowOpResponse = {
|
|
426
|
+
ok: true;
|
|
427
|
+
flow: Record<string, unknown>;
|
|
428
|
+
} | {
|
|
429
|
+
ok: false;
|
|
430
|
+
failedAt?: number;
|
|
431
|
+
op?: unknown;
|
|
432
|
+
issues: FlowIssue[];
|
|
433
|
+
};
|
|
434
|
+
/** A reusable brand kit (colors/logo/typography) for banner theming. */
|
|
435
|
+
interface BrandKit {
|
|
436
|
+
id: string;
|
|
437
|
+
orgId: string;
|
|
438
|
+
name: string;
|
|
439
|
+
/** Banner theme tokens (opaque design object). */
|
|
440
|
+
theme: Record<string, unknown>;
|
|
441
|
+
/** Optional banner content overrides (opaque). */
|
|
442
|
+
content?: Record<string, unknown>;
|
|
443
|
+
logoUrl?: string;
|
|
444
|
+
customCss?: string;
|
|
445
|
+
}
|
|
446
|
+
/** A configurable consent preference/purpose item. */
|
|
447
|
+
interface PreferenceItem {
|
|
448
|
+
id: string;
|
|
449
|
+
orgId: string;
|
|
450
|
+
cbid?: string;
|
|
451
|
+
label: string;
|
|
452
|
+
description?: string;
|
|
453
|
+
category?: string;
|
|
454
|
+
}
|
|
455
|
+
/** An organization member. */
|
|
456
|
+
interface Member {
|
|
457
|
+
userId: string;
|
|
458
|
+
email: string;
|
|
459
|
+
role: 'owner' | 'admin' | 'member' | 'viewer' | (string & {});
|
|
460
|
+
}
|
|
461
|
+
/** Display metadata for an issued key — never the secret. Returned by keys.list(). */
|
|
462
|
+
interface ApiKeyPrefix {
|
|
463
|
+
prefix: string;
|
|
464
|
+
createdAt?: number;
|
|
465
|
+
}
|
|
466
|
+
/** A newly issued key. `key` is returned ONCE and never again. Returned by keys.issue(). */
|
|
467
|
+
interface ApiKeyIssued {
|
|
468
|
+
key: string;
|
|
469
|
+
prefix: string;
|
|
470
|
+
}
|
|
471
|
+
/** @deprecated No endpoint returns this shape; use {@link ApiKeyPrefix} / {@link ApiKeyIssued}. */
|
|
472
|
+
interface ApiKey {
|
|
473
|
+
id: string;
|
|
474
|
+
orgId: string;
|
|
475
|
+
prefix: string;
|
|
476
|
+
name?: string;
|
|
477
|
+
createdAt: number;
|
|
478
|
+
lastUsedAt?: number;
|
|
479
|
+
secret?: string;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Input for issuing a new API key.
|
|
483
|
+
*
|
|
484
|
+
* NOTE: the server's POST /v1/keys currently accepts no body and always mints an
|
|
485
|
+
* unscoped key — `name` is not yet honoured server-side. It's kept here (rather than
|
|
486
|
+
* dropped) so a future scoped/named-key endpoint can start reading it without an SDK
|
|
487
|
+
* major version bump; see {@link CookieMunchClient.keys}.
|
|
488
|
+
*/
|
|
489
|
+
interface ApiKeyIssueInput {
|
|
490
|
+
name?: string;
|
|
491
|
+
/** Least privilege: grant only these scopes. Omit for a full-access key. */
|
|
492
|
+
scopes?: string[];
|
|
493
|
+
/**
|
|
494
|
+
* Lock the key to these properties. A locked key works only on those sites and on no
|
|
495
|
+
* org-wide endpoint — see "Keys locked to properties" in the client reference.
|
|
496
|
+
*/
|
|
497
|
+
cbids?: string[];
|
|
498
|
+
/** Expire the key after this many days (1–3650). */
|
|
499
|
+
expiresInDays?: number;
|
|
500
|
+
}
|
|
501
|
+
/** Org usage/quota summary. Matches the server's Usage schema. */
|
|
502
|
+
interface Usage {
|
|
503
|
+
domains: number;
|
|
504
|
+
seats: number;
|
|
505
|
+
monthlyEvents: number;
|
|
506
|
+
}
|
|
507
|
+
/** A webhook subscription. `secret` is present only in the create response. */
|
|
508
|
+
interface WebhookSubscription {
|
|
509
|
+
id: string;
|
|
510
|
+
orgId: string;
|
|
511
|
+
url: string;
|
|
512
|
+
secret?: string;
|
|
513
|
+
events: string[];
|
|
514
|
+
cbid: string | null;
|
|
515
|
+
active: boolean;
|
|
516
|
+
createdAt: number;
|
|
517
|
+
}
|
|
518
|
+
/** One cookie read from another CMP's export. */
|
|
519
|
+
interface ImportedCookie {
|
|
520
|
+
name: string;
|
|
521
|
+
domain: string;
|
|
522
|
+
/** Ours, or `unclassified` when their category did not map to one. */
|
|
523
|
+
category: 'necessary' | 'preferences' | 'statistics' | 'marketing' | 'unclassified';
|
|
524
|
+
/** What the previous vendor called it, kept for review. */
|
|
525
|
+
sourceCategory: string;
|
|
526
|
+
purpose: string;
|
|
527
|
+
provider: string;
|
|
528
|
+
expiry: string;
|
|
529
|
+
}
|
|
530
|
+
/** What a competitor's cookie-declaration export contained, in our vocabulary. */
|
|
531
|
+
interface ImportedDeclaration {
|
|
532
|
+
source: 'onetrust' | 'cookiebot' | 'cookieyes' | 'unknown';
|
|
533
|
+
cookies: ImportedCookie[];
|
|
534
|
+
/** Rows whose category could not be placed — review these first. */
|
|
535
|
+
unmapped: Array<{
|
|
536
|
+
name: string;
|
|
537
|
+
category: string;
|
|
538
|
+
}>;
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* A page that refused to load the banner renderer. The site is live and configured, so
|
|
542
|
+
* every other signal looks healthy; this is the one that says nobody can be asked.
|
|
543
|
+
*/
|
|
544
|
+
interface BlockedReport {
|
|
545
|
+
cbid: string;
|
|
546
|
+
/** Origin of the page the embed was running on. */
|
|
547
|
+
page: string;
|
|
548
|
+
/** The bundle URL that page refused. */
|
|
549
|
+
url: string;
|
|
550
|
+
reason: string;
|
|
551
|
+
firstSeen: number;
|
|
552
|
+
lastSeen: number;
|
|
553
|
+
/** How many times this page has reported. Repeats are counted, not stored. */
|
|
554
|
+
count: number;
|
|
555
|
+
}
|
|
556
|
+
/** A webhook delivery that failed every retry. Replay it by `id`. */
|
|
557
|
+
interface WebhookDeadLetter {
|
|
558
|
+
id: string;
|
|
559
|
+
orgId: string;
|
|
560
|
+
subscriptionId: string;
|
|
561
|
+
url: string;
|
|
562
|
+
eventType: string;
|
|
563
|
+
cbid: string | null;
|
|
564
|
+
payload: unknown;
|
|
565
|
+
attempts: number;
|
|
566
|
+
lastStatus?: number;
|
|
567
|
+
lastError?: string;
|
|
568
|
+
failedAt: number;
|
|
569
|
+
}
|
|
570
|
+
/** What a test delivery's endpoint answered. */
|
|
571
|
+
interface WebhookTestResult {
|
|
572
|
+
ok: boolean;
|
|
573
|
+
status?: number;
|
|
574
|
+
error?: string;
|
|
575
|
+
}
|
|
576
|
+
/** The key's organisation. */
|
|
577
|
+
interface Org {
|
|
578
|
+
id: string;
|
|
579
|
+
name: string;
|
|
580
|
+
plan: string;
|
|
581
|
+
logoUrl: string | null;
|
|
582
|
+
}
|
|
583
|
+
/** Change an org's name or logo. `logoUrl: null` removes the logo. */
|
|
584
|
+
interface OrgUpdate {
|
|
585
|
+
name?: string;
|
|
586
|
+
logoUrl?: string | null;
|
|
587
|
+
}
|
|
588
|
+
/** One entry in the org's audit log. */
|
|
589
|
+
interface AuditEntry {
|
|
590
|
+
id: string;
|
|
591
|
+
orgId: string;
|
|
592
|
+
actorUserId: string;
|
|
593
|
+
actorEmail?: string;
|
|
594
|
+
action: string;
|
|
595
|
+
target?: string;
|
|
596
|
+
meta?: Record<string, unknown>;
|
|
597
|
+
at: number;
|
|
598
|
+
}
|
|
599
|
+
/** Rename a key, or replace its scopes or the properties it is locked to. */
|
|
600
|
+
interface ApiKeyUpdate {
|
|
601
|
+
name?: string;
|
|
602
|
+
scopes?: string[];
|
|
603
|
+
cbids?: string[];
|
|
604
|
+
}
|
|
605
|
+
/** An image to upload: base64 (or a `data:` URL) plus its type. */
|
|
606
|
+
interface AssetUpload {
|
|
607
|
+
data: string;
|
|
608
|
+
contentType: 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif' | 'image/svg+xml';
|
|
609
|
+
}
|
|
610
|
+
/** Result of erasing a subject's consent for a deletion request. */
|
|
611
|
+
interface DsarEraseResult {
|
|
612
|
+
erased: number;
|
|
613
|
+
encryptionEnabled: boolean;
|
|
614
|
+
/** Present when no KEK is configured, so nothing was cryptographically erased. */
|
|
615
|
+
warning?: string;
|
|
616
|
+
request: DsarRequest;
|
|
617
|
+
}
|
|
618
|
+
/** Result of exporting a subject's consent for an access or portability request. */
|
|
619
|
+
interface DsarExportResult {
|
|
620
|
+
records: unknown[];
|
|
621
|
+
count: number;
|
|
622
|
+
request: DsarRequest;
|
|
623
|
+
}
|
|
624
|
+
/** Input for creating a webhook subscription. */
|
|
625
|
+
interface WebhookCreate {
|
|
626
|
+
url: string;
|
|
627
|
+
events: string[];
|
|
628
|
+
cbid?: string;
|
|
629
|
+
}
|
|
630
|
+
/** Fields to change on a webhook subscription. Only those present are sent. */
|
|
631
|
+
interface WebhookUpdate {
|
|
632
|
+
url?: string;
|
|
633
|
+
events?: string[];
|
|
634
|
+
/** One property, or null for every property in the org. */
|
|
635
|
+
cbid?: string | null;
|
|
636
|
+
/** false pauses delivery without deleting the subscription. */
|
|
637
|
+
active?: boolean;
|
|
638
|
+
}
|
|
639
|
+
/** One site to create in a bulk call. */
|
|
640
|
+
interface BulkSiteInput {
|
|
641
|
+
domain: string;
|
|
642
|
+
cbid?: string;
|
|
643
|
+
platform?: string;
|
|
644
|
+
}
|
|
645
|
+
/** Per-item outcome of a bulk create, in input order. */
|
|
646
|
+
interface BulkSiteResult {
|
|
647
|
+
ok: boolean;
|
|
648
|
+
cbid?: string;
|
|
649
|
+
domain?: string;
|
|
650
|
+
error?: string;
|
|
651
|
+
}
|
|
652
|
+
/** Input for creating a brand kit. */
|
|
653
|
+
interface BrandKitCreate {
|
|
654
|
+
name: string;
|
|
655
|
+
theme: unknown;
|
|
656
|
+
content?: unknown;
|
|
657
|
+
logoUrl?: string;
|
|
658
|
+
customCss?: string;
|
|
659
|
+
}
|
|
660
|
+
/** A lightweight summary of an account-level banner, as returned by GET /v1/banners. */
|
|
661
|
+
interface BannerSummary {
|
|
662
|
+
id: string;
|
|
663
|
+
name: string;
|
|
664
|
+
updatedAt: number;
|
|
665
|
+
assignedCbids: string[];
|
|
666
|
+
}
|
|
667
|
+
/** A full account-level banner record, including its config JSON. */
|
|
668
|
+
interface BannerRecord {
|
|
669
|
+
id: string;
|
|
670
|
+
orgId: string;
|
|
671
|
+
name: string;
|
|
672
|
+
json: SiteConfig;
|
|
673
|
+
createdAt: number;
|
|
674
|
+
updatedAt: number;
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Input for the public consent-log ingest endpoint (POST /api/v1/consent) — the
|
|
678
|
+
* tamper-evident, hash-chained ledger write the browser embed makes. Mirrors the
|
|
679
|
+
* server's ConsentPayload; optional fields are sent only when set. Records are
|
|
680
|
+
* anonymised (IP truncated) and hash-chained server-side.
|
|
681
|
+
*/
|
|
682
|
+
interface ConsentIngestInput {
|
|
683
|
+
/** The registered site id the consent belongs to. */
|
|
684
|
+
cbid: string;
|
|
685
|
+
/** Stable per-subject consent-receipt id (used for erase/export). */
|
|
686
|
+
stamp: string;
|
|
687
|
+
/** The subject's cookie-category choices. */
|
|
688
|
+
choices: {
|
|
689
|
+
preferences: boolean;
|
|
690
|
+
statistics: boolean;
|
|
691
|
+
marketing: boolean;
|
|
692
|
+
};
|
|
693
|
+
/** How consent was captured. */
|
|
694
|
+
method: 'explicit' | 'implied';
|
|
695
|
+
/** Consent/notice version number. */
|
|
696
|
+
ver: number;
|
|
697
|
+
/** Epoch-ms the decision was made. */
|
|
698
|
+
utc: number;
|
|
699
|
+
/** The URL / screen where consent was captured. */
|
|
700
|
+
url: string;
|
|
701
|
+
/** Optional IAB TCF consent string (TCF mode only). */
|
|
702
|
+
tcString?: string;
|
|
703
|
+
/** Optional GPP string (GPP mode only). */
|
|
704
|
+
gppString?: string;
|
|
705
|
+
/** Optional named-purpose map beyond the standard categories. */
|
|
706
|
+
purposes?: Record<string, boolean>;
|
|
707
|
+
/** Optional opaque digest of the exact notice text shown to the subject. */
|
|
708
|
+
subjectPolicyHash?: string;
|
|
709
|
+
/** Optional map: named purpose → RoPA entry id. */
|
|
710
|
+
purposeRopa?: Record<string, string>;
|
|
711
|
+
/** Optional A/B variant id. */
|
|
712
|
+
variant?: string;
|
|
713
|
+
/**
|
|
714
|
+
* Optional, app-supplied STABLE cross-surface subject id. Lets an org retrieve one
|
|
715
|
+
* subject's consent history across ALL its sites/surfaces (web + mobile + desktop).
|
|
716
|
+
* Opaque — stored and bound into the record hash server-side, never interpreted.
|
|
717
|
+
*/
|
|
718
|
+
subjectId?: string;
|
|
719
|
+
}
|
|
720
|
+
/** One of a person's identifiers: an identity-space code plus the normalised value. */
|
|
721
|
+
interface Identifier {
|
|
722
|
+
space: string;
|
|
723
|
+
value: string;
|
|
724
|
+
}
|
|
725
|
+
interface ConsentDecisionInput {
|
|
726
|
+
purpose: string;
|
|
727
|
+
allowed: boolean;
|
|
728
|
+
legalBasis?: string;
|
|
729
|
+
jurisdiction?: string;
|
|
730
|
+
provenance?: string;
|
|
731
|
+
collectedAt?: number;
|
|
732
|
+
}
|
|
733
|
+
interface ProfileAttributeInput {
|
|
734
|
+
value: string;
|
|
735
|
+
purpose?: string;
|
|
736
|
+
collectedAt?: number;
|
|
737
|
+
}
|
|
738
|
+
interface SubscriptionTopicInput {
|
|
739
|
+
code: string;
|
|
740
|
+
name?: string;
|
|
741
|
+
channels: string[];
|
|
742
|
+
downstream?: Record<string, string>;
|
|
743
|
+
}
|
|
744
|
+
/** A warehouse-native enforcement rule. See POST /v1/discovery/enforcement. */
|
|
745
|
+
interface EnforcementRuleInput {
|
|
746
|
+
id: string;
|
|
747
|
+
action: 'mask' | 'restrict';
|
|
748
|
+
/** Select columns at or above this sensitivity. */
|
|
749
|
+
minSensitivity?: 'personal' | 'sensitive';
|
|
750
|
+
/** Select columns in any of these categories. */
|
|
751
|
+
categories?: string[];
|
|
752
|
+
/** mask: roles that still see the raw value. */
|
|
753
|
+
allowRoles?: string[];
|
|
754
|
+
/** restrict: the purpose a subject must have consented to. */
|
|
755
|
+
purpose?: string;
|
|
756
|
+
/** restrict: the column holding the subject id. Default SUBJECT_ID. */
|
|
757
|
+
subjectColumn?: string;
|
|
758
|
+
}
|
|
759
|
+
interface RegulationSummary {
|
|
760
|
+
id: string;
|
|
761
|
+
jurisdiction: string;
|
|
762
|
+
name: string;
|
|
763
|
+
/** ISO date the law takes (or took) effect. */
|
|
764
|
+
effective: string;
|
|
765
|
+
model: 'opt-in' | 'opt-out';
|
|
766
|
+
obligations: string[];
|
|
767
|
+
/** Primary source — the statute or the regulator. */
|
|
768
|
+
source: string;
|
|
769
|
+
}
|
|
770
|
+
interface RegulatoryFeedResult {
|
|
771
|
+
/** When a human last checked the dataset against its sources. */
|
|
772
|
+
reviewedAt: string;
|
|
773
|
+
/** Days since that review. */
|
|
774
|
+
ageDays: number;
|
|
775
|
+
/** How long a review is considered good for. */
|
|
776
|
+
reviewAfterDays: number;
|
|
777
|
+
/** True once the review interval has passed — treat the answer with caution. */
|
|
778
|
+
stale: boolean;
|
|
779
|
+
regulations: RegulationSummary[];
|
|
780
|
+
}
|
|
781
|
+
interface AiInspectInput {
|
|
782
|
+
prompt: string;
|
|
783
|
+
purpose: string;
|
|
784
|
+
model?: string;
|
|
785
|
+
actor?: string;
|
|
786
|
+
direction?: 'prompt' | 'response';
|
|
787
|
+
/** The subject's current permits, when the call concerns an identified person. */
|
|
788
|
+
consent?: Record<string, boolean>;
|
|
789
|
+
}
|
|
790
|
+
interface AiInspectResult {
|
|
791
|
+
action: 'allow' | 'redact' | 'block';
|
|
792
|
+
/** The text to forward: redacted when `redact`, empty when `block`. */
|
|
793
|
+
prompt: string;
|
|
794
|
+
findings: unknown[];
|
|
795
|
+
reasons: string[];
|
|
796
|
+
policyIds: string[];
|
|
797
|
+
blocked: boolean;
|
|
798
|
+
direction: 'prompt' | 'response';
|
|
799
|
+
}
|
|
800
|
+
type FulfillmentOp = 'locate' | 'export' | 'erase' | 'optOut';
|
|
801
|
+
/** A child org provisioned by a reseller. */
|
|
802
|
+
interface ResellerChild {
|
|
803
|
+
id: string;
|
|
804
|
+
name: string;
|
|
805
|
+
status: 'active' | 'suspended';
|
|
806
|
+
delegatedAccess?: boolean;
|
|
807
|
+
/** Per-child DSAR routing override; unset defers to the reseller's policy. */
|
|
808
|
+
dsarRouting?: 'reseller' | 'child';
|
|
809
|
+
createdAt?: number;
|
|
810
|
+
usage?: unknown;
|
|
811
|
+
}
|
|
812
|
+
interface ResellerChildList {
|
|
813
|
+
children: ResellerChild[];
|
|
814
|
+
/** Pooled usage across the reseller and all its children, when metering is wired. */
|
|
815
|
+
aggregate?: {
|
|
816
|
+
childOrgs: number;
|
|
817
|
+
sites: number;
|
|
818
|
+
monthlyEvents: number;
|
|
819
|
+
monthlyEventsCap: number | null;
|
|
820
|
+
overCap: boolean;
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
interface ResellerChildCreate {
|
|
824
|
+
name: string;
|
|
825
|
+
ownerEmail?: string;
|
|
826
|
+
/** legalName, contactEmail, address, dpoContact. */
|
|
827
|
+
controller?: Record<string, unknown>;
|
|
828
|
+
/** Branding overrides, merged onto the reseller's white-label defaults. */
|
|
829
|
+
whiteLabel?: Record<string, unknown>;
|
|
830
|
+
delegatedAccess?: boolean;
|
|
831
|
+
/** Also issue an API key for the new child; it is returned once, as `apiKey`. */
|
|
832
|
+
mintKey?: boolean;
|
|
833
|
+
/** Scopes for that key. Defaults to ["sites:read"]. */
|
|
834
|
+
keyScopes?: string[];
|
|
835
|
+
}
|
|
836
|
+
interface ResellerChildPatch {
|
|
837
|
+
status?: 'active' | 'suspended';
|
|
838
|
+
delegatedAccess?: boolean;
|
|
839
|
+
/** Pin this child's DSAR routing; null clears the override. */
|
|
840
|
+
dsarRouting?: 'reseller' | 'child' | null;
|
|
841
|
+
controller?: Record<string, unknown>;
|
|
842
|
+
}
|
|
843
|
+
interface ChildKeyInput {
|
|
844
|
+
name?: string;
|
|
845
|
+
scopes?: string[];
|
|
846
|
+
/** Lock the key to these properties of the child org. */
|
|
847
|
+
cbids?: string[];
|
|
848
|
+
}
|
|
849
|
+
interface PolicyOptions {
|
|
850
|
+
/** Contact email shown in the policy. Falls back to the org controller's, then the owner's. */
|
|
851
|
+
contactEmail?: string;
|
|
852
|
+
/** YYYY-MM-DD. Defaults to today. */
|
|
853
|
+
effectiveDate?: string;
|
|
854
|
+
/** Override the jurisdictions the policy addresses. */
|
|
855
|
+
jurisdictions?: string[];
|
|
856
|
+
}
|
|
857
|
+
interface AdPersonalizationInput {
|
|
858
|
+
enabled: boolean;
|
|
859
|
+
/** Whether personalised ads start on before the visitor chooses. */
|
|
860
|
+
default?: boolean;
|
|
861
|
+
label?: string;
|
|
862
|
+
}
|
|
863
|
+
interface SessionAnalysisInput {
|
|
864
|
+
/** A HAR export of the captured session. */
|
|
865
|
+
har?: unknown;
|
|
866
|
+
/** Or the requests directly. */
|
|
867
|
+
requests?: unknown[];
|
|
868
|
+
/** The consent state the session ran under. */
|
|
869
|
+
consent?: Record<string, boolean>;
|
|
870
|
+
/** Whether Global Privacy Control was set. */
|
|
871
|
+
gpc?: boolean;
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* How to drive one system's rights API, as data. This is what makes a connection specific to
|
|
875
|
+
* a platform — Cookie Munch names none of them, so connecting a new system is a profile
|
|
876
|
+
* rather than a release. Paths are relative to `baseUrl`; placeholders are `{email}`,
|
|
877
|
+
* `{subject}`, `{operation}`, `{correlation}` and `{id}`.
|
|
878
|
+
*/
|
|
879
|
+
interface ExecutorProfile {
|
|
880
|
+
/** How requests carry the credential. Defaults to `Authorization: Bearer {secret}`. */
|
|
881
|
+
auth?: {
|
|
882
|
+
header: string;
|
|
883
|
+
format: string;
|
|
884
|
+
};
|
|
885
|
+
/**
|
|
886
|
+
* Optional first step: turn the subject's email into the id this system uses. `noMatch`
|
|
887
|
+
* names how the system says "no record of that person" in its body — a sentinel id is
|
|
888
|
+
* never read as a person when it is set.
|
|
889
|
+
*/
|
|
890
|
+
subjectLookup?: {
|
|
891
|
+
method: 'GET' | 'POST';
|
|
892
|
+
path: string;
|
|
893
|
+
body?: unknown;
|
|
894
|
+
idPath: string;
|
|
895
|
+
noMatch?: {
|
|
896
|
+
statusPath: string;
|
|
897
|
+
values: string[];
|
|
898
|
+
};
|
|
899
|
+
};
|
|
900
|
+
/** Response header carrying the system's version, recorded in the task log. Default `X-Version`. */
|
|
901
|
+
versionHeader?: string;
|
|
902
|
+
/** How to open a request. An operation left out of `operations` is one this system does not run. */
|
|
903
|
+
open: {
|
|
904
|
+
method: 'POST' | 'PUT';
|
|
905
|
+
path: string;
|
|
906
|
+
body?: unknown;
|
|
907
|
+
operations: {
|
|
908
|
+
export?: string;
|
|
909
|
+
erase?: string;
|
|
910
|
+
};
|
|
911
|
+
idPath: string;
|
|
912
|
+
statusPath?: string;
|
|
913
|
+
};
|
|
914
|
+
/** How to ask how it is going. Polling is the truth; a webhook only prompts a check. */
|
|
915
|
+
poll: {
|
|
916
|
+
method?: 'GET';
|
|
917
|
+
path: string;
|
|
918
|
+
statusPath: string;
|
|
919
|
+
resultPath?: string;
|
|
920
|
+
/** Whether `resultPath` holds the bundle itself or a URL to fetch it from. */
|
|
921
|
+
resultIs?: 'inline' | 'url';
|
|
922
|
+
/** Where a date the work is waiting for lives (an erasure in a grace period). */
|
|
923
|
+
scheduledPath?: string;
|
|
924
|
+
};
|
|
925
|
+
/** That system's status words → the three answers a sub-task can have. */
|
|
926
|
+
statuses: {
|
|
927
|
+
running: string[];
|
|
928
|
+
done: string[];
|
|
929
|
+
failed: string[];
|
|
930
|
+
};
|
|
931
|
+
idempotencyHeader?: string;
|
|
932
|
+
/** How that system signs its webhooks, if it sends any. */
|
|
933
|
+
webhook?: {
|
|
934
|
+
algorithm: 'hmac-sha256';
|
|
935
|
+
/** Must include `{body}`, or the signature proves nothing about it. */
|
|
936
|
+
signedPayload: string;
|
|
937
|
+
headers: {
|
|
938
|
+
signature: string;
|
|
939
|
+
timestamp?: string;
|
|
940
|
+
id?: string;
|
|
941
|
+
};
|
|
942
|
+
encoding?: 'base64' | 'hex';
|
|
943
|
+
prefix?: string;
|
|
944
|
+
toleranceSeconds?: number;
|
|
945
|
+
timestampUnit?: 'seconds' | 'milliseconds' | 'auto';
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
/** A system connected to run part of a rights request. Credentials are never included. */
|
|
949
|
+
interface DsarExecutor {
|
|
950
|
+
id: string;
|
|
951
|
+
/** The name it answers to in a fulfillment plan, e.g. `identity` or `crm`. */
|
|
952
|
+
system: string;
|
|
953
|
+
profile: ExecutorProfile;
|
|
954
|
+
baseUrl: string;
|
|
955
|
+
keyPrefix: string;
|
|
956
|
+
hasWebhookSecret: boolean;
|
|
957
|
+
/** Open a sub-task automatically when a request reaches fulfilment. */
|
|
958
|
+
auto: boolean;
|
|
959
|
+
createdAt: number;
|
|
960
|
+
}
|
|
961
|
+
interface DsarExecutorInput {
|
|
962
|
+
/** The name this connection answers to in a plan, e.g. `identity` or `crm`. */
|
|
963
|
+
system: string;
|
|
964
|
+
/** The system's public https origin. */
|
|
965
|
+
baseUrl: string;
|
|
966
|
+
/** Its API key. Stored encrypted; never returned. */
|
|
967
|
+
secretKey: string;
|
|
968
|
+
/** The signing secret of its webhook endpoint. Optional — polling closes tasks without it. */
|
|
969
|
+
webhookSecret?: string;
|
|
970
|
+
auto?: boolean;
|
|
971
|
+
/** How to drive it. */
|
|
972
|
+
profile: ExecutorProfile;
|
|
973
|
+
}
|
|
974
|
+
interface DsarExecutorCreated extends DsarExecutor {
|
|
975
|
+
/** Point the connected system's webhook endpoint here. */
|
|
976
|
+
webhookUrl: string;
|
|
977
|
+
}
|
|
978
|
+
/** One entry in a fulfilment task's status history. */
|
|
979
|
+
interface DsarTaskEvent {
|
|
980
|
+
at: number;
|
|
981
|
+
kind: 'created' | 'changed' | 'version_changed';
|
|
982
|
+
status: 'pending' | 'running' | 'done' | 'failed';
|
|
983
|
+
detail?: string;
|
|
984
|
+
outcome?: DsarTaskOutcome;
|
|
985
|
+
scheduledFor?: number;
|
|
986
|
+
externalRef?: string;
|
|
987
|
+
}
|
|
988
|
+
/** What a task's answer means for the person. `exported` only once the export was fetched. */
|
|
989
|
+
type DsarTaskOutcome = 'located' | 'exported' | 'erased' | 'no_record' | 'done_without_artifact' | 'not_applicable';
|
|
990
|
+
/** One request made to a connected system on a task's behalf, credentials removed. Kept 30 days. */
|
|
991
|
+
interface DsarTaskLogEntry {
|
|
992
|
+
id?: string;
|
|
993
|
+
system?: string;
|
|
994
|
+
step: 'lookup' | 'open' | 'poll' | 'export';
|
|
995
|
+
method: string;
|
|
996
|
+
path: string;
|
|
997
|
+
/** Absent when the system never answered. */
|
|
998
|
+
status?: number;
|
|
999
|
+
latencyMs: number;
|
|
1000
|
+
requestHeaders?: Record<string, string>;
|
|
1001
|
+
/** The first ~2 KB of what was sent. */
|
|
1002
|
+
request?: string;
|
|
1003
|
+
/** The first ~2 KB of what came back. */
|
|
1004
|
+
response?: string;
|
|
1005
|
+
error?: string;
|
|
1006
|
+
/** The system's version header on this answer. */
|
|
1007
|
+
version?: string;
|
|
1008
|
+
at: number;
|
|
1009
|
+
}
|
|
1010
|
+
/** One fulfilment task with its history and its upstream request log. */
|
|
1011
|
+
interface DsarTask {
|
|
1012
|
+
id: string;
|
|
1013
|
+
requestId: string;
|
|
1014
|
+
system: string;
|
|
1015
|
+
operation: FulfillmentOp;
|
|
1016
|
+
status: 'pending' | 'running' | 'done' | 'failed';
|
|
1017
|
+
detail?: string;
|
|
1018
|
+
outcome?: DsarTaskOutcome;
|
|
1019
|
+
attempts: number;
|
|
1020
|
+
executor?: string;
|
|
1021
|
+
externalRef?: string;
|
|
1022
|
+
scheduledFor?: number;
|
|
1023
|
+
artifacts?: Array<{
|
|
1024
|
+
kind: string;
|
|
1025
|
+
system: string;
|
|
1026
|
+
ref: string;
|
|
1027
|
+
}>;
|
|
1028
|
+
createdAt: number;
|
|
1029
|
+
updatedAt: number;
|
|
1030
|
+
events: DsarTaskEvent[];
|
|
1031
|
+
log: DsarTaskLogEntry[];
|
|
1032
|
+
/** Versions the system reported while working on this task, in order of change. */
|
|
1033
|
+
upstreamVersions?: string[];
|
|
1034
|
+
/** The system was redeployed while this task was in flight. */
|
|
1035
|
+
versionChanged: boolean;
|
|
1036
|
+
}
|
|
1037
|
+
/** What testing a connection found. Nothing was filed. */
|
|
1038
|
+
interface ExecutorTestResult {
|
|
1039
|
+
system: string;
|
|
1040
|
+
/** Did the lookup find the person; null when there is no lookup step or it failed. */
|
|
1041
|
+
matched: boolean | null;
|
|
1042
|
+
subject?: string;
|
|
1043
|
+
operationWord?: string;
|
|
1044
|
+
/** The open request a real request would send, when it was not sent. */
|
|
1045
|
+
wouldSend?: {
|
|
1046
|
+
method: string;
|
|
1047
|
+
path: string;
|
|
1048
|
+
body: unknown;
|
|
1049
|
+
};
|
|
1050
|
+
/** One sentence: what a real request would have done. */
|
|
1051
|
+
verdict: string;
|
|
1052
|
+
ok: boolean;
|
|
1053
|
+
/** Every upstream answer, as the system gave it (credentials removed). */
|
|
1054
|
+
exchanges: DsarTaskLogEntry[];
|
|
1055
|
+
}
|
|
1056
|
+
interface ExecutorTestInput {
|
|
1057
|
+
email: string;
|
|
1058
|
+
/** Default `locate`. */
|
|
1059
|
+
operation?: 'locate' | 'export' | 'erase';
|
|
1060
|
+
/** For `export` only: open a real export and poll it once. An erasure is never sent. */
|
|
1061
|
+
open?: boolean;
|
|
1062
|
+
}
|
|
1063
|
+
interface DsarTaskExport {
|
|
1064
|
+
system: string;
|
|
1065
|
+
ref: string;
|
|
1066
|
+
/** The bundle as that system returned it. Not stored here. */
|
|
1067
|
+
bundle: unknown;
|
|
1068
|
+
}
|
|
1069
|
+
/** A language the banner already has copy for. */
|
|
1070
|
+
interface SupportedLanguage {
|
|
1071
|
+
/** BCP-47 tag, lowercase. Matched exactly, then by language prefix. */
|
|
1072
|
+
code: string;
|
|
1073
|
+
/** English name. */
|
|
1074
|
+
name: string;
|
|
1075
|
+
/** The language's name in itself. */
|
|
1076
|
+
endonym: string;
|
|
1077
|
+
/** Written right to left; the banner flips for these. */
|
|
1078
|
+
rtl: boolean;
|
|
1079
|
+
/** `bundled` ships in consent.js; `extended` ships in the renderer, fetched when a banner is first drawn. */
|
|
1080
|
+
source: 'bundled' | 'extended';
|
|
1081
|
+
}
|
|
1082
|
+
interface CookieMunchClient {
|
|
1083
|
+
me(): Promise<Identity>;
|
|
1084
|
+
/**
|
|
1085
|
+
* Languages the banner already speaks. Diff this against the locales your visitors
|
|
1086
|
+
* use to see which ones you still need to write copy for in `banner.i18n`.
|
|
1087
|
+
*/
|
|
1088
|
+
languages(): Promise<SupportedLanguage[]>;
|
|
1089
|
+
orgs: {
|
|
1090
|
+
/**
|
|
1091
|
+
* Every organisation on this key's account, each with its effective plan and where that
|
|
1092
|
+
* comes from, plus the per-account org cap and the upgrade URL. Needs an unscoped key that
|
|
1093
|
+
* is not locked to properties.
|
|
1094
|
+
*/
|
|
1095
|
+
list(): Promise<AccountOrgs>;
|
|
1096
|
+
/**
|
|
1097
|
+
* Create a sibling organisation owned by the same account — for a separate business of
|
|
1098
|
+
* your own. Needs an unscoped key. Not reseller provisioning, which is for your customers.
|
|
1099
|
+
*/
|
|
1100
|
+
create(name: string, opts?: {
|
|
1101
|
+
mintKey?: boolean;
|
|
1102
|
+
keyScopes?: string[];
|
|
1103
|
+
}): Promise<{
|
|
1104
|
+
org: {
|
|
1105
|
+
id: string;
|
|
1106
|
+
name: string;
|
|
1107
|
+
role: string;
|
|
1108
|
+
};
|
|
1109
|
+
apiKey?: string;
|
|
1110
|
+
keyError?: string;
|
|
1111
|
+
}>;
|
|
1112
|
+
};
|
|
1113
|
+
sites: {
|
|
1114
|
+
list(): Promise<Site[]>;
|
|
1115
|
+
create(input: SiteCreate): Promise<Site>;
|
|
1116
|
+
get(cbid: string): Promise<Site>;
|
|
1117
|
+
delete(cbid: string): Promise<void>;
|
|
1118
|
+
getConfig(cbid: string): Promise<SiteConfig>;
|
|
1119
|
+
/** Replaces the whole config — a top-level field you omit reverts to its default. */
|
|
1120
|
+
putConfig(cbid: string, config: SiteConfig): Promise<SiteConfig>;
|
|
1121
|
+
/** Changes some of the config — omitted fields keep their stored value. */
|
|
1122
|
+
patchConfig(cbid: string, config: Partial<SiteConfig>): Promise<SiteConfig>;
|
|
1123
|
+
/**
|
|
1124
|
+
* Preview a config write without saving it: the merged result and a diff. `mode: 'put'`
|
|
1125
|
+
* previews a replace (the diff then lists everything that would revert to its default).
|
|
1126
|
+
*/
|
|
1127
|
+
dryRunConfig(cbid: string, config: Partial<SiteConfig>, opts?: {
|
|
1128
|
+
mode?: 'patch' | 'put';
|
|
1129
|
+
}): Promise<ConfigDryRun>;
|
|
1130
|
+
cookies(cbid: string): Promise<CookieDeclaration>;
|
|
1131
|
+
scan(cbid: string): Promise<ScanStatus>;
|
|
1132
|
+
scanStatus(cbid: string): Promise<ScanStatus>;
|
|
1133
|
+
ab(cbid: string): Promise<AbResult[]>;
|
|
1134
|
+
/** Generate the site's privacy and cookie policy, as Markdown. */
|
|
1135
|
+
policy(cbid: string, opts?: PolicyOptions): Promise<string>;
|
|
1136
|
+
/** Turn on the personalised-ads split on whichever banner form the site uses. */
|
|
1137
|
+
setAdPersonalization(cbid: string, input: AdPersonalizationInput): Promise<unknown>;
|
|
1138
|
+
/** Analyse a captured session: trackers that fired after opt-out, personal data leaving the page. */
|
|
1139
|
+
analyzeSession(cbid: string, input: SessionAnalysisInput): Promise<unknown>;
|
|
1140
|
+
/** Which banner design this site uses, or null when none is assigned. */
|
|
1141
|
+
banner(cbid: string): Promise<{
|
|
1142
|
+
bannerId: string | null;
|
|
1143
|
+
}>;
|
|
1144
|
+
/**
|
|
1145
|
+
* Pages where the embed could not load its banner renderer — the host page's CSP or
|
|
1146
|
+
* Trusted Types policy refused it, so nobody on that page can be asked. An empty list
|
|
1147
|
+
* is the healthy answer.
|
|
1148
|
+
*/
|
|
1149
|
+
blocked(cbid: string): Promise<{
|
|
1150
|
+
reports: BlockedReport[];
|
|
1151
|
+
}>;
|
|
1152
|
+
/**
|
|
1153
|
+
* Read a cookie declaration exported from another CMP and translate its categories
|
|
1154
|
+
* into ours. Nothing is applied: their vocabulary is not ours, and a cookie in the
|
|
1155
|
+
* wrong category is a tag firing against a refusal, so the result is for review.
|
|
1156
|
+
*/
|
|
1157
|
+
importDeclaration(cbid: string, data: string): Promise<ImportedDeclaration>;
|
|
1158
|
+
snippet(cbid: string, opts?: SnippetOptions): Promise<InstallSnippet>;
|
|
1159
|
+
/**
|
|
1160
|
+
* Mint a short-lived signed token to see the banner as a visitor in a given region and
|
|
1161
|
+
* language sees it — even from a headless browser, and without recording anything.
|
|
1162
|
+
*/
|
|
1163
|
+
previewToken(cbid: string, opts?: PreviewTokenOptions): Promise<PreviewToken>;
|
|
1164
|
+
verify(cbid: string, method: 'dns' | 'meta' | 'file' | 'embed'): Promise<VerifyResult>;
|
|
1165
|
+
/** Exactly what to publish to prove control of the domain, for each verification method. */
|
|
1166
|
+
verifyChallenge(cbid: string): Promise<unknown>;
|
|
1167
|
+
/** Create up to 100 sites. Partial success: a bad or duplicate item fails only itself. */
|
|
1168
|
+
createBulk(sites: BulkSiteInput[]): Promise<{
|
|
1169
|
+
results: BulkSiteResult[];
|
|
1170
|
+
}>;
|
|
1171
|
+
brand(cbid: string): Promise<BrandExtractionResult>;
|
|
1172
|
+
/** Read a site's v2 banner flow (views, categories) plus any lint issues. */
|
|
1173
|
+
getFlow(cbid: string): Promise<SiteFlow>;
|
|
1174
|
+
/** Apply an ordered batch of structured edit ops; validated + persisted if lint-clean. */
|
|
1175
|
+
editFlow(cbid: string, operations: FlowOp[]): Promise<FlowOpResponse>;
|
|
1176
|
+
/** Wholesale-replace the flow with a full v2 config; validated + persisted if valid. */
|
|
1177
|
+
setFlow(cbid: string, config: Record<string, unknown>): Promise<FlowOpResponse>;
|
|
1178
|
+
};
|
|
1179
|
+
consent: {
|
|
1180
|
+
/**
|
|
1181
|
+
* Verify the consent log's tamper-evident hash chain. Each record carries the hash of the
|
|
1182
|
+
* one before it, so an edited, reordered or removed record answers `false`. This is the
|
|
1183
|
+
* evidence behind the log: proof that what it says today is what it said when written.
|
|
1184
|
+
*/
|
|
1185
|
+
verify(cbid: string): Promise<{
|
|
1186
|
+
valid: boolean;
|
|
1187
|
+
}>;
|
|
1188
|
+
stats(cbid: string, query?: RangeQuery): Promise<ConsentDay[]>;
|
|
1189
|
+
log(cbid: string, query?: LogQuery): Promise<ConsentLogRow[]>;
|
|
1190
|
+
export(cbid: string, query?: RangeQuery): Promise<string>;
|
|
1191
|
+
receipt(cbid: string, stamp: string): Promise<SignedReceipt>;
|
|
1192
|
+
/** Crypto-erase a subject's consent records by their consent-receipt stamp. Irreversible. */
|
|
1193
|
+
eraseSubject(cbid: string, stamp: string): Promise<{
|
|
1194
|
+
erased: number;
|
|
1195
|
+
}>;
|
|
1196
|
+
/** Export a data subject's consent records by their consent-receipt stamp (GDPR access/portability). */
|
|
1197
|
+
exportSubject(cbid: string, stamp: string): Promise<{
|
|
1198
|
+
cbid: string;
|
|
1199
|
+
stamp: string;
|
|
1200
|
+
records: unknown[];
|
|
1201
|
+
count: number;
|
|
1202
|
+
}>;
|
|
1203
|
+
/** Record a consent decision via the PUBLIC ingest endpoint (POST /api/v1/consent). No `/v1`
|
|
1204
|
+
* prefix and no auth is required by the server (the cbid must be a registered site); for
|
|
1205
|
+
* server-side / non-browser consent flows. Pass `subjectId` to correlate a subject cross-surface. */
|
|
1206
|
+
ingest(input: ConsentIngestInput): Promise<void>;
|
|
1207
|
+
};
|
|
1208
|
+
dsar: {
|
|
1209
|
+
list(): Promise<DsarRequest[]>;
|
|
1210
|
+
/**
|
|
1211
|
+
* One request, in the same shape `list` returns — note that `create` answers with it
|
|
1212
|
+
* wrapped as `{ request }`, so `create(...).request.id` is what you pass here.
|
|
1213
|
+
*/
|
|
1214
|
+
get(id: string): Promise<DsarRequest>;
|
|
1215
|
+
create(input: DsarCreate): Promise<{
|
|
1216
|
+
request: DsarRequest;
|
|
1217
|
+
}>;
|
|
1218
|
+
advance(id: string, toStatus: DsarStatus): Promise<{
|
|
1219
|
+
request: DsarRequest;
|
|
1220
|
+
}>;
|
|
1221
|
+
/** The subject-facing response notice for a request, as plain text. */
|
|
1222
|
+
response(id: string): Promise<string>;
|
|
1223
|
+
/**
|
|
1224
|
+
* Erase a subject's consent records on one site, for a deletion request past identity
|
|
1225
|
+
* verification. Noted on the request. Requires dsar:write and consent:write.
|
|
1226
|
+
*/
|
|
1227
|
+
erase(id: string, cbid: string, stamp: string): Promise<DsarEraseResult>;
|
|
1228
|
+
/**
|
|
1229
|
+
* A subject's consent records on one site, for an access or portability request past
|
|
1230
|
+
* identity verification. Noted on the request. Requires dsar:write and consent:read.
|
|
1231
|
+
*/
|
|
1232
|
+
export(id: string, cbid: string, stamp: string): Promise<DsarExportResult>;
|
|
1233
|
+
/**
|
|
1234
|
+
* Delete a TEST request (created with `test: true`), with its tasks and their log. A
|
|
1235
|
+
* real request cannot be deleted (409 `not_a_test_request`); the deletion is audited.
|
|
1236
|
+
*/
|
|
1237
|
+
delete(id: string): Promise<void>;
|
|
1238
|
+
};
|
|
1239
|
+
vendors: {
|
|
1240
|
+
list(): Promise<ScoredVendor[]>;
|
|
1241
|
+
create(input: VendorInput): Promise<{
|
|
1242
|
+
vendor: VendorRecord;
|
|
1243
|
+
risk: RiskScore;
|
|
1244
|
+
}>;
|
|
1245
|
+
};
|
|
1246
|
+
ropa: {
|
|
1247
|
+
list(): Promise<RopaEntry[]>;
|
|
1248
|
+
create(input: RopaInput): Promise<{
|
|
1249
|
+
entry: RopaEntry;
|
|
1250
|
+
}>;
|
|
1251
|
+
/** The org's RoPA (GDPR Art. 30) as CSV. */
|
|
1252
|
+
exportCsv(): Promise<string>;
|
|
1253
|
+
};
|
|
1254
|
+
brandKits: {
|
|
1255
|
+
list(): Promise<BrandKit[]>;
|
|
1256
|
+
create(input: BrandKitCreate): Promise<{
|
|
1257
|
+
kit: BrandKit;
|
|
1258
|
+
}>;
|
|
1259
|
+
delete(id: string): Promise<void>;
|
|
1260
|
+
};
|
|
1261
|
+
/**
|
|
1262
|
+
* Identity resolution. Reads are POSTs on purpose: a person's identifiers travel in the
|
|
1263
|
+
* body, never a URL where they would land in access logs.
|
|
1264
|
+
*/
|
|
1265
|
+
identity: {
|
|
1266
|
+
/** Canonical subject id for any known identifier, else null. */
|
|
1267
|
+
resolve(identifiers: Identifier[]): Promise<{
|
|
1268
|
+
subjectId: string | null;
|
|
1269
|
+
}>;
|
|
1270
|
+
/** Stitch identifiers into one subject (merging clusters when a link bridges them). */
|
|
1271
|
+
link(identifiers: Identifier[]): Promise<{
|
|
1272
|
+
subjectId: string;
|
|
1273
|
+
}>;
|
|
1274
|
+
cluster(subjectId: string): Promise<{
|
|
1275
|
+
subjectId: string;
|
|
1276
|
+
identifiers: Identifier[];
|
|
1277
|
+
}>;
|
|
1278
|
+
};
|
|
1279
|
+
/** The Permission Vault: a resolved person's current consent state. */
|
|
1280
|
+
vault: {
|
|
1281
|
+
record(identifiers: Identifier[], decisions: ConsentDecisionInput[]): Promise<{
|
|
1282
|
+
subjectId: string;
|
|
1283
|
+
permits: unknown[];
|
|
1284
|
+
}>;
|
|
1285
|
+
current(identifiers: Identifier[]): Promise<{
|
|
1286
|
+
purposes: Record<string, boolean>;
|
|
1287
|
+
}>;
|
|
1288
|
+
permits(identifiers: Identifier[]): Promise<{
|
|
1289
|
+
permits: unknown[];
|
|
1290
|
+
}>;
|
|
1291
|
+
};
|
|
1292
|
+
/** The unified profile, with consent enforced at ACTIVATION time. */
|
|
1293
|
+
profile: {
|
|
1294
|
+
get(identifiers: Identifier[]): Promise<unknown>;
|
|
1295
|
+
setAttributes(identifiers: Identifier[], attributes: Record<string, ProfileAttributeInput>): Promise<{
|
|
1296
|
+
subjectId: string;
|
|
1297
|
+
}>;
|
|
1298
|
+
/** Attribute values usable for `purpose` — {} when the person hasn't consented to it. */
|
|
1299
|
+
activate(identifiers: Identifier[], purpose: string): Promise<{
|
|
1300
|
+
attributes: Record<string, string>;
|
|
1301
|
+
}>;
|
|
1302
|
+
};
|
|
1303
|
+
/** Marketing preferences as topics x channels. */
|
|
1304
|
+
subscriptions: {
|
|
1305
|
+
/** The org's topic catalog — what a subject can subscribe TO. */
|
|
1306
|
+
topics(): Promise<{
|
|
1307
|
+
topics: SubscriptionTopicInput[];
|
|
1308
|
+
}>;
|
|
1309
|
+
/** Replace the catalog. It is authored whole, not patched. */
|
|
1310
|
+
setTopics(topics: SubscriptionTopicInput[]): Promise<{
|
|
1311
|
+
topics: SubscriptionTopicInput[];
|
|
1312
|
+
}>;
|
|
1313
|
+
get(subjectId: string): Promise<unknown>;
|
|
1314
|
+
set(subjectId: string, topic: string, channel: string, optedIn: boolean): Promise<unknown>;
|
|
1315
|
+
unsubscribeAll(subjectId: string): Promise<unknown>;
|
|
1316
|
+
resubscribe(subjectId: string): Promise<unknown>;
|
|
1317
|
+
activation(subjectId: string, topics: SubscriptionTopicInput[]): Promise<{
|
|
1318
|
+
entries: unknown[];
|
|
1319
|
+
}>;
|
|
1320
|
+
};
|
|
1321
|
+
/** DPIA / PIA / LIA / TIA / AI-impact / vendor assessments. */
|
|
1322
|
+
assessments: {
|
|
1323
|
+
templates(): Promise<{
|
|
1324
|
+
templates: unknown[];
|
|
1325
|
+
}>;
|
|
1326
|
+
list(): Promise<{
|
|
1327
|
+
assessments: unknown[];
|
|
1328
|
+
}>;
|
|
1329
|
+
start(template: string, subject: string): Promise<unknown>;
|
|
1330
|
+
/** The record plus its derived score, completeness and SME routing. */
|
|
1331
|
+
get(id: string): Promise<unknown>;
|
|
1332
|
+
answer(id: string, questionId: string, value: string | number | boolean): Promise<unknown>;
|
|
1333
|
+
/** Fill from the org's latest data map; never overwrites a human answer. */
|
|
1334
|
+
autoPopulateFromMap(id: string): Promise<{
|
|
1335
|
+
assessment: unknown;
|
|
1336
|
+
applied: string[];
|
|
1337
|
+
}>;
|
|
1338
|
+
/** Fill from evidence you supply. Never overwrites a human answer; records `source` as provenance. */
|
|
1339
|
+
autoPopulate(id: string, evidence: Record<string, unknown>, source?: string): Promise<{
|
|
1340
|
+
assessment: unknown;
|
|
1341
|
+
applied: string[];
|
|
1342
|
+
}>;
|
|
1343
|
+
submit(id: string): Promise<unknown>;
|
|
1344
|
+
approve(id: string, by: string): Promise<unknown>;
|
|
1345
|
+
reject(id: string, by: string, reason: string): Promise<unknown>;
|
|
1346
|
+
};
|
|
1347
|
+
/** The data map produced by an in-environment scan (metadata only). */
|
|
1348
|
+
discovery: {
|
|
1349
|
+
ingestMap(map: unknown): Promise<{
|
|
1350
|
+
scannedAt: number;
|
|
1351
|
+
systems: number;
|
|
1352
|
+
}>;
|
|
1353
|
+
getMap(): Promise<unknown>;
|
|
1354
|
+
ropaDrafts(): Promise<{
|
|
1355
|
+
drafts: unknown[];
|
|
1356
|
+
}>;
|
|
1357
|
+
evidence(): Promise<{
|
|
1358
|
+
evidence: Record<string, unknown>;
|
|
1359
|
+
}>;
|
|
1360
|
+
/** What changed since the last scan, and where the RoPA disagrees with reality. */
|
|
1361
|
+
drift(): Promise<{
|
|
1362
|
+
comparedTo: number | null;
|
|
1363
|
+
sinceLastScan: unknown[];
|
|
1364
|
+
againstRecord: unknown[];
|
|
1365
|
+
}>;
|
|
1366
|
+
/**
|
|
1367
|
+
* Plan warehouse-native policy from the latest map. Returns a PLAN with its own
|
|
1368
|
+
* revert — nothing is applied to your warehouse by calling this.
|
|
1369
|
+
*/
|
|
1370
|
+
planEnforcement(dialect: 'postgres' | 'mysql' | 'snowflake', rules: EnforcementRuleInput[], opts?: {
|
|
1371
|
+
permitsTable?: string;
|
|
1372
|
+
policyPrefix?: string;
|
|
1373
|
+
}): Promise<{
|
|
1374
|
+
plan: {
|
|
1375
|
+
statements: unknown[];
|
|
1376
|
+
revert: unknown[];
|
|
1377
|
+
skipped: unknown[];
|
|
1378
|
+
};
|
|
1379
|
+
}>;
|
|
1380
|
+
};
|
|
1381
|
+
/**
|
|
1382
|
+
* Regulatory intelligence: the curated privacy-law dataset. Every response carries
|
|
1383
|
+
* `reviewedAt` — the dataset ships with the product and is only as current as its
|
|
1384
|
+
* last review. Not legal advice.
|
|
1385
|
+
*/
|
|
1386
|
+
regulatory: {
|
|
1387
|
+
/** The dataset, optionally narrowed to the jurisdictions you operate in. */
|
|
1388
|
+
feed(jurisdictions?: string[]): Promise<RegulatoryFeedResult>;
|
|
1389
|
+
/** What takes effect within `days` (default 180), soonest first. */
|
|
1390
|
+
upcoming(days?: number): Promise<RegulatoryFeedResult>;
|
|
1391
|
+
};
|
|
1392
|
+
/** AI governance: policy, the inline gateway, inventory and lineage. */
|
|
1393
|
+
ai: {
|
|
1394
|
+
getPolicy(): Promise<{
|
|
1395
|
+
policy: unknown;
|
|
1396
|
+
configured: boolean;
|
|
1397
|
+
}>;
|
|
1398
|
+
setPolicy(policy: unknown): Promise<{
|
|
1399
|
+
policy: unknown;
|
|
1400
|
+
}>;
|
|
1401
|
+
/** Enforce consent + policy on a prompt or response. Requires the ai:inspect scope. */
|
|
1402
|
+
inspect(input: AiInspectInput): Promise<AiInspectResult>;
|
|
1403
|
+
inventory(): Promise<{
|
|
1404
|
+
systems: unknown[];
|
|
1405
|
+
shadow: unknown[];
|
|
1406
|
+
}>;
|
|
1407
|
+
lineage(): Promise<{
|
|
1408
|
+
lineage: Record<string, string[]>;
|
|
1409
|
+
}>;
|
|
1410
|
+
registerSystem(input: {
|
|
1411
|
+
id: string;
|
|
1412
|
+
name: string;
|
|
1413
|
+
provider?: string;
|
|
1414
|
+
purpose?: string;
|
|
1415
|
+
}): Promise<unknown>;
|
|
1416
|
+
/** The AI systems declared with registerSystem. */
|
|
1417
|
+
systems(): Promise<unknown>;
|
|
1418
|
+
audit(limit?: number): Promise<{
|
|
1419
|
+
entries: unknown[];
|
|
1420
|
+
}>;
|
|
1421
|
+
};
|
|
1422
|
+
/** DSR fulfillment: plan work per system, poll it from an in-VPC agent, report outcomes. */
|
|
1423
|
+
fulfillment: {
|
|
1424
|
+
sla(): Promise<unknown>;
|
|
1425
|
+
plan(requestId: string, systems: Array<{
|
|
1426
|
+
system: string;
|
|
1427
|
+
operation: FulfillmentOp;
|
|
1428
|
+
}>, includeHistorical?: boolean): Promise<{
|
|
1429
|
+
requestId: string;
|
|
1430
|
+
tasks: unknown[];
|
|
1431
|
+
}>;
|
|
1432
|
+
status(requestId: string): Promise<unknown>;
|
|
1433
|
+
/** In-VPC agent: poll pending tasks. */
|
|
1434
|
+
pendingTasks(limit?: number): Promise<{
|
|
1435
|
+
tasks: unknown[];
|
|
1436
|
+
}>;
|
|
1437
|
+
/** In-VPC agent: report an outcome. Only the outcome crosses the boundary. */
|
|
1438
|
+
reportTask(taskId: string, ok: boolean, error?: string): Promise<unknown>;
|
|
1439
|
+
/**
|
|
1440
|
+
* Systems you have connected that run part of a request themselves — an identity
|
|
1441
|
+
* platform holding your users' accounts, for instance. The in-VPC agent covers the
|
|
1442
|
+
* systems we cannot reach; these are the ones we can.
|
|
1443
|
+
*/
|
|
1444
|
+
executors(): Promise<DsarExecutor[]>;
|
|
1445
|
+
/**
|
|
1446
|
+
* Connect one. The secret is stored encrypted and never returned; the response carries
|
|
1447
|
+
* the URL to point that system's webhook at.
|
|
1448
|
+
*/
|
|
1449
|
+
connectExecutor(input: DsarExecutorInput): Promise<DsarExecutorCreated>;
|
|
1450
|
+
/**
|
|
1451
|
+
* Change a connection in place. Only what you send changes, and the stored credential
|
|
1452
|
+
* is kept unless you pass a new `secretKey` — so adding a field to a profile does not
|
|
1453
|
+
* cost you the connection or its id.
|
|
1454
|
+
*/
|
|
1455
|
+
updateExecutor(id: string, patch: {
|
|
1456
|
+
profile?: unknown;
|
|
1457
|
+
baseUrl?: string;
|
|
1458
|
+
secretKey?: string;
|
|
1459
|
+
webhookSecret?: string | null;
|
|
1460
|
+
auto?: boolean;
|
|
1461
|
+
}): Promise<DsarExecutor>;
|
|
1462
|
+
/** Disconnect a system; its open sub-tasks stop being driven. */
|
|
1463
|
+
disconnectExecutor(id: string): Promise<void>;
|
|
1464
|
+
/** The export bundle a connected system produced, fetched from it on demand. */
|
|
1465
|
+
taskExport(requestId: string, taskId: string): Promise<DsarTaskExport>;
|
|
1466
|
+
/**
|
|
1467
|
+
* One task: its status history (`events`), every request made to a connected system on
|
|
1468
|
+
* its behalf (`log`, redacted, 30 days) and whether that system's version changed mid-way.
|
|
1469
|
+
*/
|
|
1470
|
+
task(requestId: string, taskId: string): Promise<DsarTask>;
|
|
1471
|
+
/**
|
|
1472
|
+
* Try a connection against one email without filing anything: runs the lookup, returns
|
|
1473
|
+
* the raw (redacted) upstream answers and what a real request would have sent.
|
|
1474
|
+
*/
|
|
1475
|
+
testExecutor(id: string, input: ExecutorTestInput): Promise<ExecutorTestResult>;
|
|
1476
|
+
};
|
|
1477
|
+
preferences: {
|
|
1478
|
+
list(): Promise<PreferenceItem[]>;
|
|
1479
|
+
/** Save/update a subject's named-purpose opt-ins. Returns the persisted record. */
|
|
1480
|
+
save(subjectId: string, purposes: Record<string, boolean>): Promise<{
|
|
1481
|
+
record: PreferenceRecord;
|
|
1482
|
+
}>;
|
|
1483
|
+
/** One subject's record. A subject with none has empty `purposes`. */
|
|
1484
|
+
get(subjectId: string): Promise<PreferenceRecord>;
|
|
1485
|
+
};
|
|
1486
|
+
members: {
|
|
1487
|
+
list(): Promise<Member[]>;
|
|
1488
|
+
invite(email: string, role: string): Promise<{
|
|
1489
|
+
member: {
|
|
1490
|
+
userId: string;
|
|
1491
|
+
email: string;
|
|
1492
|
+
role: string;
|
|
1493
|
+
};
|
|
1494
|
+
}>;
|
|
1495
|
+
setRole(userId: string, role: string): Promise<{
|
|
1496
|
+
member: {
|
|
1497
|
+
userId: string;
|
|
1498
|
+
email: string;
|
|
1499
|
+
role: string;
|
|
1500
|
+
};
|
|
1501
|
+
}>;
|
|
1502
|
+
remove(userId: string): Promise<{
|
|
1503
|
+
ok: true;
|
|
1504
|
+
}>;
|
|
1505
|
+
};
|
|
1506
|
+
keys: {
|
|
1507
|
+
list(): Promise<ApiKeyPrefix[]>;
|
|
1508
|
+
/**
|
|
1509
|
+
* Issue a new API key; the secret is returned once. Pass `scopes` and/or `cbids` for a
|
|
1510
|
+
* least-privilege key — omit both for full access to the whole org.
|
|
1511
|
+
*/
|
|
1512
|
+
issue(input?: ApiKeyIssueInput): Promise<ApiKeyIssued>;
|
|
1513
|
+
/** Revoke a key by its prefix. Immediate. */
|
|
1514
|
+
revoke(prefix: string): Promise<void>;
|
|
1515
|
+
/** Rotate a key: a new secret, returned once, with the same scopes, lock and expiry. The old one stops working. */
|
|
1516
|
+
roll(prefix: string): Promise<ApiKeyIssued>;
|
|
1517
|
+
/** Rename a key, or replace its scopes or property lock. Only the fields sent change. */
|
|
1518
|
+
update(prefix: string, patch: ApiKeyUpdate): Promise<{
|
|
1519
|
+
ok: true;
|
|
1520
|
+
}>;
|
|
1521
|
+
};
|
|
1522
|
+
usage(): Promise<Usage>;
|
|
1523
|
+
/** The key's organisation. Requires an unscoped key that is not property-locked. */
|
|
1524
|
+
org: {
|
|
1525
|
+
get(): Promise<Org>;
|
|
1526
|
+
/** Rename the org or set its logo. Deleting the org is not available through the API. */
|
|
1527
|
+
update(patch: OrgUpdate): Promise<Org>;
|
|
1528
|
+
};
|
|
1529
|
+
/** The org's audit log, newest first. API actions appear as `apikey:<prefix>`. */
|
|
1530
|
+
audit(limit?: number): Promise<{
|
|
1531
|
+
entries: AuditEntry[];
|
|
1532
|
+
}>;
|
|
1533
|
+
assets: {
|
|
1534
|
+
/** Upload a banner image (≤ 1,000,000 bytes) and get its public URL. Requires sites:write. */
|
|
1535
|
+
upload(input: AssetUpload): Promise<{
|
|
1536
|
+
url: string;
|
|
1537
|
+
}>;
|
|
1538
|
+
/**
|
|
1539
|
+
* Delete a stored image. Takes the URL `upload` returned, or just its file name. Only
|
|
1540
|
+
* your own org's images are reachable — the folder comes from your API key.
|
|
1541
|
+
*/
|
|
1542
|
+
delete(urlOrFileName: string): Promise<void>;
|
|
1543
|
+
};
|
|
1544
|
+
/** Provision and manage child orgs. Requires a key with the reseller:* scopes. */
|
|
1545
|
+
reseller: {
|
|
1546
|
+
list(): Promise<ResellerChildList>;
|
|
1547
|
+
/** Provision a child org. With `mintKey`, its first API key is returned once, as `apiKey`. */
|
|
1548
|
+
create(input: ResellerChildCreate): Promise<{
|
|
1549
|
+
child: ResellerChild;
|
|
1550
|
+
apiKey?: string;
|
|
1551
|
+
}>;
|
|
1552
|
+
get(id: string): Promise<unknown>;
|
|
1553
|
+
update(id: string, patch: ResellerChildPatch): Promise<unknown>;
|
|
1554
|
+
/**
|
|
1555
|
+
* Deprovision a child. Suspends it by default, which is reversible; `{ purge: true }`
|
|
1556
|
+
* hard-deletes it and its data, which is not.
|
|
1557
|
+
*/
|
|
1558
|
+
deprovision(id: string, opts?: {
|
|
1559
|
+
purge?: boolean;
|
|
1560
|
+
}): Promise<void>;
|
|
1561
|
+
listKeys(id: string): Promise<ApiKeyPrefix[]>;
|
|
1562
|
+
/** Mint an API key for a child. The secret is returned once. */
|
|
1563
|
+
mintKey(id: string, input?: ChildKeyInput): Promise<ApiKeyIssued>;
|
|
1564
|
+
revokeKey(id: string, prefix: string): Promise<void>;
|
|
1565
|
+
};
|
|
1566
|
+
webhooks: {
|
|
1567
|
+
list(): Promise<WebhookSubscription[]>;
|
|
1568
|
+
create(input: WebhookCreate): Promise<WebhookSubscription>;
|
|
1569
|
+
/** Change or pause a subscription. `{ active: false }` pauses without deleting it. */
|
|
1570
|
+
update(id: string, patch: WebhookUpdate): Promise<WebhookSubscription>;
|
|
1571
|
+
delete(id: string): Promise<void>;
|
|
1572
|
+
/** Rotate the signing secret. The new secret is returned once. */
|
|
1573
|
+
rollSecret(id: string): Promise<{
|
|
1574
|
+
secret: string;
|
|
1575
|
+
}>;
|
|
1576
|
+
/** Send a signed test event now and report what the endpoint answered. */
|
|
1577
|
+
test(id: string): Promise<WebhookTestResult>;
|
|
1578
|
+
/** Deliveries that failed every retry, newest first. */
|
|
1579
|
+
deadLetters(): Promise<{
|
|
1580
|
+
deadLetters: WebhookDeadLetter[];
|
|
1581
|
+
}>;
|
|
1582
|
+
/** Deliver a dead letter again, to the subscription as it is now. */
|
|
1583
|
+
replayDeadLetter(id: string): Promise<unknown>;
|
|
1584
|
+
};
|
|
1585
|
+
/** One person's consent across every site in the org, by the subjectId your apps attach. */
|
|
1586
|
+
subjects: {
|
|
1587
|
+
/** Requires consent:read; not available to property-locked keys. */
|
|
1588
|
+
consent(subjectId: string): Promise<{
|
|
1589
|
+
subjectId: string;
|
|
1590
|
+
records: unknown[];
|
|
1591
|
+
count: number;
|
|
1592
|
+
sites: string[];
|
|
1593
|
+
}>;
|
|
1594
|
+
};
|
|
1595
|
+
banners: {
|
|
1596
|
+
list(): Promise<BannerSummary[]>;
|
|
1597
|
+
create(input: {
|
|
1598
|
+
name: string;
|
|
1599
|
+
json: SiteConfig;
|
|
1600
|
+
}): Promise<BannerRecord>;
|
|
1601
|
+
get(id: string): Promise<BannerRecord>;
|
|
1602
|
+
update(id: string, patch: {
|
|
1603
|
+
name?: string;
|
|
1604
|
+
json?: SiteConfig;
|
|
1605
|
+
}): Promise<BannerRecord>;
|
|
1606
|
+
delete(id: string): Promise<void>;
|
|
1607
|
+
assignments(id: string): Promise<{
|
|
1608
|
+
cbids: string[];
|
|
1609
|
+
}>;
|
|
1610
|
+
setAssignments(id: string, cbids: string[]): Promise<{
|
|
1611
|
+
cbids: string[];
|
|
1612
|
+
}>;
|
|
1613
|
+
publish(id: string): Promise<{
|
|
1614
|
+
publishedCbids: string[];
|
|
1615
|
+
}>;
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
declare function createCookieMunch(opts: CookieMunchOptions): CookieMunchClient;
|
|
1619
|
+
|
|
1620
|
+
export { type AbResult, type AccountOrg, type AccountOrgs, type AdPersonalizationInput, type AiInspectInput, type AiInspectResult, type ApiKey, type ApiKeyIssueInput, type ApiKeyIssued, type ApiKeyPrefix, type ApiKeyUpdate, 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 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 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 };
|