@cookiemunch/sdk 0.5.1 → 0.7.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,219 @@ 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
+
223
+ // src/token-exchange.ts
224
+ var TokenExchangeError = class extends Error {
225
+ constructor(error, status, description) {
226
+ super(description ? `${error}: ${description}` : error);
227
+ this.error = error;
228
+ this.status = status;
229
+ this.name = "TokenExchangeError";
230
+ }
231
+ };
232
+ async function exchangeOperatorToken(input) {
233
+ const base = (input.baseUrl ?? "https://api.cookiemunch.net").replace(/\/+$/, "");
234
+ const form = new URLSearchParams({
235
+ grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
236
+ subject_token: input.subjectToken,
237
+ subject_token_type: `urn:ietf:params:oauth:token-type:${input.subjectTokenType ?? "access_token"}`,
238
+ scope: input.scope.join(" "),
239
+ resource: input.resource,
240
+ audience: "cookiemunch",
241
+ ...input.expiresIn !== void 0 ? { expires_in: String(input.expiresIn) } : {}
242
+ });
243
+ const res = await (input.fetch ?? fetch)(`${base}/v1/oauth/token`, {
244
+ method: "POST",
245
+ headers: { "Content-Type": "application/x-www-form-urlencoded", Accept: "application/json" },
246
+ body: form.toString()
247
+ });
248
+ const body = await res.json().catch(() => ({}));
249
+ if (!res.ok) {
250
+ throw new TokenExchangeError(typeof body.error === "string" ? body.error : `http_${res.status}`, res.status, typeof body.error_description === "string" ? body.error_description : void 0);
251
+ }
252
+ return {
253
+ accessToken: String(body.access_token),
254
+ expiresIn: Number(body.expires_in),
255
+ scope: String(body.scope ?? "").split(" ").filter(Boolean)
256
+ };
257
+ }
258
+
44
259
  // src/index.ts
45
- var SDK_VERSION = "0.5.1";
260
+ var SDK_VERSION = "0.7.0";
46
261
  var CookieMunchApiError = class extends Error {
47
262
  constructor(status, message, code, body) {
48
263
  super(message);
@@ -53,6 +268,10 @@ var CookieMunchApiError = class extends Error {
53
268
  }
54
269
  };
55
270
  var withBase = (doc, opts) => opts?.baseUpdatedAt !== void 0 ? { ...doc, baseUpdatedAt: opts.baseUpdatedAt } : doc;
271
+ function metaQs(o) {
272
+ const parts = Object.entries(o?.metadata ?? {}).map(([k, v]) => `metadata%5B${encodeURIComponent(k)}%5D=${encodeURIComponent(v)}`);
273
+ return parts.length ? `?${parts.join("&")}` : "";
274
+ }
56
275
  function qs(query) {
57
276
  if (!query) return "";
58
277
  const parts = [];
@@ -68,9 +287,12 @@ function createCookieMunch(opts) {
68
287
  const base = `${opts.baseUrl.replace(/\/+$/, "")}/v1`;
69
288
  const doFetch = opts.fetch ?? globalThis.fetch;
70
289
  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}` };
290
+ async function request(method, path, body, raw = false, extraHeaders = {}) {
291
+ const headers = { Authorization: `Bearer ${opts.apiKey}`, "User-Agent": opts.userAgent ?? `cookiemunch-js/${SDK_VERSION}`, ...extraHeaders };
73
292
  if (opts.strictUnknownFields && method !== "GET") headers["Prefer"] = "strict-unknown-fields";
293
+ if (opts.apiVersion) headers["CookieMunch-Version"] = opts.apiVersion;
294
+ if (opts.secretRecipient && method !== "GET") headers["X-Secret-Recipient"] = opts.secretRecipient;
295
+ for (const [k, v] of Object.entries(opts.headers ?? {})) headers[k] = v;
74
296
  const init = { method, headers };
75
297
  if (body !== void 0) {
76
298
  headers["Content-Type"] = "application/json";
@@ -96,22 +318,49 @@ function createCookieMunch(opts) {
96
318
  return contentType.includes("application/json") ? res.json() : res.text();
97
319
  }
98
320
  const get = (p) => request("GET", p);
321
+ async function requestBytes(path) {
322
+ const res = await doFetch(`${base}${path}`, { method: "GET", headers: { Authorization: `Bearer ${opts.apiKey}`, "User-Agent": opts.userAgent ?? `cookiemunch-js/${SDK_VERSION}` } });
323
+ if (!res.ok) {
324
+ let message = `request failed with status ${res.status}`;
325
+ let code;
326
+ try {
327
+ const data = await res.json();
328
+ if (typeof data.error === "string") message = data.error;
329
+ if (typeof data.code === "string") code = data.code;
330
+ } catch {
331
+ }
332
+ throw new CookieMunchApiError(res.status, message, code);
333
+ }
334
+ return res.arrayBuffer();
335
+ }
99
336
  const enc = encodeURIComponent;
100
337
  return {
101
338
  me: () => get("/me"),
102
339
  languages: () => get("/languages"),
103
340
  orgs: {
104
- list: () => get("/orgs"),
105
- create: (name, opts2) => request("POST", "/orgs", { name, ...opts2 ?? {} })
341
+ list: (o) => get(`/orgs${metaQs(o)}`),
342
+ create: (name, opts2) => request("POST", "/orgs", { name, ...opts2 ?? {} }),
343
+ deleteSandbox: (id) => request("DELETE", `/orgs/${enc(id)}?hard=1`)
344
+ },
345
+ metadata: {
346
+ get: (type, id) => get(`/metadata/${enc(type)}/${enc(id)}`),
347
+ update: (type, id, metadata, o) => request("PATCH", `/metadata/${enc(type)}/${enc(id)}${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, { metadata })
106
348
  },
349
+ partnerLinks: {
350
+ list: (o) => get(`/partner_links${metaQs(o)}`),
351
+ create: (input) => request("POST", "/partner_links", input),
352
+ revoke: (id) => request("DELETE", `/partner_links/${enc(id)}`)
353
+ },
354
+ provisionEnv: (ref) => get(`/provision/env${qs({ ref })}`),
107
355
  sites: {
108
- list: () => get("/sites"),
356
+ list: (o) => get(`/sites${metaQs(o)}`),
109
357
  create: (input) => request("POST", "/sites", input),
110
358
  get: (cbid) => get(`/sites/${enc(cbid)}`),
111
359
  update: (cbid, patch, o) => request("PATCH", `/sites/${enc(cbid)}${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, patch),
112
360
  delete: async (cbid) => {
113
361
  await request("DELETE", `/sites/${enc(cbid)}`);
114
362
  },
363
+ deleteSandbox: (cbid) => request("DELETE", `/sites/${enc(cbid)}?hard=1`),
115
364
  listPartners: (cbid) => get(`/sites/${enc(cbid)}/partners`),
116
365
  linkPartner: (cbid, input, o) => request("POST", `/sites/${enc(cbid)}/partners${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, input),
117
366
  unlinkPartner: (cbid, linkId) => request("DELETE", `/sites/${enc(cbid)}/partners/${enc(linkId)}`),
@@ -160,6 +409,9 @@ function createCookieMunch(opts) {
160
409
  }),
161
410
  cookiePresets: (cbid) => get(`/sites/${enc(cbid)}/cookies/presets`),
162
411
  applyCookiePreset: (cbid, vendor, params, o) => request("PUT", `/sites/${enc(cbid)}/cookies/presets/${enc(vendor)}${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, params ?? {}),
412
+ importCookieManifest: (cbid, input, o) => request("PUT", `/sites/${enc(cbid)}/cookies/presets/custom${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, input),
413
+ cookieSuggestions: (cbid) => get(`/sites/${enc(cbid)}/cookies/suggestions`),
414
+ declareCookieSuggestions: (cbid, input, o) => request("POST", `/sites/${enc(cbid)}/cookies/suggestions/declare${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, input ?? {}),
163
415
  removeCookiePreset: (cbid, vendor, o) => request("DELETE", `/sites/${enc(cbid)}/cookies/presets/${enc(vendor)}${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`),
164
416
  deleteObservedCookie: (async (cbid, name, o) => {
165
417
  const out = await request("DELETE", `/sites/${enc(cbid)}/observed-cookies/${enc(name)}${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`);
@@ -177,6 +429,8 @@ function createCookieMunch(opts) {
177
429
  verifyChallenge: (cbid) => get(`/sites/${enc(cbid)}/verify/challenge`),
178
430
  createBulk: (sites) => request("POST", "/sites/bulk", { sites }),
179
431
  brand: (cbid) => request("POST", `/sites/${enc(cbid)}/brand`, {}),
432
+ getBrand: (cbid) => get(`/sites/${enc(cbid)}/brand`),
433
+ setBrand: (cbid, input, o) => request("PUT", `/sites/${enc(cbid)}/brand${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, input),
180
434
  getFlow: (cbid) => get(`/sites/${enc(cbid)}/flow`),
181
435
  editFlow: (cbid, operations) => request("POST", `/sites/${enc(cbid)}/flow/ops`, { operations }),
182
436
  setFlow: (cbid, config) => request("PUT", `/sites/${enc(cbid)}/flow`, config)
@@ -184,11 +438,13 @@ function createCookieMunch(opts) {
184
438
  consent: {
185
439
  verify: (cbid) => get(`/sites/${enc(cbid)}/consent/verify`),
186
440
  stats: (cbid, query) => get(`/sites/${enc(cbid)}/consent/stats${qs(toQuery(query))}`),
441
+ insights: (cbid, query) => get(`/sites/${enc(cbid)}/consent/insights${qs(toQuery(query))}`),
187
442
  log: (cbid, query) => get(`/sites/${enc(cbid)}/consent/log${qs(toQuery(query))}`),
188
443
  export: (cbid, query) => request("GET", `/sites/${enc(cbid)}/consent/export${qs(toQuery(query))}`, void 0, true),
189
444
  receipt: (cbid, stamp) => get(`/sites/${enc(cbid)}/receipt/${enc(stamp)}`),
190
445
  eraseSubject: (cbid, stamp) => request("POST", `/sites/${enc(cbid)}/erase-consent`, { stamp }),
191
446
  exportSubject: (cbid, stamp) => request("GET", `/sites/${enc(cbid)}/subject-export?stamp=${enc(stamp)}`),
447
+ categoryRegistry: () => get("/categories/registry"),
192
448
  ingest: async (input) => {
193
449
  const res = await doFetch(`${opts.baseUrl.replace(/\/+$/, "")}/api/v1/consent`, {
194
450
  method: "POST",
@@ -219,7 +475,16 @@ function createCookieMunch(opts) {
219
475
  delete: async (id) => {
220
476
  await request("DELETE", `/dsar/${enc(id)}`);
221
477
  },
222
- markTest: (id) => request("POST", `/dsar/${enc(id)}/mark-test`)
478
+ markTest: (id) => request("POST", `/dsar/${enc(id)}/mark-test`),
479
+ listByTrace: (trace) => get(`/dsar${qs({ trace })}`),
480
+ openCase: (input, o) => request("POST", "/dsar/requests", input, false, {
481
+ ...o?.idempotencyKey ? { "Idempotency-Key": o.idempotencyKey } : {},
482
+ ...o?.trace ? { "X-ForgeDeck-Trace": o.trace } : {}
483
+ }),
484
+ getCase: (id) => get(`/dsar/requests/${enc(id)}`),
485
+ cancelCase: (id) => request("POST", `/dsar/requests/${enc(id)}/cancel`),
486
+ caseReceipt: (id) => get(`/dsar/requests/${enc(id)}/receipt`),
487
+ caseReceiptPdf: (id) => requestBytes(`/dsar/requests/${enc(id)}/receipt?format=pdf`)
223
488
  },
224
489
  vendors: {
225
490
  list: () => get("/vendors"),
@@ -322,7 +587,8 @@ function createCookieMunch(opts) {
322
587
  status: (requestId) => get(`/dsar/${enc(requestId)}/fulfillment`),
323
588
  pendingTasks: (limit) => get(`/dsar/agent/tasks${qs({ limit })}`),
324
589
  reportTask: (taskId, ok, error) => request("POST", `/dsar/agent/tasks/${enc(taskId)}/result`, { ok, ...error !== void 0 ? { error } : {} }),
325
- executors: () => get("/dsar/executors"),
590
+ executors: (o) => get(`/dsar/executors${metaQs(o)}`),
591
+ executor: (id) => get(`/dsar/executors/${enc(id)}`),
326
592
  connectExecutor: (input) => request("POST", "/dsar/executors", input),
327
593
  updateExecutor: (id, patch) => request("PATCH", `/dsar/executors/${enc(id)}`, patch),
328
594
  dryRunConnectExecutor: (input) => request("POST", "/dsar/executors?dryRun=1", input),
@@ -337,7 +603,11 @@ function createCookieMunch(opts) {
337
603
  },
338
604
  taskExport: (requestId, taskId) => get(`/dsar/${enc(requestId)}/tasks/${enc(taskId)}/export`),
339
605
  task: (requestId, taskId) => get(`/dsar/${enc(requestId)}/tasks/${enc(taskId)}`),
340
- testExecutor: (id, input) => request("POST", `/dsar/executors/${enc(id)}/test`, input)
606
+ testExecutor: (id, input) => request("POST", `/dsar/executors/${enc(id)}/test`, input),
607
+ recheckExecutor: (id) => request("POST", `/dsar/executors/${enc(id)}/recheck`),
608
+ executorHealthHistory: (id, opts2 = {}) => get(`/dsar/executors/${enc(id)}/health/history${qs({ limit: opts2.limit })}`),
609
+ executorConformance: (id) => request("POST", `/dsar/executors/${enc(id)}/test`, { conformance: true }),
610
+ rollExecutorCompletionSecret: (id) => request("POST", `/dsar/executors/${enc(id)}/completion-secret/roll`)
341
611
  },
342
612
  preferences: {
343
613
  list: () => get("/preferences"),
@@ -361,11 +631,32 @@ function createCookieMunch(opts) {
361
631
  },
362
632
  roll: (prefix) => request("POST", `/keys/${enc(prefix)}/roll`),
363
633
  update: (prefix, patch) => request("PATCH", `/keys/${enc(prefix)}`, patch),
364
- report: (o) => get(`/keys/report${qs({ unusedDays: o?.unusedDays, expiringDays: o?.expiringDays })}`)
634
+ report: (o) => get(`/keys/report${qs({ unusedDays: o?.unusedDays, expiringDays: o?.expiringDays })}`),
635
+ listStandard: () => get("/keys?shape=standard"),
636
+ self: () => get("/keys/self"),
637
+ updateSelf: (input) => request("PATCH", "/keys/self", input),
638
+ rollSelf: () => request("POST", "/keys/self/roll"),
639
+ vend: (input) => request("POST", "/keys/vend", input),
640
+ revokeLeaked: (report) => request("POST", "/keys/revoke_leaked", report)
365
641
  },
366
642
  usage: () => get("/usage"),
643
+ entitlements: () => get("/entitlements"),
644
+ versions: () => get("/versions"),
645
+ sandbox: {
646
+ get: async () => (await get("/sandbox")).sandbox,
647
+ create: (input) => request("POST", "/sandbox", input ?? {}),
648
+ delete: () => request("DELETE", "/sandbox")
649
+ },
367
650
  integrationHealth: (cbid) => get(`/integration-health${qs({ cbid })}`),
368
- provision: (input, o) => request("POST", `/provision${qs({ dryRun: o?.dryRun ? "1" : void 0 })}`, input),
651
+ healthWaivers: {
652
+ list: (cbid) => get(`/integration-health/waivers${qs({ cbid })}`),
653
+ set: (input) => request("PUT", "/integration-health/waivers", input),
654
+ remove: async (check, opts2) => {
655
+ await request("DELETE", `/integration-health/waivers${qs({ check, cbid: opts2?.cbid, subject: opts2?.subject })}`);
656
+ }
657
+ },
658
+ embedManifest: (cbid) => get(`/embed${qs({ cbid })}`),
659
+ provision: (input, o) => request("POST", `/provision${qs({ dryRun: o?.dryRun ? "1" : void 0, fromStep: o?.fromStep })}`, input),
369
660
  org: {
370
661
  get: () => get("/org"),
371
662
  update: (patch) => request("PATCH", "/org", patch),
@@ -395,7 +686,14 @@ function createCookieMunch(opts) {
395
686
  remove: () => request("DELETE", "/org/rights-identity")
396
687
  }
397
688
  },
398
- audit: (limit) => get(`/audit${qs({ limit })}`),
689
+ audit: (limit, opts2) => get(`/audit${qs({ limit, actor: opts2?.actor })}`),
690
+ auditSink: {
691
+ get: () => get("/audit/sink"),
692
+ set: (input) => request("PUT", "/audit/sink", input),
693
+ remove: async () => {
694
+ await request("DELETE", "/audit/sink");
695
+ }
696
+ },
399
697
  assets: {
400
698
  upload: (input) => request("POST", "/assets", input),
401
699
  delete: async (urlOrFileName) => {
@@ -418,7 +716,7 @@ function createCookieMunch(opts) {
418
716
  }
419
717
  },
420
718
  webhooks: {
421
- list: () => get("/webhooks"),
719
+ list: (o) => get(`/webhooks${metaQs(o)}`),
422
720
  create: (input) => request("POST", "/webhooks", input),
423
721
  update: (id, patch) => request("PATCH", `/webhooks/${enc(id)}`, patch),
424
722
  delete: async (id) => {
@@ -427,7 +725,8 @@ function createCookieMunch(opts) {
427
725
  rollSecret: (id) => request("POST", `/webhooks/${enc(id)}/roll`),
428
726
  test: (id) => request("POST", `/webhooks/${enc(id)}/test`),
429
727
  deadLetters: () => get("/webhooks/dead-letters"),
430
- replayDeadLetter: (id) => request("POST", `/webhooks/dead-letters/${enc(id)}/replay`)
728
+ replayDeadLetter: (id) => request("POST", `/webhooks/dead-letters/${enc(id)}/replay`),
729
+ replay: (id, since, opts2) => request("POST", `/webhooks/${enc(id)}/replay${qs({ since: String(since), limit: opts2?.limit })}`)
431
730
  },
432
731
  rightsLinks: {
433
732
  create: (cbid, input) => request("POST", `/sites/${enc(cbid)}/rights-links`, input)
@@ -447,6 +746,13 @@ function createCookieMunch(opts) {
447
746
  set: (cbid, input) => request("PUT", `/sites/${enc(cbid)}/rights-identity`, input),
448
747
  remove: (cbid) => request("DELETE", `/sites/${enc(cbid)}/rights-identity`)
449
748
  },
749
+ dsarSettings: {
750
+ get: (cbid) => get(`/sites/${enc(cbid)}/dsar-settings`),
751
+ set: (cbid, input) => request("PUT", `/sites/${enc(cbid)}/dsar-settings`, input)
752
+ },
753
+ integrations: {
754
+ subjectCard: (app, person) => get(`/integrations/${enc(app)}/card${qs(person)}`)
755
+ },
450
756
  subjects: {
451
757
  consent: (subjectId) => get(`/subjects/${enc(subjectId)}/consent`)
452
758
  },
@@ -465,15 +771,25 @@ function createCookieMunch(opts) {
465
771
  };
466
772
  }
467
773
  export {
774
+ CANARY_ISSUER,
775
+ CONFORMANCE_RULES,
468
776
  CONSENT_COOKIE_NAME,
469
777
  CookieMunchApiError,
778
+ DEFAULT_JWKS_URL,
470
779
  SDK_VERSION,
780
+ TokenExchangeError,
781
+ canaryIdentityFor,
782
+ consentSignaturePayload,
471
783
  createCookieMunch,
784
+ exchangeOperatorToken,
472
785
  getConsent,
473
786
  isAllowed,
474
787
  mintConsentSyncToken,
475
788
  parseConsentValue,
476
789
  readConsent,
790
+ runExecutorConformance,
791
+ verifyDecisionSignature,
792
+ verifyToken,
477
793
  verifyWebhookSignature
478
794
  };
479
795
  //# sourceMappingURL=index.js.map