@cookiemunch/sdk 0.5.0 → 0.6.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.js CHANGED
@@ -1,10 +1,14 @@
1
1
  import {
2
2
  CONSENT_COOKIE_NAME,
3
+ DEFAULT_JWKS_URL,
4
+ consentSignaturePayload,
3
5
  getConsent,
4
6
  isAllowed,
5
7
  parseConsentValue,
6
- readConsent
7
- } from "./chunk-G7ORTXTK.js";
8
+ readConsent,
9
+ verifyDecisionSignature,
10
+ verifyToken
11
+ } from "./chunk-OSVTQPQG.js";
8
12
 
9
13
  // src/webhooks.ts
10
14
  import { createHmac, timingSafeEqual } from "crypto";
@@ -41,8 +45,183 @@ function mintConsentSyncToken(input) {
41
45
  return `cms1.${payload}.${sig}`;
42
46
  }
43
47
 
48
+ // src/executor-conformance.ts
49
+ var CANARY_ISSUER = "https://canary.cookiemunch.net";
50
+ var CANARY_EMAIL_RE = /^canary-([0-9a-f]{16})@canary\.cookiemunch\.net$/;
51
+ function canaryIdentityFor(canaryEmail) {
52
+ const m = CANARY_EMAIL_RE.exec(canaryEmail.trim().toLowerCase());
53
+ if (!m) throw new Error("canaryEmail must be the canary address canary-<16 hex>@canary.cookiemunch.net");
54
+ return { iss: CANARY_ISSUER, sub: `canary_${m[1]}`, ext: `canary:${m[1]}` };
55
+ }
56
+ var CONFORMANCE_RULES = [
57
+ { id: "auth.required", title: "A request without the credential is refused (401 or 403)." },
58
+ { id: "lookup.email.found", title: "The canary subject is found by its email." },
59
+ { id: "lookup.identity.found", title: "The canary subject is found by its identity alone (iss + sub), and it is the same subject." },
60
+ { id: "lookup.unknown.no_match", title: 'An address nobody has answers { subjectId: null, status: "no_match" }.' },
61
+ { id: "lookup.identity_beats_email", title: "An identity that matches no one is never matched through the email of someone else." },
62
+ { id: "requests.bad_body.400", title: "A request with an unknown type answers 400 { error, field }." },
63
+ { id: "requests.alias.canonical_type", title: 'An alias (erasure) is accepted and answered with canonicalType "deletion".' },
64
+ { id: "requests.execute_after.scheduled", title: 'A deletion with a future executeAfter is "scheduled" with eta equal to executeAfter \u2014 nothing is deleted before it.' },
65
+ { id: "requests.idempotency.replay", title: "The same Idempotency-Key with the same body returns the same request, not a second one." },
66
+ { id: "requests.idempotency.mismatch_409", title: "The same Idempotency-Key with a different body answers 409." },
67
+ { id: "requests.get", title: "GET /privacy/requests/{id} returns the request, still scheduled." },
68
+ { id: "requests.unknown.404", title: "An unknown request id answers 404." },
69
+ { id: "requests.cancel.before_execute_after", title: 'A cancel before executeAfter answers status "cancelled".' },
70
+ { id: "requests.cancel.keeps_data", title: "After a cancel the subject is still there: a lookup finds it." },
71
+ { id: "version.header", title: "Answers carry X-Version (the highest contract version the executor supports)." }
72
+ ];
73
+ function randomTag() {
74
+ const bytes = new Uint8Array(8);
75
+ const c = globalThis.crypto;
76
+ if (c?.getRandomValues) c.getRandomValues(bytes);
77
+ else for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
78
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
79
+ }
80
+ function field(json, key) {
81
+ return json && typeof json === "object" ? json[key] : void 0;
82
+ }
83
+ async function runExecutorConformance(o) {
84
+ const doFetch = o.fetch ?? fetch;
85
+ const now = o.now ?? (() => Date.now());
86
+ const base = o.baseUrl.replace(/\/+$/, "") + (o.prefix ?? "/privacy");
87
+ let url;
88
+ try {
89
+ url = new URL(base);
90
+ } catch {
91
+ throw new Error("baseUrl must be an absolute URL");
92
+ }
93
+ if (url.protocol !== "https:" && !(url.protocol === "http:" && /^(localhost|127\.0\.0\.1|\[::1\])$/.test(url.hostname))) {
94
+ throw new Error("baseUrl must be https (http only for localhost)");
95
+ }
96
+ const identity = canaryIdentityFor(o.canaryEmail);
97
+ const canaryEmail = o.canaryEmail.trim().toLowerCase();
98
+ const auth = o.auth ?? { header: "Authorization", format: "Bearer {secret}" };
99
+ const run = o.runId ?? randomTag();
100
+ const results = /* @__PURE__ */ new Map();
101
+ let version;
102
+ const set = (id, status, detail) => {
103
+ const rule = CONFORMANCE_RULES.find((r) => r.id === id);
104
+ results.set(id, { id, title: rule.title, status, ...detail ? { detail } : {} });
105
+ };
106
+ const pass = (id) => set(id, "pass");
107
+ const fail = (id, detail) => set(id, "fail", detail);
108
+ const skip = (id, detail) => set(id, "skip", detail);
109
+ async function call(method, path, body, extra = {}, withAuth = true) {
110
+ const headers = {
111
+ accept: "application/json",
112
+ "X-Version": "2",
113
+ ...withAuth ? { [auth.header]: auth.format.replace("{secret}", o.secret) } : {},
114
+ ...body !== void 0 ? { "content-type": "application/json" } : {},
115
+ ...extra
116
+ };
117
+ try {
118
+ const res = await doFetch(base + path, { method, headers, ...body !== void 0 ? { body: JSON.stringify(body) } : {} });
119
+ const text = await res.text().catch(() => "");
120
+ let json;
121
+ try {
122
+ json = text ? JSON.parse(text) : void 0;
123
+ } catch {
124
+ json = void 0;
125
+ }
126
+ const v = res.headers.get("x-version");
127
+ if (v && !version) version = v;
128
+ return { status: res.status, json, version: v };
129
+ } catch (err) {
130
+ return { status: 0, json: void 0, version: null, error: err instanceof Error ? err.message : String(err) };
131
+ }
132
+ }
133
+ const said = (a) => a.status === 0 ? `unreachable: ${a.error}` : `HTTP ${a.status} ${JSON.stringify(a.json ?? null).slice(0, 200)}`;
134
+ const key = (rule) => `conformance:${run}:${rule}`;
135
+ const anon = await call("POST", "/lookup", { emails: [canaryEmail] }, {}, false);
136
+ if (anon.status === 0) {
137
+ for (const r of CONFORMANCE_RULES) skip(r.id, said(anon));
138
+ fail("auth.required", said(anon));
139
+ return report();
140
+ }
141
+ if (anon.status === 401 || anon.status === 403) pass("auth.required");
142
+ else fail("auth.required", `without a credential: ${said(anon)}`);
143
+ const byEmail = await call("POST", "/lookup", { emails: [canaryEmail] }, { "Idempotency-Key": key("lookup-email") });
144
+ const subjectId = field(byEmail.json, "subjectId");
145
+ if (byEmail.status === 200 && field(byEmail.json, "status") === "found" && typeof subjectId === "string" && subjectId) pass("lookup.email.found");
146
+ else fail("lookup.email.found", `the canary address: ${said(byEmail)}`);
147
+ const byIdentity = await call("POST", "/lookup", { emails: [], identity, atlas: identity }, { "Idempotency-Key": key("lookup-identity") });
148
+ if (byIdentity.status === 200 && field(byIdentity.json, "status") === "found" && field(byIdentity.json, "subjectId") === subjectId && typeof subjectId === "string") {
149
+ pass("lookup.identity.found");
150
+ } else {
151
+ fail("lookup.identity.found", `the canary identity ${identity.sub}: ${said(byIdentity)}${typeof subjectId === "string" ? ` (by email it was ${subjectId})` : ""}`);
152
+ }
153
+ const nobody = await call("POST", "/lookup", { emails: [`nobody-${run}@canary.cookiemunch.net`] }, { "Idempotency-Key": key("lookup-nobody") });
154
+ if (nobody.status === 200 && field(nobody.json, "status") === "no_match" && field(nobody.json, "subjectId") === null) pass("lookup.unknown.no_match");
155
+ else fail("lookup.unknown.no_match", said(nobody));
156
+ const stranger = { iss: identity.iss, sub: `canary_other_${run}` };
157
+ const crossed = await call("POST", "/lookup", { emails: [canaryEmail], identity: stranger, atlas: stranger }, { "Idempotency-Key": key("lookup-crossed") });
158
+ if (crossed.status === 200 && field(crossed.json, "status") === "no_match") pass("lookup.identity_beats_email");
159
+ else {
160
+ fail(
161
+ "lookup.identity_beats_email",
162
+ `an identity nobody has (${stranger.sub}) with the canary's email: ${said(crossed)} \u2014 the email belongs to a different identity, so this must be no_match`
163
+ );
164
+ }
165
+ const bad = await call("POST", "/requests", { subjectId: subjectId ?? "x", type: "teleport", caseId: `conformance-${run}` }, { "Idempotency-Key": key("bad-body") });
166
+ if (bad.status === 400 && typeof field(bad.json, "error") === "string" && typeof field(bad.json, "field") === "string") pass("requests.bad_body.400");
167
+ else fail("requests.bad_body.400", said(bad));
168
+ if (typeof subjectId !== "string") {
169
+ for (const id of ["requests.alias.canonical_type", "requests.execute_after.scheduled", "requests.idempotency.replay", "requests.idempotency.mismatch_409", "requests.get", "requests.cancel.before_execute_after", "requests.cancel.keeps_data"]) {
170
+ skip(id, "needs the canary subject, which the lookup did not find");
171
+ }
172
+ } else {
173
+ const executeAfter = new Date(Math.ceil((now() + 36e5) / 1e3) * 1e3).toISOString();
174
+ const body = { subjectId, type: "erasure", executeAfter, caseId: `conformance-${run}`, reason: "Cookie Munch conformance check (canary subject)" };
175
+ const opened = await call("POST", "/requests", body, { "Idempotency-Key": key("open") });
176
+ const id = field(opened.json, "id");
177
+ const st = field(opened.json, "status");
178
+ if ((opened.status === 200 || opened.status === 201) && field(opened.json, "canonicalType") === "deletion") pass("requests.alias.canonical_type");
179
+ else fail("requests.alias.canonical_type", `type "erasure": ${said(opened)}`);
180
+ const eta = field(opened.json, "eta");
181
+ if ((opened.status === 200 || opened.status === 201) && st === "scheduled" && typeof eta === "string" && Date.parse(eta) === Date.parse(executeAfter)) {
182
+ pass("requests.execute_after.scheduled");
183
+ } else if (st === "completed" || st === "completed_with_retention" || st === "processing") {
184
+ fail("requests.execute_after.scheduled", `executeAfter is ${executeAfter}, an hour away, and the executor answered "${String(st)}": it acted before executeAfter`);
185
+ } else {
186
+ fail("requests.execute_after.scheduled", `expected status "scheduled" with eta ${executeAfter}: ${said(opened)}`);
187
+ }
188
+ const replay = await call("POST", "/requests", body, { "Idempotency-Key": key("open") });
189
+ if (typeof id === "string" && (replay.status === 200 || replay.status === 201) && field(replay.json, "id") === id) pass("requests.idempotency.replay");
190
+ else fail("requests.idempotency.replay", `a retry with the same key: ${said(replay)}${typeof id === "string" ? ` (first answer id ${id})` : ""}`);
191
+ const mismatch = await call("POST", "/requests", { ...body, reason: "a different body" }, { "Idempotency-Key": key("open") });
192
+ if (mismatch.status === 409) pass("requests.idempotency.mismatch_409");
193
+ else fail("requests.idempotency.mismatch_409", `the same key with a different body: ${said(mismatch)}`);
194
+ if (typeof id !== "string") {
195
+ skip("requests.get", "no request id came back");
196
+ skip("requests.cancel.before_execute_after", "no request id came back");
197
+ skip("requests.cancel.keeps_data", "no request id came back");
198
+ } else {
199
+ const got = await call("GET", `/requests/${encodeURIComponent(id)}`, void 0, { "Idempotency-Key": key("get") });
200
+ if (got.status === 200 && field(got.json, "id") === id && field(got.json, "status") === "scheduled") pass("requests.get");
201
+ else fail("requests.get", said(got));
202
+ const cancelled = await call("POST", `/requests/${encodeURIComponent(id)}/cancel`, {}, { "Idempotency-Key": key("cancel") });
203
+ if (cancelled.status === 200 && field(cancelled.json, "status") === "cancelled") pass("requests.cancel.before_execute_after");
204
+ else fail("requests.cancel.before_execute_after", said(cancelled));
205
+ const after = await call("POST", "/lookup", { emails: [canaryEmail] }, { "Idempotency-Key": key("lookup-after-cancel") });
206
+ if (after.status === 200 && field(after.json, "status") === "found") pass("requests.cancel.keeps_data");
207
+ else fail("requests.cancel.keeps_data", `a lookup after the cancel: ${said(after)} \u2014 a cancel before executeAfter must leave the data intact`);
208
+ }
209
+ }
210
+ const unknown = await call("GET", `/requests/conformance-missing-${run}`, void 0, { "Idempotency-Key": key("unknown") });
211
+ if (unknown.status === 404) pass("requests.unknown.404");
212
+ else fail("requests.unknown.404", said(unknown));
213
+ if (version) pass("version.header");
214
+ else fail("version.header", "no answer carried an X-Version header");
215
+ return report();
216
+ function report() {
217
+ const rules = CONFORMANCE_RULES.map((r) => results.get(r.id) ?? { id: r.id, title: r.title, status: "skip", detail: "not reached" });
218
+ const count = (s) => rules.filter((r) => r.status === s).length;
219
+ return { ok: count("fail") === 0, passed: count("pass"), failed: count("fail"), skipped: count("skip"), rules, ...version ? { version } : {} };
220
+ }
221
+ }
222
+
44
223
  // src/index.ts
45
- var SDK_VERSION = "0.5.0";
224
+ var SDK_VERSION = "0.6.0";
46
225
  var CookieMunchApiError = class extends Error {
47
226
  constructor(status, message, code, body) {
48
227
  super(message);
@@ -53,6 +232,10 @@ var CookieMunchApiError = class extends Error {
53
232
  }
54
233
  };
55
234
  var withBase = (doc, opts) => opts?.baseUpdatedAt !== void 0 ? { ...doc, baseUpdatedAt: opts.baseUpdatedAt } : doc;
235
+ function metaQs(o) {
236
+ const parts = Object.entries(o?.metadata ?? {}).map(([k, v]) => `metadata%5B${encodeURIComponent(k)}%5D=${encodeURIComponent(v)}`);
237
+ return parts.length ? `?${parts.join("&")}` : "";
238
+ }
56
239
  function qs(query) {
57
240
  if (!query) return "";
58
241
  const parts = [];
@@ -68,9 +251,11 @@ function createCookieMunch(opts) {
68
251
  const base = `${opts.baseUrl.replace(/\/+$/, "")}/v1`;
69
252
  const doFetch = opts.fetch ?? globalThis.fetch;
70
253
  if (!doFetch) throw new Error("No fetch available; pass { fetch } in CookieMunchOptions.");
71
- async function request(method, path, body, raw = false) {
72
- const headers = { Authorization: `Bearer ${opts.apiKey}`, "User-Agent": opts.userAgent ?? `cookiemunch-js/${SDK_VERSION}` };
254
+ async function request(method, path, body, raw = false, extraHeaders = {}) {
255
+ const headers = { Authorization: `Bearer ${opts.apiKey}`, "User-Agent": opts.userAgent ?? `cookiemunch-js/${SDK_VERSION}`, ...extraHeaders };
73
256
  if (opts.strictUnknownFields && method !== "GET") headers["Prefer"] = "strict-unknown-fields";
257
+ if (opts.secretRecipient && method !== "GET") headers["X-Secret-Recipient"] = opts.secretRecipient;
258
+ for (const [k, v] of Object.entries(opts.headers ?? {})) headers[k] = v;
74
259
  const init = { method, headers };
75
260
  if (body !== void 0) {
76
261
  headers["Content-Type"] = "application/json";
@@ -96,22 +281,49 @@ function createCookieMunch(opts) {
96
281
  return contentType.includes("application/json") ? res.json() : res.text();
97
282
  }
98
283
  const get = (p) => request("GET", p);
284
+ async function requestBytes(path) {
285
+ const res = await doFetch(`${base}${path}`, { method: "GET", headers: { Authorization: `Bearer ${opts.apiKey}`, "User-Agent": opts.userAgent ?? `cookiemunch-js/${SDK_VERSION}` } });
286
+ if (!res.ok) {
287
+ let message = `request failed with status ${res.status}`;
288
+ let code;
289
+ try {
290
+ const data = await res.json();
291
+ if (typeof data.error === "string") message = data.error;
292
+ if (typeof data.code === "string") code = data.code;
293
+ } catch {
294
+ }
295
+ throw new CookieMunchApiError(res.status, message, code);
296
+ }
297
+ return res.arrayBuffer();
298
+ }
99
299
  const enc = encodeURIComponent;
100
300
  return {
101
301
  me: () => get("/me"),
102
302
  languages: () => get("/languages"),
103
303
  orgs: {
104
- list: () => get("/orgs"),
105
- create: (name, opts2) => request("POST", "/orgs", { name, ...opts2 ?? {} })
304
+ list: (o) => get(`/orgs${metaQs(o)}`),
305
+ create: (name, opts2) => request("POST", "/orgs", { name, ...opts2 ?? {} }),
306
+ deleteSandbox: (id) => request("DELETE", `/orgs/${enc(id)}?hard=1`)
307
+ },
308
+ metadata: {
309
+ get: (type, id) => get(`/metadata/${enc(type)}/${enc(id)}`),
310
+ update: (type, id, metadata, o) => request("PATCH", `/metadata/${enc(type)}/${enc(id)}${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, { metadata })
106
311
  },
312
+ partnerLinks: {
313
+ list: (o) => get(`/partner_links${metaQs(o)}`),
314
+ create: (input) => request("POST", "/partner_links", input),
315
+ revoke: (id) => request("DELETE", `/partner_links/${enc(id)}`)
316
+ },
317
+ provisionEnv: (ref) => get(`/provision/env${qs({ ref })}`),
107
318
  sites: {
108
- list: () => get("/sites"),
319
+ list: (o) => get(`/sites${metaQs(o)}`),
109
320
  create: (input) => request("POST", "/sites", input),
110
321
  get: (cbid) => get(`/sites/${enc(cbid)}`),
111
322
  update: (cbid, patch, o) => request("PATCH", `/sites/${enc(cbid)}${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, patch),
112
323
  delete: async (cbid) => {
113
324
  await request("DELETE", `/sites/${enc(cbid)}`);
114
325
  },
326
+ deleteSandbox: (cbid) => request("DELETE", `/sites/${enc(cbid)}?hard=1`),
115
327
  listPartners: (cbid) => get(`/sites/${enc(cbid)}/partners`),
116
328
  linkPartner: (cbid, input, o) => request("POST", `/sites/${enc(cbid)}/partners${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, input),
117
329
  unlinkPartner: (cbid, linkId) => request("DELETE", `/sites/${enc(cbid)}/partners/${enc(linkId)}`),
@@ -134,7 +346,7 @@ function createCookieMunch(opts) {
134
346
  const asked = Math.max(0, Math.min(6e4, left));
135
347
  const t0 = Date.now();
136
348
  const s = await get(`/sites/${enc(cbid)}/scan${qs({ wait: asked / 1e3 })}`);
137
- if (s.status !== "scanning" || until - Date.now() <= 0) return s;
349
+ if (s.status !== "scanning" || until - Date.now() < 50) return s;
138
350
  const early = Math.min(1e3, until - Date.now()) - (Date.now() - t0);
139
351
  if (early > 0) await new Promise((r) => setTimeout(r, early));
140
352
  }
@@ -160,6 +372,9 @@ function createCookieMunch(opts) {
160
372
  }),
161
373
  cookiePresets: (cbid) => get(`/sites/${enc(cbid)}/cookies/presets`),
162
374
  applyCookiePreset: (cbid, vendor, params, o) => request("PUT", `/sites/${enc(cbid)}/cookies/presets/${enc(vendor)}${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, params ?? {}),
375
+ importCookieManifest: (cbid, input, o) => request("PUT", `/sites/${enc(cbid)}/cookies/presets/custom${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, input),
376
+ cookieSuggestions: (cbid) => get(`/sites/${enc(cbid)}/cookies/suggestions`),
377
+ declareCookieSuggestions: (cbid, input, o) => request("POST", `/sites/${enc(cbid)}/cookies/suggestions/declare${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, input ?? {}),
163
378
  removeCookiePreset: (cbid, vendor, o) => request("DELETE", `/sites/${enc(cbid)}/cookies/presets/${enc(vendor)}${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`),
164
379
  deleteObservedCookie: (async (cbid, name, o) => {
165
380
  const out = await request("DELETE", `/sites/${enc(cbid)}/observed-cookies/${enc(name)}${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`);
@@ -177,6 +392,8 @@ function createCookieMunch(opts) {
177
392
  verifyChallenge: (cbid) => get(`/sites/${enc(cbid)}/verify/challenge`),
178
393
  createBulk: (sites) => request("POST", "/sites/bulk", { sites }),
179
394
  brand: (cbid) => request("POST", `/sites/${enc(cbid)}/brand`, {}),
395
+ getBrand: (cbid) => get(`/sites/${enc(cbid)}/brand`),
396
+ setBrand: (cbid, input, o) => request("PUT", `/sites/${enc(cbid)}/brand${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, input),
180
397
  getFlow: (cbid) => get(`/sites/${enc(cbid)}/flow`),
181
398
  editFlow: (cbid, operations) => request("POST", `/sites/${enc(cbid)}/flow/ops`, { operations }),
182
399
  setFlow: (cbid, config) => request("PUT", `/sites/${enc(cbid)}/flow`, config)
@@ -184,11 +401,13 @@ function createCookieMunch(opts) {
184
401
  consent: {
185
402
  verify: (cbid) => get(`/sites/${enc(cbid)}/consent/verify`),
186
403
  stats: (cbid, query) => get(`/sites/${enc(cbid)}/consent/stats${qs(toQuery(query))}`),
404
+ insights: (cbid, query) => get(`/sites/${enc(cbid)}/consent/insights${qs(toQuery(query))}`),
187
405
  log: (cbid, query) => get(`/sites/${enc(cbid)}/consent/log${qs(toQuery(query))}`),
188
406
  export: (cbid, query) => request("GET", `/sites/${enc(cbid)}/consent/export${qs(toQuery(query))}`, void 0, true),
189
407
  receipt: (cbid, stamp) => get(`/sites/${enc(cbid)}/receipt/${enc(stamp)}`),
190
408
  eraseSubject: (cbid, stamp) => request("POST", `/sites/${enc(cbid)}/erase-consent`, { stamp }),
191
409
  exportSubject: (cbid, stamp) => request("GET", `/sites/${enc(cbid)}/subject-export?stamp=${enc(stamp)}`),
410
+ categoryRegistry: () => get("/categories/registry"),
192
411
  ingest: async (input) => {
193
412
  const res = await doFetch(`${opts.baseUrl.replace(/\/+$/, "")}/api/v1/consent`, {
194
413
  method: "POST",
@@ -219,7 +438,16 @@ function createCookieMunch(opts) {
219
438
  delete: async (id) => {
220
439
  await request("DELETE", `/dsar/${enc(id)}`);
221
440
  },
222
- markTest: (id) => request("POST", `/dsar/${enc(id)}/mark-test`)
441
+ markTest: (id) => request("POST", `/dsar/${enc(id)}/mark-test`),
442
+ listByTrace: (trace) => get(`/dsar${qs({ trace })}`),
443
+ openCase: (input, o) => request("POST", "/dsar/requests", input, false, {
444
+ ...o?.idempotencyKey ? { "Idempotency-Key": o.idempotencyKey } : {},
445
+ ...o?.trace ? { "X-ForgeDeck-Trace": o.trace } : {}
446
+ }),
447
+ getCase: (id) => get(`/dsar/requests/${enc(id)}`),
448
+ cancelCase: (id) => request("POST", `/dsar/requests/${enc(id)}/cancel`),
449
+ caseReceipt: (id) => get(`/dsar/requests/${enc(id)}/receipt`),
450
+ caseReceiptPdf: (id) => requestBytes(`/dsar/requests/${enc(id)}/receipt?format=pdf`)
223
451
  },
224
452
  vendors: {
225
453
  list: () => get("/vendors"),
@@ -322,7 +550,8 @@ function createCookieMunch(opts) {
322
550
  status: (requestId) => get(`/dsar/${enc(requestId)}/fulfillment`),
323
551
  pendingTasks: (limit) => get(`/dsar/agent/tasks${qs({ limit })}`),
324
552
  reportTask: (taskId, ok, error) => request("POST", `/dsar/agent/tasks/${enc(taskId)}/result`, { ok, ...error !== void 0 ? { error } : {} }),
325
- executors: () => get("/dsar/executors"),
553
+ executors: (o) => get(`/dsar/executors${metaQs(o)}`),
554
+ executor: (id) => get(`/dsar/executors/${enc(id)}`),
326
555
  connectExecutor: (input) => request("POST", "/dsar/executors", input),
327
556
  updateExecutor: (id, patch) => request("PATCH", `/dsar/executors/${enc(id)}`, patch),
328
557
  dryRunConnectExecutor: (input) => request("POST", "/dsar/executors?dryRun=1", input),
@@ -337,7 +566,11 @@ function createCookieMunch(opts) {
337
566
  },
338
567
  taskExport: (requestId, taskId) => get(`/dsar/${enc(requestId)}/tasks/${enc(taskId)}/export`),
339
568
  task: (requestId, taskId) => get(`/dsar/${enc(requestId)}/tasks/${enc(taskId)}`),
340
- testExecutor: (id, input) => request("POST", `/dsar/executors/${enc(id)}/test`, input)
569
+ testExecutor: (id, input) => request("POST", `/dsar/executors/${enc(id)}/test`, input),
570
+ recheckExecutor: (id) => request("POST", `/dsar/executors/${enc(id)}/recheck`),
571
+ executorHealthHistory: (id, opts2 = {}) => get(`/dsar/executors/${enc(id)}/health/history${qs({ limit: opts2.limit })}`),
572
+ executorConformance: (id) => request("POST", `/dsar/executors/${enc(id)}/test`, { conformance: true }),
573
+ rollExecutorCompletionSecret: (id) => request("POST", `/dsar/executors/${enc(id)}/completion-secret/roll`)
341
574
  },
342
575
  preferences: {
343
576
  list: () => get("/preferences"),
@@ -361,11 +594,25 @@ function createCookieMunch(opts) {
361
594
  },
362
595
  roll: (prefix) => request("POST", `/keys/${enc(prefix)}/roll`),
363
596
  update: (prefix, patch) => request("PATCH", `/keys/${enc(prefix)}`, patch),
364
- report: (o) => get(`/keys/report${qs({ unusedDays: o?.unusedDays, expiringDays: o?.expiringDays })}`)
597
+ report: (o) => get(`/keys/report${qs({ unusedDays: o?.unusedDays, expiringDays: o?.expiringDays })}`),
598
+ listStandard: () => get("/keys?shape=standard"),
599
+ self: () => get("/keys/self"),
600
+ rollSelf: () => request("POST", "/keys/self/roll"),
601
+ vend: (input) => request("POST", "/keys/vend", input),
602
+ revokeLeaked: (report) => request("POST", "/keys/revoke_leaked", report)
365
603
  },
366
604
  usage: () => get("/usage"),
605
+ entitlements: () => get("/entitlements"),
367
606
  integrationHealth: (cbid) => get(`/integration-health${qs({ cbid })}`),
368
- provision: (input, o) => request("POST", `/provision${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, input),
607
+ healthWaivers: {
608
+ list: (cbid) => get(`/integration-health/waivers${qs({ cbid })}`),
609
+ set: (input) => request("PUT", "/integration-health/waivers", input),
610
+ remove: async (check, opts2) => {
611
+ await request("DELETE", `/integration-health/waivers${qs({ check, cbid: opts2?.cbid, subject: opts2?.subject })}`);
612
+ }
613
+ },
614
+ embedManifest: (cbid) => get(`/embed${qs({ cbid })}`),
615
+ provision: (input, o) => request("POST", `/provision${qs({ dryRun: o?.dryRun ? "1" : void 0, fromStep: o?.fromStep })}`, input),
369
616
  org: {
370
617
  get: () => get("/org"),
371
618
  update: (patch) => request("PATCH", "/org", patch),
@@ -395,7 +642,14 @@ function createCookieMunch(opts) {
395
642
  remove: () => request("DELETE", "/org/rights-identity")
396
643
  }
397
644
  },
398
- audit: (limit) => get(`/audit${qs({ limit })}`),
645
+ audit: (limit, opts2) => get(`/audit${qs({ limit, actor: opts2?.actor })}`),
646
+ auditSink: {
647
+ get: () => get("/audit/sink"),
648
+ set: (input) => request("PUT", "/audit/sink", input),
649
+ remove: async () => {
650
+ await request("DELETE", "/audit/sink");
651
+ }
652
+ },
399
653
  assets: {
400
654
  upload: (input) => request("POST", "/assets", input),
401
655
  delete: async (urlOrFileName) => {
@@ -418,7 +672,7 @@ function createCookieMunch(opts) {
418
672
  }
419
673
  },
420
674
  webhooks: {
421
- list: () => get("/webhooks"),
675
+ list: (o) => get(`/webhooks${metaQs(o)}`),
422
676
  create: (input) => request("POST", "/webhooks", input),
423
677
  update: (id, patch) => request("PATCH", `/webhooks/${enc(id)}`, patch),
424
678
  delete: async (id) => {
@@ -427,7 +681,8 @@ function createCookieMunch(opts) {
427
681
  rollSecret: (id) => request("POST", `/webhooks/${enc(id)}/roll`),
428
682
  test: (id) => request("POST", `/webhooks/${enc(id)}/test`),
429
683
  deadLetters: () => get("/webhooks/dead-letters"),
430
- replayDeadLetter: (id) => request("POST", `/webhooks/dead-letters/${enc(id)}/replay`)
684
+ replayDeadLetter: (id) => request("POST", `/webhooks/dead-letters/${enc(id)}/replay`),
685
+ replay: (id, since, opts2) => request("POST", `/webhooks/${enc(id)}/replay${qs({ since: String(since), limit: opts2?.limit })}`)
431
686
  },
432
687
  rightsLinks: {
433
688
  create: (cbid, input) => request("POST", `/sites/${enc(cbid)}/rights-links`, input)
@@ -447,6 +702,13 @@ function createCookieMunch(opts) {
447
702
  set: (cbid, input) => request("PUT", `/sites/${enc(cbid)}/rights-identity`, input),
448
703
  remove: (cbid) => request("DELETE", `/sites/${enc(cbid)}/rights-identity`)
449
704
  },
705
+ dsarSettings: {
706
+ get: (cbid) => get(`/sites/${enc(cbid)}/dsar-settings`),
707
+ set: (cbid, input) => request("PUT", `/sites/${enc(cbid)}/dsar-settings`, input)
708
+ },
709
+ integrations: {
710
+ subjectCard: (app, person) => get(`/integrations/${enc(app)}/card${qs(person)}`)
711
+ },
450
712
  subjects: {
451
713
  consent: (subjectId) => get(`/subjects/${enc(subjectId)}/consent`)
452
714
  },
@@ -465,15 +727,23 @@ function createCookieMunch(opts) {
465
727
  };
466
728
  }
467
729
  export {
730
+ CANARY_ISSUER,
731
+ CONFORMANCE_RULES,
468
732
  CONSENT_COOKIE_NAME,
469
733
  CookieMunchApiError,
734
+ DEFAULT_JWKS_URL,
470
735
  SDK_VERSION,
736
+ canaryIdentityFor,
737
+ consentSignaturePayload,
471
738
  createCookieMunch,
472
739
  getConsent,
473
740
  isAllowed,
474
741
  mintConsentSyncToken,
475
742
  parseConsentValue,
476
743
  readConsent,
744
+ runExecutorConformance,
745
+ verifyDecisionSignature,
746
+ verifyToken,
477
747
  verifyWebhookSignature
478
748
  };
479
749
  //# sourceMappingURL=index.js.map