@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/CHANGELOG.md +19 -0
- package/dist/chunk-OSVTQPQG.js +187 -0
- package/dist/chunk-OSVTQPQG.js.map +1 -0
- package/dist/consent.cjs +89 -2
- package/dist/consent.cjs.map +1 -1
- package/dist/consent.d.cts +83 -2
- package/dist/consent.d.ts +83 -2
- package/dist/consent.js +11 -3
- package/dist/index.cjs +368 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1163 -41
- package/dist/index.d.ts +1163 -41
- package/dist/index.js +287 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-G7ORTXTK.js +0 -104
- package/dist/chunk-G7ORTXTK.js.map +0 -1
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
|
-
|
|
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.
|
|
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(
|
|
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(
|
|
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()
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|