@cookiemunch/cli 0.6.0 → 0.7.1

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 CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  Every published release, newest first. Dates are the day the version was cut.
4
4
 
5
+ ## 0.7.1 (2026-10-24)
6
+
7
+ - Changed: `cookiemunch csp --merge <product>` reads each product's manifest under its own name first (`/.well-known/<product>-embed.json`), and the suite-named `forgedeck-embed.json` only as a fallback.
8
+
9
+ ## 0.7.0 (2026-10-24)
10
+
11
+ - Added: `cookiemunch sandbox [show] | create [--key-name <n>] | delete [--yes]`.
12
+ - Added: `cookiemunch token exchange --subject-token-env NAME --scope a,b --resource org:<id>|site:<cbid>` — a key for at most an hour from your identity provider's sign-in, no API key needed.
13
+
5
14
  ## 0.6.0 (2026-10-24)
6
15
 
7
16
  - Added: `cookiemunch executors conformance <baseUrl> --secret-env NAME` — checks any system against the open cm-standard-v2 executor contract, no Cookie Munch key needed with `--canary-email`; `--connection <id>` runs it from Cookie Munch.
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  run
4
- } from "./chunk-LJ433UVC.js";
4
+ } from "./chunk-CWBS6Z2H.js";
5
5
 
6
6
  // src/bin.ts
7
7
  import { readFile, writeFile } from "fs/promises";
@@ -196,7 +196,8 @@ function manifestSources(list, opts) {
196
196
  sources.push({ label: `cookiemunch (site ${opts.site})`, urls: [`${opts.apiBase.replace(/\/$/, "")}/v1/embed?cbid=${encodeURIComponent(opts.site)}`], product: name });
197
197
  continue;
198
198
  }
199
- sources.push({ label: name, urls: hosts.map((h) => `https://${h}/.well-known/forgedeck-embed.json`), product: name });
199
+ const own = hosts.map((h) => `https://${h}/.well-known/${name}-embed.json`);
200
+ sources.push({ label: name, urls: [...own, ...hosts.map((h) => `https://${h}/.well-known/forgedeck-embed.json`)], product: name });
200
201
  }
201
202
  return { sources, unknown };
202
203
  }
@@ -321,7 +322,7 @@ async function cspCommand(opts, io, usage) {
321
322
  }
322
323
 
323
324
  // src/cli.ts
324
- import { createCookieMunch, CookieMunchApiError as CookieMunchApiError2, mintConsentSyncToken, runExecutorConformance } from "@cookiemunch/sdk";
325
+ import { createCookieMunch, CookieMunchApiError as CookieMunchApiError2, exchangeOperatorToken, mintConsentSyncToken, runExecutorConformance } from "@cookiemunch/sdk";
325
326
 
326
327
  // src/integrations.ts
327
328
  var out = (io, v) => io.stdout(`${JSON.stringify(v, null, 2)}
@@ -778,6 +779,46 @@ async function keysExtraCommand(sub, io, client, h) {
778
779
  }
779
780
  throw h.usage("usage: cookiemunch keys report|vend|self|rotate-self");
780
781
  }
782
+ async function sandboxCommand(sub, io, client, h) {
783
+ if (sub === void 0 || sub === "show") {
784
+ const s = await client.sandbox.get();
785
+ if (json(h) || s) print(io, s);
786
+ else io.stderr("This organisation has no sandbox. Make one with: cookiemunch sandbox create\n");
787
+ return 0;
788
+ }
789
+ if (sub === "create") {
790
+ const keyName = str(h, "key-name");
791
+ const r = await client.sandbox.create(keyName ? { keyName } : {});
792
+ if (json(h)) print(io, r);
793
+ else {
794
+ io.stdout(`${r.key}
795
+ `);
796
+ io.stderr(`${r.created ? "Made" : "Using"} sandbox ${r.sandbox.orgId} (${r.sandbox.name}). The key above is shown once: store it now.
797
+ `);
798
+ }
799
+ return 0;
800
+ }
801
+ if (sub === "delete") {
802
+ const s = await client.sandbox.get();
803
+ if (!s) {
804
+ io.stderr("There is no sandbox.\n");
805
+ return 1;
806
+ }
807
+ if (h.flag("yes") !== true) {
808
+ if (!io.confirm) throw h.usage("sandbox delete erases the sandbox and everything in it, and there is no terminal to confirm in. Pass --yes to delete without a prompt.");
809
+ if (!await io.confirm(`Erase sandbox ${s.orgId} (${s.name}) and everything in it? This cannot be undone. [y/N] `)) {
810
+ io.stderr("Not deleted.\n");
811
+ return 1;
812
+ }
813
+ }
814
+ const r = await client.sandbox.delete();
815
+ if (json(h)) print(io, r);
816
+ else io.stderr(`Erased sandbox ${r.orgId ?? s.orgId}: ${Object.entries(r.counts).map(([k, v]) => `${v} ${k}`).join(", ")}.
817
+ `);
818
+ return 0;
819
+ }
820
+ throw h.usage("usage: cookiemunch sandbox [show] | create [--key-name <n>] | delete [--yes]");
821
+ }
781
822
  var PARTS = ["site", "config", "cookies", "presets", "rightsPage", "executors", "webhooks", "partners"];
782
823
  async function bundleCommand(sub, io, client, h) {
783
824
  const path = h.positional[1] ?? "cookiemunch.json";
@@ -1014,7 +1055,7 @@ Usage:
1014
1055
  Remove every declaration that vendor's preset made.
1015
1056
  cookiemunch cookies import-manifest <url> --site <cbid> [--file <manifest.json>] [--dry-run]
1016
1057
  Declare any vendor's cookies and storage from its embed manifest
1017
- (/.well-known/forgedeck-embed.json), by URL or from a file. Remove it with
1058
+ (/.well-known/<product>-embed.json), by URL or from a file. Remove it with
1018
1059
  cookies unpreset <product>.
1019
1060
  cookiemunch cookies suggestions --site <cbid>
1020
1061
  What to declare: the platforms detected on the site and each undeclared row.
@@ -1059,9 +1100,12 @@ Usage:
1059
1100
  Grant a partner platform the site's consent events (no secret is created), list
1060
1101
  the grants, or revoke one. Any partner this deployment knows (forumulate, atlas, chatly,
1061
1102
  referalli, or one registered for it).
1103
+ cookiemunch token exchange --subject-token-env NAME --scope <a,b> --resource org:<id>|site:<cbid> [--expires-in <s>]
1104
+ Swap your identity provider's token (read from the variable NAME) for a short-lived, scoped
1105
+ API key (at most 1 hour); prints the key alone. Needs no API key.
1062
1106
  cookiemunch csp --merge <vendors|urls> [--framework next|express|nginx] [--site <cbid>]
1063
1107
  One Content-Security-Policy from several products' embed manifests
1064
- (/.well-known/forgedeck-embed.json): cookiemunch, atlas, chatly, forumulate,
1108
+ (/.well-known/<product>-embed.json): cookiemunch, atlas, chatly, forumulate,
1065
1109
  referalli, or any manifest URL. --framework prints it for next.config.js,
1066
1110
  Express or nginx; without it, the header value. --site uses your site's own
1067
1111
  Cookie Munch manifest (its logo, fonts, sync endpoint). Needs no API key. Exits 1
@@ -1084,6 +1128,11 @@ Usage:
1084
1128
  Needs keys:write (or a full-access key).
1085
1129
  cookiemunch keys self | rotate-self
1086
1130
  This key's own prefix, scopes and expiry; or rotate it (the new key is printed once).
1131
+ cookiemunch sandbox [show] | create [--key-name <n>] | delete [--yes]
1132
+ The organisation's sandbox: a separate test organisation with the same people and plan
1133
+ features, never billed; its keys are test keys and its rights requests are all tests.
1134
+ create makes it (or reuses it) and prints a new key for it alone; delete erases it and
1135
+ everything in it, after asking. create and delete need a full-access key or orgs:create.
1087
1136
  cookiemunch plan [cookiemunch.json] [--exit-code] [--json]
1088
1137
  cookiemunch apply [cookiemunch.json] [--secret-env NAME] [--secrets-out <file>]
1089
1138
  One file for a site: {site, config, cookies, presets, executors, webhooks, rightsPage,
@@ -1171,7 +1220,7 @@ async function readConfigFile(io, path) {
1171
1220
  function proposed(current, file, replace, cbid) {
1172
1221
  return replace ? { ...file, cbid } : mergeLikeServer(current, file);
1173
1222
  }
1174
- var CLI_VERSION = "0.6.0";
1223
+ var CLI_VERSION = "0.7.1";
1175
1224
  function userAgent(io) {
1176
1225
  return io.env.COOKIEMUNCH_USER_AGENT || `cookiemunch-cli/${CLI_VERSION}`;
1177
1226
  }
@@ -1589,7 +1638,7 @@ async function cookiesCommand(sub, p, io, client) {
1589
1638
  const cbid = requireSite(p, io);
1590
1639
  const src = p.positional[2];
1591
1640
  const file = str2(p.flags, "file");
1592
- if (!src && !file) throw new UsageError("a manifest URL (https://\u2026/.well-known/forgedeck-embed.json) or --file <manifest.json> is required");
1641
+ if (!src && !file) throw new UsageError("a manifest URL (https://\u2026/.well-known/<product>-embed.json) or --file <manifest.json> is required");
1593
1642
  const input = file ? { manifest: JSON.parse(await io.readFile(file)) } : { url: src };
1594
1643
  const r = await client.sites.importCookieManifest(cbid, input, dry);
1595
1644
  print2(r);
@@ -1670,6 +1719,48 @@ ${USAGE}`);
1670
1719
  }
1671
1720
  }
1672
1721
  const base = io.env.COOKIEMUNCH_BASE_URL || DEFAULT_BASE_URL;
1722
+ if (cmd === "token" && p.positional[1] === "exchange") {
1723
+ const envName = str2(p.flags, "subject-token-env");
1724
+ const subjectToken = envName ? io.env[envName] : void 0;
1725
+ const scope = (str2(p.flags, "scope") ?? "").split(/[,\s]+/).filter(Boolean);
1726
+ const resource = str2(p.flags, "resource");
1727
+ const exp = str2(p.flags, "expires-in");
1728
+ if (!envName || !subjectToken) {
1729
+ io.stderr(`token exchange needs --subject-token-env NAME, naming a variable that holds your identity provider's token
1730
+ `);
1731
+ return 2;
1732
+ }
1733
+ if (!scope.length) {
1734
+ io.stderr("token exchange needs --scope a,b (an exchanged key is never full access)\n");
1735
+ return 2;
1736
+ }
1737
+ if (!resource || !/^(org|site):.+/.test(resource)) {
1738
+ io.stderr("token exchange needs --resource org:<id> or site:<cbid>\n");
1739
+ return 2;
1740
+ }
1741
+ if (exp !== void 0 && !/^\d+$/.test(exp)) {
1742
+ io.stderr("--expires-in must be a number of seconds\n");
1743
+ return 2;
1744
+ }
1745
+ try {
1746
+ const r = await exchangeOperatorToken({
1747
+ subjectToken,
1748
+ scope,
1749
+ resource,
1750
+ baseUrl: base,
1751
+ fetch: io.fetch,
1752
+ ...exp !== void 0 ? { expiresIn: Number(exp) } : {}
1753
+ });
1754
+ io.stdout(p.flags.json === true ? `${JSON.stringify(r, null, 2)}
1755
+ ` : `${r.accessToken}
1756
+ `);
1757
+ return 0;
1758
+ } catch (e) {
1759
+ io.stderr(`${e.message}
1760
+ `);
1761
+ return 1;
1762
+ }
1763
+ }
1673
1764
  if (cmd === "csp") {
1674
1765
  try {
1675
1766
  const merge = str2(p.flags, "merge");
@@ -1720,6 +1811,7 @@ ${USAGE}`);
1720
1811
  if (cmd === "dsar" && sub === "test") return await dsarTestCommand(io, client, ops);
1721
1812
  if (cmd === "doctor") return await doctorCommand(io, client, ops, CLI_VERSION);
1722
1813
  if (cmd === "keys" && sub && sub !== "report") return await keysExtraCommand(sub, io, client, ops);
1814
+ if (cmd === "sandbox") return await sandboxCommand(sub, io, client, ops);
1723
1815
  if (cmd === "plan" || cmd === "apply") return await bundleCommand(cmd, io, client, ops);
1724
1816
  if (cmd === "config") return await configCommand(sub, p, io, client);
1725
1817
  if (cmd === "preview") return await previewCommand(p, io, client);
@@ -1782,4 +1874,4 @@ export {
1782
1874
  parseArgs,
1783
1875
  run
1784
1876
  };
1785
- //# sourceMappingURL=chunk-LJ433UVC.js.map
1877
+ //# sourceMappingURL=chunk-CWBS6Z2H.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/diff.ts","../src/rights-page.ts","../src/csp.ts","../src/cli.ts","../src/integrations.ts","../src/design-warnings.ts","../src/ops.ts"],"sourcesContent":["/**\n * What a config push would change, computed on this side of the wire.\n *\n * `mergeLikeServer` mirrors the server's `PATCH /v1/sites/{cbid}/config` semantics exactly\n * (JSON Merge Patch, RFC 7386 — packages/server/src/site-config-write.ts mergePatch): the\n * patch wins, nested plain objects merge, arrays and primitives replace wholesale, and a\n * `null` removes the key. A diff computed against any other merge would describe a change\n * the server is not going to make.\n */\n\nexport type Json = null | boolean | number | string | Json[] | { [k: string]: Json };\n\nexport interface Change {\n /** Dotted path; array indices in brackets: `banner.content.title`, `geoRules[0].mode`. */\n path: string;\n kind: 'added' | 'removed' | 'changed';\n from?: Json;\n to?: Json;\n}\n\n/**\n * Returned by a config read, never a setting; the server drops them from a write\n * (packages/server/src/site-config-write.ts READ_ONLY_CONFIG_FIELDS, pinned by a test).\n */\nexport const READ_ONLY_CONFIG_FIELDS = ['effective', 'warnings', 'designWarnings', 'region', 'regulation', 'copy', 'rightsFormUrl', 'version', 'observeToken', 'sdkBoot', 'originEnv'] as const;\n\n/** A copy of a config without its read-only fields, so a pulled file diffs clean against the server. */\nexport function withoutReadOnly(cfg: Record<string, unknown>): Record<string, unknown> {\n const out = { ...cfg };\n for (const k of READ_ONLY_CONFIG_FIELDS) delete out[k];\n return out;\n}\n\nexport function isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\nexport function mergeLikeServer(base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...base };\n for (const [k, v] of Object.entries(patch)) {\n const b = base[k];\n if (v === null) delete out[k];\n else out[k] = isPlainObject(v) ? mergeLikeServer(isPlainObject(b) ? b : {}, v) : v;\n }\n return out;\n}\n\nfunction join(path: string, key: string): string {\n return path ? `${path}.${key}` : key;\n}\n\n/** Every leaf that differs between `before` and `after`, in a stable order. */\nexport function diffJson(before: unknown, after: unknown, path = ''): Change[] {\n if (isPlainObject(before) && isPlainObject(after)) {\n const keys = [...new Set([...Object.keys(before), ...Object.keys(after)])].sort();\n return keys.flatMap((k) => {\n const p = join(path, k);\n if (!(k in after)) return [{ path: p, kind: 'removed' as const, from: before[k] as Json }];\n if (!(k in before)) return [{ path: p, kind: 'added' as const, to: after[k] as Json }];\n return diffJson(before[k], after[k], p);\n });\n }\n if (Array.isArray(before) && Array.isArray(after)) {\n const out: Change[] = [];\n const n = Math.max(before.length, after.length);\n for (let i = 0; i < n; i++) {\n const p = `${path}[${i}]`;\n if (i >= after.length) out.push({ path: p, kind: 'removed', from: before[i] as Json });\n else if (i >= before.length) out.push({ path: p, kind: 'added', to: after[i] as Json });\n else out.push(...diffJson(before[i], after[i], p));\n }\n return out;\n }\n if (JSON.stringify(before) === JSON.stringify(after)) return [];\n return [{ path: path || '(root)', kind: 'changed', from: before as Json, to: after as Json }];\n}\n\nfunction show(v: Json | undefined): string {\n const s = JSON.stringify(v);\n return s === undefined ? 'undefined' : s.length > 120 ? `${s.slice(0, 117)}...` : s;\n}\n\n/** A unified-diff-ish rendering: one line per change. */\nexport function formatChanges(changes: Change[]): string {\n return changes\n .map((c) =>\n c.kind === 'added'\n ? `+ ${c.path}: ${show(c.to)}`\n : c.kind === 'removed'\n ? `- ${c.path}: ${show(c.from)}`\n : `~ ${c.path}: ${show(c.from)} -> ${show(c.to)}`,\n )\n .join('\\n');\n}\n","/**\n * `cookiemunch rights-page pull|diff|push|publish` — the hosted rights page as code.\n *\n * Unlike `config diff`, `diff` asks the server: the rights page has a real dry run, so the\n * diff is against what the server would store (normalised and sanitised), and an invalid\n * file fails with the server's issues before anything is written.\n */\nimport { CookieMunchApiError, type CookieMunchClient } from '@cookiemunch/sdk';\nimport type { CliIo } from './cli.js';\nimport { diffJson, formatChanges } from './diff.js';\n\ninterface Helpers { requireSite(): string; readJson(path: string | undefined): Promise<Record<string, unknown>>; usage(msg: string): Error }\ntype Issue = { path: string; message: string };\n\nconst isConflict = (e: unknown) => e instanceof CookieMunchApiError && e.status === 409;\n\n/** `--base <updatedAt>` (epoch ms or an ISO date), else the updatedAt this command just read. */\nfunction baseFrom(flag: string | true | undefined, read: number | null | undefined, h: Helpers): number | string | null {\n if (flag === undefined) return read ?? null;\n if (typeof flag === 'string' && /^\\d+$/.test(flag)) return Number(flag);\n if (typeof flag === 'string' && /^\\d{4}-\\d{2}-\\d{2}T/.test(flag) && Number.isFinite(Date.parse(flag))) return flag;\n throw h.usage('--base must be the draft’s updatedAt (epoch ms, as pull prints it, or an ISO date)');\n}\n\nfunction issuesOf(e: unknown): Issue[] | null {\n if (!(e instanceof CookieMunchApiError) || e.status !== 422) return null;\n const body = e.body as { issues?: Issue[]; problems?: Issue[] } | undefined;\n return body?.issues ?? body?.problems ?? [];\n}\n\nexport async function rightsPageCommand(\n sub: string | undefined,\n p: { positional: string[]; flags: Record<string, string | true> },\n io: CliIo,\n client: CookieMunchClient,\n h: Helpers,\n): Promise<number> {\n const cbid = h.requireSite();\n const report = (list: Issue[]) => io.stderr(`${list.map((i) => ` ${i.path || '(document)'}: ${i.message}`).join('\\n')}\\n`);\n if (sub === 'pull') {\n const { draft, updatedAt } = await client.rightsPage.get(cbid);\n const text = `${JSON.stringify(draft, null, 2)}\\n`;\n const out = typeof p.flags.out === 'string' ? p.flags.out : undefined;\n if (out) {\n await io.writeFile(out, text);\n io.stderr(`Wrote ${cbid}'s rights page draft to ${out}\\n`);\n } else io.stdout(text);\n if (updatedAt != null) io.stderr(`To refuse a push if anyone saves the draft after this pull, push with: --base ${updatedAt}\\n`);\n return 0;\n }\n if (sub === 'diff' || sub === 'push') {\n const file = await h.readJson(p.positional[2]);\n const read = await client.rightsPage.get(cbid);\n const current = read.draft;\n // The base the diff is against (or the one pull printed): a save after it is a conflict, never lost.\n const base = baseFrom(p.flags.base, read.updatedAt, h);\n let proposed: unknown;\n try {\n proposed = (await client.rightsPage.dryRun(cbid, file, { mode: 'put' })).draft;\n } catch (e) {\n const list = issuesOf(e);\n if (!list) throw e;\n io.stderr(`${p.positional[2]} is not a valid rights page:\\n`);\n report(list);\n return 1;\n }\n const changes = diffJson(current, proposed);\n if (p.flags.json === true && (sub === 'diff' || !changes.length)) io.stdout(`${JSON.stringify({ cbid, changes }, null, 2)}\\n`);\n if (!changes.length) { io.stderr(`No changes: ${cbid}'s rights page draft already matches.\\n`); return 0; }\n if (p.flags.json !== true) io.stdout(`${formatChanges(changes)}\\n`);\n if (sub === 'diff') {\n io.stderr(`${changes.length} change${changes.length === 1 ? '' : 's'} (nothing saved). Apply with: cookiemunch rights-page push --site ${cbid} ${p.positional[2]}\\n`);\n return p.flags['exit-code'] === true ? 1 : 0;\n }\n let saved;\n try {\n saved = await client.rightsPage.put(cbid, file as never, { baseUpdatedAt: base });\n } catch (e) {\n if (!isConflict(e)) throw e;\n io.stderr(`Not saved: ${cbid}'s rights page draft changed since ${p.flags.base !== undefined ? 'the --base you gave' : 'this diff'} (someone else saved it).\\n`\n + `See what changed with: cookiemunch rights-page diff --site ${cbid} ${p.positional[2]}\\nthen push again.\\n`);\n return 1;\n }\n io.stderr(`Saved the draft (${changes.length} change${changes.length === 1 ? '' : 's'}). Nothing is live until: cookiemunch rights-page publish --site ${cbid}\\n`);\n if (saved.warnings.length) { io.stderr('It cannot be published yet:\\n'); report(saved.warnings); }\n return 0;\n }\n if (sub === 'publish') {\n // Read before asking, so the draft that goes live is the one that existed when you said yes.\n const base = p.flags.base !== undefined ? baseFrom(p.flags.base, null, h) : (await client.rightsPage.get(cbid)).updatedAt ?? null;\n if (p.flags.yes !== true) {\n if (!io.confirm) throw h.usage('rights-page publish puts the draft live and there is no terminal to confirm in. Pass --yes to publish without a prompt.');\n if (!(await io.confirm(`Publish ${cbid}'s rights page draft? It goes live at once. [y/N] `))) {\n io.stderr('Not published.\\n');\n return 1;\n }\n }\n try {\n const r = await client.rightsPage.publish(cbid, { baseUpdatedAt: base });\n io.stderr(`Published version ${r.version} of ${cbid}'s rights page.\\n`);\n return 0;\n } catch (e) {\n if (isConflict(e)) {\n io.stderr(`Nothing was published: ${cbid}'s rights page draft changed since it was read (someone else saved it).\\n`\n + `Review it with: cookiemunch rights-page pull --site ${cbid}\\nthen publish again.\\n`);\n return 1;\n }\n const list = issuesOf(e);\n if (!list) throw e;\n io.stderr('The rights page cannot be published:\\n');\n report(list);\n return 1;\n }\n }\n throw h.usage(`unknown rights-page command: ${sub ?? '(none)'} — use pull, diff, push or publish`);\n}\n","/**\n * `cookiemunch csp --merge <vendors|urls> [--framework next|express|nginx] [--site <cbid>]`\n *\n * One Content-Security-Policy from several products' embed manifests\n * (`/.well-known/forgedeck-embed.json`, schema https://cookiemunch.net/schemas/embed-v1.json):\n * each manifest lists its origins by directive (`csp`) and the non-origin sources it needs\n * (`requires`); the policy is their union, plus `'self'`.\n *\n * Vendor-neutral: `--merge` takes any manifest URL. The names below are first-class shortcuts\n * for products whose manifest host is known — the same host map the API's importer uses\n * (packages/server/src/manifest-importer.ts; a test keeps the two equal). A product that has not\n * published its manifest yet is reported, and the policy is built from the rest.\n *\n * Needs no API key: every manifest is public, `--site` included (`GET /v1/embed?cbid=`).\n */\n\n/** Where a known product publishes its manifest: the apex first, then its API host. */\nexport const KNOWN_MANIFEST_HOSTS: Readonly<Record<string, readonly string[]>> = {\n cookiemunch: ['cookiemunch.net', 'api.cookiemunch.net'],\n atlas: ['atlasauth.net', 'api.atlasauth.net'],\n chatly: ['chatlychat.com', 'api.chatlychat.com'],\n forumulate: ['forumulate.com'],\n referalli: ['referalli.com'],\n};\n\n/** Old names still accepted. */\nconst ALIASES: Record<string, string> = { referally: 'referalli' };\n\nexport const CSP_FRAMEWORKS = ['next', 'express', 'nginx'] as const;\nexport type CspFramework = (typeof CSP_FRAMEWORKS)[number];\n\ntype Surface = { csp?: Record<string, unknown>; requires?: Record<string, unknown> };\ntype Manifest = { product?: unknown; surfaces?: Record<string, Surface> };\n\nexport interface ManifestSource {\n /** What the user named: a vendor or a URL. */\n label: string;\n /** URLs to try, in order. */\n urls: string[];\n product?: string;\n}\n\n/** `atlas,chatly,https://x/.well-known/x-embed.json` → sources to fetch. */\nexport function manifestSources(list: string, opts: { site?: string; apiBase: string }): { sources: ManifestSource[]; unknown: string[] } {\n const sources: ManifestSource[] = [];\n const unknown: string[] = [];\n for (const raw of list.split(',').map((s) => s.trim()).filter(Boolean)) {\n if (/^https:\\/\\//i.test(raw)) {\n sources.push({ label: raw, urls: [raw] });\n continue;\n }\n const name = ALIASES[raw.toLowerCase()] ?? raw.toLowerCase();\n const hosts = KNOWN_MANIFEST_HOSTS[name];\n if (!hosts) {\n unknown.push(raw);\n continue;\n }\n if (name === 'cookiemunch' && opts.site) {\n sources.push({ label: `cookiemunch (site ${opts.site})`, urls: [`${opts.apiBase.replace(/\\/$/, '')}/v1/embed?cbid=${encodeURIComponent(opts.site)}`], product: name });\n continue;\n }\n // Each product's manifest under its own name first; the suite-named path is the fallback.\n const own = hosts.map((h) => `https://${h}/.well-known/${name}-embed.json`);\n sources.push({ label: name, urls: [...own, ...hosts.map((h) => `https://${h}/.well-known/forgedeck-embed.json`)], product: name });\n }\n return { sources, unknown };\n}\n\nconst ORIGIN = /^(https|wss):\\/\\/[^\\s*'\"]+$/;\nconst KEYWORD = /^('unsafe-inline'|'unsafe-eval'|'wasm-unsafe-eval'|'unsafe-hashes'|data:|blob:)$/;\n\n/** The union of every surface's origins and requirements, by directive; `'self'` first. */\nexport function mergeManifests(manifests: Manifest[]): Map<string, string[]> {\n const byDirective = new Map<string, Set<string>>();\n const add = (directive: string, list: unknown, allowKeywords: boolean) => {\n if (!Array.isArray(list) || !/^[a-z-]+-src$|^form-action$/.test(directive)) return;\n let set = byDirective.get(directive);\n if (!set) byDirective.set(directive, (set = new Set()));\n for (const src of list) {\n if (typeof src !== 'string') continue;\n // A placeholder (`https://{instance}.example.com`) is a tenant's value: it cannot be pasted.\n if (src.includes('{')) continue;\n if (ORIGIN.test(src) || (allowKeywords && KEYWORD.test(src))) set.add(src);\n }\n };\n for (const m of manifests) {\n for (const s of Object.values(m.surfaces ?? {})) {\n for (const [d, list] of Object.entries(s.csp ?? {})) add(d, list, false);\n for (const [d, list] of Object.entries(s.requires ?? {})) add(d, list, true);\n }\n }\n const out = new Map<string, string[]>();\n out.set('default-src', [\"'self'\"]);\n for (const [d, set] of [...byDirective.entries()].sort(([a], [b]) => a.localeCompare(b))) {\n if (set.size === 0) continue;\n const keywords = [...set].filter((s) => !ORIGIN.test(s)).sort();\n const origins = [...set].filter((s) => ORIGIN.test(s)).sort();\n out.set(d, [\"'self'\", ...keywords, ...origins]);\n }\n return out;\n}\n\n/** Placeholders a manifest left for the tenant to fill in: reported, never guessed. */\nexport function placeholders(manifests: Manifest[]): string[] {\n const out = new Set<string>();\n for (const m of manifests) {\n for (const s of Object.values(m.surfaces ?? {})) {\n for (const map of [s.csp, s.requires]) {\n for (const list of Object.values(map ?? {})) {\n if (Array.isArray(list)) for (const src of list) if (typeof src === 'string' && src.includes('{')) out.add(src);\n }\n }\n }\n }\n return [...out].sort();\n}\n\nexport function policyString(policy: Map<string, string[]>): string {\n return [...policy.entries()].map(([d, list]) => `${d} ${list.join(' ')}`).join('; ');\n}\n\n/** The policy as the framework writes it. */\nexport function renderPolicy(policy: Map<string, string[]>, framework?: CspFramework): string {\n const value = policyString(policy);\n if (framework === 'next') {\n return [\n '// next.config.js',\n 'async headers() {',\n ' return [{',\n \" source: '/(.*)',\",\n ` headers: [{ key: 'Content-Security-Policy', value: ${JSON.stringify(value)} }],`,\n ' }];',\n '},',\n ].join('\\n');\n }\n if (framework === 'express') {\n return `app.use((req, res, next) => { res.setHeader('Content-Security-Policy', ${JSON.stringify(value)}); next(); });`;\n }\n if (framework === 'nginx') return `add_header Content-Security-Policy \"${value.replace(/\"/g, '\\\\\"')}\" always;`;\n return value;\n}\n\n/** Fetch one manifest, trying each URL in turn. */\nexport async function fetchManifest(src: ManifestSource, fetchImpl: typeof fetch): Promise<{ ok: true; manifest: Manifest; url: string } | { ok: false; error: string }> {\n const tried: string[] = [];\n for (const url of src.urls) {\n try {\n const res = await fetchImpl(url, { headers: { Accept: 'application/json' }, redirect: 'manual' });\n if (!res.ok) {\n tried.push(`${url} answered ${res.status}`);\n continue;\n }\n const doc = (await res.json()) as Manifest;\n if (!doc || typeof doc !== 'object' || !doc.surfaces || typeof doc.surfaces !== 'object') {\n tried.push(`${url} is not an embed manifest (no surfaces)`);\n continue;\n }\n if (src.product && doc.product !== src.product) {\n tried.push(`${url} speaks for \"${String(doc.product)}\", not ${src.product}`);\n continue;\n }\n return { ok: true, manifest: doc, url };\n } catch (e) {\n tried.push(`${url}: ${(e as Error).message}`);\n }\n }\n return { ok: false, error: tried.join('; ') || 'no URL to try' };\n}\n\nexport interface CspIo {\n fetch: typeof fetch;\n stdout: (text: string) => void;\n stderr: (text: string) => void;\n}\n\nexport async function cspCommand(\n opts: { merge?: string; framework?: string; site?: string; apiBase: string },\n io: CspIo,\n usage: (message: string) => Error,\n): Promise<number> {\n if (!opts.merge) throw usage('--merge is required: vendor names (cookiemunch, atlas, chatly, forumulate, referalli) or manifest URLs, comma-separated');\n if (opts.framework !== undefined && !(CSP_FRAMEWORKS as readonly string[]).includes(opts.framework)) {\n throw usage(`--framework must be one of ${CSP_FRAMEWORKS.join(', ')}`);\n }\n const { sources, unknown } = manifestSources(opts.merge, { apiBase: opts.apiBase, ...(opts.site ? { site: opts.site } : {}) });\n if (unknown.length) throw usage(`unknown vendor: ${unknown.join(', ')}. Name one of ${Object.keys(KNOWN_MANIFEST_HOSTS).join(', ')}, or pass its manifest URL (https://…/.well-known/forgedeck-embed.json).`);\n const manifests: Manifest[] = [];\n let failed = 0;\n for (const src of sources) {\n const r = await fetchManifest(src, io.fetch);\n if (r.ok) manifests.push(r.manifest);\n else {\n failed++;\n io.stderr(`${src.label}: no manifest — ${r.error}\\n`);\n }\n }\n if (manifests.length === 0) return 1;\n const policy = mergeManifests(manifests);\n io.stdout(`${renderPolicy(policy, opts.framework as CspFramework | undefined)}\\n`);\n const left = placeholders(manifests);\n if (left.length) io.stderr(`Tenant-specific sources left out (fill in your own value): ${left.join(', ')}\\n`);\n return failed ? 1 : 0;\n}\n","/**\n * `cookiemunch` — the Developer API from a terminal or a CI job.\n *\n * cookiemunch config pull --site <cbid> [--out file]\n * cookiemunch config diff --site <cbid> <file> [--replace] [--exit-code]\n * cookiemunch config push --site <cbid> <file> [--replace] [--strict]\n * cookiemunch config validate --site <cbid> <file> [--replace] [--strict]\n * cookiemunch preview --site <cbid> [--url <url>] [--region eu] [--lang de] [--ttl 900] [--open]\n * cookiemunch executors test <id> --email <email> [--operation locate]\n * cookiemunch executors webhook-test <id> --headers-file <json> --body-file <file>\n * cookiemunch executors deliveries <id>\n * cookiemunch executors presets\n * cookiemunch executors conformance <baseUrl> --secret-env <NAME> [--canary-email <addr>] [--prefix /privacy] [--json]\n * cookiemunch executors conformance --connection <id> [--json]\n * cookiemunch executors roll-completion-secret <id>\n * cookiemunch executors upgrade-preset <id> [--preset <name>] [--version <n>] [--org-id <id>] [--atlas-id-app-id <id>]\n * [--revoke-atlas-id-grant] [--accept-preset <path> …] [--dry-run]\n * cookiemunch executors recheck <id>\n * cookiemunch executors health <id> [--limit <n>]\n * cookiemunch rights-page pull|diff|push|publish --site <cbid> [<file>] [--base <updatedAt>] [--yes]\n * cookiemunch scan --site <cbid> [--wait] [--timeout <seconds>]\n * cookiemunch cookies presets|preset|unpreset|delete-observed|purge-observed --site <cbid> …\n * cookiemunch site update --site <cbid> [--domain <host>] [--name <name>] [--aliases a,b] [--dry-run]\n * cookiemunch site brand --site <cbid> [--url <https URL> | <brand.json>] [--dry-run]\n * cookiemunch health [--site <cbid>] [--json] [--fail-on error|warning|never]\n * cookiemunch provision <file> [--dry-run]\n * cookiemunch partners list|link|unlink --site <cbid> …\n * cookiemunch consent-sync status|rotate|remove|token --site <cbid> …\n * cookiemunch csp --merge <vendors|urls> [--framework next|express|nginx] [--site <cbid>]\n *\n * Everything goes through the typed SDK (@cookiemunch/sdk) except where the SDK has no\n * method yet; those calls go through `rawRequest` with the same key and base URL. All I/O\n * is injected, so the whole CLI is testable with a mocked fetch.\n */\n\nimport { createCookieMunch, CookieMunchApiError, exchangeOperatorToken, mintConsentSyncToken, runExecutorConformance, type CookieMunchClient } from '@cookiemunch/sdk';\nimport { diffJson, formatChanges, isPlainObject, mergeLikeServer, withoutReadOnly, type Change, type Json } from './diff.js';\nimport { rightsPageCommand } from './rights-page.js';\nimport { healthCommand, keysCommand, partnersCommand, provisionCommand, siteCommand } from './integrations.js';\nimport { countBySeverity, formatDesignWarnings, summaryLine } from './design-warnings.js';\nimport { cspCommand } from './csp.js';\nimport { bundleCommand, cookiesFileCommand, doctorCommand, dsarTestCommand, executorsFileCommand, keysExtraCommand, sandboxCommand, versionCommand, type OpsHelpers } from './ops.js';\n\nexport const DEFAULT_BASE_URL = 'https://api.cookiemunch.net';\n\nexport interface CliIo {\n env: Record<string, string | undefined>;\n fetch: typeof fetch;\n stdout: (text: string) => void;\n stderr: (text: string) => void;\n readFile: (path: string) => Promise<string>;\n /** `mode` is the file mode for a new file (0o600 for anything holding a secret). */\n writeFile: (path: string, data: string, mode?: number) => Promise<void>;\n /** Open a URL in the user's browser. */\n openUrl: (url: string) => Promise<void>;\n /**\n * Ask a yes/no question. Present only when a person can answer (an interactive terminal);\n * absent, a command that needs confirmation refuses unless given --yes.\n */\n confirm?: (question: string) => Promise<boolean>;\n}\n\nexport const USAGE = `cookiemunch — Cookie Munch from the command line\n\nUsage:\n cookiemunch config pull --site <cbid> [--out <file>]\n Write the site's config as JSON (to stdout, or to <file>).\n cookiemunch config diff --site <cbid> <file> [--replace] [--exit-code]\n Show what pushing <file> would change (the server's dry run; nothing is stored).\n Read-only fields a pulled file carries (effective, designWarnings, ...) are ignored.\n cookiemunch config push --site <cbid> <file> [--replace] [--strict]\n Apply <file>. Default: merged over the stored config (PATCH) — fields the file\n leaves out keep their value, and a field set to null is removed (it takes its\n default). --replace sends it whole (PUT): a top-level field the file leaves out\n reverts to its default. Prints any design warnings the server found. --strict\n checks the file first and does not push it (exit 1) when Accept all is pushed\n harder than Reject all anywhere — for CI.\n cookiemunch config validate --site <cbid> <file> [--replace] [--strict]\n Check <file> for consent-button parity on the server, without writing: is Accept\n all more prominent than Reject all (colour, size, placement, copy, custom CSS)?\n Merged over the stored config like push; --replace checks it as sent. --strict\n exits 1 when there is any warning (notices never fail).\n cookiemunch preview --site <cbid> [--url <page>] [--region <eu|de|us-ca…>] [--lang <de…>]\n [--ttl <seconds>] [--open]\n Print (and with --open, open) a link showing the banner as a visitor in that\n region and language sees it. Works in headless browsers; nothing is recorded.\n cookiemunch executors test <id> (--email <email> | --canary) [--operation <locate|export|erase>]\n Try a connected system against one person without filing a request.\n --operation defaults to locate (lookup is accepted as another name for it).\n --canary uses the organisation's canary address instead: no real person, and\n a canary locate also updates the connection's health. Exits 1 when not ok.\n cookiemunch executors webhook-test <id> --headers-file <json> --body-file <file>\n Would this webhook delivery verify? Sends the headers (a JSON object) and the\n body file byte for byte to the receiver's check; nothing is acted on. Prints\n { verified, stage, reason } and exits 1 when it does not verify.\n cookiemunch executors deliveries <id>\n The last 50 deliveries to that connection's webhook, each with its reason.\n cookiemunch executors presets\n The versioned presets, which are usable now and which wait on another\n platform, and the organisation's canary address.\n cookiemunch executors conformance <baseUrl> --secret-env <NAME> [--canary-email <addr>]\n [--prefix /privacy] [--json]\n Check any system against the open cm-standard-v2 executor contract, rule by\n rule, using only the canary subject. The credential is read from the\n environment variable NAME, never from the command line. Without\n --canary-email the organisation's canary address is fetched (needs\n COOKIEMUNCH_API_KEY); with it, no Cookie Munch key is needed at all.\n Exits 1 when any rule fails.\n cookiemunch executors conformance --connection <id> [--json]\n The same suite, run by Cookie Munch against a connected system.\n cookiemunch executors roll-completion-secret <id>\n A new completion secret for that connection, printed once; the old one keeps\n verifying for 24 hours.\n cookiemunch executors upgrade-preset <id> [--preset <name>] [--version <n>]\n [--org-id <id>] [--atlas-id-app-id <id>] [--revoke-atlas-id-grant]\n [--accept-preset <path> …] [--dry-run]\n Rebuild a connection from its preset's latest version (or --version), keeping\n its id and credentials; --preset adopts one on a hand-written connection.\n Your hand edits are kept (the diff marks them kept or conflict); --accept-preset\n (repeatable) takes the preset's value for that path. Prints the diff; --dry-run\n changes nothing. A pinned connection is refused.\n cookiemunch executors recheck <id>\n Re-check a connection now (a canary test that records its health): the hook to\n run after deploying that system's rights API. Exits 1 when it is not ok.\n cookiemunch executors health <id> [--limit <n>]\n The connection's last health checks, newest first (up to 50).\n cookiemunch rights-page pull --site <cbid> [--out <file>]\n Write the site's rights page draft as JSON, and print its updatedAt for --base.\n cookiemunch rights-page diff --site <cbid> <file> [--exit-code]\n Validate <file> on the server (dry run) and show what pushing it would change.\n cookiemunch rights-page push --site <cbid> <file> [--base <updatedAt>]\n Replace the draft with <file>. Nothing is live until publish. Refused (exit 1)\n if the draft changed since the diff, or since --base (the updatedAt pull printed).\n cookiemunch rights-page publish --site <cbid> [--yes] [--base <updatedAt>]\n Publish the draft (it goes live at once). Asks first; --yes skips the question\n and is required when there is no terminal to ask in. Prints why when the page\n cannot go live. Refused (exit 1) if the draft changed after it was read (or\n since --base); --yes never overrides that.\n\n cookiemunch scan --site <cbid> [--wait] [--timeout <seconds>]\n Start a cookie crawl of the site and print its state (JSON). --wait holds on\n until it is done or failed (default up to 120 s, --timeout to change) and exits\n 1 when it failed or is still running at the end. A scan already running is\n waited on rather than started twice.\n\n cookiemunch cookies presets --site <cbid>\n The declaration presets (atlas, forumulate, chatly, cookiemunch, referalli, firstpromoter,\n partnerstack, tapfiliate, impact; referally is the deprecated old name of referalli): what each takes,\n what it declared on this site, and whether the vendor's own manifest exists yet.\n cookiemunch cookies preset <vendor> --site <cbid> [--param k=v …] [--dry-run]\n Declare what that platform writes (cookies and browser storage), marked as\n declared by it; run again to re-sync. Atlas: --param frontendApiHost=auth.example.com\n [--param crossSubdomainCookies=false]. Chatly: --param publicId=ch_web_… .\n Referral and affiliate presets (referalli, firstpromoter, partnerstack, tapfiliate, impact):\n [--param cookieDomain=.example.com] [--param cookieDays=60] [--param category=…];\n referalli [--param legacyName=false], impact [--param campaignId=…]. A row filed under a\n disabled category prints a warning and a suggestedConfigPatch. Any other vendor is\n declared with the API (PUT /v1/sites/{cbid}/cookies).\n cookiemunch cookies unpreset <vendor> --site <cbid> [--dry-run]\n Remove every declaration that vendor's preset made.\n cookiemunch cookies import-manifest <url> --site <cbid> [--file <manifest.json>] [--dry-run]\n Declare any vendor's cookies and storage from its embed manifest\n (/.well-known/<product>-embed.json), by URL or from a file. Remove it with\n cookies unpreset <product>.\n cookiemunch cookies suggestions --site <cbid>\n What to declare: the platforms detected on the site and each undeclared row.\n cookiemunch cookies declare-suggestions --site <cbid> [--names a,b] [--dry-run]\n Declare them: detected vendors' presets, then every other suggestion with a purpose.\n cookiemunch cookies delete-observed <name> --site <cbid> [--dry-run]\n Remove every stored row of that name (a name the site never sets). A declaration stays.\n cookiemunch cookies purge-observed --site <cbid> --since <time> [--until <time>] [--dry-run]\n Remove every row a real visit first reported in that window (ISO-8601 or epoch ms).\n Crawled rows and declarations stay. Run with --dry-run first.\n cookiemunch site update --site <cbid> [--domain <host>] [--name <name> | --clear-name]\n [--aliases <a,b>] [--dry-run]\n Rename or move a site. The cbid and consent ledger stay; a domain move clears\n verification. --dry-run prints the diff and its effects without saving.\n cookiemunch site brand --site <cbid> [--url <https URL> | <brand.json>] [--dry-run]\n Import a brand.json into the banner theme (the rights page uses it too). Values the\n site set itself are kept. With neither --url nor a file, prints the last import.\n cookiemunch consent-sync status --site <cbid>\n Whether hosted consent sync is set up (the secret's last four characters, when it was minted).\n cookiemunch consent-sync rotate --site <cbid>\n Mint the site's consent-sync signing secret, or replace it (the old one stops at once).\n Prints the secret alone on stdout, so it can be piped into your secret store: it is shown once.\n cookiemunch consent-sync remove --site <cbid> --yes\n Remove it: hosted consent sync stops for every visitor.\n cookiemunch consent-sync token --site <cbid> --subject <id> [--ttl <seconds>]\n Sign a test token locally with COOKIEMUNCH_CONSENT_SYNC_SECRET (nothing is sent), e.g. to try\n GET /api/v1/<cbid>/profile with curl.\n cookiemunch health [--site <cbid>] [--json] [--fail-on error|warning|never]\n Every link the site's privacy wiring depends on, with a fix hint for each that\n fails. Exits 1 when a check fails (checks that could not run, or are waived, do not count).\n --fail-on error ignores warnings; --fail-on never always exits 0.\n cookiemunch provision <file> [--dry-run]\n Wire a product's privacy in one call (site, connections, Atlas, Forumulate) from\n a JSON file without secrets: the Atlas key and Forumulate token come from\n COOKIEMUNCH_ATLAS_SECRET_KEY and COOKIEMUNCH_FORUMULATE_TOKEN. Re-running is a\n no-op. Exits 1 when a step failed.\n cookiemunch keys report [--unused-days <n>] [--expiring-days <n>] [--json]\n Key hygiene: keys unused for n days (default 90), keys with broad access, and\n keys expiring within n days (default 14). Needs a full-access key.\n cookiemunch partners list|link|unlink --site <cbid> [--partner <id>]\n [--external-id <id>] [--label <text>] [<linkId>]\n Grant a partner platform the site's consent events (no secret is created), list\n the grants, or revoke one. Any partner this deployment knows (forumulate, atlas, chatly,\n referalli, or one registered for it).\n cookiemunch token exchange --subject-token-env NAME --scope <a,b> --resource org:<id>|site:<cbid> [--expires-in <s>]\n Swap your identity provider's token (read from the variable NAME) for a short-lived, scoped\n API key (at most 1 hour); prints the key alone. Needs no API key.\n cookiemunch csp --merge <vendors|urls> [--framework next|express|nginx] [--site <cbid>]\n One Content-Security-Policy from several products' embed manifests\n (/.well-known/<product>-embed.json): cookiemunch, atlas, chatly, forumulate,\n referalli, or any manifest URL. --framework prints it for next.config.js,\n Express or nginx; without it, the header value. --site uses your site's own\n Cookie Munch manifest (its logo, fonts, sync endpoint). Needs no API key. Exits 1\n when a named product has not published a manifest (the rest are still merged).\n cookiemunch cookies diff|push <file> --site <cbid> [--replace] [--exit-code]\n Declarations as a file ({\"cookies\": [...]}), through the server's dry run. push applies\n only when something differs; --replace also removes declarations the file leaves out.\n cookiemunch executors pull [<file>] | diff <file> | push <file> [--secret-env NAME]\n Connected systems as a file. The file never carries a secret: a new connection's API key\n comes from the environment variable --secret-env names.\n cookiemunch dsar test [--types access,deletion] [--with-cbid --site <cbid>] [--without-cbid]\n [--email <addr>] [--cleanup]\n File TEST rights requests and read each back. --cleanup deletes exactly the ones this run\n filed (by id; it never deletes by listing).\n cookiemunch doctor [--site <cbid>] [--org <id>]\n The key (and whose org it is, against --org or COOKIEMUNCH_ORG), its expiry, the CLI\n version against the latest, and integration health. Exits 1 when a check fails.\n cookiemunch keys vend --scopes <a,b> --ttl <1h|30m|seconds> [--cbids <x,y>] [--name <n>]\n A short-lived key (at most 12 h) within this key's own scopes; prints the key alone.\n Needs keys:write (or a full-access key).\n cookiemunch keys self | rotate-self\n This key's own prefix, scopes and expiry; or rotate it (the new key is printed once).\n cookiemunch sandbox [show] | create [--key-name <n>] | delete [--yes]\n The organisation's sandbox: a separate test organisation with the same people and plan\n features, never billed; its keys are test keys and its rights requests are all tests.\n create makes it (or reuses it) and prints a new key for it alone; delete erases it and\n everything in it, after asking. create and delete need a full-access key or orgs:create.\n cookiemunch plan [cookiemunch.json] [--exit-code] [--json]\n cookiemunch apply [cookiemunch.json] [--secret-env NAME] [--secrets-out <file>]\n One file for a site: {site, config, cookies, presets, executors, webhooks, rightsPage,\n partners}, no secrets. plan prints the server's dry run of every part (\"No changes\" when\n it matches); apply applies them in dependency order and logs each. New webhook secrets\n go to --secrets-out (mode 0600).\n cookiemunch --version | version [--json]\n The CLI version; --json adds the API version the server documents.\n\nEvery command takes --json for machine-readable output.\n\nExit codes:\n 0 ok, or nothing to change\n 1 a difference (with --exit-code), a failure, or a failed check\n 2 a usage mistake\n\nEnvironment:\n COOKIEMUNCH_API_KEY an API key (cookiemunch_live_…, or a legacy fck_…). Required.\n COOKIEMUNCH_BASE_URL the API origin. Default ${DEFAULT_BASE_URL}.\n COOKIEMUNCH_SITE default for --site.\n COOKIEMUNCH_STRICT_FIELDS=1 send Prefer: strict-unknown-fields on writes: a field the\n API does not know is refused (400 unknown_field), not ignored.\n COOKIEMUNCH_SECRET_RECIPIENT=x25519:<base64> answers carry once-shown secrets sealed to\n this key (sealed_secret), never in plaintext.\n COOKIEMUNCH_ORG the org id doctor checks the key against.\n --idempotency-key <k> send Idempotency-Key on writes: a retry replays the first answer.\n`;\n\n/** A usage mistake: exit code 2. */\nclass UsageError extends Error {}\n\ninterface Parsed {\n positional: string[];\n flags: Record<string, string | true>;\n}\n\nconst BOOLEAN_FLAGS = new Set(['replace', 'exit-code', 'open', 'help', 'json', 'yes', 'strict', 'wait', 'canary', 'dry-run', 'clear-name', 'revoke-atlas-id-grant', 'with-cbid', 'without-cbid', 'cleanup']);\n\nexport function parseArgs(argv: string[]): Parsed {\n const positional: string[] = [];\n const flags: Record<string, string | true> = {};\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!;\n if (a === '-h') {\n flags.help = true;\n } else if (a.startsWith('--')) {\n const eq = a.indexOf('=');\n const name = eq > 0 ? a.slice(2, eq) : a.slice(2);\n let value: string | true;\n if (eq > 0) value = a.slice(eq + 1);\n else if (BOOLEAN_FLAGS.has(name)) value = true;\n else {\n const v = argv[i + 1];\n if (v === undefined || v.startsWith('--')) throw new UsageError(`--${name} needs a value`);\n value = v;\n i++;\n }\n // --param repeats (k=v each); kept newline-joined so the rest of the parser stays simple.\n if ((name === 'param' || name === 'accept-preset') && typeof value === 'string' && typeof flags[name] === 'string') flags[name] = `${flags[name]}\\n${value}`;\n else flags[name] = value;\n } else {\n positional.push(a);\n }\n }\n return { positional, flags };\n}\n\nfunction str(flags: Parsed['flags'], name: string): string | undefined {\n const v = flags[name];\n return typeof v === 'string' ? v : undefined;\n}\n\nfunction requireSite(p: Parsed, io: CliIo): string {\n const site = str(p.flags, 'site') ?? io.env.COOKIEMUNCH_SITE;\n if (!site) throw new UsageError('--site <cbid> is required (or set COOKIEMUNCH_SITE)');\n return site;\n}\n\nasync function readConfigFile(io: CliIo, path: string | undefined): Promise<Record<string, unknown>> {\n if (!path) throw new UsageError('a config file is required');\n let text: string;\n try {\n text = await io.readFile(path);\n } catch (e) {\n throw new UsageError(`cannot read ${path}: ${(e as Error).message}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch (e) {\n throw new UsageError(`${path} is not valid JSON: ${(e as Error).message}`);\n }\n if (!isPlainObject(parsed)) throw new UsageError(`${path} must hold a JSON object`);\n return parsed;\n}\n\n/** What the stored config would become, per push mode. */\nfunction proposed(current: Record<string, unknown>, file: Record<string, unknown>, replace: boolean, cbid: string) {\n return replace ? { ...file, cbid } : mergeLikeServer(current, file);\n}\n\n/** This package's version, sent in the default User-Agent (a test pins it to package.json). */\nexport const CLI_VERSION = '0.7.1';\n\n/** `COOKIEMUNCH_USER_AGENT`, else `cookiemunch-cli/<version>`. */\nfunction userAgent(io: CliIo): string {\n return io.env.COOKIEMUNCH_USER_AGENT || `cookiemunch-cli/${CLI_VERSION}`;\n}\n\nasync function rawRequest(io: CliIo, base: string, key: string, method: string, path: string, body?: unknown): Promise<unknown> {\n const res = await io.fetch(`${base.replace(/\\/+$/, '')}/v1${path}`, {\n method,\n headers: { Authorization: `Bearer ${key}`, 'User-Agent': userAgent(io), ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}) },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n const text = await res.text();\n let data: unknown = text;\n try {\n data = text ? JSON.parse(text) : undefined;\n } catch {\n /* keep the text */\n }\n if (!res.ok) {\n const err = isPlainObject(data) ? data : {};\n throw new CookieMunchApiError(\n res.status,\n typeof err.error === 'string' ? err.error : `request failed with status ${res.status}`,\n typeof err.code === 'string' ? err.code : undefined,\n );\n }\n return data;\n}\n\n/**\n * What a write would change. The server's own `?dryRun=1` diff is the source of truth (it knows\n * its defaults and read-only fields); if it cannot answer, the same is computed here, with the\n * read-only fields (`effective`, `designWarnings`, `rightsFormUrl`, ...) dropped from both sides:\n * a file made by `config pull` carries them, and the server ignores them on a write.\n */\nasync function configChanges(client: CookieMunchClient, cbid: string, file: Record<string, unknown>, replace: boolean): Promise<Change[]> {\n const body = withoutReadOnly(file);\n try {\n const r = await client.sites.dryRunConfig(cbid, body as never, { mode: replace ? 'put' : 'patch' });\n if (r && r.dryRun === true && Array.isArray(r.diff)) {\n return r.diff.map((c) => {\n const ch: Change = { path: c.path, kind: c.from === undefined ? 'added' : c.to === undefined ? 'removed' : 'changed' };\n if (c.from !== undefined) ch.from = c.from as Json;\n if (c.to !== undefined) ch.to = c.to as Json;\n return ch;\n });\n }\n } catch {\n /* an older or unreachable dry run: fall back to the local diff below */\n }\n const current = withoutReadOnly((await client.sites.getConfig(cbid)) as unknown as Record<string, unknown>);\n return diffJson(current, proposed(current, body, replace, cbid));\n}\n\nasync function configCommand(sub: string | undefined, p: Parsed, io: CliIo, client: CookieMunchClient): Promise<number> {\n const cbid = requireSite(p, io);\n if (sub === 'pull') {\n const cfg = await client.sites.getConfig(cbid);\n const text = `${JSON.stringify(cfg, null, 2)}\\n`;\n const out = str(p.flags, 'out');\n if (out) {\n await io.writeFile(out, text);\n io.stderr(`Wrote ${cbid}'s config to ${out}\\n`);\n } else {\n io.stdout(text);\n }\n return 0;\n }\n if (sub === 'validate') {\n const file = await readConfigFile(io, p.positional[2]);\n const r = await client.sites.lintConfig(cbid, file as never, p.flags.replace === true ? { replace: true } : {});\n if (p.flags.json === true) io.stdout(`${JSON.stringify({ cbid, designWarnings: r.designWarnings }, null, 2)}\\n`);\n else if (r.designWarnings.length) io.stdout(`${formatDesignWarnings(r.designWarnings)}\\n`);\n io.stderr(`${summaryLine(r.designWarnings)}\\n`);\n return p.flags.strict === true && countBySeverity(r.designWarnings).warnings > 0 ? 1 : 0;\n }\n if (sub === 'diff' || sub === 'push') {\n const file = await readConfigFile(io, p.positional[2]);\n const replace = p.flags.replace === true;\n // --strict (push): check first, and do not write a config that fails it.\n if (sub === 'push' && p.flags.strict === true) {\n const lint = await client.sites.lintConfig(cbid, file as never, replace ? { replace: true } : {});\n if (countBySeverity(lint.designWarnings).warnings > 0) {\n io.stderr(`${formatDesignWarnings(lint.designWarnings)}\\n${summaryLine(lint.designWarnings)}\\nnot pushed (--strict).\\n`);\n return 1;\n }\n }\n const changes = await configChanges(client, cbid, file, replace);\n if (p.flags.json === true && (sub === 'diff' || changes.length === 0)) io.stdout(`${JSON.stringify({ cbid, changes }, null, 2)}\\n`);\n if (changes.length === 0) {\n io.stderr(`No changes: ${cbid}'s config already matches.\\n`);\n return 0;\n }\n if (p.flags.json !== true) io.stdout(`${formatChanges(changes)}\\n`);\n if (sub === 'diff') {\n io.stderr(`${changes.length} change${changes.length === 1 ? '' : 's'} (nothing sent). Apply with: cookiemunch config push --site ${cbid} ${p.positional[2]}${replace ? ' --replace' : ''}\\n`);\n return p.flags['exit-code'] === true ? 1 : 0;\n }\n const saved = (replace\n ? await client.sites.putConfig(cbid, { ...file, cbid } as never)\n : await client.sites.patchConfig(cbid, file as never)) as { designWarnings?: unknown };\n io.stderr(`Applied ${changes.length} change${changes.length === 1 ? '' : 's'} to ${cbid}.\\n`);\n const found = Array.isArray(saved?.designWarnings) ? (saved.designWarnings as Parameters<typeof formatDesignWarnings>[0]) : [];\n if (p.flags.json === true) io.stdout(`${JSON.stringify({ cbid, applied: changes, designWarnings: found }, null, 2)}\\n`);\n if (found.length) io.stderr(`${formatDesignWarnings(found)}\\n${summaryLine(found)}\\n`);\n return 0;\n }\n throw new UsageError(`unknown config command: ${sub ?? '(none)'} — use pull, diff, push or validate`);\n}\n\nasync function previewCommand(p: Parsed, io: CliIo, client: CookieMunchClient): Promise<number> {\n const cbid = requireSite(p, io);\n const ttl = str(p.flags, 'ttl');\n const ttlSeconds = ttl === undefined ? undefined : Number(ttl);\n if (ttlSeconds !== undefined && (!Number.isInteger(ttlSeconds) || ttlSeconds < 1 || ttlSeconds > 3600)) {\n throw new UsageError('--ttl must be a whole number of seconds from 1 to 3600');\n }\n const r = await client.sites.previewToken(cbid, {\n ...(str(p.flags, 'region') ? { region: str(p.flags, 'region')! } : {}),\n ...(str(p.flags, 'lang') ? { lang: str(p.flags, 'lang')! } : {}),\n ...(str(p.flags, 'url') ? { url: str(p.flags, 'url')! } : {}),\n ...(ttlSeconds !== undefined ? { ttlSeconds } : {}),\n });\n if (p.flags.json === true) {\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n } else if (r.previewUrl) {\n io.stdout(`${r.previewUrl}\\n`);\n } else {\n // No page to put it on (the site has no domain and no --url): hand over the token.\n io.stdout(`${r.token}\\n`);\n io.stderr('Add ?cm_preview=<token>&cm_region=..&cm_lang=.. to any page of the site.\\n');\n }\n io.stderr(`Valid until ${new Date(r.expiresAt).toISOString()}.\\n`);\n if (p.flags.open === true && r.previewUrl) await io.openUrl(r.previewUrl);\n return 0;\n}\n\nasync function consentSyncCommand(sub: string | undefined, p: Parsed, io: CliIo, client: CookieMunchClient): Promise<number> {\n const cbid = requireSite(p, io);\n if (sub === 'status') {\n io.stdout(`${JSON.stringify(await client.consentSyncSecret.get(cbid), null, 2)}\\n`);\n return 0;\n }\n if (sub === 'rotate') {\n const r = await client.consentSyncSecret.rotate(cbid);\n io.stdout(p.flags.json === true ? `${JSON.stringify(r, null, 2)}\\n` : `${r.secret}\\n`);\n io.stderr('This secret is shown once: store it on your server (never in a page). A previous secret stopped working.\\n');\n return 0;\n }\n if (sub === 'remove') {\n if (p.flags.yes !== true) throw new UsageError('consent-sync remove stops hosted consent sync for every visitor: add --yes');\n await client.consentSyncSecret.remove(cbid);\n io.stderr(`Hosted consent sync is off for ${cbid}.\\n`);\n return 0;\n }\n if (sub === 'token') {\n const secret = io.env.COOKIEMUNCH_CONSENT_SYNC_SECRET;\n if (!secret) throw new UsageError('set COOKIEMUNCH_CONSENT_SYNC_SECRET to the site\\'s consent-sync secret');\n const subject = str(p.flags, 'subject');\n if (!subject) throw new UsageError('--subject <id> is required');\n const ttl = str(p.flags, 'ttl');\n try {\n const token = mintConsentSyncToken({ secret, cbid, subject, ...(ttl !== undefined ? { ttlSeconds: Number(ttl) } : {}) });\n io.stdout(p.flags.json === true ? `${JSON.stringify({ token }, null, 2)}\\n` : `${token}\\n`);\n } catch (e) {\n throw new UsageError((e as Error).message);\n }\n return 0;\n }\n throw new UsageError(`unknown consent-sync command: ${sub ?? '(none)'} — use status, rotate, remove or token`);\n}\n\nasync function executorsCommand(\n sub: string | undefined,\n p: Parsed,\n io: CliIo,\n base: string,\n key: string,\n client: CookieMunchClient,\n): Promise<number> {\n if (sub === 'webhook-test') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors webhook-test <id> needs the connection id');\n const headersFile = str(p.flags, 'headers-file');\n const bodyFile = str(p.flags, 'body-file');\n if (!headersFile || !bodyFile) throw new UsageError('--headers-file and --body-file are both required');\n let headers: unknown;\n try {\n headers = JSON.parse(await io.readFile(headersFile));\n } catch {\n throw new UsageError(`${headersFile} is not a JSON object of header name to value`);\n }\n if (!isPlainObject(headers)) throw new UsageError(`${headersFile} is not a JSON object of header name to value`);\n // The body is sent exactly as read: the signature is over these bytes, so no trimming.\n const body = await io.readFile(bodyFile);\n const r = await client.fulfillment.testExecutorWebhook(id, { headers: headers as Record<string, string>, body });\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n return r.verified ? 0 : 1;\n }\n if (sub === 'deliveries') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors deliveries <id> needs the connection id');\n io.stdout(`${JSON.stringify(await client.fulfillment.executorWebhookDeliveries(id), null, 2)}\\n`);\n return 0;\n }\n if (sub === 'presets') {\n io.stdout(`${JSON.stringify(await client.fulfillment.executorPresets(), null, 2)}\\n`);\n return 0;\n }\n if (sub === 'conformance') return conformanceCommand(p, io, client);\n if (sub === 'roll-completion-secret') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors roll-completion-secret <id> needs the connection id');\n io.stdout(`${JSON.stringify(await client.fulfillment.rollExecutorCompletionSecret(id), null, 2)}\\n`);\n return 0;\n }\n if (sub === 'upgrade-preset') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors upgrade-preset <id> needs the connection id');\n const version = str(p.flags, 'version');\n if (version !== undefined && !/^[1-9]\\d*$/.test(version)) throw new UsageError('--version must be a positive whole number');\n const preset = str(p.flags, 'preset');\n const orgId = str(p.flags, 'org-id');\n const atlasIdAppId = str(p.flags, 'atlas-id-app-id');\n const accept = str(p.flags, 'accept-preset');\n const input = {\n ...(preset ? { preset: preset as never } : {}),\n ...(version ? { presetVersion: Number(version) } : {}),\n ...(orgId ? { orgId } : {}),\n ...(atlasIdAppId ? { atlasIdAppId } : {}),\n ...(p.flags['revoke-atlas-id-grant'] === true ? { revokeAtlasIdGrant: true } : {}),\n ...(accept ? { acceptPreset: accept.split('\\n') } : {}),\n };\n const r =\n p.flags['dry-run'] === true\n ? await client.fulfillment.dryRunUpgradeExecutorPreset(id, input)\n : await client.fulfillment.upgradeExecutorPreset(id, input);\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n return 0;\n }\n if (sub === 'recheck') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors recheck <id> needs the connection id');\n const r = await client.fulfillment.recheckExecutor(id);\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n // A deploy hook: a failing check fails the step.\n return r.ok === false ? 1 : 0;\n }\n if (sub === 'health') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors health <id> needs the connection id');\n const limit = str(p.flags, 'limit');\n if (limit !== undefined && !/^[1-9]\\d*$/.test(limit)) throw new UsageError('--limit must be a whole number from 1 to 50');\n io.stdout(`${JSON.stringify(await client.fulfillment.executorHealthHistory(id, limit ? { limit: Number(limit) } : {}), null, 2)}\\n`);\n return 0;\n }\n if (sub !== 'test') throw new UsageError(`unknown executors command: ${sub ?? '(none)'} — use test, webhook-test, deliveries, presets, upgrade-preset, conformance, roll-completion-secret, recheck or health`);\n const id = p.positional[2];\n if (!id) throw new UsageError('executors test <id> needs the connection id');\n const canary = p.flags.canary === true;\n const email = str(p.flags, 'email');\n if (canary && email) throw new UsageError('use --email or --canary, not both');\n if (!email && !canary) throw new UsageError('--email (or --canary) is required');\n // The API's operations are locate, export and erase. `lookup` was this CLI's documented\n // default and the API refused it (400), so it stays accepted as another name for locate.\n const asked = str(p.flags, 'operation') ?? 'locate';\n const operation = asked === 'lookup' ? 'locate' : asked;\n // The typed SDK has no method for this yet, so it is a direct call with the same key.\n try {\n const r = await rawRequest(io, base, key, 'POST', `/dsar/executors/${encodeURIComponent(id)}/test`, canary ? { canary: true, operation } : { email, operation });\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n // A canary test is a health check: a failing one fails the command, so it can gate a deploy.\n return canary && (r as { ok?: unknown }).ok === false ? 1 : 0;\n } catch (e) {\n // The API's generic route miss is a bare `not found`; an unknown connection says so.\n if (e instanceof CookieMunchApiError && e.status === 404 && e.message === 'not found') {\n io.stderr('This server does not offer connection tests yet (POST /v1/dsar/executors/{id}/test).\\n');\n return 1;\n }\n throw e;\n }\n}\n\n/** One rule per line: PASS/FAIL/SKIP, its id, and what was seen when it did not pass. */\nfunction printConformance(io: CliIo, report: { ok: boolean; passed: number; failed: number; skipped: number; rules: Array<{ id: string; title: string; status: string; detail?: string }> }, asJson: boolean): number {\n if (asJson) {\n io.stdout(`${JSON.stringify(report, null, 2)}\\n`);\n } else {\n for (const r of report.rules) {\n io.stdout(`${r.status.toUpperCase().padEnd(4)} ${r.id} ${r.title}\\n`);\n if (r.detail && r.status !== 'pass') io.stdout(` ${r.detail}\\n`);\n }\n io.stdout(`\\n${report.passed} passed, ${report.failed} failed, ${report.skipped} skipped\\n`);\n }\n return report.ok ? 0 : 1;\n}\n\nasync function conformanceCommand(p: Parsed, io: CliIo, client: CookieMunchClient | null): Promise<number> {\n const asJson = p.flags.json === true;\n const connection = str(p.flags, 'connection');\n if (connection) {\n if (!client) throw new UsageError('--connection runs on Cookie Munch: set COOKIEMUNCH_API_KEY');\n return printConformance(io, await client.fulfillment.executorConformance(connection), asJson);\n }\n const baseUrl = p.positional[2];\n if (!baseUrl) throw new UsageError('executors conformance <baseUrl> --secret-env <NAME> (or --connection <id>)');\n const secretEnv = str(p.flags, 'secret-env');\n if (!secretEnv) throw new UsageError('--secret-env <NAME> names the environment variable holding the executor credential');\n const secret = io.env[secretEnv];\n if (!secret) throw new UsageError(`the environment variable ${secretEnv} is empty`);\n let canaryEmail = str(p.flags, 'canary-email');\n if (!canaryEmail) {\n if (!client) throw new UsageError('pass --canary-email, or set COOKIEMUNCH_API_KEY to use your organisation\\'s canary address');\n canaryEmail = (await client.fulfillment.executorPresets()).canaryEmail;\n }\n const prefix = str(p.flags, 'prefix');\n let report;\n try {\n report = await runExecutorConformance({ baseUrl, secret, canaryEmail, fetch: io.fetch, ...(prefix ? { prefix } : {}) });\n } catch (e) {\n throw new UsageError((e as Error).message);\n }\n return printConformance(io, report, asJson);\n}\n\nasync function scanCommand(p: Parsed, io: CliIo, client: CookieMunchClient): Promise<number> {\n const cbid = requireSite(p, io);\n const timeout = str(p.flags, 'timeout');\n const timeoutS = timeout === undefined ? 120 : Number(timeout);\n if (!Number.isFinite(timeoutS) || timeoutS < 1 || timeoutS > 3600) throw new UsageError('--timeout must be a number of seconds from 1 to 3600');\n let started: Awaited<ReturnType<CookieMunchClient['sites']['scan']>> | null = null;\n try {\n started = await client.sites.scan(cbid);\n } catch (e) {\n if (!(e instanceof CookieMunchApiError && e.status === 409)) throw e;\n io.stderr(`A scan of ${cbid} is already running${p.flags.wait === true ? '; waiting for it' : ''}.\\n`);\n if (p.flags.wait !== true) return 0;\n }\n if (p.flags.wait !== true) {\n io.stdout(`${JSON.stringify(started, null, 2)}\\n`);\n return 0;\n }\n const r = await client.sites.waitForScan(cbid, { timeoutMs: timeoutS * 1000 });\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n if (r.state === 'failed') {\n io.stderr(`Scan ${r.scanId ?? ''} failed: ${r.error ?? 'no reason given'}\\n`);\n return 1;\n }\n if (r.status === 'scanning') {\n io.stderr(`Scan ${r.scanId ?? ''} is still running after ${timeoutS} s.\\n`);\n return 1;\n }\n const n = r.cookieCount ?? 0;\n const pages = r.pagesVisited !== undefined ? ` on ${r.pagesVisited} page${r.pagesVisited === 1 ? '' : 's'}` : '';\n const kept = r.keptFromEarlier ? `, ${r.keptFromEarlier} kept from earlier crawls and visits` : '';\n const took = r.durationMs !== undefined ? ` in ${Math.round(r.durationMs / 1000)} s` : '';\n const landed = r.finalUrl ? ` (redirected to ${r.finalUrl})` : '';\n io.stderr(`Scan ${r.scanId ?? ''} done${took}: ${n} cookie${n === 1 ? '' : 's'} seen${pages}${kept}${landed}.\\n`);\n return 0;\n}\n\nconst PRESET_VENDORS = ['atlas', 'forumulate', 'chatly', 'cookiemunch', 'referalli', 'firstpromoter', 'partnerstack', 'tapfiliate', 'impact'] as const;\n/** Old preset names still accepted (the server answers them with a Deprecation header). */\nconst PRESET_ALIASES: Record<string, Vendor> = { referally: 'referalli' };\ntype Vendor = (typeof PRESET_VENDORS)[number];\n\nfunction vendorArg(v: string | undefined): Vendor {\n if (v && Object.prototype.hasOwnProperty.call(PRESET_ALIASES, v)) return PRESET_ALIASES[v]!;\n if (!v || !(PRESET_VENDORS as readonly string[]).includes(v)) throw new UsageError(`a vendor is required: ${PRESET_VENDORS.join(', ')}`);\n return v as Vendor;\n}\n\n/** `--param k=v` (repeatable) → an object; `true`/`false` become booleans, `cookieDays` a number. */\nfunction presetParams(p: Parsed): Record<string, string | boolean | number> {\n const raw = str(p.flags, 'param');\n const out: Record<string, string | boolean | number> = {};\n for (const line of raw ? raw.split('\\n') : []) {\n const eq = line.indexOf('=');\n if (eq <= 0) throw new UsageError(`--param takes key=value, got \"${line}\"`);\n const v = line.slice(eq + 1);\n const k = line.slice(0, eq);\n out[k] = v === 'true' ? true : v === 'false' ? false : k === 'cookieDays' && /^\\d+$/.test(v) ? Number(v) : v;\n }\n return out;\n}\n\n/** `cookiemunch cookies …`: vendor presets and removing what real-visit beacons stored (CKM-S-02, S-29). */\nasync function cookiesCommand(sub: string | undefined, p: Parsed, io: CliIo, client: CookieMunchClient): Promise<number> {\n const dry = p.flags['dry-run'] === true ? { dryRun: true as const } : undefined;\n const print = (v: unknown) => io.stdout(`${JSON.stringify(v, null, 2)}\\n`);\n if (sub === 'presets') {\n print(await client.sites.cookiePresets(requireSite(p, io)));\n return 0;\n }\n // A custom preset (import-manifest) is removed by its product id, which no list here knows.\n if (sub === 'unpreset' && p.positional[2] && !(PRESET_VENDORS as readonly string[]).includes(p.positional[2])) {\n print(await client.sites.removeCookiePreset(requireSite(p, io), p.positional[2], dry));\n return 0;\n }\n if (sub === 'preset' || sub === 'unpreset') {\n const cbid = requireSite(p, io);\n const vendor = vendorArg(p.positional[2]);\n if (sub === 'unpreset') {\n print(await client.sites.removeCookiePreset(cbid, vendor, dry));\n return 0;\n }\n const r = await client.sites.applyCookiePreset(cbid, vendor, presetParams(p), dry);\n print(r);\n if (r.note) io.stderr(`${r.note}\\n`);\n for (const s of r.skipped ?? []) io.stderr(`skipped ${s.name}: ${s.reason}\\n`);\n if (r.manifest.status === 'waiting_on_vendor') io.stderr(`Built-in rows: ${r.manifest.waitingOn} does not publish a manifest yet (${r.manifest.item}).\\n`);\n return 0;\n }\n // Any vendor's embed manifest as a preset; what to declare; declare it (CMU-X36, CMU-D15).\n if (sub === 'import-manifest') {\n const cbid = requireSite(p, io);\n const src = p.positional[2];\n const file = str(p.flags, 'file');\n if (!src && !file) throw new UsageError('a manifest URL (https://…/.well-known/<product>-embed.json) or --file <manifest.json> is required');\n const input = file ? { manifest: JSON.parse(await io.readFile(file)) as never } : { url: src! };\n const r = await client.sites.importCookieManifest(cbid, input, dry);\n print(r);\n for (const s of r.skipped ?? []) io.stderr(`skipped ${s.name}: ${s.reason}\\n`);\n return 0;\n }\n if (sub === 'suggestions') {\n const r = await client.sites.cookieSuggestions(requireSite(p, io));\n print(r);\n io.stderr(`${r.suggestions.length} suggestion${r.suggestions.length === 1 ? '' : 's'}; ${r.vendors.length} platform${r.vendors.length === 1 ? '' : 's'} detected.\\n`);\n return 0;\n }\n if (sub === 'declare-suggestions') {\n const cbid = requireSite(p, io);\n const names = str(p.flags, 'names');\n const r = await client.sites.declareCookieSuggestions(cbid, names ? { names: names.split(',').map((n) => n.trim()).filter(Boolean) } : {}, dry);\n print(r);\n io.stderr(`${dry ? 'Would declare' : 'Declared'} ${r.declaredCount} row${r.declaredCount === 1 ? '' : 's'} and ${r.presetsApplied.length} preset${r.presetsApplied.length === 1 ? '' : 's'}.\\n`);\n return 0;\n }\n if (sub === 'delete-observed') {\n const cbid = requireSite(p, io);\n const name = p.positional[2];\n if (!name) throw new UsageError('a cookie name is required');\n if (dry) print(await client.sites.deleteObservedCookie(cbid, name, dry));\n else {\n await client.sites.deleteObservedCookie(cbid, name);\n io.stderr(`Removed ${name}.\\n`);\n }\n return 0;\n }\n if (sub === 'purge-observed') {\n const cbid = requireSite(p, io);\n const since = str(p.flags, 'since');\n if (!since) throw new UsageError('--since is required (ISO-8601 or epoch ms)');\n const until = str(p.flags, 'until');\n const r = await client.sites.purgeObservedCookies(cbid, { since, ...(until ? { until } : {}) }, dry);\n print(r);\n io.stderr(`${dry ? 'Would remove' : 'Removed'} ${r.count} row${r.count === 1 ? '' : 's'}.\\n`);\n return 0;\n }\n throw new UsageError(`unknown cookies command: ${sub ?? '(none)'}`);\n}\n\n/** Run the CLI. Returns the process exit code: 0 ok, 1 failed, 2 usage. */\nexport async function run(argv: string[], io: CliIo): Promise<number> {\n // CMU-B15: a leading --version (or -V) prints the version and needs no key. Only leading: `--version <n>`\n // is a value flag of `executors upgrade-preset`.\n if (argv[0] === '--version' || argv[0] === '-V') return versionCommand(io, CLI_VERSION, io.env.COOKIEMUNCH_BASE_URL || DEFAULT_BASE_URL, argv.includes('--json'));\n let p: Parsed;\n try {\n p = parseArgs(argv);\n } catch (e) {\n io.stderr(`${(e as Error).message}\\n\\n${USAGE}`);\n return 2;\n }\n const [cmd, sub] = p.positional;\n // `version [--json]` needs no key either.\n if (cmd === 'version') {\n return versionCommand(io, CLI_VERSION, io.env.COOKIEMUNCH_BASE_URL || DEFAULT_BASE_URL, p.flags.json === true);\n }\n if (!cmd || p.flags.help === true || cmd === 'help') {\n io.stdout(USAGE);\n return cmd || p.flags.help === true ? 0 : 2;\n }\n // The conformance kit checks the open contract against any system; with --canary-email it\n // needs no Cookie Munch key at all, so anyone implementing the contract can run it.\n if (cmd === 'executors' && sub === 'conformance' && !io.env.COOKIEMUNCH_API_KEY && str(p.flags, 'canary-email')) {\n try {\n return await conformanceCommand(p, io, null);\n } catch (e) {\n if (e instanceof UsageError) {\n io.stderr(`${e.message}\\n`);\n return 2;\n }\n throw e;\n }\n }\n const base = io.env.COOKIEMUNCH_BASE_URL || DEFAULT_BASE_URL;\n // Token exchange (CMU-X33) needs no API key: it is how you get one. The subject token is read from the\n // environment variable --subject-token-env names, never from the command line (shell history, ps).\n if (cmd === 'token' && p.positional[1] === 'exchange') {\n const envName = str(p.flags, 'subject-token-env');\n const subjectToken = envName ? io.env[envName] : undefined;\n const scope = (str(p.flags, 'scope') ?? '').split(/[,\\s]+/).filter(Boolean);\n const resource = str(p.flags, 'resource');\n const exp = str(p.flags, 'expires-in');\n if (!envName || !subjectToken) { io.stderr(`token exchange needs --subject-token-env NAME, naming a variable that holds your identity provider's token\\n`); return 2; }\n if (!scope.length) { io.stderr('token exchange needs --scope a,b (an exchanged key is never full access)\\n'); return 2; }\n if (!resource || !/^(org|site):.+/.test(resource)) { io.stderr('token exchange needs --resource org:<id> or site:<cbid>\\n'); return 2; }\n if (exp !== undefined && !/^\\d+$/.test(exp)) { io.stderr('--expires-in must be a number of seconds\\n'); return 2; }\n try {\n const r = await exchangeOperatorToken({\n subjectToken, scope, resource: resource as `org:${string}`, baseUrl: base, fetch: io.fetch,\n ...(exp !== undefined ? { expiresIn: Number(exp) } : {}),\n });\n // The key alone on stdout, so `export COOKIEMUNCH_API_KEY=$(cookiemunch token exchange …)` works.\n io.stdout(p.flags.json === true ? `${JSON.stringify(r, null, 2)}\\n` : `${r.accessToken}\\n`);\n return 0;\n } catch (e) {\n io.stderr(`${(e as Error).message}\\n`);\n return 1;\n }\n }\n // Every embed manifest is public: csp needs no key.\n if (cmd === 'csp') {\n try {\n const merge = str(p.flags, 'merge');\n const framework = str(p.flags, 'framework');\n const site = str(p.flags, 'site') ?? io.env.COOKIEMUNCH_SITE;\n return await cspCommand(\n { apiBase: base, ...(merge ? { merge } : {}), ...(framework ? { framework } : {}), ...(site ? { site } : {}) },\n io,\n (m) => new UsageError(m),\n );\n } catch (e) {\n if (e instanceof UsageError) {\n io.stderr(`${e.message}\\n\\n${USAGE}`);\n return 2;\n }\n io.stderr(`${(e as Error).message ?? String(e)}\\n`);\n return 1;\n }\n }\n const key = io.env.COOKIEMUNCH_API_KEY;\n if (!key) {\n io.stderr('COOKIEMUNCH_API_KEY is not set. Create a key under Developers in the dashboard.\\n');\n return 2;\n }\n const client = createCookieMunch({\n apiKey: key, baseUrl: base, fetch: io.fetch, userAgent: userAgent(io),\n ...(io.env.COOKIEMUNCH_STRICT_FIELDS === '1' ? { strictUnknownFields: true } : {}),\n ...(io.env.COOKIEMUNCH_SECRET_RECIPIENT ? { secretRecipient: io.env.COOKIEMUNCH_SECRET_RECIPIENT } : {}),\n ...(typeof p.flags['idempotency-key'] === 'string' ? { headers: { 'Idempotency-Key': p.flags['idempotency-key'] } } : {}),\n });\n const ops: OpsHelpers = {\n requireSite: () => requireSite(p, io),\n site: () => str(p.flags, 'site') ?? io.env.COOKIEMUNCH_SITE,\n readJson: (path) => readConfigFile(io, path),\n usage: (m) => new UsageError(m),\n flag: (name) => p.flags[name],\n positional: p.positional,\n };\n try {\n if (cmd === 'cookies' && (sub === 'diff' || sub === 'push')) return await cookiesFileCommand(sub, io, client, ops);\n if (cmd === 'executors' && (sub === 'pull' || sub === 'diff' || sub === 'push')) return await executorsFileCommand(sub, io, client, ops);\n if (cmd === 'dsar' && sub === 'test') return await dsarTestCommand(io, client, ops);\n if (cmd === 'doctor') return await doctorCommand(io, client, ops, CLI_VERSION);\n if (cmd === 'keys' && sub && sub !== 'report') return await keysExtraCommand(sub, io, client, ops);\n if (cmd === 'sandbox') return await sandboxCommand(sub, io, client, ops);\n if (cmd === 'plan' || cmd === 'apply') return await bundleCommand(cmd, io, client, ops);\n if (cmd === 'config') return await configCommand(sub, p, io, client);\n if (cmd === 'preview') return await previewCommand(p, io, client);\n if (cmd === 'scan') return await scanCommand(p, io, client);\n if (cmd === 'consent-sync') return await consentSyncCommand(sub, p, io, client);\n if (cmd === 'cookies') return await cookiesCommand(sub, p, io, client);\n if (cmd === 'executors') return await executorsCommand(sub, p, io, base, key, client);\n const helpers = {\n requireSite: () => requireSite(p, io),\n site: () => str(p.flags, 'site') ?? io.env.COOKIEMUNCH_SITE,\n readJson: (path: string | undefined) => readConfigFile(io, path),\n usage: (m: string) => new UsageError(m),\n flag: (name: string) => p.flags[name],\n };\n if (cmd === 'site') return await siteCommand(sub, io, client, helpers, p.positional[2]);\n if (cmd === 'health') return await healthCommand(io, client, helpers);\n if (cmd === 'provision') return await provisionCommand(sub, io, client, helpers);\n if (cmd === 'keys') return await keysCommand(sub, io, client, helpers);\n if (cmd === 'partners') return await partnersCommand(sub, p.positional.slice(2), io, client, helpers);\n if (cmd === 'rights-page') {\n return await rightsPageCommand(sub, p, io, client, {\n requireSite: () => requireSite(p, io),\n readJson: (path) => readConfigFile(io, path),\n usage: (m) => new UsageError(m),\n });\n }\n throw new UsageError(`unknown command: ${cmd}`);\n } catch (e) {\n if (e instanceof UsageError) {\n io.stderr(`${e.message}\\n\\n${USAGE}`);\n return 2;\n }\n if (e instanceof CookieMunchApiError) {\n io.stderr(`API error ${e.status}${e.code ? ` (${e.code})` : ''}: ${e.message}\\n`);\n return 1;\n }\n io.stderr(`${(e as Error).message ?? String(e)}\\n`);\n return 1;\n }\n}\n","/**\n * `cookiemunch site update`, `cookiemunch health`, `cookiemunch provision` and `cookiemunch partners`.\n *\n * Provisioning secrets are read from the environment (COOKIEMUNCH_ATLAS_SECRET_KEY,\n * COOKIEMUNCH_FORUMULATE_TOKEN), never from the command line where they would land in shell history,\n * and are never printed.\n */\nimport type { CookieMunchClient, PartnerLinkCreate, ProvisionRequest } from '@cookiemunch/sdk';\nimport type { CliIo } from './cli.js';\n\ninterface Helpers {\n requireSite(): string;\n site(): string | undefined;\n readJson(path: string | undefined): Promise<Record<string, unknown>>;\n usage(msg: string): Error;\n flag(name: string): string | true | undefined;\n}\n\nconst out = (io: CliIo, v: unknown) => io.stdout(`${JSON.stringify(v, null, 2)}\\n`);\n\n/** `cookiemunch site update --site <cbid> [--domain d] [--name n | --clear-name] [--aliases a,b] [--dry-run]` */\nexport async function siteCommand(sub: string | undefined, io: CliIo, client: CookieMunchClient, h: Helpers, file?: string): Promise<number> {\n if (sub === 'brand') return brandCommand(io, client, h, file);\n if (sub !== 'update') throw h.usage('usage: cookiemunch site update --site <cbid> [--domain <host>] [--name <name>] [--aliases a,b] [--dry-run]');\n const cbid = h.requireSite();\n const domain = h.flag('domain');\n const name = h.flag('name');\n const aliases = h.flag('aliases');\n const patch: { domain?: string; name?: string | null; aliases?: string[] } = {};\n if (typeof domain === 'string') patch.domain = domain;\n if (h.flag('clear-name') === true) patch.name = null;\n else if (typeof name === 'string') patch.name = name;\n if (typeof aliases === 'string') patch.aliases = aliases.split(',').map((a) => a.trim()).filter(Boolean);\n if (Object.keys(patch).length === 0) throw h.usage('nothing to change: give --domain, --name, --clear-name or --aliases');\n const r = await client.sites.update(cbid, patch, { dryRun: h.flag('dry-run') === true });\n out(io, r);\n if (r.effects.verification === 'reset') io.stderr('The domain moved: verify the new domain (GET /v1/sites/{cbid}/verify/challenge).\\n');\n for (const w of r.warnings ?? []) io.stderr(`warning (${w.field}): ${w.reason}\\n`);\n return 0;\n}\n\n/**\n * `cookiemunch site brand --site <cbid> (--url <https URL> | <brand.json>) [--dry-run]` imports a brand.json into the\n * banner theme (CMU-X44); with neither, it prints the read-back of the last import.\n */\nasync function brandCommand(io: CliIo, client: CookieMunchClient, h: Helpers, file: string | undefined): Promise<number> {\n const cbid = h.requireSite();\n const url = h.flag('url');\n const r = typeof url === 'string'\n ? await client.sites.setBrand(cbid, { url }, { dryRun: h.flag('dry-run') === true })\n : file\n ? await client.sites.setBrand(cbid, (await h.readJson(file)) as Record<string, unknown>, { dryRun: h.flag('dry-run') === true })\n : await client.sites.getBrand(cbid);\n out(io, r);\n for (const w of r.warnings) io.stderr(`warning (${w.role}): ${w.message}\\n`);\n for (const w of r.configWarnings ?? []) io.stderr(`warning (${w.field}): ${w.reason}\\n`);\n return 0;\n}\n\n/** `cookiemunch health [--site <cbid>]` — exits 1 when a check fails, so CI can gate on it. */\nexport async function healthCommand(io: CliIo, client: CookieMunchClient, h: Helpers): Promise<number> {\n // --fail-on error | warning (default) | never: which failing severity makes the exit code 1, for CI.\n const failOn = h.flag('fail-on') ?? 'warning';\n if (failOn !== 'error' && failOn !== 'warning' && failOn !== 'never') throw h.usage('--fail-on must be error, warning or never');\n const r = await client.integrationHealth(h.site());\n if (h.flag('json') === true) out(io, r);\n else {\n for (const c of r.checks) {\n const mark = c.waived ? 'WAIV' : c.ok === true ? 'ok ' : c.ok === false ? (c.severity === 'error' ? 'FAIL' : 'WARN') : '-- ';\n const net = c.hop ? ` (${c.hop}${c.status !== undefined ? ` ${c.status}` : ''}${c.elapsedMs !== undefined ? `, ${c.elapsedMs} ms` : ''})` : '';\n io.stdout(`${mark} ${c.check} — ${c.subject}${c.detail ? `: ${c.detail}` : ''}${net}${c.waived ? ` — waived: ${c.waived.reason}` : ''}\\n`);\n const fix = c.fix ?? c.fixHint;\n if (c.ok === false && fix) io.stdout(` fix: ${fix}\\n`);\n }\n io.stdout(`${r.counts.error} error(s), ${r.counts.warning} warning(s), ${r.counts.notChecked} not checked${r.counts.waived ? `, ${r.counts.waived} waived` : ''}\\n`);\n }\n if (failOn === 'never') return 0;\n const failing = r.checks.filter((c) => c.ok === false && (c.severity === 'error' || (failOn === 'warning' && c.severity === 'warning')));\n return failing.length ? 1 : 0;\n}\n\n/** `cookiemunch provision <file> [--dry-run]` — the file has no secrets; the environment supplies them. */\nexport async function provisionCommand(file: string | undefined, io: CliIo, client: CookieMunchClient, h: Helpers): Promise<number> {\n const input = (await h.readJson(file)) as unknown as ProvisionRequest;\n // v2 (a forgedeck body): `self.keyEnv` names the env var holding the product's own API key (never in the file).\n const v2 = input as unknown as Record<string, any>;\n if (v2.forgedeck !== undefined || (v2.site && typeof v2.site === 'object')) {\n const body: Record<string, any> = { ...v2 };\n if (body.self) {\n const { keyEnv, ...self } = body.self as Record<string, unknown>;\n const secret = typeof keyEnv === 'string' ? io.env[keyEnv] : undefined;\n if (!secret) throw h.usage(`self needs its key: set self.keyEnv in the file and export that variable`);\n body.self = { ...self, secret };\n }\n if (body.atlas && io.env.COOKIEMUNCH_ATLAS_SECRET_KEY) body.atlas = { ...body.atlas, secretKey: io.env.COOKIEMUNCH_ATLAS_SECRET_KEY };\n if (body.forumulate && io.env.COOKIEMUNCH_FORUMULATE_TOKEN) body.forumulate = { ...body.forumulate, token: io.env.COOKIEMUNCH_FORUMULATE_TOKEN };\n const fromStep = h.flag('from-step');\n const r = await client.provision(body as never, { dryRun: h.flag('dry-run') === true, ...(typeof fromStep === 'string' ? { fromStep } : {}) }) as unknown as { steps: Array<{ id?: string; step: string; status: string; detail?: string; waitingOn?: unknown }>; dryRun: boolean; summary: Record<string, number> };\n if (h.flag('json') === true) out(io, r);\n else {\n for (const s of r.steps) {\n const w = s.waitingOn as { platform?: string; items?: string[] } | string | undefined;\n const waiting = typeof w === 'string' ? w : w ? `${w.platform}: ${(w.items ?? []).join(', ')}` : '';\n io.stdout(`${s.status.padEnd(12)} ${s.id ?? s.step}${s.detail ? ` — ${s.detail}` : ''}${waiting ? ` (waiting on ${waiting})` : ''}\\n`);\n }\n io.stdout(`${r.dryRun ? 'dry run: ' : ''}${r.summary.changed} changed, ${r.summary.unchanged} unchanged, ${r.summary.waiting} waiting, ${r.summary.failed} failed\\n`);\n }\n return r.summary.failed ? 1 : 0;\n }\n const withSecrets: ProvisionRequest = { ...input };\n if (input.atlas || io.env.COOKIEMUNCH_ATLAS_SECRET_KEY) {\n const secretKey = io.env.COOKIEMUNCH_ATLAS_SECRET_KEY ?? input.atlas?.secretKey;\n if (!secretKey) throw h.usage('set COOKIEMUNCH_ATLAS_SECRET_KEY for the atlas step');\n withSecrets.atlas = { ...(input.atlas ?? {}), secretKey };\n }\n if (input.forumulate) {\n const token = io.env.COOKIEMUNCH_FORUMULATE_TOKEN ?? input.forumulate.token;\n if (!token) throw h.usage('set COOKIEMUNCH_FORUMULATE_TOKEN for the forumulate step');\n withSecrets.forumulate = { ...input.forumulate, token };\n }\n const r = await client.provision(withSecrets, { dryRun: h.flag('dry-run') === true });\n if (h.flag('json') === true) { out(io, r); return r.summary.failed ? 1 : 0; }\n for (const s of r.steps) {\n io.stdout(`${s.status.padEnd(12)} ${s.step}${s.detail ? ` — ${s.detail}` : ''}${s.waitingOn ? ` (waiting on ${s.waitingOn})` : ''}\\n`);\n }\n io.stdout(`${r.dryRun ? 'dry run: ' : ''}${r.summary.changed} changed, ${r.summary.unchanged} unchanged, ${r.summary.waiting} waiting, ${r.summary.failed} failed\\n`);\n return r.summary.failed ? 1 : 0;\n}\n\n/** `cookiemunch partners list|link|unlink --site <cbid> …` */\nexport async function partnersCommand(sub: string | undefined, rest: string[], io: CliIo, client: CookieMunchClient, h: Helpers): Promise<number> {\n const cbid = h.requireSite();\n if (sub === 'list') { out(io, await client.sites.listPartners(cbid)); return 0; }\n if (sub === 'link') {\n const partner = h.flag('partner');\n const externalId = h.flag('external-id');\n if (typeof partner !== 'string' || !/^[a-z][a-z0-9_]{1,39}$/.test(partner)) throw h.usage('--partner <id> is required: forumulate, atlas, chatly, referalli, or one registered on the deployment');\n if (typeof externalId !== 'string') throw h.usage('--external-id <the partner’s account id> is required');\n const label = h.flag('label');\n const input: PartnerLinkCreate = { partner, externalId, ...(typeof label === 'string' ? { label } : {}) };\n out(io, await client.sites.linkPartner(cbid, input, { dryRun: h.flag('dry-run') === true }));\n return 0;\n }\n if (sub === 'unlink') {\n const id = rest[0];\n if (!id) throw h.usage('usage: cookiemunch partners unlink <linkId> --site <cbid>');\n out(io, await client.sites.unlinkPartner(cbid, id));\n return 0;\n }\n throw h.usage('usage: cookiemunch partners list|link|unlink --site <cbid>');\n}\n\n/** `cookiemunch keys report [--unused-days n] [--expiring-days n] [--json]` */\nexport async function keysCommand(sub: string | undefined, io: CliIo, client: CookieMunchClient, h: Helpers): Promise<number> {\n if (sub !== 'report') throw h.usage('usage: cookiemunch keys report [--unused-days <n>] [--expiring-days <n>] [--json]');\n const n = (name: string): number | undefined => {\n const v = h.flag(name);\n if (v === undefined) return undefined;\n const x = Number(v);\n if (!Number.isInteger(x) || x < 1 || x > 3650) throw h.usage(`--${name} must be whole days from 1 to 3650`);\n return x;\n };\n const unusedDays = n('unused-days');\n const expiringDays = n('expiring-days');\n const r = await client.keys.report({ ...(unusedDays ? { unusedDays } : {}), ...(expiringDays ? { expiringDays } : {}) });\n if (h.flag('json') === true) { out(io, r); return 0; }\n const section = (title: string, rows: Array<{ prefix: string; name?: string | null; reason: string }>) => {\n io.stdout(`${title}: ${rows.length}\\n`);\n for (const k of rows) io.stdout(` ${k.prefix}${k.name ? ` (${k.name})` : ''} — ${k.reason}\\n`);\n };\n section(`Unused for ${r.unusedDays}+ days`, r.unused);\n section('Broad access', r.broad);\n section(`Expiring within ${r.expiringDays} days`, r.expiringSoon);\n const revoked = r.revoked ?? [];\n io.stdout(`Revoked: ${revoked.length}\\n`);\n for (const k of revoked) io.stdout(` ${k.prefix}${k.name ? ` (${k.name})` : ''} — ${k.reason} ${new Date(k.revokedAt).toISOString()} by ${k.revokedBy}; last used ${k.lastUsedAt ? new Date(k.lastUsedAt).toISOString() : 'never'}\\n`);\n io.stdout(`${r.total} key(s), ${r.noExpiry} with no expiry\\n`);\n return 0;\n}\n","/**\n * Consent-button parity findings, as terminal text: one line per finding (severity, code,\n * where), then its explanation and fix, indented. See /docs/fair-consent-buttons.\n */\nimport type { ButtonParityFinding } from '@cookiemunch/sdk';\n\nfunction where(f: ButtonParityFinding): string {\n const w = f.where ?? {};\n return [\n f.layer === 'banner' ? 'first layer' : `${f.layer} layer`,\n w.view ? `view \"${w.view}\"` : '',\n w.variant && w.variant !== 'base' ? `variant ${w.variant}` : '',\n w.theme === 'dark' ? 'dark theme' : '',\n w.breakpoint === 'mobile' ? 'mobile' : '',\n w.language ? `language ${w.language}` : '',\n ]\n .filter(Boolean)\n .join(', ');\n}\n\nexport function formatDesignWarnings(findings: ButtonParityFinding[]): string {\n return findings\n .map((f) => `${f.severity === 'warning' ? 'warning' : 'notice '} ${f.code} ${where(f)}\\n ${f.detail}\\n fix: ${f.fix}`)\n .join('\\n');\n}\n\nexport function countBySeverity(findings: ButtonParityFinding[]): { warnings: number; notices: number } {\n const warnings = findings.filter((f) => f.severity === 'warning').length;\n return { warnings, notices: findings.length - warnings };\n}\n\nexport function summaryLine(findings: ButtonParityFinding[]): string {\n const { warnings, notices } = countBySeverity(findings);\n if (warnings + notices === 0) return 'No design warnings: Accept all and Reject all have equal weight.';\n // Notices are hints (wording, custom CSS a live scan must confirm), not proof of a dark pattern.\n if (warnings === 0) {\n return (\n `Design: 0 warnings, ${notices} notice${notices === 1 ? '' : 's'} — worth a look, not a finding that Accept is favoured. ` +\n 'See https://cookiemunch.net/docs/fair-consent-buttons'\n );\n }\n return (\n `Design: ${warnings} warning${warnings === 1 ? '' : 's'}, ${notices} notice${notices === 1 ? '' : 's'} — ` +\n 'Accept is pushed harder than Reject. Regulators treat that as a dark pattern; make both buttons the same style. ' +\n 'See https://cookiemunch.net/docs/fair-consent-buttons'\n );\n}\n","/**\n * CLI completeness (CMU-B15, D11, D12, S02):\n *\n * cookiemunch --version | version [--json]\n * cookiemunch cookies diff|push <file> --site <cbid> [--replace] declarations as a file, through the server's dry run\n * cookiemunch executors pull|diff|push <file> [--secret-env NAME] connected systems as a file, never carrying a secret\n * cookiemunch dsar test --types access,deletion [--with-cbid] [--without-cbid] [--cleanup]\n * cookiemunch doctor [--site <cbid>] [--org <id>]\n * cookiemunch keys vend --scopes a,b --ttl 1h [--cbids x,y] [--name n]\n * cookiemunch keys self | rotate-self\n * cookiemunch sandbox [show] | create [--key-name n] | delete [--yes]\n * cookiemunch plan|apply <cookiemunch.json>\n *\n * Exit codes everywhere: 0 ok (or no changes), 1 a difference, a failure or a failed check, 2 a usage mistake.\n */\n\nimport type { CookieMunchClient, DsarExecutor } from '@cookiemunch/sdk';\nimport type { CliIo } from './cli.js';\nimport { diffJson, formatChanges, type Change, type Json } from './diff.js';\n\nexport interface OpsHelpers {\n requireSite(): string;\n site(): string | undefined;\n readJson(path: string | undefined): Promise<Record<string, unknown>>;\n usage(msg: string): Error;\n flag(name: string): string | true | undefined;\n positional: string[];\n}\n\nconst json = (h: OpsHelpers) => h.flag('json') === true;\nconst print = (io: CliIo, v: unknown) => io.stdout(`${JSON.stringify(v, null, 2)}\\n`);\nconst str = (h: OpsHelpers, name: string) => { const v = h.flag(name); return typeof v === 'string' ? v : undefined; };\n\n// ---- version (CMU-B15) ----\n\n/** `version [--json]`: the CLI's version, and with --json the API version the server documents. */\nexport async function versionCommand(io: CliIo, cliVersion: string, base: string, asJson: boolean): Promise<number> {\n if (!asJson) {\n io.stdout(`${cliVersion}\\n`);\n return 0;\n }\n let api: string | null = null;\n try {\n const res = await io.fetch(`${base.replace(/\\/+$/, '')}/v1/openapi.json`);\n if (res.ok) api = ((await res.json()) as { info?: { version?: string } }).info?.version ?? null;\n } catch {\n /* unreachable: api stays null */\n }\n print(io, { cli: cliVersion, api });\n return 0;\n}\n\n// ---- cookies diff|push <file> (CMU-D11) ----\n\nfunction cookieRows(file: Record<string, unknown>): Array<Record<string, unknown> & { name: string }> {\n const rows = Array.isArray(file) ? file : Array.isArray(file.cookies) ? file.cookies : null;\n if (!rows || !rows.every((r) => r && typeof r === 'object' && typeof (r as { name?: unknown }).name === 'string')) {\n throw new Error('the file must hold { \"cookies\": [ { \"name\", \"category\", \"purpose\", … } ] } or that array');\n }\n return rows as Array<Record<string, unknown> & { name: string }>;\n}\n\nexport async function cookiesFileCommand(sub: 'diff' | 'push', io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n const cbid = h.requireSite();\n const path = h.positional[2];\n if (!path) throw h.usage(`usage: cookiemunch cookies ${sub} <file> --site <cbid> [--replace]`);\n let rows;\n try { rows = cookieRows(await h.readJson(path)); } catch (e) { throw h.usage((e as Error).message); }\n const replace = h.flag('replace') === true;\n const dry = await client.sites.declareCookies(cbid, rows as never, { replace, dryRun: true });\n const diff = dry.diff ?? { added: [], removed: [], changed: [] };\n const n = diff.added.length + diff.removed.length + diff.changed.length;\n if (json(h)) print(io, { cbid, changes: n, diff, ...(dry.warnings?.length ? { warnings: dry.warnings } : {}) });\n else if (n === 0) io.stderr(`No changes: ${cbid}'s declarations already match.\\n`);\n else {\n for (const c of diff.added) io.stdout(`+ ${c.name} (${c.category})\\n`);\n for (const c of diff.removed) io.stdout(`- ${c.name}\\n`);\n for (const c of diff.changed) io.stdout(`~ ${c.name}: ${formatChanges(diffJson(c.before as unknown as Json, c.after as unknown as Json))}\\n`);\n }\n for (const w of dry.warnings ?? []) io.stderr(`warning: ${JSON.stringify(w)}\\n`);\n if (sub === 'diff') return n > 0 && h.flag('exit-code') === true ? 1 : 0;\n if (n === 0) return 0;\n const saved = await client.sites.declareCookies(cbid, rows as never, { replace });\n io.stderr(`Applied: ${saved.saved} saved, ${saved.removed} removed.\\n`);\n return 0;\n}\n\n// ---- executors pull|diff|push <file> (CMU-D11) ----\n\n/** What a file holds for a connection: everything that is not a secret, an id the server assigns, or state. */\nconst EXECUTOR_FIELDS = ['system', 'baseUrl', 'profile', 'auto', 'subjectNote', 'cbid', 'preset', 'presetVersion', 'presetParams'] as const;\nfunction executorFileView(e: DsarExecutor): Record<string, Json> {\n const out: Record<string, Json> = { id: e.id };\n for (const k of EXECUTOR_FIELDS) {\n const v = (e as unknown as Record<string, unknown>)[k];\n if (v !== undefined) out[k] = v as Json;\n }\n return out;\n}\n\nexport async function executorsFileCommand(sub: 'pull' | 'diff' | 'push', io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n const current = (await client.fulfillment.executors()).map(executorFileView);\n if (sub === 'pull') {\n const text = `${JSON.stringify({ executors: current }, null, 2)}\\n`;\n const path = str(h, 'out') ?? h.positional[2];\n if (path) { await io.writeFile(path, text); io.stderr(`Wrote ${current.length} connection(s) to ${path} (no secrets).\\n`); } else io.stdout(text);\n return 0;\n }\n const path = h.positional[2];\n if (!path) throw h.usage(`usage: cookiemunch executors ${sub} <file> [--secret-env NAME]`);\n const file = await h.readJson(path);\n const wanted = Array.isArray(file.executors) ? (file.executors as Array<Record<string, Json>>) : null;\n if (!wanted) throw h.usage(`${path} must hold { \"executors\": [ … ] } (cookiemunch executors pull writes one)`);\n for (const w of wanted) {\n for (const k of ['secretKey', 'secret', 'webhookSecret']) if (k in w) throw h.usage(`${path} carries ${k}: secrets never go in this file; pass --secret-env NAME`);\n }\n const plan: Array<{ system: string; action: 'create' | 'update' | 'unchanged'; id?: string; changes: Change[] }> = [];\n for (const w of wanted) {\n const match = current.find((c) => (w.id && c.id === w.id) || (!w.id && c.system === w.system));\n const { id: _i, ...want } = w;\n if (!match) { plan.push({ system: String(w.system), action: 'create', changes: diffJson({}, want as Json) }); continue; }\n const { id, ...have } = match;\n const changes = diffJson(Object.fromEntries(Object.keys(want).map((k) => [k, have[k] ?? null])) as Json, want as Json);\n plan.push({ system: String(w.system), action: changes.length ? 'update' : 'unchanged', id: String(id), changes });\n }\n const pending = plan.filter((p) => p.action !== 'unchanged');\n if (json(h)) print(io, { plan });\n else if (!pending.length) io.stderr('No changes: every connection already matches.\\n');\n else for (const p of pending) io.stdout(`${p.action} ${p.system}${p.id ? ` (${p.id})` : ''}\\n${formatChanges(p.changes).replace(/^/gm, ' ')}\\n`);\n if (sub === 'diff') return pending.length && h.flag('exit-code') === true ? 1 : 0;\n const secretEnv = str(h, 'secret-env');\n // Every create needs its key BEFORE anything is applied: half a push is worse than none.\n const creating = pending.filter((p) => p.action === 'create');\n if (creating.length && !(secretEnv && io.env[secretEnv])) {\n throw h.usage(`creating ${creating.map((p) => p.system).join(', ')} needs its API key: pass --secret-env NAME and export NAME`);\n }\n for (const p of pending) {\n const w = wanted.find((x) => String(x.system) === p.system)!;\n const { id: _i, ...body } = w;\n if (p.action === 'update') {\n await client.fulfillment.updateExecutor(p.id!, Object.fromEntries(p.changes.map((c) => c.path.split(/[.[]/)[0]!).filter((k, i, a) => a.indexOf(k) === i).map((k) => [k, body[k]])) as never);\n } else {\n const secretKey = secretEnv ? io.env[secretEnv] : undefined;\n if (!secretKey) throw h.usage(`creating ${p.system} needs its API key: set --secret-env NAME and export NAME`);\n await client.fulfillment.connectExecutor({ ...(body as object), secretKey } as never);\n }\n }\n io.stderr(`Applied ${pending.length} change(s).\\n`);\n return 0;\n}\n\n// ---- dsar test (CMU-D11) ----\n\n/**\n * File test rights requests (guide step 16), read each back, and with --cleanup delete EXACTLY the ids this\n * run created: never a list-and-delete, which once removed live rows (memory never-clean-up-by-listing).\n */\nexport async function dsarTestCommand(io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n const types = (str(h, 'types') ?? 'access').split(',').map((t) => t.trim()).filter(Boolean);\n const allowed = ['access', 'deletion', 'rectification', 'portability', 'opt-out'];\n const bad = types.filter((t) => !allowed.includes(t));\n if (bad.length) throw h.usage(`--types takes ${allowed.join(', ')}; not ${bad.join(', ')}`);\n const withCbid = h.flag('with-cbid') === true;\n const without = h.flag('without-cbid') === true || !withCbid;\n const cbid = withCbid ? h.requireSite() : undefined;\n const email = str(h, 'email') ?? 'cookiemunch-cli-test@example.invalid';\n const created: Array<{ id: string; type: string; cbid: string | null; status: string }> = [];\n let failed = false;\n try {\n for (const type of types) {\n for (const scoped of [...(withCbid ? [true] : []), ...(without ? [false] : [])]) {\n const r = await client.dsar.create({ type, subjectEmail: email, regulation: 'gdpr', test: true, ...(scoped ? { cbid } : {}) } as never);\n const back = await client.dsar.get(r.request.id);\n created.push({ id: r.request.id, type, cbid: scoped ? cbid! : null, status: String((back as { status?: string }).status) });\n }\n }\n } catch (e) {\n failed = true;\n io.stderr(`dsar test: ${(e as Error).message}\\n`);\n }\n const deleted: string[] = [];\n if (h.flag('cleanup') === true) {\n for (const c of created) {\n try { await client.dsar.delete(c.id); deleted.push(c.id); } catch (e) { failed = true; io.stderr(`could not delete test request ${c.id}: ${(e as Error).message}\\n`); }\n }\n }\n if (json(h)) print(io, { created, deleted });\n else {\n for (const c of created) io.stdout(`${c.id} ${c.type}${c.cbid ? ` cbid=${c.cbid}` : ' (no cbid)'} ${c.status}${deleted.includes(c.id) ? ' (deleted)' : ''}\\n`);\n io.stderr(`${created.length} test request(s) filed${h.flag('cleanup') === true ? `, ${deleted.length} deleted` : '; delete them with --cleanup or DELETE /v1/dsar/{id}'}.\\n`);\n }\n return failed ? 1 : 0;\n}\n\n// ---- doctor (CMU-D11) ----\n\nexport async function doctorCommand(io: CliIo, client: CookieMunchClient, h: OpsHelpers, cliVersion: string): Promise<number> {\n const checks: Array<{ check: string; ok: boolean | null; detail: string }> = [];\n type Me = { orgId?: string; orgName?: string | null; keyPrefix?: string; unscoped?: boolean };\n let me: Me | null = null;\n try {\n me = (await client.me()) as unknown as Me;\n checks.push({ check: 'key', ok: true, detail: `org ${me?.orgName ?? me?.orgId} (${me?.orgId}), key ${me?.keyPrefix}${me?.unscoped ? ', full access' : ''}` });\n } catch (e) {\n checks.push({ check: 'key', ok: false, detail: (e as Error).message });\n }\n const wantOrg = str(h, 'org') ?? io.env.COOKIEMUNCH_ORG;\n if (wantOrg && me?.orgId) checks.push({ check: 'org', ok: me.orgId === wantOrg, detail: me.orgId === wantOrg ? `this key belongs to ${wantOrg}` : `this key's org is ${me.orgId}, not ${wantOrg}, the org your config names` });\n try {\n const self = await client.keys.self();\n const left = typeof self.expiresAt === 'number' ? Math.floor((self.expiresAt - Date.now()) / 86_400_000) : null;\n checks.push({ check: 'key expiry', ok: left === null ? null : left > 7, detail: left === null ? 'no expiry: give automation keys one' : `expires in ${left} day(s)` });\n } catch {\n checks.push({ check: 'key expiry', ok: null, detail: 'this server cannot read the key itself (GET /v1/keys/self)' });\n }\n try {\n const res = await io.fetch('https://registry.npmjs.org/@cookiemunch/cli/latest');\n const latest = res.ok ? ((await res.json()) as { version?: string }).version : undefined;\n checks.push({ check: 'cli version', ok: latest ? latest === cliVersion : null, detail: latest ? (latest === cliVersion ? `${cliVersion}, the latest` : `${cliVersion}; ${latest} is out`) : `${cliVersion}; could not check the latest` });\n } catch {\n checks.push({ check: 'cli version', ok: null, detail: `${cliVersion}; could not check the latest` });\n }\n const site = h.site();\n if (site || me) {\n try {\n const r = await client.integrationHealth(site);\n checks.push({ check: 'integration health', ok: r.ok, detail: `${r.counts.error} error(s), ${r.counts.warning} warning(s)` });\n } catch (e) {\n checks.push({ check: 'integration health', ok: null, detail: (e as Error).message });\n }\n }\n if (json(h)) print(io, { ok: checks.every((c) => c.ok !== false), checks });\n else for (const c of checks) io.stdout(`${c.ok === true ? 'ok ' : c.ok === false ? 'FAIL' : '-- '} ${c.check}: ${c.detail}\\n`);\n return checks.some((c) => c.ok === false) ? 1 : 0;\n}\n\n// ---- keys vend | self | rotate-self (CMU-S02, D09) ----\n\n/** `1h`, `30m`, `90s`, `3600` → seconds. */\nexport function parseTtl(v: string): number | null {\n const m = /^(\\d+)([smh]?)$/.exec(v.trim());\n if (!m) return null;\n const n = Number(m[1]) * (m[2] === 'h' ? 3600 : m[2] === 'm' ? 60 : 1);\n return n >= 60 && n <= 43200 ? n : null;\n}\n\nexport async function keysExtraCommand(sub: string, io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n if (sub === 'self') { print(io, await client.keys.self()); return 0; }\n if (sub === 'rotate-self') {\n const r = await client.keys.rollSelf();\n if (json(h)) print(io, r);\n else { io.stdout(`${r.key ?? r.sealed_secret}\\n`); io.stderr('The old key stopped working. This new one is shown once: store it now.\\n'); }\n return 0;\n }\n if (sub === 'vend') {\n const scopes = (str(h, 'scopes') ?? '').split(',').map((s) => s.trim()).filter(Boolean);\n if (!scopes.length) throw h.usage('--scopes a,b is required (a vended key is never full access)');\n const ttl = parseTtl(str(h, 'ttl') ?? '');\n if (ttl === null) throw h.usage('--ttl is required: 1h, 30m or seconds, from 60 s to 12 h');\n const cbids = str(h, 'cbids')?.split(',').map((s) => s.trim()).filter(Boolean);\n const name = str(h, 'name');\n const r = await client.keys.vend({ scopes, ttlSeconds: ttl, ...(cbids?.length ? { cbids } : {}), ...(name ? { name } : {}) });\n if (json(h)) print(io, r);\n else { io.stdout(`${r.key ?? (r as { sealed_secret?: string }).sealed_secret}\\n`); io.stderr(`Valid until ${new Date(r.expiresAt).toISOString()} (${scopes.join(', ')}).\\n`); }\n return 0;\n }\n throw h.usage('usage: cookiemunch keys report|vend|self|rotate-self');\n}\n\n// ---- sandbox (CMU-F10) ----\n\n/** `sandbox [show]`, `sandbox create [--key-name n]` (prints the test key alone), `sandbox delete [--yes]`. */\nexport async function sandboxCommand(sub: string | undefined, io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n if (sub === undefined || sub === 'show') {\n const s = await client.sandbox.get();\n if (json(h) || s) print(io, s);\n else io.stderr('This organisation has no sandbox. Make one with: cookiemunch sandbox create\\n');\n return 0;\n }\n if (sub === 'create') {\n const keyName = str(h, 'key-name');\n const r = await client.sandbox.create(keyName ? { keyName } : {});\n if (json(h)) print(io, r);\n else {\n io.stdout(`${r.key}\\n`);\n io.stderr(`${r.created ? 'Made' : 'Using'} sandbox ${r.sandbox.orgId} (${r.sandbox.name}). The key above is shown once: store it now.\\n`);\n }\n return 0;\n }\n if (sub === 'delete') {\n const s = await client.sandbox.get();\n if (!s) { io.stderr('There is no sandbox.\\n'); return 1; }\n if (h.flag('yes') !== true) {\n if (!io.confirm) throw h.usage('sandbox delete erases the sandbox and everything in it, and there is no terminal to confirm in. Pass --yes to delete without a prompt.');\n if (!(await io.confirm(`Erase sandbox ${s.orgId} (${s.name}) and everything in it? This cannot be undone. [y/N] `))) {\n io.stderr('Not deleted.\\n');\n return 1;\n }\n }\n const r = await client.sandbox.delete();\n if (json(h)) print(io, r);\n else io.stderr(`Erased sandbox ${r.orgId ?? s.orgId}: ${Object.entries(r.counts).map(([k, v]) => `${v} ${k}`).join(', ')}.\\n`);\n return 0;\n }\n throw h.usage('usage: cookiemunch sandbox [show] | create [--key-name <n>] | delete [--yes]');\n}\n\n// ---- plan | apply <cookiemunch.json> (CMU-D12) ----\n\ninterface Bundle {\n site?: { cbid?: string; domain?: string; name?: string; aliases?: string[] };\n config?: Record<string, unknown>;\n cookies?: Array<Record<string, unknown> & { name: string }>;\n presets?: Array<{ vendor: string; params?: Record<string, unknown> }>;\n executors?: Array<Record<string, Json>>;\n webhooks?: Array<{ url: string; events: string[]; cbid?: string | null }>;\n rightsPage?: Record<string, unknown>;\n partners?: Array<{ partner: string; resource: string; scopes: string[]; externalId?: string; label?: string }>;\n}\n\nconst PARTS = ['site', 'config', 'cookies', 'presets', 'rightsPage', 'executors', 'webhooks', 'partners'] as const;\ntype Part = (typeof PARTS)[number];\ninterface PartPlan { part: Part; changes: number; detail: string[]; apply?: () => Promise<string> }\n\n/**\n * One file for everything a site's privacy setup is (CMU-D12). `plan` asks the server's dry run of every part\n * and prints one combined diff; `apply` applies the parts in dependency order (site → config → cookies →\n * presets → rights page → executors → webhooks → partners), reads each back, and logs when.\n * No secret ever goes in the file: an executor's key comes from --secret-env, a new webhook's secret is\n * written to --secrets-out (0600) or the webhook is not created.\n */\nexport async function bundleCommand(sub: 'plan' | 'apply', io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n const path = h.positional[1] ?? 'cookiemunch.json';\n const b = (await h.readJson(path)) as unknown as Bundle;\n for (const k of Object.keys(b)) if (!(PARTS as readonly string[]).includes(k) && k !== '$schema') throw h.usage(`${path}: unknown part ${k}; parts are ${PARTS.join(', ')}`);\n const cbid = b.site?.cbid ?? h.site();\n if (!cbid) throw h.usage(`${path} needs site.cbid (or --site)`);\n const plans: PartPlan[] = [];\n\n if (b.site) {\n const patch = { ...(b.site.domain ? { domain: b.site.domain } : {}), ...(b.site.name !== undefined ? { name: b.site.name } : {}), ...(b.site.aliases ? { aliases: b.site.aliases } : {}) };\n if (Object.keys(patch).length) {\n const r = await client.sites.update(cbid, patch, { dryRun: true });\n plans.push({ part: 'site', changes: r.diff.length, detail: r.diff.map((d) => `${d.field}: ${JSON.stringify(d.before)} → ${JSON.stringify(d.after)}`), apply: async () => { await client.sites.update(cbid, patch); return 'site updated'; } });\n } else plans.push({ part: 'site', changes: 0, detail: [] });\n }\n if (b.config) {\n const r = await client.sites.dryRunConfig(cbid, b.config as never, { mode: 'patch' });\n const diff = r.diff ?? [];\n plans.push({ part: 'config', changes: diff.length, detail: diff.map((d) => `${d.path}: ${JSON.stringify(d.from)} → ${JSON.stringify(d.to)}`), apply: async () => { await client.sites.patchConfig(cbid, b.config as never); return 'config patched'; } });\n }\n if (b.cookies) {\n const r = await client.sites.declareCookies(cbid, b.cookies as never, { dryRun: true });\n const d = r.diff ?? { added: [], removed: [], changed: [] };\n plans.push({ part: 'cookies', changes: d.added.length + d.removed.length + d.changed.length, detail: [...d.added.map((c) => `+ ${c.name}`), ...d.removed.map((c) => `- ${c.name}`), ...d.changed.map((c) => `~ ${c.name}`)], apply: async () => { const s = await client.sites.declareCookies(cbid, b.cookies as never); return `${s.saved} declaration(s) saved`; } });\n }\n for (const p of b.presets ?? []) {\n const r = await client.sites.applyCookiePreset(cbid, p.vendor as never, (p.params ?? {}) as never, { dryRun: true });\n const d = (r as { diff?: { added: unknown[]; removed: unknown[]; changed: unknown[] } }).diff;\n const n = d ? d.added.length + d.removed.length + d.changed.length : 0;\n plans.push({ part: 'presets', changes: n, detail: n ? [`${p.vendor}: ${n} declaration change(s)`] : [], apply: async () => { await client.sites.applyCookiePreset(cbid, p.vendor as never, (p.params ?? {}) as never); return `preset ${p.vendor} applied`; } });\n }\n if (b.rightsPage) {\n const r = await client.rightsPage.dryRun(cbid, b.rightsPage, { mode: 'put' });\n const diff = ((r as { diff?: Array<{ path: string }> }).diff ?? []);\n plans.push({ part: 'rightsPage', changes: diff.length, detail: diff.map((d) => d.path), apply: async () => { await client.rightsPage.put(cbid, b.rightsPage as never); return 'rights page draft saved (publish it with cookiemunch rights-page publish)'; } });\n }\n if (b.executors) {\n const current = (await client.fulfillment.executors()).map(executorFileView);\n let n = 0;\n const detail: string[] = [];\n for (const w of b.executors) {\n for (const k of ['secretKey', 'secret', 'webhookSecret']) if (k in w) throw h.usage(`${path}: executors carry no secrets (${k}); use --secret-env`);\n const m = current.find((c) => c.system === w.system);\n const { id: _i, ...want } = w;\n const changes = m ? diffJson(Object.fromEntries(Object.keys(want).map((k) => [k, m[k] ?? null])) as Json, want as Json) : diffJson({}, want as Json);\n if (changes.length) { n++; detail.push(`${m ? 'update' : 'create'} ${String(w.system)}`); }\n }\n plans.push({ part: 'executors', changes: n, detail, apply: async () => { await executorsFileCommand('push', io, client, { ...h, positional: ['executors', 'push', path], readJson: async () => ({ executors: b.executors }) }); return 'executors pushed'; } });\n }\n if (b.webhooks) {\n const have = await client.webhooks.list();\n const missing = b.webhooks.filter((w) => !have.some((x) => x.url === w.url));\n const changed = b.webhooks.filter((w) => { const x = have.find((y) => y.url === w.url); return x && JSON.stringify([...x.events].sort()) !== JSON.stringify([...w.events].sort()); });\n plans.push({\n part: 'webhooks', changes: missing.length + changed.length,\n detail: [...missing.map((w) => `+ ${w.url}`), ...changed.map((w) => `~ ${w.url} events`)],\n apply: async () => {\n const secretsOut = str(h, 'secrets-out');\n if (missing.length && !secretsOut) throw h.usage('creating webhooks shows their signing secrets once: pass --secrets-out <file> (written 0600)');\n const secrets: Record<string, string> = {};\n for (const w of missing) { const s = await client.webhooks.create({ url: w.url, events: w.events, ...(w.cbid !== undefined ? { cbid: w.cbid } : {}) } as never); if (s.secret) secrets[w.url] = s.secret; }\n for (const w of changed) { const x = have.find((y) => y.url === w.url)!; await client.webhooks.update(x.id, { events: w.events } as never); }\n if (secretsOut && Object.keys(secrets).length) await io.writeFile(secretsOut, `${JSON.stringify(secrets, null, 2)}\\n`, 0o600);\n return `${missing.length} created, ${changed.length} updated`;\n },\n });\n }\n if (b.partners) {\n const have = await client.partnerLinks.list();\n const missing = b.partners.filter((p) => !have.some((l) => l.partner === p.partner && l.resource === p.resource && l.status !== 'revoked'));\n plans.push({ part: 'partners', changes: missing.length, detail: missing.map((p) => `+ ${p.partner} on ${p.resource} (${p.scopes.join(', ')})`), apply: async () => { for (const p of missing) await client.partnerLinks.create(p as never); return `${missing.length} link(s) created`; } });\n }\n\n const total = plans.reduce((n, p) => n + p.changes, 0);\n if (sub === 'plan') {\n if (json(h)) print(io, { file: path, cbid, changes: total, parts: plans.map(({ apply: _a, ...p }) => p) });\n else for (const p of plans) {\n io.stdout(`${p.part}: ${p.changes ? `${p.changes} change(s)` : 'No changes'}\\n`);\n for (const d of p.detail) io.stdout(` ${d}\\n`);\n }\n if (!json(h)) io.stderr(total ? `${total} change(s) in ${plans.filter((p) => p.changes).length} part(s). Apply with: cookiemunch apply ${path}\\n` : `No changes: all ${plans.length} part(s) match.\\n`);\n return total && h.flag('exit-code') === true ? 1 : 0;\n }\n const log: Array<{ part: Part; at: string; result: string }> = [];\n for (const p of plans) {\n if (!p.changes || !p.apply) continue;\n const result = await p.apply();\n log.push({ part: p.part, at: new Date().toISOString(), result });\n if (!json(h)) io.stderr(`${log[log.length - 1]!.at} ${p.part}: ${result}\\n`);\n }\n if (json(h)) print(io, { file: path, cbid, applied: log });\n else if (!log.length) io.stderr('No changes: nothing to apply.\\n');\n return 0;\n}\n"],"mappings":"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","names":["out","out","proposed","out","CookieMunchApiError","r","out","path","str","CookieMunchApiError","out","id","print"]}
package/dist/index.d.ts CHANGED
@@ -51,7 +51,7 @@ interface CliIo {
51
51
  */
52
52
  confirm?: (question: string) => Promise<boolean>;
53
53
  }
54
- declare const USAGE = "cookiemunch \u2014 Cookie Munch from the command line\n\nUsage:\n cookiemunch config pull --site <cbid> [--out <file>]\n Write the site's config as JSON (to stdout, or to <file>).\n cookiemunch config diff --site <cbid> <file> [--replace] [--exit-code]\n Show what pushing <file> would change (the server's dry run; nothing is stored).\n Read-only fields a pulled file carries (effective, designWarnings, ...) are ignored.\n cookiemunch config push --site <cbid> <file> [--replace] [--strict]\n Apply <file>. Default: merged over the stored config (PATCH) \u2014 fields the file\n leaves out keep their value, and a field set to null is removed (it takes its\n default). --replace sends it whole (PUT): a top-level field the file leaves out\n reverts to its default. Prints any design warnings the server found. --strict\n checks the file first and does not push it (exit 1) when Accept all is pushed\n harder than Reject all anywhere \u2014 for CI.\n cookiemunch config validate --site <cbid> <file> [--replace] [--strict]\n Check <file> for consent-button parity on the server, without writing: is Accept\n all more prominent than Reject all (colour, size, placement, copy, custom CSS)?\n Merged over the stored config like push; --replace checks it as sent. --strict\n exits 1 when there is any warning (notices never fail).\n cookiemunch preview --site <cbid> [--url <page>] [--region <eu|de|us-ca\u2026>] [--lang <de\u2026>]\n [--ttl <seconds>] [--open]\n Print (and with --open, open) a link showing the banner as a visitor in that\n region and language sees it. Works in headless browsers; nothing is recorded.\n cookiemunch executors test <id> (--email <email> | --canary) [--operation <locate|export|erase>]\n Try a connected system against one person without filing a request.\n --operation defaults to locate (lookup is accepted as another name for it).\n --canary uses the organisation's canary address instead: no real person, and\n a canary locate also updates the connection's health. Exits 1 when not ok.\n cookiemunch executors webhook-test <id> --headers-file <json> --body-file <file>\n Would this webhook delivery verify? Sends the headers (a JSON object) and the\n body file byte for byte to the receiver's check; nothing is acted on. Prints\n { verified, stage, reason } and exits 1 when it does not verify.\n cookiemunch executors deliveries <id>\n The last 50 deliveries to that connection's webhook, each with its reason.\n cookiemunch executors presets\n The versioned presets, which are usable now and which wait on another\n platform, and the organisation's canary address.\n cookiemunch executors conformance <baseUrl> --secret-env <NAME> [--canary-email <addr>]\n [--prefix /privacy] [--json]\n Check any system against the open cm-standard-v2 executor contract, rule by\n rule, using only the canary subject. The credential is read from the\n environment variable NAME, never from the command line. Without\n --canary-email the organisation's canary address is fetched (needs\n COOKIEMUNCH_API_KEY); with it, no Cookie Munch key is needed at all.\n Exits 1 when any rule fails.\n cookiemunch executors conformance --connection <id> [--json]\n The same suite, run by Cookie Munch against a connected system.\n cookiemunch executors roll-completion-secret <id>\n A new completion secret for that connection, printed once; the old one keeps\n verifying for 24 hours.\n cookiemunch executors upgrade-preset <id> [--preset <name>] [--version <n>]\n [--org-id <id>] [--atlas-id-app-id <id>] [--revoke-atlas-id-grant]\n [--accept-preset <path> \u2026] [--dry-run]\n Rebuild a connection from its preset's latest version (or --version), keeping\n its id and credentials; --preset adopts one on a hand-written connection.\n Your hand edits are kept (the diff marks them kept or conflict); --accept-preset\n (repeatable) takes the preset's value for that path. Prints the diff; --dry-run\n changes nothing. A pinned connection is refused.\n cookiemunch executors recheck <id>\n Re-check a connection now (a canary test that records its health): the hook to\n run after deploying that system's rights API. Exits 1 when it is not ok.\n cookiemunch executors health <id> [--limit <n>]\n The connection's last health checks, newest first (up to 50).\n cookiemunch rights-page pull --site <cbid> [--out <file>]\n Write the site's rights page draft as JSON, and print its updatedAt for --base.\n cookiemunch rights-page diff --site <cbid> <file> [--exit-code]\n Validate <file> on the server (dry run) and show what pushing it would change.\n cookiemunch rights-page push --site <cbid> <file> [--base <updatedAt>]\n Replace the draft with <file>. Nothing is live until publish. Refused (exit 1)\n if the draft changed since the diff, or since --base (the updatedAt pull printed).\n cookiemunch rights-page publish --site <cbid> [--yes] [--base <updatedAt>]\n Publish the draft (it goes live at once). Asks first; --yes skips the question\n and is required when there is no terminal to ask in. Prints why when the page\n cannot go live. Refused (exit 1) if the draft changed after it was read (or\n since --base); --yes never overrides that.\n\n cookiemunch scan --site <cbid> [--wait] [--timeout <seconds>]\n Start a cookie crawl of the site and print its state (JSON). --wait holds on\n until it is done or failed (default up to 120 s, --timeout to change) and exits\n 1 when it failed or is still running at the end. A scan already running is\n waited on rather than started twice.\n\n cookiemunch cookies presets --site <cbid>\n The declaration presets (atlas, forumulate, chatly, cookiemunch, referalli, firstpromoter,\n partnerstack, tapfiliate, impact; referally is the deprecated old name of referalli): what each takes,\n what it declared on this site, and whether the vendor's own manifest exists yet.\n cookiemunch cookies preset <vendor> --site <cbid> [--param k=v \u2026] [--dry-run]\n Declare what that platform writes (cookies and browser storage), marked as\n declared by it; run again to re-sync. Atlas: --param frontendApiHost=auth.example.com\n [--param crossSubdomainCookies=false]. Chatly: --param publicId=ch_web_\u2026 .\n Referral and affiliate presets (referalli, firstpromoter, partnerstack, tapfiliate, impact):\n [--param cookieDomain=.example.com] [--param cookieDays=60] [--param category=\u2026];\n referalli [--param legacyName=false], impact [--param campaignId=\u2026]. A row filed under a\n disabled category prints a warning and a suggestedConfigPatch. Any other vendor is\n declared with the API (PUT /v1/sites/{cbid}/cookies).\n cookiemunch cookies unpreset <vendor> --site <cbid> [--dry-run]\n Remove every declaration that vendor's preset made.\n cookiemunch cookies import-manifest <url> --site <cbid> [--file <manifest.json>] [--dry-run]\n Declare any vendor's cookies and storage from its embed manifest\n (/.well-known/forgedeck-embed.json), by URL or from a file. Remove it with\n cookies unpreset <product>.\n cookiemunch cookies suggestions --site <cbid>\n What to declare: the platforms detected on the site and each undeclared row.\n cookiemunch cookies declare-suggestions --site <cbid> [--names a,b] [--dry-run]\n Declare them: detected vendors' presets, then every other suggestion with a purpose.\n cookiemunch cookies delete-observed <name> --site <cbid> [--dry-run]\n Remove every stored row of that name (a name the site never sets). A declaration stays.\n cookiemunch cookies purge-observed --site <cbid> --since <time> [--until <time>] [--dry-run]\n Remove every row a real visit first reported in that window (ISO-8601 or epoch ms).\n Crawled rows and declarations stay. Run with --dry-run first.\n cookiemunch site update --site <cbid> [--domain <host>] [--name <name> | --clear-name]\n [--aliases <a,b>] [--dry-run]\n Rename or move a site. The cbid and consent ledger stay; a domain move clears\n verification. --dry-run prints the diff and its effects without saving.\n cookiemunch site brand --site <cbid> [--url <https URL> | <brand.json>] [--dry-run]\n Import a brand.json into the banner theme (the rights page uses it too). Values the\n site set itself are kept. With neither --url nor a file, prints the last import.\n cookiemunch consent-sync status --site <cbid>\n Whether hosted consent sync is set up (the secret's last four characters, when it was minted).\n cookiemunch consent-sync rotate --site <cbid>\n Mint the site's consent-sync signing secret, or replace it (the old one stops at once).\n Prints the secret alone on stdout, so it can be piped into your secret store: it is shown once.\n cookiemunch consent-sync remove --site <cbid> --yes\n Remove it: hosted consent sync stops for every visitor.\n cookiemunch consent-sync token --site <cbid> --subject <id> [--ttl <seconds>]\n Sign a test token locally with COOKIEMUNCH_CONSENT_SYNC_SECRET (nothing is sent), e.g. to try\n GET /api/v1/<cbid>/profile with curl.\n cookiemunch health [--site <cbid>] [--json] [--fail-on error|warning|never]\n Every link the site's privacy wiring depends on, with a fix hint for each that\n fails. Exits 1 when a check fails (checks that could not run, or are waived, do not count).\n --fail-on error ignores warnings; --fail-on never always exits 0.\n cookiemunch provision <file> [--dry-run]\n Wire a product's privacy in one call (site, connections, Atlas, Forumulate) from\n a JSON file without secrets: the Atlas key and Forumulate token come from\n COOKIEMUNCH_ATLAS_SECRET_KEY and COOKIEMUNCH_FORUMULATE_TOKEN. Re-running is a\n no-op. Exits 1 when a step failed.\n cookiemunch keys report [--unused-days <n>] [--expiring-days <n>] [--json]\n Key hygiene: keys unused for n days (default 90), keys with broad access, and\n keys expiring within n days (default 14). Needs a full-access key.\n cookiemunch partners list|link|unlink --site <cbid> [--partner <id>]\n [--external-id <id>] [--label <text>] [<linkId>]\n Grant a partner platform the site's consent events (no secret is created), list\n the grants, or revoke one. Any partner this deployment knows (forumulate, atlas, chatly,\n referalli, or one registered for it).\n cookiemunch csp --merge <vendors|urls> [--framework next|express|nginx] [--site <cbid>]\n One Content-Security-Policy from several products' embed manifests\n (/.well-known/forgedeck-embed.json): cookiemunch, atlas, chatly, forumulate,\n referalli, or any manifest URL. --framework prints it for next.config.js,\n Express or nginx; without it, the header value. --site uses your site's own\n Cookie Munch manifest (its logo, fonts, sync endpoint). Needs no API key. Exits 1\n when a named product has not published a manifest (the rest are still merged).\n cookiemunch cookies diff|push <file> --site <cbid> [--replace] [--exit-code]\n Declarations as a file ({\"cookies\": [...]}), through the server's dry run. push applies\n only when something differs; --replace also removes declarations the file leaves out.\n cookiemunch executors pull [<file>] | diff <file> | push <file> [--secret-env NAME]\n Connected systems as a file. The file never carries a secret: a new connection's API key\n comes from the environment variable --secret-env names.\n cookiemunch dsar test [--types access,deletion] [--with-cbid --site <cbid>] [--without-cbid]\n [--email <addr>] [--cleanup]\n File TEST rights requests and read each back. --cleanup deletes exactly the ones this run\n filed (by id; it never deletes by listing).\n cookiemunch doctor [--site <cbid>] [--org <id>]\n The key (and whose org it is, against --org or COOKIEMUNCH_ORG), its expiry, the CLI\n version against the latest, and integration health. Exits 1 when a check fails.\n cookiemunch keys vend --scopes <a,b> --ttl <1h|30m|seconds> [--cbids <x,y>] [--name <n>]\n A short-lived key (at most 12 h) within this key's own scopes; prints the key alone.\n Needs keys:write (or a full-access key).\n cookiemunch keys self | rotate-self\n This key's own prefix, scopes and expiry; or rotate it (the new key is printed once).\n cookiemunch plan [cookiemunch.json] [--exit-code] [--json]\n cookiemunch apply [cookiemunch.json] [--secret-env NAME] [--secrets-out <file>]\n One file for a site: {site, config, cookies, presets, executors, webhooks, rightsPage,\n partners}, no secrets. plan prints the server's dry run of every part (\"No changes\" when\n it matches); apply applies them in dependency order and logs each. New webhook secrets\n go to --secrets-out (mode 0600).\n cookiemunch --version | version [--json]\n The CLI version; --json adds the API version the server documents.\n\nEvery command takes --json for machine-readable output.\n\nExit codes:\n 0 ok, or nothing to change\n 1 a difference (with --exit-code), a failure, or a failed check\n 2 a usage mistake\n\nEnvironment:\n COOKIEMUNCH_API_KEY an API key (cookiemunch_live_\u2026, or a legacy fck_\u2026). Required.\n COOKIEMUNCH_BASE_URL the API origin. Default https://api.cookiemunch.net.\n COOKIEMUNCH_SITE default for --site.\n COOKIEMUNCH_STRICT_FIELDS=1 send Prefer: strict-unknown-fields on writes: a field the\n API does not know is refused (400 unknown_field), not ignored.\n COOKIEMUNCH_SECRET_RECIPIENT=x25519:<base64> answers carry once-shown secrets sealed to\n this key (sealed_secret), never in plaintext.\n COOKIEMUNCH_ORG the org id doctor checks the key against.\n --idempotency-key <k> send Idempotency-Key on writes: a retry replays the first answer.\n";
54
+ declare const USAGE = "cookiemunch \u2014 Cookie Munch from the command line\n\nUsage:\n cookiemunch config pull --site <cbid> [--out <file>]\n Write the site's config as JSON (to stdout, or to <file>).\n cookiemunch config diff --site <cbid> <file> [--replace] [--exit-code]\n Show what pushing <file> would change (the server's dry run; nothing is stored).\n Read-only fields a pulled file carries (effective, designWarnings, ...) are ignored.\n cookiemunch config push --site <cbid> <file> [--replace] [--strict]\n Apply <file>. Default: merged over the stored config (PATCH) \u2014 fields the file\n leaves out keep their value, and a field set to null is removed (it takes its\n default). --replace sends it whole (PUT): a top-level field the file leaves out\n reverts to its default. Prints any design warnings the server found. --strict\n checks the file first and does not push it (exit 1) when Accept all is pushed\n harder than Reject all anywhere \u2014 for CI.\n cookiemunch config validate --site <cbid> <file> [--replace] [--strict]\n Check <file> for consent-button parity on the server, without writing: is Accept\n all more prominent than Reject all (colour, size, placement, copy, custom CSS)?\n Merged over the stored config like push; --replace checks it as sent. --strict\n exits 1 when there is any warning (notices never fail).\n cookiemunch preview --site <cbid> [--url <page>] [--region <eu|de|us-ca\u2026>] [--lang <de\u2026>]\n [--ttl <seconds>] [--open]\n Print (and with --open, open) a link showing the banner as a visitor in that\n region and language sees it. Works in headless browsers; nothing is recorded.\n cookiemunch executors test <id> (--email <email> | --canary) [--operation <locate|export|erase>]\n Try a connected system against one person without filing a request.\n --operation defaults to locate (lookup is accepted as another name for it).\n --canary uses the organisation's canary address instead: no real person, and\n a canary locate also updates the connection's health. Exits 1 when not ok.\n cookiemunch executors webhook-test <id> --headers-file <json> --body-file <file>\n Would this webhook delivery verify? Sends the headers (a JSON object) and the\n body file byte for byte to the receiver's check; nothing is acted on. Prints\n { verified, stage, reason } and exits 1 when it does not verify.\n cookiemunch executors deliveries <id>\n The last 50 deliveries to that connection's webhook, each with its reason.\n cookiemunch executors presets\n The versioned presets, which are usable now and which wait on another\n platform, and the organisation's canary address.\n cookiemunch executors conformance <baseUrl> --secret-env <NAME> [--canary-email <addr>]\n [--prefix /privacy] [--json]\n Check any system against the open cm-standard-v2 executor contract, rule by\n rule, using only the canary subject. The credential is read from the\n environment variable NAME, never from the command line. Without\n --canary-email the organisation's canary address is fetched (needs\n COOKIEMUNCH_API_KEY); with it, no Cookie Munch key is needed at all.\n Exits 1 when any rule fails.\n cookiemunch executors conformance --connection <id> [--json]\n The same suite, run by Cookie Munch against a connected system.\n cookiemunch executors roll-completion-secret <id>\n A new completion secret for that connection, printed once; the old one keeps\n verifying for 24 hours.\n cookiemunch executors upgrade-preset <id> [--preset <name>] [--version <n>]\n [--org-id <id>] [--atlas-id-app-id <id>] [--revoke-atlas-id-grant]\n [--accept-preset <path> \u2026] [--dry-run]\n Rebuild a connection from its preset's latest version (or --version), keeping\n its id and credentials; --preset adopts one on a hand-written connection.\n Your hand edits are kept (the diff marks them kept or conflict); --accept-preset\n (repeatable) takes the preset's value for that path. Prints the diff; --dry-run\n changes nothing. A pinned connection is refused.\n cookiemunch executors recheck <id>\n Re-check a connection now (a canary test that records its health): the hook to\n run after deploying that system's rights API. Exits 1 when it is not ok.\n cookiemunch executors health <id> [--limit <n>]\n The connection's last health checks, newest first (up to 50).\n cookiemunch rights-page pull --site <cbid> [--out <file>]\n Write the site's rights page draft as JSON, and print its updatedAt for --base.\n cookiemunch rights-page diff --site <cbid> <file> [--exit-code]\n Validate <file> on the server (dry run) and show what pushing it would change.\n cookiemunch rights-page push --site <cbid> <file> [--base <updatedAt>]\n Replace the draft with <file>. Nothing is live until publish. Refused (exit 1)\n if the draft changed since the diff, or since --base (the updatedAt pull printed).\n cookiemunch rights-page publish --site <cbid> [--yes] [--base <updatedAt>]\n Publish the draft (it goes live at once). Asks first; --yes skips the question\n and is required when there is no terminal to ask in. Prints why when the page\n cannot go live. Refused (exit 1) if the draft changed after it was read (or\n since --base); --yes never overrides that.\n\n cookiemunch scan --site <cbid> [--wait] [--timeout <seconds>]\n Start a cookie crawl of the site and print its state (JSON). --wait holds on\n until it is done or failed (default up to 120 s, --timeout to change) and exits\n 1 when it failed or is still running at the end. A scan already running is\n waited on rather than started twice.\n\n cookiemunch cookies presets --site <cbid>\n The declaration presets (atlas, forumulate, chatly, cookiemunch, referalli, firstpromoter,\n partnerstack, tapfiliate, impact; referally is the deprecated old name of referalli): what each takes,\n what it declared on this site, and whether the vendor's own manifest exists yet.\n cookiemunch cookies preset <vendor> --site <cbid> [--param k=v \u2026] [--dry-run]\n Declare what that platform writes (cookies and browser storage), marked as\n declared by it; run again to re-sync. Atlas: --param frontendApiHost=auth.example.com\n [--param crossSubdomainCookies=false]. Chatly: --param publicId=ch_web_\u2026 .\n Referral and affiliate presets (referalli, firstpromoter, partnerstack, tapfiliate, impact):\n [--param cookieDomain=.example.com] [--param cookieDays=60] [--param category=\u2026];\n referalli [--param legacyName=false], impact [--param campaignId=\u2026]. A row filed under a\n disabled category prints a warning and a suggestedConfigPatch. Any other vendor is\n declared with the API (PUT /v1/sites/{cbid}/cookies).\n cookiemunch cookies unpreset <vendor> --site <cbid> [--dry-run]\n Remove every declaration that vendor's preset made.\n cookiemunch cookies import-manifest <url> --site <cbid> [--file <manifest.json>] [--dry-run]\n Declare any vendor's cookies and storage from its embed manifest\n (/.well-known/<product>-embed.json), by URL or from a file. Remove it with\n cookies unpreset <product>.\n cookiemunch cookies suggestions --site <cbid>\n What to declare: the platforms detected on the site and each undeclared row.\n cookiemunch cookies declare-suggestions --site <cbid> [--names a,b] [--dry-run]\n Declare them: detected vendors' presets, then every other suggestion with a purpose.\n cookiemunch cookies delete-observed <name> --site <cbid> [--dry-run]\n Remove every stored row of that name (a name the site never sets). A declaration stays.\n cookiemunch cookies purge-observed --site <cbid> --since <time> [--until <time>] [--dry-run]\n Remove every row a real visit first reported in that window (ISO-8601 or epoch ms).\n Crawled rows and declarations stay. Run with --dry-run first.\n cookiemunch site update --site <cbid> [--domain <host>] [--name <name> | --clear-name]\n [--aliases <a,b>] [--dry-run]\n Rename or move a site. The cbid and consent ledger stay; a domain move clears\n verification. --dry-run prints the diff and its effects without saving.\n cookiemunch site brand --site <cbid> [--url <https URL> | <brand.json>] [--dry-run]\n Import a brand.json into the banner theme (the rights page uses it too). Values the\n site set itself are kept. With neither --url nor a file, prints the last import.\n cookiemunch consent-sync status --site <cbid>\n Whether hosted consent sync is set up (the secret's last four characters, when it was minted).\n cookiemunch consent-sync rotate --site <cbid>\n Mint the site's consent-sync signing secret, or replace it (the old one stops at once).\n Prints the secret alone on stdout, so it can be piped into your secret store: it is shown once.\n cookiemunch consent-sync remove --site <cbid> --yes\n Remove it: hosted consent sync stops for every visitor.\n cookiemunch consent-sync token --site <cbid> --subject <id> [--ttl <seconds>]\n Sign a test token locally with COOKIEMUNCH_CONSENT_SYNC_SECRET (nothing is sent), e.g. to try\n GET /api/v1/<cbid>/profile with curl.\n cookiemunch health [--site <cbid>] [--json] [--fail-on error|warning|never]\n Every link the site's privacy wiring depends on, with a fix hint for each that\n fails. Exits 1 when a check fails (checks that could not run, or are waived, do not count).\n --fail-on error ignores warnings; --fail-on never always exits 0.\n cookiemunch provision <file> [--dry-run]\n Wire a product's privacy in one call (site, connections, Atlas, Forumulate) from\n a JSON file without secrets: the Atlas key and Forumulate token come from\n COOKIEMUNCH_ATLAS_SECRET_KEY and COOKIEMUNCH_FORUMULATE_TOKEN. Re-running is a\n no-op. Exits 1 when a step failed.\n cookiemunch keys report [--unused-days <n>] [--expiring-days <n>] [--json]\n Key hygiene: keys unused for n days (default 90), keys with broad access, and\n keys expiring within n days (default 14). Needs a full-access key.\n cookiemunch partners list|link|unlink --site <cbid> [--partner <id>]\n [--external-id <id>] [--label <text>] [<linkId>]\n Grant a partner platform the site's consent events (no secret is created), list\n the grants, or revoke one. Any partner this deployment knows (forumulate, atlas, chatly,\n referalli, or one registered for it).\n cookiemunch token exchange --subject-token-env NAME --scope <a,b> --resource org:<id>|site:<cbid> [--expires-in <s>]\n Swap your identity provider's token (read from the variable NAME) for a short-lived, scoped\n API key (at most 1 hour); prints the key alone. Needs no API key.\n cookiemunch csp --merge <vendors|urls> [--framework next|express|nginx] [--site <cbid>]\n One Content-Security-Policy from several products' embed manifests\n (/.well-known/<product>-embed.json): cookiemunch, atlas, chatly, forumulate,\n referalli, or any manifest URL. --framework prints it for next.config.js,\n Express or nginx; without it, the header value. --site uses your site's own\n Cookie Munch manifest (its logo, fonts, sync endpoint). Needs no API key. Exits 1\n when a named product has not published a manifest (the rest are still merged).\n cookiemunch cookies diff|push <file> --site <cbid> [--replace] [--exit-code]\n Declarations as a file ({\"cookies\": [...]}), through the server's dry run. push applies\n only when something differs; --replace also removes declarations the file leaves out.\n cookiemunch executors pull [<file>] | diff <file> | push <file> [--secret-env NAME]\n Connected systems as a file. The file never carries a secret: a new connection's API key\n comes from the environment variable --secret-env names.\n cookiemunch dsar test [--types access,deletion] [--with-cbid --site <cbid>] [--without-cbid]\n [--email <addr>] [--cleanup]\n File TEST rights requests and read each back. --cleanup deletes exactly the ones this run\n filed (by id; it never deletes by listing).\n cookiemunch doctor [--site <cbid>] [--org <id>]\n The key (and whose org it is, against --org or COOKIEMUNCH_ORG), its expiry, the CLI\n version against the latest, and integration health. Exits 1 when a check fails.\n cookiemunch keys vend --scopes <a,b> --ttl <1h|30m|seconds> [--cbids <x,y>] [--name <n>]\n A short-lived key (at most 12 h) within this key's own scopes; prints the key alone.\n Needs keys:write (or a full-access key).\n cookiemunch keys self | rotate-self\n This key's own prefix, scopes and expiry; or rotate it (the new key is printed once).\n cookiemunch sandbox [show] | create [--key-name <n>] | delete [--yes]\n The organisation's sandbox: a separate test organisation with the same people and plan\n features, never billed; its keys are test keys and its rights requests are all tests.\n create makes it (or reuses it) and prints a new key for it alone; delete erases it and\n everything in it, after asking. create and delete need a full-access key or orgs:create.\n cookiemunch plan [cookiemunch.json] [--exit-code] [--json]\n cookiemunch apply [cookiemunch.json] [--secret-env NAME] [--secrets-out <file>]\n One file for a site: {site, config, cookies, presets, executors, webhooks, rightsPage,\n partners}, no secrets. plan prints the server's dry run of every part (\"No changes\" when\n it matches); apply applies them in dependency order and logs each. New webhook secrets\n go to --secrets-out (mode 0600).\n cookiemunch --version | version [--json]\n The CLI version; --json adds the API version the server documents.\n\nEvery command takes --json for machine-readable output.\n\nExit codes:\n 0 ok, or nothing to change\n 1 a difference (with --exit-code), a failure, or a failed check\n 2 a usage mistake\n\nEnvironment:\n COOKIEMUNCH_API_KEY an API key (cookiemunch_live_\u2026, or a legacy fck_\u2026). Required.\n COOKIEMUNCH_BASE_URL the API origin. Default https://api.cookiemunch.net.\n COOKIEMUNCH_SITE default for --site.\n COOKIEMUNCH_STRICT_FIELDS=1 send Prefer: strict-unknown-fields on writes: a field the\n API does not know is refused (400 unknown_field), not ignored.\n COOKIEMUNCH_SECRET_RECIPIENT=x25519:<base64> answers carry once-shown secrets sealed to\n this key (sealed_secret), never in plaintext.\n COOKIEMUNCH_ORG the org id doctor checks the key against.\n --idempotency-key <k> send Idempotency-Key on writes: a retry replays the first answer.\n";
55
55
  interface Parsed {
56
56
  positional: string[];
57
57
  flags: Record<string, string | true>;
@@ -137,7 +137,7 @@ interface ManifestSource {
137
137
  urls: string[];
138
138
  product?: string;
139
139
  }
140
- /** `atlas,chatly,https://x/.well-known/forgedeck-embed.json` → sources to fetch. */
140
+ /** `atlas,chatly,https://x/.well-known/x-embed.json` → sources to fetch. */
141
141
  declare function manifestSources(list: string, opts: {
142
142
  site?: string;
143
143
  apiBase: string;
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  renderPolicy,
15
15
  rightsPageCommand,
16
16
  run
17
- } from "./chunk-LJ433UVC.js";
17
+ } from "./chunk-CWBS6Z2H.js";
18
18
  export {
19
19
  CSP_FRAMEWORKS,
20
20
  DEFAULT_BASE_URL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cookiemunch/cli",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "cookiemunch — config as code, banner previews and connection tests from a terminal or CI, over the Cookie Munch Developer API",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  "test": "vitest run"
36
36
  },
37
37
  "dependencies": {
38
- "@cookiemunch/sdk": "^0.6.0"
38
+ "@cookiemunch/sdk": "^0.7.1"
39
39
  },
40
40
  "homepage": "https://cookiemunch.net/docs",
41
41
  "bugs": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/diff.ts","../src/rights-page.ts","../src/csp.ts","../src/cli.ts","../src/integrations.ts","../src/design-warnings.ts","../src/ops.ts"],"sourcesContent":["/**\n * What a config push would change, computed on this side of the wire.\n *\n * `mergeLikeServer` mirrors the server's `PATCH /v1/sites/{cbid}/config` semantics exactly\n * (JSON Merge Patch, RFC 7386 — packages/server/src/site-config-write.ts mergePatch): the\n * patch wins, nested plain objects merge, arrays and primitives replace wholesale, and a\n * `null` removes the key. A diff computed against any other merge would describe a change\n * the server is not going to make.\n */\n\nexport type Json = null | boolean | number | string | Json[] | { [k: string]: Json };\n\nexport interface Change {\n /** Dotted path; array indices in brackets: `banner.content.title`, `geoRules[0].mode`. */\n path: string;\n kind: 'added' | 'removed' | 'changed';\n from?: Json;\n to?: Json;\n}\n\n/**\n * Returned by a config read, never a setting; the server drops them from a write\n * (packages/server/src/site-config-write.ts READ_ONLY_CONFIG_FIELDS, pinned by a test).\n */\nexport const READ_ONLY_CONFIG_FIELDS = ['effective', 'warnings', 'designWarnings', 'region', 'regulation', 'copy', 'rightsFormUrl', 'version', 'observeToken', 'sdkBoot', 'originEnv'] as const;\n\n/** A copy of a config without its read-only fields, so a pulled file diffs clean against the server. */\nexport function withoutReadOnly(cfg: Record<string, unknown>): Record<string, unknown> {\n const out = { ...cfg };\n for (const k of READ_ONLY_CONFIG_FIELDS) delete out[k];\n return out;\n}\n\nexport function isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\nexport function mergeLikeServer(base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...base };\n for (const [k, v] of Object.entries(patch)) {\n const b = base[k];\n if (v === null) delete out[k];\n else out[k] = isPlainObject(v) ? mergeLikeServer(isPlainObject(b) ? b : {}, v) : v;\n }\n return out;\n}\n\nfunction join(path: string, key: string): string {\n return path ? `${path}.${key}` : key;\n}\n\n/** Every leaf that differs between `before` and `after`, in a stable order. */\nexport function diffJson(before: unknown, after: unknown, path = ''): Change[] {\n if (isPlainObject(before) && isPlainObject(after)) {\n const keys = [...new Set([...Object.keys(before), ...Object.keys(after)])].sort();\n return keys.flatMap((k) => {\n const p = join(path, k);\n if (!(k in after)) return [{ path: p, kind: 'removed' as const, from: before[k] as Json }];\n if (!(k in before)) return [{ path: p, kind: 'added' as const, to: after[k] as Json }];\n return diffJson(before[k], after[k], p);\n });\n }\n if (Array.isArray(before) && Array.isArray(after)) {\n const out: Change[] = [];\n const n = Math.max(before.length, after.length);\n for (let i = 0; i < n; i++) {\n const p = `${path}[${i}]`;\n if (i >= after.length) out.push({ path: p, kind: 'removed', from: before[i] as Json });\n else if (i >= before.length) out.push({ path: p, kind: 'added', to: after[i] as Json });\n else out.push(...diffJson(before[i], after[i], p));\n }\n return out;\n }\n if (JSON.stringify(before) === JSON.stringify(after)) return [];\n return [{ path: path || '(root)', kind: 'changed', from: before as Json, to: after as Json }];\n}\n\nfunction show(v: Json | undefined): string {\n const s = JSON.stringify(v);\n return s === undefined ? 'undefined' : s.length > 120 ? `${s.slice(0, 117)}...` : s;\n}\n\n/** A unified-diff-ish rendering: one line per change. */\nexport function formatChanges(changes: Change[]): string {\n return changes\n .map((c) =>\n c.kind === 'added'\n ? `+ ${c.path}: ${show(c.to)}`\n : c.kind === 'removed'\n ? `- ${c.path}: ${show(c.from)}`\n : `~ ${c.path}: ${show(c.from)} -> ${show(c.to)}`,\n )\n .join('\\n');\n}\n","/**\n * `cookiemunch rights-page pull|diff|push|publish` — the hosted rights page as code.\n *\n * Unlike `config diff`, `diff` asks the server: the rights page has a real dry run, so the\n * diff is against what the server would store (normalised and sanitised), and an invalid\n * file fails with the server's issues before anything is written.\n */\nimport { CookieMunchApiError, type CookieMunchClient } from '@cookiemunch/sdk';\nimport type { CliIo } from './cli.js';\nimport { diffJson, formatChanges } from './diff.js';\n\ninterface Helpers { requireSite(): string; readJson(path: string | undefined): Promise<Record<string, unknown>>; usage(msg: string): Error }\ntype Issue = { path: string; message: string };\n\nconst isConflict = (e: unknown) => e instanceof CookieMunchApiError && e.status === 409;\n\n/** `--base <updatedAt>` (epoch ms or an ISO date), else the updatedAt this command just read. */\nfunction baseFrom(flag: string | true | undefined, read: number | null | undefined, h: Helpers): number | string | null {\n if (flag === undefined) return read ?? null;\n if (typeof flag === 'string' && /^\\d+$/.test(flag)) return Number(flag);\n if (typeof flag === 'string' && /^\\d{4}-\\d{2}-\\d{2}T/.test(flag) && Number.isFinite(Date.parse(flag))) return flag;\n throw h.usage('--base must be the draft’s updatedAt (epoch ms, as pull prints it, or an ISO date)');\n}\n\nfunction issuesOf(e: unknown): Issue[] | null {\n if (!(e instanceof CookieMunchApiError) || e.status !== 422) return null;\n const body = e.body as { issues?: Issue[]; problems?: Issue[] } | undefined;\n return body?.issues ?? body?.problems ?? [];\n}\n\nexport async function rightsPageCommand(\n sub: string | undefined,\n p: { positional: string[]; flags: Record<string, string | true> },\n io: CliIo,\n client: CookieMunchClient,\n h: Helpers,\n): Promise<number> {\n const cbid = h.requireSite();\n const report = (list: Issue[]) => io.stderr(`${list.map((i) => ` ${i.path || '(document)'}: ${i.message}`).join('\\n')}\\n`);\n if (sub === 'pull') {\n const { draft, updatedAt } = await client.rightsPage.get(cbid);\n const text = `${JSON.stringify(draft, null, 2)}\\n`;\n const out = typeof p.flags.out === 'string' ? p.flags.out : undefined;\n if (out) {\n await io.writeFile(out, text);\n io.stderr(`Wrote ${cbid}'s rights page draft to ${out}\\n`);\n } else io.stdout(text);\n if (updatedAt != null) io.stderr(`To refuse a push if anyone saves the draft after this pull, push with: --base ${updatedAt}\\n`);\n return 0;\n }\n if (sub === 'diff' || sub === 'push') {\n const file = await h.readJson(p.positional[2]);\n const read = await client.rightsPage.get(cbid);\n const current = read.draft;\n // The base the diff is against (or the one pull printed): a save after it is a conflict, never lost.\n const base = baseFrom(p.flags.base, read.updatedAt, h);\n let proposed: unknown;\n try {\n proposed = (await client.rightsPage.dryRun(cbid, file, { mode: 'put' })).draft;\n } catch (e) {\n const list = issuesOf(e);\n if (!list) throw e;\n io.stderr(`${p.positional[2]} is not a valid rights page:\\n`);\n report(list);\n return 1;\n }\n const changes = diffJson(current, proposed);\n if (p.flags.json === true && (sub === 'diff' || !changes.length)) io.stdout(`${JSON.stringify({ cbid, changes }, null, 2)}\\n`);\n if (!changes.length) { io.stderr(`No changes: ${cbid}'s rights page draft already matches.\\n`); return 0; }\n if (p.flags.json !== true) io.stdout(`${formatChanges(changes)}\\n`);\n if (sub === 'diff') {\n io.stderr(`${changes.length} change${changes.length === 1 ? '' : 's'} (nothing saved). Apply with: cookiemunch rights-page push --site ${cbid} ${p.positional[2]}\\n`);\n return p.flags['exit-code'] === true ? 1 : 0;\n }\n let saved;\n try {\n saved = await client.rightsPage.put(cbid, file as never, { baseUpdatedAt: base });\n } catch (e) {\n if (!isConflict(e)) throw e;\n io.stderr(`Not saved: ${cbid}'s rights page draft changed since ${p.flags.base !== undefined ? 'the --base you gave' : 'this diff'} (someone else saved it).\\n`\n + `See what changed with: cookiemunch rights-page diff --site ${cbid} ${p.positional[2]}\\nthen push again.\\n`);\n return 1;\n }\n io.stderr(`Saved the draft (${changes.length} change${changes.length === 1 ? '' : 's'}). Nothing is live until: cookiemunch rights-page publish --site ${cbid}\\n`);\n if (saved.warnings.length) { io.stderr('It cannot be published yet:\\n'); report(saved.warnings); }\n return 0;\n }\n if (sub === 'publish') {\n // Read before asking, so the draft that goes live is the one that existed when you said yes.\n const base = p.flags.base !== undefined ? baseFrom(p.flags.base, null, h) : (await client.rightsPage.get(cbid)).updatedAt ?? null;\n if (p.flags.yes !== true) {\n if (!io.confirm) throw h.usage('rights-page publish puts the draft live and there is no terminal to confirm in. Pass --yes to publish without a prompt.');\n if (!(await io.confirm(`Publish ${cbid}'s rights page draft? It goes live at once. [y/N] `))) {\n io.stderr('Not published.\\n');\n return 1;\n }\n }\n try {\n const r = await client.rightsPage.publish(cbid, { baseUpdatedAt: base });\n io.stderr(`Published version ${r.version} of ${cbid}'s rights page.\\n`);\n return 0;\n } catch (e) {\n if (isConflict(e)) {\n io.stderr(`Nothing was published: ${cbid}'s rights page draft changed since it was read (someone else saved it).\\n`\n + `Review it with: cookiemunch rights-page pull --site ${cbid}\\nthen publish again.\\n`);\n return 1;\n }\n const list = issuesOf(e);\n if (!list) throw e;\n io.stderr('The rights page cannot be published:\\n');\n report(list);\n return 1;\n }\n }\n throw h.usage(`unknown rights-page command: ${sub ?? '(none)'} — use pull, diff, push or publish`);\n}\n","/**\n * `cookiemunch csp --merge <vendors|urls> [--framework next|express|nginx] [--site <cbid>]`\n *\n * One Content-Security-Policy from several products' embed manifests\n * (`/.well-known/forgedeck-embed.json`, schema https://cookiemunch.net/schemas/embed-v1.json):\n * each manifest lists its origins by directive (`csp`) and the non-origin sources it needs\n * (`requires`); the policy is their union, plus `'self'`.\n *\n * Vendor-neutral: `--merge` takes any manifest URL. The names below are first-class shortcuts\n * for products whose manifest host is known — the same host map the API's importer uses\n * (packages/server/src/manifest-importer.ts; a test keeps the two equal). A product that has not\n * published its manifest yet is reported, and the policy is built from the rest.\n *\n * Needs no API key: every manifest is public, `--site` included (`GET /v1/embed?cbid=`).\n */\n\n/** Where a known product publishes its manifest: the apex first, then its API host. */\nexport const KNOWN_MANIFEST_HOSTS: Readonly<Record<string, readonly string[]>> = {\n cookiemunch: ['cookiemunch.net', 'api.cookiemunch.net'],\n atlas: ['atlasauth.net', 'api.atlasauth.net'],\n chatly: ['chatlychat.com', 'api.chatlychat.com'],\n forumulate: ['forumulate.com'],\n referalli: ['referalli.com'],\n};\n\n/** Old names still accepted. */\nconst ALIASES: Record<string, string> = { referally: 'referalli' };\n\nexport const CSP_FRAMEWORKS = ['next', 'express', 'nginx'] as const;\nexport type CspFramework = (typeof CSP_FRAMEWORKS)[number];\n\ntype Surface = { csp?: Record<string, unknown>; requires?: Record<string, unknown> };\ntype Manifest = { product?: unknown; surfaces?: Record<string, Surface> };\n\nexport interface ManifestSource {\n /** What the user named: a vendor or a URL. */\n label: string;\n /** URLs to try, in order. */\n urls: string[];\n product?: string;\n}\n\n/** `atlas,chatly,https://x/.well-known/forgedeck-embed.json` → sources to fetch. */\nexport function manifestSources(list: string, opts: { site?: string; apiBase: string }): { sources: ManifestSource[]; unknown: string[] } {\n const sources: ManifestSource[] = [];\n const unknown: string[] = [];\n for (const raw of list.split(',').map((s) => s.trim()).filter(Boolean)) {\n if (/^https:\\/\\//i.test(raw)) {\n sources.push({ label: raw, urls: [raw] });\n continue;\n }\n const name = ALIASES[raw.toLowerCase()] ?? raw.toLowerCase();\n const hosts = KNOWN_MANIFEST_HOSTS[name];\n if (!hosts) {\n unknown.push(raw);\n continue;\n }\n if (name === 'cookiemunch' && opts.site) {\n sources.push({ label: `cookiemunch (site ${opts.site})`, urls: [`${opts.apiBase.replace(/\\/$/, '')}/v1/embed?cbid=${encodeURIComponent(opts.site)}`], product: name });\n continue;\n }\n sources.push({ label: name, urls: hosts.map((h) => `https://${h}/.well-known/forgedeck-embed.json`), product: name });\n }\n return { sources, unknown };\n}\n\nconst ORIGIN = /^(https|wss):\\/\\/[^\\s*'\"]+$/;\nconst KEYWORD = /^('unsafe-inline'|'unsafe-eval'|'wasm-unsafe-eval'|'unsafe-hashes'|data:|blob:)$/;\n\n/** The union of every surface's origins and requirements, by directive; `'self'` first. */\nexport function mergeManifests(manifests: Manifest[]): Map<string, string[]> {\n const byDirective = new Map<string, Set<string>>();\n const add = (directive: string, list: unknown, allowKeywords: boolean) => {\n if (!Array.isArray(list) || !/^[a-z-]+-src$|^form-action$/.test(directive)) return;\n let set = byDirective.get(directive);\n if (!set) byDirective.set(directive, (set = new Set()));\n for (const src of list) {\n if (typeof src !== 'string') continue;\n // A placeholder (`https://{instance}.example.com`) is a tenant's value: it cannot be pasted.\n if (src.includes('{')) continue;\n if (ORIGIN.test(src) || (allowKeywords && KEYWORD.test(src))) set.add(src);\n }\n };\n for (const m of manifests) {\n for (const s of Object.values(m.surfaces ?? {})) {\n for (const [d, list] of Object.entries(s.csp ?? {})) add(d, list, false);\n for (const [d, list] of Object.entries(s.requires ?? {})) add(d, list, true);\n }\n }\n const out = new Map<string, string[]>();\n out.set('default-src', [\"'self'\"]);\n for (const [d, set] of [...byDirective.entries()].sort(([a], [b]) => a.localeCompare(b))) {\n if (set.size === 0) continue;\n const keywords = [...set].filter((s) => !ORIGIN.test(s)).sort();\n const origins = [...set].filter((s) => ORIGIN.test(s)).sort();\n out.set(d, [\"'self'\", ...keywords, ...origins]);\n }\n return out;\n}\n\n/** Placeholders a manifest left for the tenant to fill in: reported, never guessed. */\nexport function placeholders(manifests: Manifest[]): string[] {\n const out = new Set<string>();\n for (const m of manifests) {\n for (const s of Object.values(m.surfaces ?? {})) {\n for (const map of [s.csp, s.requires]) {\n for (const list of Object.values(map ?? {})) {\n if (Array.isArray(list)) for (const src of list) if (typeof src === 'string' && src.includes('{')) out.add(src);\n }\n }\n }\n }\n return [...out].sort();\n}\n\nexport function policyString(policy: Map<string, string[]>): string {\n return [...policy.entries()].map(([d, list]) => `${d} ${list.join(' ')}`).join('; ');\n}\n\n/** The policy as the framework writes it. */\nexport function renderPolicy(policy: Map<string, string[]>, framework?: CspFramework): string {\n const value = policyString(policy);\n if (framework === 'next') {\n return [\n '// next.config.js',\n 'async headers() {',\n ' return [{',\n \" source: '/(.*)',\",\n ` headers: [{ key: 'Content-Security-Policy', value: ${JSON.stringify(value)} }],`,\n ' }];',\n '},',\n ].join('\\n');\n }\n if (framework === 'express') {\n return `app.use((req, res, next) => { res.setHeader('Content-Security-Policy', ${JSON.stringify(value)}); next(); });`;\n }\n if (framework === 'nginx') return `add_header Content-Security-Policy \"${value.replace(/\"/g, '\\\\\"')}\" always;`;\n return value;\n}\n\n/** Fetch one manifest, trying each URL in turn. */\nexport async function fetchManifest(src: ManifestSource, fetchImpl: typeof fetch): Promise<{ ok: true; manifest: Manifest; url: string } | { ok: false; error: string }> {\n const tried: string[] = [];\n for (const url of src.urls) {\n try {\n const res = await fetchImpl(url, { headers: { Accept: 'application/json' }, redirect: 'manual' });\n if (!res.ok) {\n tried.push(`${url} answered ${res.status}`);\n continue;\n }\n const doc = (await res.json()) as Manifest;\n if (!doc || typeof doc !== 'object' || !doc.surfaces || typeof doc.surfaces !== 'object') {\n tried.push(`${url} is not an embed manifest (no surfaces)`);\n continue;\n }\n if (src.product && doc.product !== src.product) {\n tried.push(`${url} speaks for \"${String(doc.product)}\", not ${src.product}`);\n continue;\n }\n return { ok: true, manifest: doc, url };\n } catch (e) {\n tried.push(`${url}: ${(e as Error).message}`);\n }\n }\n return { ok: false, error: tried.join('; ') || 'no URL to try' };\n}\n\nexport interface CspIo {\n fetch: typeof fetch;\n stdout: (text: string) => void;\n stderr: (text: string) => void;\n}\n\nexport async function cspCommand(\n opts: { merge?: string; framework?: string; site?: string; apiBase: string },\n io: CspIo,\n usage: (message: string) => Error,\n): Promise<number> {\n if (!opts.merge) throw usage('--merge is required: vendor names (cookiemunch, atlas, chatly, forumulate, referalli) or manifest URLs, comma-separated');\n if (opts.framework !== undefined && !(CSP_FRAMEWORKS as readonly string[]).includes(opts.framework)) {\n throw usage(`--framework must be one of ${CSP_FRAMEWORKS.join(', ')}`);\n }\n const { sources, unknown } = manifestSources(opts.merge, { apiBase: opts.apiBase, ...(opts.site ? { site: opts.site } : {}) });\n if (unknown.length) throw usage(`unknown vendor: ${unknown.join(', ')}. Name one of ${Object.keys(KNOWN_MANIFEST_HOSTS).join(', ')}, or pass its manifest URL (https://…/.well-known/forgedeck-embed.json).`);\n const manifests: Manifest[] = [];\n let failed = 0;\n for (const src of sources) {\n const r = await fetchManifest(src, io.fetch);\n if (r.ok) manifests.push(r.manifest);\n else {\n failed++;\n io.stderr(`${src.label}: no manifest — ${r.error}\\n`);\n }\n }\n if (manifests.length === 0) return 1;\n const policy = mergeManifests(manifests);\n io.stdout(`${renderPolicy(policy, opts.framework as CspFramework | undefined)}\\n`);\n const left = placeholders(manifests);\n if (left.length) io.stderr(`Tenant-specific sources left out (fill in your own value): ${left.join(', ')}\\n`);\n return failed ? 1 : 0;\n}\n","/**\n * `cookiemunch` — the Developer API from a terminal or a CI job.\n *\n * cookiemunch config pull --site <cbid> [--out file]\n * cookiemunch config diff --site <cbid> <file> [--replace] [--exit-code]\n * cookiemunch config push --site <cbid> <file> [--replace] [--strict]\n * cookiemunch config validate --site <cbid> <file> [--replace] [--strict]\n * cookiemunch preview --site <cbid> [--url <url>] [--region eu] [--lang de] [--ttl 900] [--open]\n * cookiemunch executors test <id> --email <email> [--operation locate]\n * cookiemunch executors webhook-test <id> --headers-file <json> --body-file <file>\n * cookiemunch executors deliveries <id>\n * cookiemunch executors presets\n * cookiemunch executors conformance <baseUrl> --secret-env <NAME> [--canary-email <addr>] [--prefix /privacy] [--json]\n * cookiemunch executors conformance --connection <id> [--json]\n * cookiemunch executors roll-completion-secret <id>\n * cookiemunch executors upgrade-preset <id> [--preset <name>] [--version <n>] [--org-id <id>] [--atlas-id-app-id <id>]\n * [--revoke-atlas-id-grant] [--accept-preset <path> …] [--dry-run]\n * cookiemunch executors recheck <id>\n * cookiemunch executors health <id> [--limit <n>]\n * cookiemunch rights-page pull|diff|push|publish --site <cbid> [<file>] [--base <updatedAt>] [--yes]\n * cookiemunch scan --site <cbid> [--wait] [--timeout <seconds>]\n * cookiemunch cookies presets|preset|unpreset|delete-observed|purge-observed --site <cbid> …\n * cookiemunch site update --site <cbid> [--domain <host>] [--name <name>] [--aliases a,b] [--dry-run]\n * cookiemunch site brand --site <cbid> [--url <https URL> | <brand.json>] [--dry-run]\n * cookiemunch health [--site <cbid>] [--json] [--fail-on error|warning|never]\n * cookiemunch provision <file> [--dry-run]\n * cookiemunch partners list|link|unlink --site <cbid> …\n * cookiemunch consent-sync status|rotate|remove|token --site <cbid> …\n * cookiemunch csp --merge <vendors|urls> [--framework next|express|nginx] [--site <cbid>]\n *\n * Everything goes through the typed SDK (@cookiemunch/sdk) except where the SDK has no\n * method yet; those calls go through `rawRequest` with the same key and base URL. All I/O\n * is injected, so the whole CLI is testable with a mocked fetch.\n */\n\nimport { createCookieMunch, CookieMunchApiError, mintConsentSyncToken, runExecutorConformance, type CookieMunchClient } from '@cookiemunch/sdk';\nimport { diffJson, formatChanges, isPlainObject, mergeLikeServer, withoutReadOnly, type Change, type Json } from './diff.js';\nimport { rightsPageCommand } from './rights-page.js';\nimport { healthCommand, keysCommand, partnersCommand, provisionCommand, siteCommand } from './integrations.js';\nimport { countBySeverity, formatDesignWarnings, summaryLine } from './design-warnings.js';\nimport { cspCommand } from './csp.js';\nimport { bundleCommand, cookiesFileCommand, doctorCommand, dsarTestCommand, executorsFileCommand, keysExtraCommand, versionCommand, type OpsHelpers } from './ops.js';\n\nexport const DEFAULT_BASE_URL = 'https://api.cookiemunch.net';\n\nexport interface CliIo {\n env: Record<string, string | undefined>;\n fetch: typeof fetch;\n stdout: (text: string) => void;\n stderr: (text: string) => void;\n readFile: (path: string) => Promise<string>;\n /** `mode` is the file mode for a new file (0o600 for anything holding a secret). */\n writeFile: (path: string, data: string, mode?: number) => Promise<void>;\n /** Open a URL in the user's browser. */\n openUrl: (url: string) => Promise<void>;\n /**\n * Ask a yes/no question. Present only when a person can answer (an interactive terminal);\n * absent, a command that needs confirmation refuses unless given --yes.\n */\n confirm?: (question: string) => Promise<boolean>;\n}\n\nexport const USAGE = `cookiemunch — Cookie Munch from the command line\n\nUsage:\n cookiemunch config pull --site <cbid> [--out <file>]\n Write the site's config as JSON (to stdout, or to <file>).\n cookiemunch config diff --site <cbid> <file> [--replace] [--exit-code]\n Show what pushing <file> would change (the server's dry run; nothing is stored).\n Read-only fields a pulled file carries (effective, designWarnings, ...) are ignored.\n cookiemunch config push --site <cbid> <file> [--replace] [--strict]\n Apply <file>. Default: merged over the stored config (PATCH) — fields the file\n leaves out keep their value, and a field set to null is removed (it takes its\n default). --replace sends it whole (PUT): a top-level field the file leaves out\n reverts to its default. Prints any design warnings the server found. --strict\n checks the file first and does not push it (exit 1) when Accept all is pushed\n harder than Reject all anywhere — for CI.\n cookiemunch config validate --site <cbid> <file> [--replace] [--strict]\n Check <file> for consent-button parity on the server, without writing: is Accept\n all more prominent than Reject all (colour, size, placement, copy, custom CSS)?\n Merged over the stored config like push; --replace checks it as sent. --strict\n exits 1 when there is any warning (notices never fail).\n cookiemunch preview --site <cbid> [--url <page>] [--region <eu|de|us-ca…>] [--lang <de…>]\n [--ttl <seconds>] [--open]\n Print (and with --open, open) a link showing the banner as a visitor in that\n region and language sees it. Works in headless browsers; nothing is recorded.\n cookiemunch executors test <id> (--email <email> | --canary) [--operation <locate|export|erase>]\n Try a connected system against one person without filing a request.\n --operation defaults to locate (lookup is accepted as another name for it).\n --canary uses the organisation's canary address instead: no real person, and\n a canary locate also updates the connection's health. Exits 1 when not ok.\n cookiemunch executors webhook-test <id> --headers-file <json> --body-file <file>\n Would this webhook delivery verify? Sends the headers (a JSON object) and the\n body file byte for byte to the receiver's check; nothing is acted on. Prints\n { verified, stage, reason } and exits 1 when it does not verify.\n cookiemunch executors deliveries <id>\n The last 50 deliveries to that connection's webhook, each with its reason.\n cookiemunch executors presets\n The versioned presets, which are usable now and which wait on another\n platform, and the organisation's canary address.\n cookiemunch executors conformance <baseUrl> --secret-env <NAME> [--canary-email <addr>]\n [--prefix /privacy] [--json]\n Check any system against the open cm-standard-v2 executor contract, rule by\n rule, using only the canary subject. The credential is read from the\n environment variable NAME, never from the command line. Without\n --canary-email the organisation's canary address is fetched (needs\n COOKIEMUNCH_API_KEY); with it, no Cookie Munch key is needed at all.\n Exits 1 when any rule fails.\n cookiemunch executors conformance --connection <id> [--json]\n The same suite, run by Cookie Munch against a connected system.\n cookiemunch executors roll-completion-secret <id>\n A new completion secret for that connection, printed once; the old one keeps\n verifying for 24 hours.\n cookiemunch executors upgrade-preset <id> [--preset <name>] [--version <n>]\n [--org-id <id>] [--atlas-id-app-id <id>] [--revoke-atlas-id-grant]\n [--accept-preset <path> …] [--dry-run]\n Rebuild a connection from its preset's latest version (or --version), keeping\n its id and credentials; --preset adopts one on a hand-written connection.\n Your hand edits are kept (the diff marks them kept or conflict); --accept-preset\n (repeatable) takes the preset's value for that path. Prints the diff; --dry-run\n changes nothing. A pinned connection is refused.\n cookiemunch executors recheck <id>\n Re-check a connection now (a canary test that records its health): the hook to\n run after deploying that system's rights API. Exits 1 when it is not ok.\n cookiemunch executors health <id> [--limit <n>]\n The connection's last health checks, newest first (up to 50).\n cookiemunch rights-page pull --site <cbid> [--out <file>]\n Write the site's rights page draft as JSON, and print its updatedAt for --base.\n cookiemunch rights-page diff --site <cbid> <file> [--exit-code]\n Validate <file> on the server (dry run) and show what pushing it would change.\n cookiemunch rights-page push --site <cbid> <file> [--base <updatedAt>]\n Replace the draft with <file>. Nothing is live until publish. Refused (exit 1)\n if the draft changed since the diff, or since --base (the updatedAt pull printed).\n cookiemunch rights-page publish --site <cbid> [--yes] [--base <updatedAt>]\n Publish the draft (it goes live at once). Asks first; --yes skips the question\n and is required when there is no terminal to ask in. Prints why when the page\n cannot go live. Refused (exit 1) if the draft changed after it was read (or\n since --base); --yes never overrides that.\n\n cookiemunch scan --site <cbid> [--wait] [--timeout <seconds>]\n Start a cookie crawl of the site and print its state (JSON). --wait holds on\n until it is done or failed (default up to 120 s, --timeout to change) and exits\n 1 when it failed or is still running at the end. A scan already running is\n waited on rather than started twice.\n\n cookiemunch cookies presets --site <cbid>\n The declaration presets (atlas, forumulate, chatly, cookiemunch, referalli, firstpromoter,\n partnerstack, tapfiliate, impact; referally is the deprecated old name of referalli): what each takes,\n what it declared on this site, and whether the vendor's own manifest exists yet.\n cookiemunch cookies preset <vendor> --site <cbid> [--param k=v …] [--dry-run]\n Declare what that platform writes (cookies and browser storage), marked as\n declared by it; run again to re-sync. Atlas: --param frontendApiHost=auth.example.com\n [--param crossSubdomainCookies=false]. Chatly: --param publicId=ch_web_… .\n Referral and affiliate presets (referalli, firstpromoter, partnerstack, tapfiliate, impact):\n [--param cookieDomain=.example.com] [--param cookieDays=60] [--param category=…];\n referalli [--param legacyName=false], impact [--param campaignId=…]. A row filed under a\n disabled category prints a warning and a suggestedConfigPatch. Any other vendor is\n declared with the API (PUT /v1/sites/{cbid}/cookies).\n cookiemunch cookies unpreset <vendor> --site <cbid> [--dry-run]\n Remove every declaration that vendor's preset made.\n cookiemunch cookies import-manifest <url> --site <cbid> [--file <manifest.json>] [--dry-run]\n Declare any vendor's cookies and storage from its embed manifest\n (/.well-known/forgedeck-embed.json), by URL or from a file. Remove it with\n cookies unpreset <product>.\n cookiemunch cookies suggestions --site <cbid>\n What to declare: the platforms detected on the site and each undeclared row.\n cookiemunch cookies declare-suggestions --site <cbid> [--names a,b] [--dry-run]\n Declare them: detected vendors' presets, then every other suggestion with a purpose.\n cookiemunch cookies delete-observed <name> --site <cbid> [--dry-run]\n Remove every stored row of that name (a name the site never sets). A declaration stays.\n cookiemunch cookies purge-observed --site <cbid> --since <time> [--until <time>] [--dry-run]\n Remove every row a real visit first reported in that window (ISO-8601 or epoch ms).\n Crawled rows and declarations stay. Run with --dry-run first.\n cookiemunch site update --site <cbid> [--domain <host>] [--name <name> | --clear-name]\n [--aliases <a,b>] [--dry-run]\n Rename or move a site. The cbid and consent ledger stay; a domain move clears\n verification. --dry-run prints the diff and its effects without saving.\n cookiemunch site brand --site <cbid> [--url <https URL> | <brand.json>] [--dry-run]\n Import a brand.json into the banner theme (the rights page uses it too). Values the\n site set itself are kept. With neither --url nor a file, prints the last import.\n cookiemunch consent-sync status --site <cbid>\n Whether hosted consent sync is set up (the secret's last four characters, when it was minted).\n cookiemunch consent-sync rotate --site <cbid>\n Mint the site's consent-sync signing secret, or replace it (the old one stops at once).\n Prints the secret alone on stdout, so it can be piped into your secret store: it is shown once.\n cookiemunch consent-sync remove --site <cbid> --yes\n Remove it: hosted consent sync stops for every visitor.\n cookiemunch consent-sync token --site <cbid> --subject <id> [--ttl <seconds>]\n Sign a test token locally with COOKIEMUNCH_CONSENT_SYNC_SECRET (nothing is sent), e.g. to try\n GET /api/v1/<cbid>/profile with curl.\n cookiemunch health [--site <cbid>] [--json] [--fail-on error|warning|never]\n Every link the site's privacy wiring depends on, with a fix hint for each that\n fails. Exits 1 when a check fails (checks that could not run, or are waived, do not count).\n --fail-on error ignores warnings; --fail-on never always exits 0.\n cookiemunch provision <file> [--dry-run]\n Wire a product's privacy in one call (site, connections, Atlas, Forumulate) from\n a JSON file without secrets: the Atlas key and Forumulate token come from\n COOKIEMUNCH_ATLAS_SECRET_KEY and COOKIEMUNCH_FORUMULATE_TOKEN. Re-running is a\n no-op. Exits 1 when a step failed.\n cookiemunch keys report [--unused-days <n>] [--expiring-days <n>] [--json]\n Key hygiene: keys unused for n days (default 90), keys with broad access, and\n keys expiring within n days (default 14). Needs a full-access key.\n cookiemunch partners list|link|unlink --site <cbid> [--partner <id>]\n [--external-id <id>] [--label <text>] [<linkId>]\n Grant a partner platform the site's consent events (no secret is created), list\n the grants, or revoke one. Any partner this deployment knows (forumulate, atlas, chatly,\n referalli, or one registered for it).\n cookiemunch csp --merge <vendors|urls> [--framework next|express|nginx] [--site <cbid>]\n One Content-Security-Policy from several products' embed manifests\n (/.well-known/forgedeck-embed.json): cookiemunch, atlas, chatly, forumulate,\n referalli, or any manifest URL. --framework prints it for next.config.js,\n Express or nginx; without it, the header value. --site uses your site's own\n Cookie Munch manifest (its logo, fonts, sync endpoint). Needs no API key. Exits 1\n when a named product has not published a manifest (the rest are still merged).\n cookiemunch cookies diff|push <file> --site <cbid> [--replace] [--exit-code]\n Declarations as a file ({\"cookies\": [...]}), through the server's dry run. push applies\n only when something differs; --replace also removes declarations the file leaves out.\n cookiemunch executors pull [<file>] | diff <file> | push <file> [--secret-env NAME]\n Connected systems as a file. The file never carries a secret: a new connection's API key\n comes from the environment variable --secret-env names.\n cookiemunch dsar test [--types access,deletion] [--with-cbid --site <cbid>] [--without-cbid]\n [--email <addr>] [--cleanup]\n File TEST rights requests and read each back. --cleanup deletes exactly the ones this run\n filed (by id; it never deletes by listing).\n cookiemunch doctor [--site <cbid>] [--org <id>]\n The key (and whose org it is, against --org or COOKIEMUNCH_ORG), its expiry, the CLI\n version against the latest, and integration health. Exits 1 when a check fails.\n cookiemunch keys vend --scopes <a,b> --ttl <1h|30m|seconds> [--cbids <x,y>] [--name <n>]\n A short-lived key (at most 12 h) within this key's own scopes; prints the key alone.\n Needs keys:write (or a full-access key).\n cookiemunch keys self | rotate-self\n This key's own prefix, scopes and expiry; or rotate it (the new key is printed once).\n cookiemunch plan [cookiemunch.json] [--exit-code] [--json]\n cookiemunch apply [cookiemunch.json] [--secret-env NAME] [--secrets-out <file>]\n One file for a site: {site, config, cookies, presets, executors, webhooks, rightsPage,\n partners}, no secrets. plan prints the server's dry run of every part (\"No changes\" when\n it matches); apply applies them in dependency order and logs each. New webhook secrets\n go to --secrets-out (mode 0600).\n cookiemunch --version | version [--json]\n The CLI version; --json adds the API version the server documents.\n\nEvery command takes --json for machine-readable output.\n\nExit codes:\n 0 ok, or nothing to change\n 1 a difference (with --exit-code), a failure, or a failed check\n 2 a usage mistake\n\nEnvironment:\n COOKIEMUNCH_API_KEY an API key (cookiemunch_live_…, or a legacy fck_…). Required.\n COOKIEMUNCH_BASE_URL the API origin. Default ${DEFAULT_BASE_URL}.\n COOKIEMUNCH_SITE default for --site.\n COOKIEMUNCH_STRICT_FIELDS=1 send Prefer: strict-unknown-fields on writes: a field the\n API does not know is refused (400 unknown_field), not ignored.\n COOKIEMUNCH_SECRET_RECIPIENT=x25519:<base64> answers carry once-shown secrets sealed to\n this key (sealed_secret), never in plaintext.\n COOKIEMUNCH_ORG the org id doctor checks the key against.\n --idempotency-key <k> send Idempotency-Key on writes: a retry replays the first answer.\n`;\n\n/** A usage mistake: exit code 2. */\nclass UsageError extends Error {}\n\ninterface Parsed {\n positional: string[];\n flags: Record<string, string | true>;\n}\n\nconst BOOLEAN_FLAGS = new Set(['replace', 'exit-code', 'open', 'help', 'json', 'yes', 'strict', 'wait', 'canary', 'dry-run', 'clear-name', 'revoke-atlas-id-grant', 'with-cbid', 'without-cbid', 'cleanup']);\n\nexport function parseArgs(argv: string[]): Parsed {\n const positional: string[] = [];\n const flags: Record<string, string | true> = {};\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!;\n if (a === '-h') {\n flags.help = true;\n } else if (a.startsWith('--')) {\n const eq = a.indexOf('=');\n const name = eq > 0 ? a.slice(2, eq) : a.slice(2);\n let value: string | true;\n if (eq > 0) value = a.slice(eq + 1);\n else if (BOOLEAN_FLAGS.has(name)) value = true;\n else {\n const v = argv[i + 1];\n if (v === undefined || v.startsWith('--')) throw new UsageError(`--${name} needs a value`);\n value = v;\n i++;\n }\n // --param repeats (k=v each); kept newline-joined so the rest of the parser stays simple.\n if ((name === 'param' || name === 'accept-preset') && typeof value === 'string' && typeof flags[name] === 'string') flags[name] = `${flags[name]}\\n${value}`;\n else flags[name] = value;\n } else {\n positional.push(a);\n }\n }\n return { positional, flags };\n}\n\nfunction str(flags: Parsed['flags'], name: string): string | undefined {\n const v = flags[name];\n return typeof v === 'string' ? v : undefined;\n}\n\nfunction requireSite(p: Parsed, io: CliIo): string {\n const site = str(p.flags, 'site') ?? io.env.COOKIEMUNCH_SITE;\n if (!site) throw new UsageError('--site <cbid> is required (or set COOKIEMUNCH_SITE)');\n return site;\n}\n\nasync function readConfigFile(io: CliIo, path: string | undefined): Promise<Record<string, unknown>> {\n if (!path) throw new UsageError('a config file is required');\n let text: string;\n try {\n text = await io.readFile(path);\n } catch (e) {\n throw new UsageError(`cannot read ${path}: ${(e as Error).message}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch (e) {\n throw new UsageError(`${path} is not valid JSON: ${(e as Error).message}`);\n }\n if (!isPlainObject(parsed)) throw new UsageError(`${path} must hold a JSON object`);\n return parsed;\n}\n\n/** What the stored config would become, per push mode. */\nfunction proposed(current: Record<string, unknown>, file: Record<string, unknown>, replace: boolean, cbid: string) {\n return replace ? { ...file, cbid } : mergeLikeServer(current, file);\n}\n\n/** This package's version, sent in the default User-Agent (a test pins it to package.json). */\nexport const CLI_VERSION = '0.6.0';\n\n/** `COOKIEMUNCH_USER_AGENT`, else `cookiemunch-cli/<version>`. */\nfunction userAgent(io: CliIo): string {\n return io.env.COOKIEMUNCH_USER_AGENT || `cookiemunch-cli/${CLI_VERSION}`;\n}\n\nasync function rawRequest(io: CliIo, base: string, key: string, method: string, path: string, body?: unknown): Promise<unknown> {\n const res = await io.fetch(`${base.replace(/\\/+$/, '')}/v1${path}`, {\n method,\n headers: { Authorization: `Bearer ${key}`, 'User-Agent': userAgent(io), ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}) },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n const text = await res.text();\n let data: unknown = text;\n try {\n data = text ? JSON.parse(text) : undefined;\n } catch {\n /* keep the text */\n }\n if (!res.ok) {\n const err = isPlainObject(data) ? data : {};\n throw new CookieMunchApiError(\n res.status,\n typeof err.error === 'string' ? err.error : `request failed with status ${res.status}`,\n typeof err.code === 'string' ? err.code : undefined,\n );\n }\n return data;\n}\n\n/**\n * What a write would change. The server's own `?dryRun=1` diff is the source of truth (it knows\n * its defaults and read-only fields); if it cannot answer, the same is computed here, with the\n * read-only fields (`effective`, `designWarnings`, `rightsFormUrl`, ...) dropped from both sides:\n * a file made by `config pull` carries them, and the server ignores them on a write.\n */\nasync function configChanges(client: CookieMunchClient, cbid: string, file: Record<string, unknown>, replace: boolean): Promise<Change[]> {\n const body = withoutReadOnly(file);\n try {\n const r = await client.sites.dryRunConfig(cbid, body as never, { mode: replace ? 'put' : 'patch' });\n if (r && r.dryRun === true && Array.isArray(r.diff)) {\n return r.diff.map((c) => {\n const ch: Change = { path: c.path, kind: c.from === undefined ? 'added' : c.to === undefined ? 'removed' : 'changed' };\n if (c.from !== undefined) ch.from = c.from as Json;\n if (c.to !== undefined) ch.to = c.to as Json;\n return ch;\n });\n }\n } catch {\n /* an older or unreachable dry run: fall back to the local diff below */\n }\n const current = withoutReadOnly((await client.sites.getConfig(cbid)) as unknown as Record<string, unknown>);\n return diffJson(current, proposed(current, body, replace, cbid));\n}\n\nasync function configCommand(sub: string | undefined, p: Parsed, io: CliIo, client: CookieMunchClient): Promise<number> {\n const cbid = requireSite(p, io);\n if (sub === 'pull') {\n const cfg = await client.sites.getConfig(cbid);\n const text = `${JSON.stringify(cfg, null, 2)}\\n`;\n const out = str(p.flags, 'out');\n if (out) {\n await io.writeFile(out, text);\n io.stderr(`Wrote ${cbid}'s config to ${out}\\n`);\n } else {\n io.stdout(text);\n }\n return 0;\n }\n if (sub === 'validate') {\n const file = await readConfigFile(io, p.positional[2]);\n const r = await client.sites.lintConfig(cbid, file as never, p.flags.replace === true ? { replace: true } : {});\n if (p.flags.json === true) io.stdout(`${JSON.stringify({ cbid, designWarnings: r.designWarnings }, null, 2)}\\n`);\n else if (r.designWarnings.length) io.stdout(`${formatDesignWarnings(r.designWarnings)}\\n`);\n io.stderr(`${summaryLine(r.designWarnings)}\\n`);\n return p.flags.strict === true && countBySeverity(r.designWarnings).warnings > 0 ? 1 : 0;\n }\n if (sub === 'diff' || sub === 'push') {\n const file = await readConfigFile(io, p.positional[2]);\n const replace = p.flags.replace === true;\n // --strict (push): check first, and do not write a config that fails it.\n if (sub === 'push' && p.flags.strict === true) {\n const lint = await client.sites.lintConfig(cbid, file as never, replace ? { replace: true } : {});\n if (countBySeverity(lint.designWarnings).warnings > 0) {\n io.stderr(`${formatDesignWarnings(lint.designWarnings)}\\n${summaryLine(lint.designWarnings)}\\nnot pushed (--strict).\\n`);\n return 1;\n }\n }\n const changes = await configChanges(client, cbid, file, replace);\n if (p.flags.json === true && (sub === 'diff' || changes.length === 0)) io.stdout(`${JSON.stringify({ cbid, changes }, null, 2)}\\n`);\n if (changes.length === 0) {\n io.stderr(`No changes: ${cbid}'s config already matches.\\n`);\n return 0;\n }\n if (p.flags.json !== true) io.stdout(`${formatChanges(changes)}\\n`);\n if (sub === 'diff') {\n io.stderr(`${changes.length} change${changes.length === 1 ? '' : 's'} (nothing sent). Apply with: cookiemunch config push --site ${cbid} ${p.positional[2]}${replace ? ' --replace' : ''}\\n`);\n return p.flags['exit-code'] === true ? 1 : 0;\n }\n const saved = (replace\n ? await client.sites.putConfig(cbid, { ...file, cbid } as never)\n : await client.sites.patchConfig(cbid, file as never)) as { designWarnings?: unknown };\n io.stderr(`Applied ${changes.length} change${changes.length === 1 ? '' : 's'} to ${cbid}.\\n`);\n const found = Array.isArray(saved?.designWarnings) ? (saved.designWarnings as Parameters<typeof formatDesignWarnings>[0]) : [];\n if (p.flags.json === true) io.stdout(`${JSON.stringify({ cbid, applied: changes, designWarnings: found }, null, 2)}\\n`);\n if (found.length) io.stderr(`${formatDesignWarnings(found)}\\n${summaryLine(found)}\\n`);\n return 0;\n }\n throw new UsageError(`unknown config command: ${sub ?? '(none)'} — use pull, diff, push or validate`);\n}\n\nasync function previewCommand(p: Parsed, io: CliIo, client: CookieMunchClient): Promise<number> {\n const cbid = requireSite(p, io);\n const ttl = str(p.flags, 'ttl');\n const ttlSeconds = ttl === undefined ? undefined : Number(ttl);\n if (ttlSeconds !== undefined && (!Number.isInteger(ttlSeconds) || ttlSeconds < 1 || ttlSeconds > 3600)) {\n throw new UsageError('--ttl must be a whole number of seconds from 1 to 3600');\n }\n const r = await client.sites.previewToken(cbid, {\n ...(str(p.flags, 'region') ? { region: str(p.flags, 'region')! } : {}),\n ...(str(p.flags, 'lang') ? { lang: str(p.flags, 'lang')! } : {}),\n ...(str(p.flags, 'url') ? { url: str(p.flags, 'url')! } : {}),\n ...(ttlSeconds !== undefined ? { ttlSeconds } : {}),\n });\n if (p.flags.json === true) {\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n } else if (r.previewUrl) {\n io.stdout(`${r.previewUrl}\\n`);\n } else {\n // No page to put it on (the site has no domain and no --url): hand over the token.\n io.stdout(`${r.token}\\n`);\n io.stderr('Add ?cm_preview=<token>&cm_region=..&cm_lang=.. to any page of the site.\\n');\n }\n io.stderr(`Valid until ${new Date(r.expiresAt).toISOString()}.\\n`);\n if (p.flags.open === true && r.previewUrl) await io.openUrl(r.previewUrl);\n return 0;\n}\n\nasync function consentSyncCommand(sub: string | undefined, p: Parsed, io: CliIo, client: CookieMunchClient): Promise<number> {\n const cbid = requireSite(p, io);\n if (sub === 'status') {\n io.stdout(`${JSON.stringify(await client.consentSyncSecret.get(cbid), null, 2)}\\n`);\n return 0;\n }\n if (sub === 'rotate') {\n const r = await client.consentSyncSecret.rotate(cbid);\n io.stdout(p.flags.json === true ? `${JSON.stringify(r, null, 2)}\\n` : `${r.secret}\\n`);\n io.stderr('This secret is shown once: store it on your server (never in a page). A previous secret stopped working.\\n');\n return 0;\n }\n if (sub === 'remove') {\n if (p.flags.yes !== true) throw new UsageError('consent-sync remove stops hosted consent sync for every visitor: add --yes');\n await client.consentSyncSecret.remove(cbid);\n io.stderr(`Hosted consent sync is off for ${cbid}.\\n`);\n return 0;\n }\n if (sub === 'token') {\n const secret = io.env.COOKIEMUNCH_CONSENT_SYNC_SECRET;\n if (!secret) throw new UsageError('set COOKIEMUNCH_CONSENT_SYNC_SECRET to the site\\'s consent-sync secret');\n const subject = str(p.flags, 'subject');\n if (!subject) throw new UsageError('--subject <id> is required');\n const ttl = str(p.flags, 'ttl');\n try {\n const token = mintConsentSyncToken({ secret, cbid, subject, ...(ttl !== undefined ? { ttlSeconds: Number(ttl) } : {}) });\n io.stdout(p.flags.json === true ? `${JSON.stringify({ token }, null, 2)}\\n` : `${token}\\n`);\n } catch (e) {\n throw new UsageError((e as Error).message);\n }\n return 0;\n }\n throw new UsageError(`unknown consent-sync command: ${sub ?? '(none)'} — use status, rotate, remove or token`);\n}\n\nasync function executorsCommand(\n sub: string | undefined,\n p: Parsed,\n io: CliIo,\n base: string,\n key: string,\n client: CookieMunchClient,\n): Promise<number> {\n if (sub === 'webhook-test') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors webhook-test <id> needs the connection id');\n const headersFile = str(p.flags, 'headers-file');\n const bodyFile = str(p.flags, 'body-file');\n if (!headersFile || !bodyFile) throw new UsageError('--headers-file and --body-file are both required');\n let headers: unknown;\n try {\n headers = JSON.parse(await io.readFile(headersFile));\n } catch {\n throw new UsageError(`${headersFile} is not a JSON object of header name to value`);\n }\n if (!isPlainObject(headers)) throw new UsageError(`${headersFile} is not a JSON object of header name to value`);\n // The body is sent exactly as read: the signature is over these bytes, so no trimming.\n const body = await io.readFile(bodyFile);\n const r = await client.fulfillment.testExecutorWebhook(id, { headers: headers as Record<string, string>, body });\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n return r.verified ? 0 : 1;\n }\n if (sub === 'deliveries') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors deliveries <id> needs the connection id');\n io.stdout(`${JSON.stringify(await client.fulfillment.executorWebhookDeliveries(id), null, 2)}\\n`);\n return 0;\n }\n if (sub === 'presets') {\n io.stdout(`${JSON.stringify(await client.fulfillment.executorPresets(), null, 2)}\\n`);\n return 0;\n }\n if (sub === 'conformance') return conformanceCommand(p, io, client);\n if (sub === 'roll-completion-secret') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors roll-completion-secret <id> needs the connection id');\n io.stdout(`${JSON.stringify(await client.fulfillment.rollExecutorCompletionSecret(id), null, 2)}\\n`);\n return 0;\n }\n if (sub === 'upgrade-preset') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors upgrade-preset <id> needs the connection id');\n const version = str(p.flags, 'version');\n if (version !== undefined && !/^[1-9]\\d*$/.test(version)) throw new UsageError('--version must be a positive whole number');\n const preset = str(p.flags, 'preset');\n const orgId = str(p.flags, 'org-id');\n const atlasIdAppId = str(p.flags, 'atlas-id-app-id');\n const accept = str(p.flags, 'accept-preset');\n const input = {\n ...(preset ? { preset: preset as never } : {}),\n ...(version ? { presetVersion: Number(version) } : {}),\n ...(orgId ? { orgId } : {}),\n ...(atlasIdAppId ? { atlasIdAppId } : {}),\n ...(p.flags['revoke-atlas-id-grant'] === true ? { revokeAtlasIdGrant: true } : {}),\n ...(accept ? { acceptPreset: accept.split('\\n') } : {}),\n };\n const r =\n p.flags['dry-run'] === true\n ? await client.fulfillment.dryRunUpgradeExecutorPreset(id, input)\n : await client.fulfillment.upgradeExecutorPreset(id, input);\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n return 0;\n }\n if (sub === 'recheck') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors recheck <id> needs the connection id');\n const r = await client.fulfillment.recheckExecutor(id);\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n // A deploy hook: a failing check fails the step.\n return r.ok === false ? 1 : 0;\n }\n if (sub === 'health') {\n const id = p.positional[2];\n if (!id) throw new UsageError('executors health <id> needs the connection id');\n const limit = str(p.flags, 'limit');\n if (limit !== undefined && !/^[1-9]\\d*$/.test(limit)) throw new UsageError('--limit must be a whole number from 1 to 50');\n io.stdout(`${JSON.stringify(await client.fulfillment.executorHealthHistory(id, limit ? { limit: Number(limit) } : {}), null, 2)}\\n`);\n return 0;\n }\n if (sub !== 'test') throw new UsageError(`unknown executors command: ${sub ?? '(none)'} — use test, webhook-test, deliveries, presets, upgrade-preset, conformance, roll-completion-secret, recheck or health`);\n const id = p.positional[2];\n if (!id) throw new UsageError('executors test <id> needs the connection id');\n const canary = p.flags.canary === true;\n const email = str(p.flags, 'email');\n if (canary && email) throw new UsageError('use --email or --canary, not both');\n if (!email && !canary) throw new UsageError('--email (or --canary) is required');\n // The API's operations are locate, export and erase. `lookup` was this CLI's documented\n // default and the API refused it (400), so it stays accepted as another name for locate.\n const asked = str(p.flags, 'operation') ?? 'locate';\n const operation = asked === 'lookup' ? 'locate' : asked;\n // The typed SDK has no method for this yet, so it is a direct call with the same key.\n try {\n const r = await rawRequest(io, base, key, 'POST', `/dsar/executors/${encodeURIComponent(id)}/test`, canary ? { canary: true, operation } : { email, operation });\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n // A canary test is a health check: a failing one fails the command, so it can gate a deploy.\n return canary && (r as { ok?: unknown }).ok === false ? 1 : 0;\n } catch (e) {\n // The API's generic route miss is a bare `not found`; an unknown connection says so.\n if (e instanceof CookieMunchApiError && e.status === 404 && e.message === 'not found') {\n io.stderr('This server does not offer connection tests yet (POST /v1/dsar/executors/{id}/test).\\n');\n return 1;\n }\n throw e;\n }\n}\n\n/** One rule per line: PASS/FAIL/SKIP, its id, and what was seen when it did not pass. */\nfunction printConformance(io: CliIo, report: { ok: boolean; passed: number; failed: number; skipped: number; rules: Array<{ id: string; title: string; status: string; detail?: string }> }, asJson: boolean): number {\n if (asJson) {\n io.stdout(`${JSON.stringify(report, null, 2)}\\n`);\n } else {\n for (const r of report.rules) {\n io.stdout(`${r.status.toUpperCase().padEnd(4)} ${r.id} ${r.title}\\n`);\n if (r.detail && r.status !== 'pass') io.stdout(` ${r.detail}\\n`);\n }\n io.stdout(`\\n${report.passed} passed, ${report.failed} failed, ${report.skipped} skipped\\n`);\n }\n return report.ok ? 0 : 1;\n}\n\nasync function conformanceCommand(p: Parsed, io: CliIo, client: CookieMunchClient | null): Promise<number> {\n const asJson = p.flags.json === true;\n const connection = str(p.flags, 'connection');\n if (connection) {\n if (!client) throw new UsageError('--connection runs on Cookie Munch: set COOKIEMUNCH_API_KEY');\n return printConformance(io, await client.fulfillment.executorConformance(connection), asJson);\n }\n const baseUrl = p.positional[2];\n if (!baseUrl) throw new UsageError('executors conformance <baseUrl> --secret-env <NAME> (or --connection <id>)');\n const secretEnv = str(p.flags, 'secret-env');\n if (!secretEnv) throw new UsageError('--secret-env <NAME> names the environment variable holding the executor credential');\n const secret = io.env[secretEnv];\n if (!secret) throw new UsageError(`the environment variable ${secretEnv} is empty`);\n let canaryEmail = str(p.flags, 'canary-email');\n if (!canaryEmail) {\n if (!client) throw new UsageError('pass --canary-email, or set COOKIEMUNCH_API_KEY to use your organisation\\'s canary address');\n canaryEmail = (await client.fulfillment.executorPresets()).canaryEmail;\n }\n const prefix = str(p.flags, 'prefix');\n let report;\n try {\n report = await runExecutorConformance({ baseUrl, secret, canaryEmail, fetch: io.fetch, ...(prefix ? { prefix } : {}) });\n } catch (e) {\n throw new UsageError((e as Error).message);\n }\n return printConformance(io, report, asJson);\n}\n\nasync function scanCommand(p: Parsed, io: CliIo, client: CookieMunchClient): Promise<number> {\n const cbid = requireSite(p, io);\n const timeout = str(p.flags, 'timeout');\n const timeoutS = timeout === undefined ? 120 : Number(timeout);\n if (!Number.isFinite(timeoutS) || timeoutS < 1 || timeoutS > 3600) throw new UsageError('--timeout must be a number of seconds from 1 to 3600');\n let started: Awaited<ReturnType<CookieMunchClient['sites']['scan']>> | null = null;\n try {\n started = await client.sites.scan(cbid);\n } catch (e) {\n if (!(e instanceof CookieMunchApiError && e.status === 409)) throw e;\n io.stderr(`A scan of ${cbid} is already running${p.flags.wait === true ? '; waiting for it' : ''}.\\n`);\n if (p.flags.wait !== true) return 0;\n }\n if (p.flags.wait !== true) {\n io.stdout(`${JSON.stringify(started, null, 2)}\\n`);\n return 0;\n }\n const r = await client.sites.waitForScan(cbid, { timeoutMs: timeoutS * 1000 });\n io.stdout(`${JSON.stringify(r, null, 2)}\\n`);\n if (r.state === 'failed') {\n io.stderr(`Scan ${r.scanId ?? ''} failed: ${r.error ?? 'no reason given'}\\n`);\n return 1;\n }\n if (r.status === 'scanning') {\n io.stderr(`Scan ${r.scanId ?? ''} is still running after ${timeoutS} s.\\n`);\n return 1;\n }\n const n = r.cookieCount ?? 0;\n const pages = r.pagesVisited !== undefined ? ` on ${r.pagesVisited} page${r.pagesVisited === 1 ? '' : 's'}` : '';\n const kept = r.keptFromEarlier ? `, ${r.keptFromEarlier} kept from earlier crawls and visits` : '';\n const took = r.durationMs !== undefined ? ` in ${Math.round(r.durationMs / 1000)} s` : '';\n const landed = r.finalUrl ? ` (redirected to ${r.finalUrl})` : '';\n io.stderr(`Scan ${r.scanId ?? ''} done${took}: ${n} cookie${n === 1 ? '' : 's'} seen${pages}${kept}${landed}.\\n`);\n return 0;\n}\n\nconst PRESET_VENDORS = ['atlas', 'forumulate', 'chatly', 'cookiemunch', 'referalli', 'firstpromoter', 'partnerstack', 'tapfiliate', 'impact'] as const;\n/** Old preset names still accepted (the server answers them with a Deprecation header). */\nconst PRESET_ALIASES: Record<string, Vendor> = { referally: 'referalli' };\ntype Vendor = (typeof PRESET_VENDORS)[number];\n\nfunction vendorArg(v: string | undefined): Vendor {\n if (v && Object.prototype.hasOwnProperty.call(PRESET_ALIASES, v)) return PRESET_ALIASES[v]!;\n if (!v || !(PRESET_VENDORS as readonly string[]).includes(v)) throw new UsageError(`a vendor is required: ${PRESET_VENDORS.join(', ')}`);\n return v as Vendor;\n}\n\n/** `--param k=v` (repeatable) → an object; `true`/`false` become booleans, `cookieDays` a number. */\nfunction presetParams(p: Parsed): Record<string, string | boolean | number> {\n const raw = str(p.flags, 'param');\n const out: Record<string, string | boolean | number> = {};\n for (const line of raw ? raw.split('\\n') : []) {\n const eq = line.indexOf('=');\n if (eq <= 0) throw new UsageError(`--param takes key=value, got \"${line}\"`);\n const v = line.slice(eq + 1);\n const k = line.slice(0, eq);\n out[k] = v === 'true' ? true : v === 'false' ? false : k === 'cookieDays' && /^\\d+$/.test(v) ? Number(v) : v;\n }\n return out;\n}\n\n/** `cookiemunch cookies …`: vendor presets and removing what real-visit beacons stored (CKM-S-02, S-29). */\nasync function cookiesCommand(sub: string | undefined, p: Parsed, io: CliIo, client: CookieMunchClient): Promise<number> {\n const dry = p.flags['dry-run'] === true ? { dryRun: true as const } : undefined;\n const print = (v: unknown) => io.stdout(`${JSON.stringify(v, null, 2)}\\n`);\n if (sub === 'presets') {\n print(await client.sites.cookiePresets(requireSite(p, io)));\n return 0;\n }\n // A custom preset (import-manifest) is removed by its product id, which no list here knows.\n if (sub === 'unpreset' && p.positional[2] && !(PRESET_VENDORS as readonly string[]).includes(p.positional[2])) {\n print(await client.sites.removeCookiePreset(requireSite(p, io), p.positional[2], dry));\n return 0;\n }\n if (sub === 'preset' || sub === 'unpreset') {\n const cbid = requireSite(p, io);\n const vendor = vendorArg(p.positional[2]);\n if (sub === 'unpreset') {\n print(await client.sites.removeCookiePreset(cbid, vendor, dry));\n return 0;\n }\n const r = await client.sites.applyCookiePreset(cbid, vendor, presetParams(p), dry);\n print(r);\n if (r.note) io.stderr(`${r.note}\\n`);\n for (const s of r.skipped ?? []) io.stderr(`skipped ${s.name}: ${s.reason}\\n`);\n if (r.manifest.status === 'waiting_on_vendor') io.stderr(`Built-in rows: ${r.manifest.waitingOn} does not publish a manifest yet (${r.manifest.item}).\\n`);\n return 0;\n }\n // Any vendor's embed manifest as a preset; what to declare; declare it (CMU-X36, CMU-D15).\n if (sub === 'import-manifest') {\n const cbid = requireSite(p, io);\n const src = p.positional[2];\n const file = str(p.flags, 'file');\n if (!src && !file) throw new UsageError('a manifest URL (https://…/.well-known/forgedeck-embed.json) or --file <manifest.json> is required');\n const input = file ? { manifest: JSON.parse(await io.readFile(file)) as never } : { url: src! };\n const r = await client.sites.importCookieManifest(cbid, input, dry);\n print(r);\n for (const s of r.skipped ?? []) io.stderr(`skipped ${s.name}: ${s.reason}\\n`);\n return 0;\n }\n if (sub === 'suggestions') {\n const r = await client.sites.cookieSuggestions(requireSite(p, io));\n print(r);\n io.stderr(`${r.suggestions.length} suggestion${r.suggestions.length === 1 ? '' : 's'}; ${r.vendors.length} platform${r.vendors.length === 1 ? '' : 's'} detected.\\n`);\n return 0;\n }\n if (sub === 'declare-suggestions') {\n const cbid = requireSite(p, io);\n const names = str(p.flags, 'names');\n const r = await client.sites.declareCookieSuggestions(cbid, names ? { names: names.split(',').map((n) => n.trim()).filter(Boolean) } : {}, dry);\n print(r);\n io.stderr(`${dry ? 'Would declare' : 'Declared'} ${r.declaredCount} row${r.declaredCount === 1 ? '' : 's'} and ${r.presetsApplied.length} preset${r.presetsApplied.length === 1 ? '' : 's'}.\\n`);\n return 0;\n }\n if (sub === 'delete-observed') {\n const cbid = requireSite(p, io);\n const name = p.positional[2];\n if (!name) throw new UsageError('a cookie name is required');\n if (dry) print(await client.sites.deleteObservedCookie(cbid, name, dry));\n else {\n await client.sites.deleteObservedCookie(cbid, name);\n io.stderr(`Removed ${name}.\\n`);\n }\n return 0;\n }\n if (sub === 'purge-observed') {\n const cbid = requireSite(p, io);\n const since = str(p.flags, 'since');\n if (!since) throw new UsageError('--since is required (ISO-8601 or epoch ms)');\n const until = str(p.flags, 'until');\n const r = await client.sites.purgeObservedCookies(cbid, { since, ...(until ? { until } : {}) }, dry);\n print(r);\n io.stderr(`${dry ? 'Would remove' : 'Removed'} ${r.count} row${r.count === 1 ? '' : 's'}.\\n`);\n return 0;\n }\n throw new UsageError(`unknown cookies command: ${sub ?? '(none)'}`);\n}\n\n/** Run the CLI. Returns the process exit code: 0 ok, 1 failed, 2 usage. */\nexport async function run(argv: string[], io: CliIo): Promise<number> {\n // CMU-B15: a leading --version (or -V) prints the version and needs no key. Only leading: `--version <n>`\n // is a value flag of `executors upgrade-preset`.\n if (argv[0] === '--version' || argv[0] === '-V') return versionCommand(io, CLI_VERSION, io.env.COOKIEMUNCH_BASE_URL || DEFAULT_BASE_URL, argv.includes('--json'));\n let p: Parsed;\n try {\n p = parseArgs(argv);\n } catch (e) {\n io.stderr(`${(e as Error).message}\\n\\n${USAGE}`);\n return 2;\n }\n const [cmd, sub] = p.positional;\n // `version [--json]` needs no key either.\n if (cmd === 'version') {\n return versionCommand(io, CLI_VERSION, io.env.COOKIEMUNCH_BASE_URL || DEFAULT_BASE_URL, p.flags.json === true);\n }\n if (!cmd || p.flags.help === true || cmd === 'help') {\n io.stdout(USAGE);\n return cmd || p.flags.help === true ? 0 : 2;\n }\n // The conformance kit checks the open contract against any system; with --canary-email it\n // needs no Cookie Munch key at all, so anyone implementing the contract can run it.\n if (cmd === 'executors' && sub === 'conformance' && !io.env.COOKIEMUNCH_API_KEY && str(p.flags, 'canary-email')) {\n try {\n return await conformanceCommand(p, io, null);\n } catch (e) {\n if (e instanceof UsageError) {\n io.stderr(`${e.message}\\n`);\n return 2;\n }\n throw e;\n }\n }\n const base = io.env.COOKIEMUNCH_BASE_URL || DEFAULT_BASE_URL;\n // Every embed manifest is public: csp needs no key.\n if (cmd === 'csp') {\n try {\n const merge = str(p.flags, 'merge');\n const framework = str(p.flags, 'framework');\n const site = str(p.flags, 'site') ?? io.env.COOKIEMUNCH_SITE;\n return await cspCommand(\n { apiBase: base, ...(merge ? { merge } : {}), ...(framework ? { framework } : {}), ...(site ? { site } : {}) },\n io,\n (m) => new UsageError(m),\n );\n } catch (e) {\n if (e instanceof UsageError) {\n io.stderr(`${e.message}\\n\\n${USAGE}`);\n return 2;\n }\n io.stderr(`${(e as Error).message ?? String(e)}\\n`);\n return 1;\n }\n }\n const key = io.env.COOKIEMUNCH_API_KEY;\n if (!key) {\n io.stderr('COOKIEMUNCH_API_KEY is not set. Create a key under Developers in the dashboard.\\n');\n return 2;\n }\n const client = createCookieMunch({\n apiKey: key, baseUrl: base, fetch: io.fetch, userAgent: userAgent(io),\n ...(io.env.COOKIEMUNCH_STRICT_FIELDS === '1' ? { strictUnknownFields: true } : {}),\n ...(io.env.COOKIEMUNCH_SECRET_RECIPIENT ? { secretRecipient: io.env.COOKIEMUNCH_SECRET_RECIPIENT } : {}),\n ...(typeof p.flags['idempotency-key'] === 'string' ? { headers: { 'Idempotency-Key': p.flags['idempotency-key'] } } : {}),\n });\n const ops: OpsHelpers = {\n requireSite: () => requireSite(p, io),\n site: () => str(p.flags, 'site') ?? io.env.COOKIEMUNCH_SITE,\n readJson: (path) => readConfigFile(io, path),\n usage: (m) => new UsageError(m),\n flag: (name) => p.flags[name],\n positional: p.positional,\n };\n try {\n if (cmd === 'cookies' && (sub === 'diff' || sub === 'push')) return await cookiesFileCommand(sub, io, client, ops);\n if (cmd === 'executors' && (sub === 'pull' || sub === 'diff' || sub === 'push')) return await executorsFileCommand(sub, io, client, ops);\n if (cmd === 'dsar' && sub === 'test') return await dsarTestCommand(io, client, ops);\n if (cmd === 'doctor') return await doctorCommand(io, client, ops, CLI_VERSION);\n if (cmd === 'keys' && sub && sub !== 'report') return await keysExtraCommand(sub, io, client, ops);\n if (cmd === 'plan' || cmd === 'apply') return await bundleCommand(cmd, io, client, ops);\n if (cmd === 'config') return await configCommand(sub, p, io, client);\n if (cmd === 'preview') return await previewCommand(p, io, client);\n if (cmd === 'scan') return await scanCommand(p, io, client);\n if (cmd === 'consent-sync') return await consentSyncCommand(sub, p, io, client);\n if (cmd === 'cookies') return await cookiesCommand(sub, p, io, client);\n if (cmd === 'executors') return await executorsCommand(sub, p, io, base, key, client);\n const helpers = {\n requireSite: () => requireSite(p, io),\n site: () => str(p.flags, 'site') ?? io.env.COOKIEMUNCH_SITE,\n readJson: (path: string | undefined) => readConfigFile(io, path),\n usage: (m: string) => new UsageError(m),\n flag: (name: string) => p.flags[name],\n };\n if (cmd === 'site') return await siteCommand(sub, io, client, helpers, p.positional[2]);\n if (cmd === 'health') return await healthCommand(io, client, helpers);\n if (cmd === 'provision') return await provisionCommand(sub, io, client, helpers);\n if (cmd === 'keys') return await keysCommand(sub, io, client, helpers);\n if (cmd === 'partners') return await partnersCommand(sub, p.positional.slice(2), io, client, helpers);\n if (cmd === 'rights-page') {\n return await rightsPageCommand(sub, p, io, client, {\n requireSite: () => requireSite(p, io),\n readJson: (path) => readConfigFile(io, path),\n usage: (m) => new UsageError(m),\n });\n }\n throw new UsageError(`unknown command: ${cmd}`);\n } catch (e) {\n if (e instanceof UsageError) {\n io.stderr(`${e.message}\\n\\n${USAGE}`);\n return 2;\n }\n if (e instanceof CookieMunchApiError) {\n io.stderr(`API error ${e.status}${e.code ? ` (${e.code})` : ''}: ${e.message}\\n`);\n return 1;\n }\n io.stderr(`${(e as Error).message ?? String(e)}\\n`);\n return 1;\n }\n}\n","/**\n * `cookiemunch site update`, `cookiemunch health`, `cookiemunch provision` and `cookiemunch partners`.\n *\n * Provisioning secrets are read from the environment (COOKIEMUNCH_ATLAS_SECRET_KEY,\n * COOKIEMUNCH_FORUMULATE_TOKEN), never from the command line where they would land in shell history,\n * and are never printed.\n */\nimport type { CookieMunchClient, PartnerLinkCreate, ProvisionRequest } from '@cookiemunch/sdk';\nimport type { CliIo } from './cli.js';\n\ninterface Helpers {\n requireSite(): string;\n site(): string | undefined;\n readJson(path: string | undefined): Promise<Record<string, unknown>>;\n usage(msg: string): Error;\n flag(name: string): string | true | undefined;\n}\n\nconst out = (io: CliIo, v: unknown) => io.stdout(`${JSON.stringify(v, null, 2)}\\n`);\n\n/** `cookiemunch site update --site <cbid> [--domain d] [--name n | --clear-name] [--aliases a,b] [--dry-run]` */\nexport async function siteCommand(sub: string | undefined, io: CliIo, client: CookieMunchClient, h: Helpers, file?: string): Promise<number> {\n if (sub === 'brand') return brandCommand(io, client, h, file);\n if (sub !== 'update') throw h.usage('usage: cookiemunch site update --site <cbid> [--domain <host>] [--name <name>] [--aliases a,b] [--dry-run]');\n const cbid = h.requireSite();\n const domain = h.flag('domain');\n const name = h.flag('name');\n const aliases = h.flag('aliases');\n const patch: { domain?: string; name?: string | null; aliases?: string[] } = {};\n if (typeof domain === 'string') patch.domain = domain;\n if (h.flag('clear-name') === true) patch.name = null;\n else if (typeof name === 'string') patch.name = name;\n if (typeof aliases === 'string') patch.aliases = aliases.split(',').map((a) => a.trim()).filter(Boolean);\n if (Object.keys(patch).length === 0) throw h.usage('nothing to change: give --domain, --name, --clear-name or --aliases');\n const r = await client.sites.update(cbid, patch, { dryRun: h.flag('dry-run') === true });\n out(io, r);\n if (r.effects.verification === 'reset') io.stderr('The domain moved: verify the new domain (GET /v1/sites/{cbid}/verify/challenge).\\n');\n for (const w of r.warnings ?? []) io.stderr(`warning (${w.field}): ${w.reason}\\n`);\n return 0;\n}\n\n/**\n * `cookiemunch site brand --site <cbid> (--url <https URL> | <brand.json>) [--dry-run]` imports a brand.json into the\n * banner theme (CMU-X44); with neither, it prints the read-back of the last import.\n */\nasync function brandCommand(io: CliIo, client: CookieMunchClient, h: Helpers, file: string | undefined): Promise<number> {\n const cbid = h.requireSite();\n const url = h.flag('url');\n const r = typeof url === 'string'\n ? await client.sites.setBrand(cbid, { url }, { dryRun: h.flag('dry-run') === true })\n : file\n ? await client.sites.setBrand(cbid, (await h.readJson(file)) as Record<string, unknown>, { dryRun: h.flag('dry-run') === true })\n : await client.sites.getBrand(cbid);\n out(io, r);\n for (const w of r.warnings) io.stderr(`warning (${w.role}): ${w.message}\\n`);\n for (const w of r.configWarnings ?? []) io.stderr(`warning (${w.field}): ${w.reason}\\n`);\n return 0;\n}\n\n/** `cookiemunch health [--site <cbid>]` — exits 1 when a check fails, so CI can gate on it. */\nexport async function healthCommand(io: CliIo, client: CookieMunchClient, h: Helpers): Promise<number> {\n // --fail-on error | warning (default) | never: which failing severity makes the exit code 1, for CI.\n const failOn = h.flag('fail-on') ?? 'warning';\n if (failOn !== 'error' && failOn !== 'warning' && failOn !== 'never') throw h.usage('--fail-on must be error, warning or never');\n const r = await client.integrationHealth(h.site());\n if (h.flag('json') === true) out(io, r);\n else {\n for (const c of r.checks) {\n const mark = c.waived ? 'WAIV' : c.ok === true ? 'ok ' : c.ok === false ? (c.severity === 'error' ? 'FAIL' : 'WARN') : '-- ';\n const net = c.hop ? ` (${c.hop}${c.status !== undefined ? ` ${c.status}` : ''}${c.elapsedMs !== undefined ? `, ${c.elapsedMs} ms` : ''})` : '';\n io.stdout(`${mark} ${c.check} — ${c.subject}${c.detail ? `: ${c.detail}` : ''}${net}${c.waived ? ` — waived: ${c.waived.reason}` : ''}\\n`);\n const fix = c.fix ?? c.fixHint;\n if (c.ok === false && fix) io.stdout(` fix: ${fix}\\n`);\n }\n io.stdout(`${r.counts.error} error(s), ${r.counts.warning} warning(s), ${r.counts.notChecked} not checked${r.counts.waived ? `, ${r.counts.waived} waived` : ''}\\n`);\n }\n if (failOn === 'never') return 0;\n const failing = r.checks.filter((c) => c.ok === false && (c.severity === 'error' || (failOn === 'warning' && c.severity === 'warning')));\n return failing.length ? 1 : 0;\n}\n\n/** `cookiemunch provision <file> [--dry-run]` — the file has no secrets; the environment supplies them. */\nexport async function provisionCommand(file: string | undefined, io: CliIo, client: CookieMunchClient, h: Helpers): Promise<number> {\n const input = (await h.readJson(file)) as unknown as ProvisionRequest;\n // v2 (a forgedeck body): `self.keyEnv` names the env var holding the product's own API key (never in the file).\n const v2 = input as unknown as Record<string, any>;\n if (v2.forgedeck !== undefined || (v2.site && typeof v2.site === 'object')) {\n const body: Record<string, any> = { ...v2 };\n if (body.self) {\n const { keyEnv, ...self } = body.self as Record<string, unknown>;\n const secret = typeof keyEnv === 'string' ? io.env[keyEnv] : undefined;\n if (!secret) throw h.usage(`self needs its key: set self.keyEnv in the file and export that variable`);\n body.self = { ...self, secret };\n }\n if (body.atlas && io.env.COOKIEMUNCH_ATLAS_SECRET_KEY) body.atlas = { ...body.atlas, secretKey: io.env.COOKIEMUNCH_ATLAS_SECRET_KEY };\n if (body.forumulate && io.env.COOKIEMUNCH_FORUMULATE_TOKEN) body.forumulate = { ...body.forumulate, token: io.env.COOKIEMUNCH_FORUMULATE_TOKEN };\n const fromStep = h.flag('from-step');\n const r = await client.provision(body as never, { dryRun: h.flag('dry-run') === true, ...(typeof fromStep === 'string' ? { fromStep } : {}) }) as unknown as { steps: Array<{ id?: string; step: string; status: string; detail?: string; waitingOn?: unknown }>; dryRun: boolean; summary: Record<string, number> };\n if (h.flag('json') === true) out(io, r);\n else {\n for (const s of r.steps) {\n const w = s.waitingOn as { platform?: string; items?: string[] } | string | undefined;\n const waiting = typeof w === 'string' ? w : w ? `${w.platform}: ${(w.items ?? []).join(', ')}` : '';\n io.stdout(`${s.status.padEnd(12)} ${s.id ?? s.step}${s.detail ? ` — ${s.detail}` : ''}${waiting ? ` (waiting on ${waiting})` : ''}\\n`);\n }\n io.stdout(`${r.dryRun ? 'dry run: ' : ''}${r.summary.changed} changed, ${r.summary.unchanged} unchanged, ${r.summary.waiting} waiting, ${r.summary.failed} failed\\n`);\n }\n return r.summary.failed ? 1 : 0;\n }\n const withSecrets: ProvisionRequest = { ...input };\n if (input.atlas || io.env.COOKIEMUNCH_ATLAS_SECRET_KEY) {\n const secretKey = io.env.COOKIEMUNCH_ATLAS_SECRET_KEY ?? input.atlas?.secretKey;\n if (!secretKey) throw h.usage('set COOKIEMUNCH_ATLAS_SECRET_KEY for the atlas step');\n withSecrets.atlas = { ...(input.atlas ?? {}), secretKey };\n }\n if (input.forumulate) {\n const token = io.env.COOKIEMUNCH_FORUMULATE_TOKEN ?? input.forumulate.token;\n if (!token) throw h.usage('set COOKIEMUNCH_FORUMULATE_TOKEN for the forumulate step');\n withSecrets.forumulate = { ...input.forumulate, token };\n }\n const r = await client.provision(withSecrets, { dryRun: h.flag('dry-run') === true });\n if (h.flag('json') === true) { out(io, r); return r.summary.failed ? 1 : 0; }\n for (const s of r.steps) {\n io.stdout(`${s.status.padEnd(12)} ${s.step}${s.detail ? ` — ${s.detail}` : ''}${s.waitingOn ? ` (waiting on ${s.waitingOn})` : ''}\\n`);\n }\n io.stdout(`${r.dryRun ? 'dry run: ' : ''}${r.summary.changed} changed, ${r.summary.unchanged} unchanged, ${r.summary.waiting} waiting, ${r.summary.failed} failed\\n`);\n return r.summary.failed ? 1 : 0;\n}\n\n/** `cookiemunch partners list|link|unlink --site <cbid> …` */\nexport async function partnersCommand(sub: string | undefined, rest: string[], io: CliIo, client: CookieMunchClient, h: Helpers): Promise<number> {\n const cbid = h.requireSite();\n if (sub === 'list') { out(io, await client.sites.listPartners(cbid)); return 0; }\n if (sub === 'link') {\n const partner = h.flag('partner');\n const externalId = h.flag('external-id');\n if (typeof partner !== 'string' || !/^[a-z][a-z0-9_]{1,39}$/.test(partner)) throw h.usage('--partner <id> is required: forumulate, atlas, chatly, referalli, or one registered on the deployment');\n if (typeof externalId !== 'string') throw h.usage('--external-id <the partner’s account id> is required');\n const label = h.flag('label');\n const input: PartnerLinkCreate = { partner, externalId, ...(typeof label === 'string' ? { label } : {}) };\n out(io, await client.sites.linkPartner(cbid, input, { dryRun: h.flag('dry-run') === true }));\n return 0;\n }\n if (sub === 'unlink') {\n const id = rest[0];\n if (!id) throw h.usage('usage: cookiemunch partners unlink <linkId> --site <cbid>');\n out(io, await client.sites.unlinkPartner(cbid, id));\n return 0;\n }\n throw h.usage('usage: cookiemunch partners list|link|unlink --site <cbid>');\n}\n\n/** `cookiemunch keys report [--unused-days n] [--expiring-days n] [--json]` */\nexport async function keysCommand(sub: string | undefined, io: CliIo, client: CookieMunchClient, h: Helpers): Promise<number> {\n if (sub !== 'report') throw h.usage('usage: cookiemunch keys report [--unused-days <n>] [--expiring-days <n>] [--json]');\n const n = (name: string): number | undefined => {\n const v = h.flag(name);\n if (v === undefined) return undefined;\n const x = Number(v);\n if (!Number.isInteger(x) || x < 1 || x > 3650) throw h.usage(`--${name} must be whole days from 1 to 3650`);\n return x;\n };\n const unusedDays = n('unused-days');\n const expiringDays = n('expiring-days');\n const r = await client.keys.report({ ...(unusedDays ? { unusedDays } : {}), ...(expiringDays ? { expiringDays } : {}) });\n if (h.flag('json') === true) { out(io, r); return 0; }\n const section = (title: string, rows: Array<{ prefix: string; name?: string | null; reason: string }>) => {\n io.stdout(`${title}: ${rows.length}\\n`);\n for (const k of rows) io.stdout(` ${k.prefix}${k.name ? ` (${k.name})` : ''} — ${k.reason}\\n`);\n };\n section(`Unused for ${r.unusedDays}+ days`, r.unused);\n section('Broad access', r.broad);\n section(`Expiring within ${r.expiringDays} days`, r.expiringSoon);\n const revoked = r.revoked ?? [];\n io.stdout(`Revoked: ${revoked.length}\\n`);\n for (const k of revoked) io.stdout(` ${k.prefix}${k.name ? ` (${k.name})` : ''} — ${k.reason} ${new Date(k.revokedAt).toISOString()} by ${k.revokedBy}; last used ${k.lastUsedAt ? new Date(k.lastUsedAt).toISOString() : 'never'}\\n`);\n io.stdout(`${r.total} key(s), ${r.noExpiry} with no expiry\\n`);\n return 0;\n}\n","/**\n * Consent-button parity findings, as terminal text: one line per finding (severity, code,\n * where), then its explanation and fix, indented. See /docs/fair-consent-buttons.\n */\nimport type { ButtonParityFinding } from '@cookiemunch/sdk';\n\nfunction where(f: ButtonParityFinding): string {\n const w = f.where ?? {};\n return [\n f.layer === 'banner' ? 'first layer' : `${f.layer} layer`,\n w.view ? `view \"${w.view}\"` : '',\n w.variant && w.variant !== 'base' ? `variant ${w.variant}` : '',\n w.theme === 'dark' ? 'dark theme' : '',\n w.breakpoint === 'mobile' ? 'mobile' : '',\n w.language ? `language ${w.language}` : '',\n ]\n .filter(Boolean)\n .join(', ');\n}\n\nexport function formatDesignWarnings(findings: ButtonParityFinding[]): string {\n return findings\n .map((f) => `${f.severity === 'warning' ? 'warning' : 'notice '} ${f.code} ${where(f)}\\n ${f.detail}\\n fix: ${f.fix}`)\n .join('\\n');\n}\n\nexport function countBySeverity(findings: ButtonParityFinding[]): { warnings: number; notices: number } {\n const warnings = findings.filter((f) => f.severity === 'warning').length;\n return { warnings, notices: findings.length - warnings };\n}\n\nexport function summaryLine(findings: ButtonParityFinding[]): string {\n const { warnings, notices } = countBySeverity(findings);\n if (warnings + notices === 0) return 'No design warnings: Accept all and Reject all have equal weight.';\n // Notices are hints (wording, custom CSS a live scan must confirm), not proof of a dark pattern.\n if (warnings === 0) {\n return (\n `Design: 0 warnings, ${notices} notice${notices === 1 ? '' : 's'} — worth a look, not a finding that Accept is favoured. ` +\n 'See https://cookiemunch.net/docs/fair-consent-buttons'\n );\n }\n return (\n `Design: ${warnings} warning${warnings === 1 ? '' : 's'}, ${notices} notice${notices === 1 ? '' : 's'} — ` +\n 'Accept is pushed harder than Reject. Regulators treat that as a dark pattern; make both buttons the same style. ' +\n 'See https://cookiemunch.net/docs/fair-consent-buttons'\n );\n}\n","/**\n * CLI completeness (CMU-B15, D11, D12, S02):\n *\n * cookiemunch --version | version [--json]\n * cookiemunch cookies diff|push <file> --site <cbid> [--replace] declarations as a file, through the server's dry run\n * cookiemunch executors pull|diff|push <file> [--secret-env NAME] connected systems as a file, never carrying a secret\n * cookiemunch dsar test --types access,deletion [--with-cbid] [--without-cbid] [--cleanup]\n * cookiemunch doctor [--site <cbid>] [--org <id>]\n * cookiemunch keys vend --scopes a,b --ttl 1h [--cbids x,y] [--name n]\n * cookiemunch keys self | rotate-self\n * cookiemunch plan|apply <cookiemunch.json>\n *\n * Exit codes everywhere: 0 ok (or no changes), 1 a difference, a failure or a failed check, 2 a usage mistake.\n */\n\nimport type { CookieMunchClient, DsarExecutor } from '@cookiemunch/sdk';\nimport type { CliIo } from './cli.js';\nimport { diffJson, formatChanges, type Change, type Json } from './diff.js';\n\nexport interface OpsHelpers {\n requireSite(): string;\n site(): string | undefined;\n readJson(path: string | undefined): Promise<Record<string, unknown>>;\n usage(msg: string): Error;\n flag(name: string): string | true | undefined;\n positional: string[];\n}\n\nconst json = (h: OpsHelpers) => h.flag('json') === true;\nconst print = (io: CliIo, v: unknown) => io.stdout(`${JSON.stringify(v, null, 2)}\\n`);\nconst str = (h: OpsHelpers, name: string) => { const v = h.flag(name); return typeof v === 'string' ? v : undefined; };\n\n// ---- version (CMU-B15) ----\n\n/** `version [--json]`: the CLI's version, and with --json the API version the server documents. */\nexport async function versionCommand(io: CliIo, cliVersion: string, base: string, asJson: boolean): Promise<number> {\n if (!asJson) {\n io.stdout(`${cliVersion}\\n`);\n return 0;\n }\n let api: string | null = null;\n try {\n const res = await io.fetch(`${base.replace(/\\/+$/, '')}/v1/openapi.json`);\n if (res.ok) api = ((await res.json()) as { info?: { version?: string } }).info?.version ?? null;\n } catch {\n /* unreachable: api stays null */\n }\n print(io, { cli: cliVersion, api });\n return 0;\n}\n\n// ---- cookies diff|push <file> (CMU-D11) ----\n\nfunction cookieRows(file: Record<string, unknown>): Array<Record<string, unknown> & { name: string }> {\n const rows = Array.isArray(file) ? file : Array.isArray(file.cookies) ? file.cookies : null;\n if (!rows || !rows.every((r) => r && typeof r === 'object' && typeof (r as { name?: unknown }).name === 'string')) {\n throw new Error('the file must hold { \"cookies\": [ { \"name\", \"category\", \"purpose\", … } ] } or that array');\n }\n return rows as Array<Record<string, unknown> & { name: string }>;\n}\n\nexport async function cookiesFileCommand(sub: 'diff' | 'push', io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n const cbid = h.requireSite();\n const path = h.positional[2];\n if (!path) throw h.usage(`usage: cookiemunch cookies ${sub} <file> --site <cbid> [--replace]`);\n let rows;\n try { rows = cookieRows(await h.readJson(path)); } catch (e) { throw h.usage((e as Error).message); }\n const replace = h.flag('replace') === true;\n const dry = await client.sites.declareCookies(cbid, rows as never, { replace, dryRun: true });\n const diff = dry.diff ?? { added: [], removed: [], changed: [] };\n const n = diff.added.length + diff.removed.length + diff.changed.length;\n if (json(h)) print(io, { cbid, changes: n, diff, ...(dry.warnings?.length ? { warnings: dry.warnings } : {}) });\n else if (n === 0) io.stderr(`No changes: ${cbid}'s declarations already match.\\n`);\n else {\n for (const c of diff.added) io.stdout(`+ ${c.name} (${c.category})\\n`);\n for (const c of diff.removed) io.stdout(`- ${c.name}\\n`);\n for (const c of diff.changed) io.stdout(`~ ${c.name}: ${formatChanges(diffJson(c.before as unknown as Json, c.after as unknown as Json))}\\n`);\n }\n for (const w of dry.warnings ?? []) io.stderr(`warning: ${JSON.stringify(w)}\\n`);\n if (sub === 'diff') return n > 0 && h.flag('exit-code') === true ? 1 : 0;\n if (n === 0) return 0;\n const saved = await client.sites.declareCookies(cbid, rows as never, { replace });\n io.stderr(`Applied: ${saved.saved} saved, ${saved.removed} removed.\\n`);\n return 0;\n}\n\n// ---- executors pull|diff|push <file> (CMU-D11) ----\n\n/** What a file holds for a connection: everything that is not a secret, an id the server assigns, or state. */\nconst EXECUTOR_FIELDS = ['system', 'baseUrl', 'profile', 'auto', 'subjectNote', 'cbid', 'preset', 'presetVersion', 'presetParams'] as const;\nfunction executorFileView(e: DsarExecutor): Record<string, Json> {\n const out: Record<string, Json> = { id: e.id };\n for (const k of EXECUTOR_FIELDS) {\n const v = (e as unknown as Record<string, unknown>)[k];\n if (v !== undefined) out[k] = v as Json;\n }\n return out;\n}\n\nexport async function executorsFileCommand(sub: 'pull' | 'diff' | 'push', io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n const current = (await client.fulfillment.executors()).map(executorFileView);\n if (sub === 'pull') {\n const text = `${JSON.stringify({ executors: current }, null, 2)}\\n`;\n const path = str(h, 'out') ?? h.positional[2];\n if (path) { await io.writeFile(path, text); io.stderr(`Wrote ${current.length} connection(s) to ${path} (no secrets).\\n`); } else io.stdout(text);\n return 0;\n }\n const path = h.positional[2];\n if (!path) throw h.usage(`usage: cookiemunch executors ${sub} <file> [--secret-env NAME]`);\n const file = await h.readJson(path);\n const wanted = Array.isArray(file.executors) ? (file.executors as Array<Record<string, Json>>) : null;\n if (!wanted) throw h.usage(`${path} must hold { \"executors\": [ … ] } (cookiemunch executors pull writes one)`);\n for (const w of wanted) {\n for (const k of ['secretKey', 'secret', 'webhookSecret']) if (k in w) throw h.usage(`${path} carries ${k}: secrets never go in this file; pass --secret-env NAME`);\n }\n const plan: Array<{ system: string; action: 'create' | 'update' | 'unchanged'; id?: string; changes: Change[] }> = [];\n for (const w of wanted) {\n const match = current.find((c) => (w.id && c.id === w.id) || (!w.id && c.system === w.system));\n const { id: _i, ...want } = w;\n if (!match) { plan.push({ system: String(w.system), action: 'create', changes: diffJson({}, want as Json) }); continue; }\n const { id, ...have } = match;\n const changes = diffJson(Object.fromEntries(Object.keys(want).map((k) => [k, have[k] ?? null])) as Json, want as Json);\n plan.push({ system: String(w.system), action: changes.length ? 'update' : 'unchanged', id: String(id), changes });\n }\n const pending = plan.filter((p) => p.action !== 'unchanged');\n if (json(h)) print(io, { plan });\n else if (!pending.length) io.stderr('No changes: every connection already matches.\\n');\n else for (const p of pending) io.stdout(`${p.action} ${p.system}${p.id ? ` (${p.id})` : ''}\\n${formatChanges(p.changes).replace(/^/gm, ' ')}\\n`);\n if (sub === 'diff') return pending.length && h.flag('exit-code') === true ? 1 : 0;\n const secretEnv = str(h, 'secret-env');\n // Every create needs its key BEFORE anything is applied: half a push is worse than none.\n const creating = pending.filter((p) => p.action === 'create');\n if (creating.length && !(secretEnv && io.env[secretEnv])) {\n throw h.usage(`creating ${creating.map((p) => p.system).join(', ')} needs its API key: pass --secret-env NAME and export NAME`);\n }\n for (const p of pending) {\n const w = wanted.find((x) => String(x.system) === p.system)!;\n const { id: _i, ...body } = w;\n if (p.action === 'update') {\n await client.fulfillment.updateExecutor(p.id!, Object.fromEntries(p.changes.map((c) => c.path.split(/[.[]/)[0]!).filter((k, i, a) => a.indexOf(k) === i).map((k) => [k, body[k]])) as never);\n } else {\n const secretKey = secretEnv ? io.env[secretEnv] : undefined;\n if (!secretKey) throw h.usage(`creating ${p.system} needs its API key: set --secret-env NAME and export NAME`);\n await client.fulfillment.connectExecutor({ ...(body as object), secretKey } as never);\n }\n }\n io.stderr(`Applied ${pending.length} change(s).\\n`);\n return 0;\n}\n\n// ---- dsar test (CMU-D11) ----\n\n/**\n * File test rights requests (guide step 16), read each back, and with --cleanup delete EXACTLY the ids this\n * run created: never a list-and-delete, which once removed live rows (memory never-clean-up-by-listing).\n */\nexport async function dsarTestCommand(io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n const types = (str(h, 'types') ?? 'access').split(',').map((t) => t.trim()).filter(Boolean);\n const allowed = ['access', 'deletion', 'rectification', 'portability', 'opt-out'];\n const bad = types.filter((t) => !allowed.includes(t));\n if (bad.length) throw h.usage(`--types takes ${allowed.join(', ')}; not ${bad.join(', ')}`);\n const withCbid = h.flag('with-cbid') === true;\n const without = h.flag('without-cbid') === true || !withCbid;\n const cbid = withCbid ? h.requireSite() : undefined;\n const email = str(h, 'email') ?? 'cookiemunch-cli-test@example.invalid';\n const created: Array<{ id: string; type: string; cbid: string | null; status: string }> = [];\n let failed = false;\n try {\n for (const type of types) {\n for (const scoped of [...(withCbid ? [true] : []), ...(without ? [false] : [])]) {\n const r = await client.dsar.create({ type, subjectEmail: email, regulation: 'gdpr', test: true, ...(scoped ? { cbid } : {}) } as never);\n const back = await client.dsar.get(r.request.id);\n created.push({ id: r.request.id, type, cbid: scoped ? cbid! : null, status: String((back as { status?: string }).status) });\n }\n }\n } catch (e) {\n failed = true;\n io.stderr(`dsar test: ${(e as Error).message}\\n`);\n }\n const deleted: string[] = [];\n if (h.flag('cleanup') === true) {\n for (const c of created) {\n try { await client.dsar.delete(c.id); deleted.push(c.id); } catch (e) { failed = true; io.stderr(`could not delete test request ${c.id}: ${(e as Error).message}\\n`); }\n }\n }\n if (json(h)) print(io, { created, deleted });\n else {\n for (const c of created) io.stdout(`${c.id} ${c.type}${c.cbid ? ` cbid=${c.cbid}` : ' (no cbid)'} ${c.status}${deleted.includes(c.id) ? ' (deleted)' : ''}\\n`);\n io.stderr(`${created.length} test request(s) filed${h.flag('cleanup') === true ? `, ${deleted.length} deleted` : '; delete them with --cleanup or DELETE /v1/dsar/{id}'}.\\n`);\n }\n return failed ? 1 : 0;\n}\n\n// ---- doctor (CMU-D11) ----\n\nexport async function doctorCommand(io: CliIo, client: CookieMunchClient, h: OpsHelpers, cliVersion: string): Promise<number> {\n const checks: Array<{ check: string; ok: boolean | null; detail: string }> = [];\n type Me = { orgId?: string; orgName?: string | null; keyPrefix?: string; unscoped?: boolean };\n let me: Me | null = null;\n try {\n me = (await client.me()) as unknown as Me;\n checks.push({ check: 'key', ok: true, detail: `org ${me?.orgName ?? me?.orgId} (${me?.orgId}), key ${me?.keyPrefix}${me?.unscoped ? ', full access' : ''}` });\n } catch (e) {\n checks.push({ check: 'key', ok: false, detail: (e as Error).message });\n }\n const wantOrg = str(h, 'org') ?? io.env.COOKIEMUNCH_ORG;\n if (wantOrg && me?.orgId) checks.push({ check: 'org', ok: me.orgId === wantOrg, detail: me.orgId === wantOrg ? `this key belongs to ${wantOrg}` : `this key's org is ${me.orgId}, not ${wantOrg}, the org your config names` });\n try {\n const self = await client.keys.self();\n const left = typeof self.expiresAt === 'number' ? Math.floor((self.expiresAt - Date.now()) / 86_400_000) : null;\n checks.push({ check: 'key expiry', ok: left === null ? null : left > 7, detail: left === null ? 'no expiry: give automation keys one' : `expires in ${left} day(s)` });\n } catch {\n checks.push({ check: 'key expiry', ok: null, detail: 'this server cannot read the key itself (GET /v1/keys/self)' });\n }\n try {\n const res = await io.fetch('https://registry.npmjs.org/@cookiemunch/cli/latest');\n const latest = res.ok ? ((await res.json()) as { version?: string }).version : undefined;\n checks.push({ check: 'cli version', ok: latest ? latest === cliVersion : null, detail: latest ? (latest === cliVersion ? `${cliVersion}, the latest` : `${cliVersion}; ${latest} is out`) : `${cliVersion}; could not check the latest` });\n } catch {\n checks.push({ check: 'cli version', ok: null, detail: `${cliVersion}; could not check the latest` });\n }\n const site = h.site();\n if (site || me) {\n try {\n const r = await client.integrationHealth(site);\n checks.push({ check: 'integration health', ok: r.ok, detail: `${r.counts.error} error(s), ${r.counts.warning} warning(s)` });\n } catch (e) {\n checks.push({ check: 'integration health', ok: null, detail: (e as Error).message });\n }\n }\n if (json(h)) print(io, { ok: checks.every((c) => c.ok !== false), checks });\n else for (const c of checks) io.stdout(`${c.ok === true ? 'ok ' : c.ok === false ? 'FAIL' : '-- '} ${c.check}: ${c.detail}\\n`);\n return checks.some((c) => c.ok === false) ? 1 : 0;\n}\n\n// ---- keys vend | self | rotate-self (CMU-S02, D09) ----\n\n/** `1h`, `30m`, `90s`, `3600` → seconds. */\nexport function parseTtl(v: string): number | null {\n const m = /^(\\d+)([smh]?)$/.exec(v.trim());\n if (!m) return null;\n const n = Number(m[1]) * (m[2] === 'h' ? 3600 : m[2] === 'm' ? 60 : 1);\n return n >= 60 && n <= 43200 ? n : null;\n}\n\nexport async function keysExtraCommand(sub: string, io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n if (sub === 'self') { print(io, await client.keys.self()); return 0; }\n if (sub === 'rotate-self') {\n const r = await client.keys.rollSelf();\n if (json(h)) print(io, r);\n else { io.stdout(`${r.key ?? r.sealed_secret}\\n`); io.stderr('The old key stopped working. This new one is shown once: store it now.\\n'); }\n return 0;\n }\n if (sub === 'vend') {\n const scopes = (str(h, 'scopes') ?? '').split(',').map((s) => s.trim()).filter(Boolean);\n if (!scopes.length) throw h.usage('--scopes a,b is required (a vended key is never full access)');\n const ttl = parseTtl(str(h, 'ttl') ?? '');\n if (ttl === null) throw h.usage('--ttl is required: 1h, 30m or seconds, from 60 s to 12 h');\n const cbids = str(h, 'cbids')?.split(',').map((s) => s.trim()).filter(Boolean);\n const name = str(h, 'name');\n const r = await client.keys.vend({ scopes, ttlSeconds: ttl, ...(cbids?.length ? { cbids } : {}), ...(name ? { name } : {}) });\n if (json(h)) print(io, r);\n else { io.stdout(`${r.key ?? (r as { sealed_secret?: string }).sealed_secret}\\n`); io.stderr(`Valid until ${new Date(r.expiresAt).toISOString()} (${scopes.join(', ')}).\\n`); }\n return 0;\n }\n throw h.usage('usage: cookiemunch keys report|vend|self|rotate-self');\n}\n\n// ---- plan | apply <cookiemunch.json> (CMU-D12) ----\n\ninterface Bundle {\n site?: { cbid?: string; domain?: string; name?: string; aliases?: string[] };\n config?: Record<string, unknown>;\n cookies?: Array<Record<string, unknown> & { name: string }>;\n presets?: Array<{ vendor: string; params?: Record<string, unknown> }>;\n executors?: Array<Record<string, Json>>;\n webhooks?: Array<{ url: string; events: string[]; cbid?: string | null }>;\n rightsPage?: Record<string, unknown>;\n partners?: Array<{ partner: string; resource: string; scopes: string[]; externalId?: string; label?: string }>;\n}\n\nconst PARTS = ['site', 'config', 'cookies', 'presets', 'rightsPage', 'executors', 'webhooks', 'partners'] as const;\ntype Part = (typeof PARTS)[number];\ninterface PartPlan { part: Part; changes: number; detail: string[]; apply?: () => Promise<string> }\n\n/**\n * One file for everything a site's privacy setup is (CMU-D12). `plan` asks the server's dry run of every part\n * and prints one combined diff; `apply` applies the parts in dependency order (site → config → cookies →\n * presets → rights page → executors → webhooks → partners), reads each back, and logs when.\n * No secret ever goes in the file: an executor's key comes from --secret-env, a new webhook's secret is\n * written to --secrets-out (0600) or the webhook is not created.\n */\nexport async function bundleCommand(sub: 'plan' | 'apply', io: CliIo, client: CookieMunchClient, h: OpsHelpers): Promise<number> {\n const path = h.positional[1] ?? 'cookiemunch.json';\n const b = (await h.readJson(path)) as unknown as Bundle;\n for (const k of Object.keys(b)) if (!(PARTS as readonly string[]).includes(k) && k !== '$schema') throw h.usage(`${path}: unknown part ${k}; parts are ${PARTS.join(', ')}`);\n const cbid = b.site?.cbid ?? h.site();\n if (!cbid) throw h.usage(`${path} needs site.cbid (or --site)`);\n const plans: PartPlan[] = [];\n\n if (b.site) {\n const patch = { ...(b.site.domain ? { domain: b.site.domain } : {}), ...(b.site.name !== undefined ? { name: b.site.name } : {}), ...(b.site.aliases ? { aliases: b.site.aliases } : {}) };\n if (Object.keys(patch).length) {\n const r = await client.sites.update(cbid, patch, { dryRun: true });\n plans.push({ part: 'site', changes: r.diff.length, detail: r.diff.map((d) => `${d.field}: ${JSON.stringify(d.before)} → ${JSON.stringify(d.after)}`), apply: async () => { await client.sites.update(cbid, patch); return 'site updated'; } });\n } else plans.push({ part: 'site', changes: 0, detail: [] });\n }\n if (b.config) {\n const r = await client.sites.dryRunConfig(cbid, b.config as never, { mode: 'patch' });\n const diff = r.diff ?? [];\n plans.push({ part: 'config', changes: diff.length, detail: diff.map((d) => `${d.path}: ${JSON.stringify(d.from)} → ${JSON.stringify(d.to)}`), apply: async () => { await client.sites.patchConfig(cbid, b.config as never); return 'config patched'; } });\n }\n if (b.cookies) {\n const r = await client.sites.declareCookies(cbid, b.cookies as never, { dryRun: true });\n const d = r.diff ?? { added: [], removed: [], changed: [] };\n plans.push({ part: 'cookies', changes: d.added.length + d.removed.length + d.changed.length, detail: [...d.added.map((c) => `+ ${c.name}`), ...d.removed.map((c) => `- ${c.name}`), ...d.changed.map((c) => `~ ${c.name}`)], apply: async () => { const s = await client.sites.declareCookies(cbid, b.cookies as never); return `${s.saved} declaration(s) saved`; } });\n }\n for (const p of b.presets ?? []) {\n const r = await client.sites.applyCookiePreset(cbid, p.vendor as never, (p.params ?? {}) as never, { dryRun: true });\n const d = (r as { diff?: { added: unknown[]; removed: unknown[]; changed: unknown[] } }).diff;\n const n = d ? d.added.length + d.removed.length + d.changed.length : 0;\n plans.push({ part: 'presets', changes: n, detail: n ? [`${p.vendor}: ${n} declaration change(s)`] : [], apply: async () => { await client.sites.applyCookiePreset(cbid, p.vendor as never, (p.params ?? {}) as never); return `preset ${p.vendor} applied`; } });\n }\n if (b.rightsPage) {\n const r = await client.rightsPage.dryRun(cbid, b.rightsPage, { mode: 'put' });\n const diff = ((r as { diff?: Array<{ path: string }> }).diff ?? []);\n plans.push({ part: 'rightsPage', changes: diff.length, detail: diff.map((d) => d.path), apply: async () => { await client.rightsPage.put(cbid, b.rightsPage as never); return 'rights page draft saved (publish it with cookiemunch rights-page publish)'; } });\n }\n if (b.executors) {\n const current = (await client.fulfillment.executors()).map(executorFileView);\n let n = 0;\n const detail: string[] = [];\n for (const w of b.executors) {\n for (const k of ['secretKey', 'secret', 'webhookSecret']) if (k in w) throw h.usage(`${path}: executors carry no secrets (${k}); use --secret-env`);\n const m = current.find((c) => c.system === w.system);\n const { id: _i, ...want } = w;\n const changes = m ? diffJson(Object.fromEntries(Object.keys(want).map((k) => [k, m[k] ?? null])) as Json, want as Json) : diffJson({}, want as Json);\n if (changes.length) { n++; detail.push(`${m ? 'update' : 'create'} ${String(w.system)}`); }\n }\n plans.push({ part: 'executors', changes: n, detail, apply: async () => { await executorsFileCommand('push', io, client, { ...h, positional: ['executors', 'push', path], readJson: async () => ({ executors: b.executors }) }); return 'executors pushed'; } });\n }\n if (b.webhooks) {\n const have = await client.webhooks.list();\n const missing = b.webhooks.filter((w) => !have.some((x) => x.url === w.url));\n const changed = b.webhooks.filter((w) => { const x = have.find((y) => y.url === w.url); return x && JSON.stringify([...x.events].sort()) !== JSON.stringify([...w.events].sort()); });\n plans.push({\n part: 'webhooks', changes: missing.length + changed.length,\n detail: [...missing.map((w) => `+ ${w.url}`), ...changed.map((w) => `~ ${w.url} events`)],\n apply: async () => {\n const secretsOut = str(h, 'secrets-out');\n if (missing.length && !secretsOut) throw h.usage('creating webhooks shows their signing secrets once: pass --secrets-out <file> (written 0600)');\n const secrets: Record<string, string> = {};\n for (const w of missing) { const s = await client.webhooks.create({ url: w.url, events: w.events, ...(w.cbid !== undefined ? { cbid: w.cbid } : {}) } as never); if (s.secret) secrets[w.url] = s.secret; }\n for (const w of changed) { const x = have.find((y) => y.url === w.url)!; await client.webhooks.update(x.id, { events: w.events } as never); }\n if (secretsOut && Object.keys(secrets).length) await io.writeFile(secretsOut, `${JSON.stringify(secrets, null, 2)}\\n`, 0o600);\n return `${missing.length} created, ${changed.length} updated`;\n },\n });\n }\n if (b.partners) {\n const have = await client.partnerLinks.list();\n const missing = b.partners.filter((p) => !have.some((l) => l.partner === p.partner && l.resource === p.resource && l.status !== 'revoked'));\n plans.push({ part: 'partners', changes: missing.length, detail: missing.map((p) => `+ ${p.partner} on ${p.resource} (${p.scopes.join(', ')})`), apply: async () => { for (const p of missing) await client.partnerLinks.create(p as never); return `${missing.length} link(s) created`; } });\n }\n\n const total = plans.reduce((n, p) => n + p.changes, 0);\n if (sub === 'plan') {\n if (json(h)) print(io, { file: path, cbid, changes: total, parts: plans.map(({ apply: _a, ...p }) => p) });\n else for (const p of plans) {\n io.stdout(`${p.part}: ${p.changes ? `${p.changes} change(s)` : 'No changes'}\\n`);\n for (const d of p.detail) io.stdout(` ${d}\\n`);\n }\n if (!json(h)) io.stderr(total ? `${total} change(s) in ${plans.filter((p) => p.changes).length} part(s). Apply with: cookiemunch apply ${path}\\n` : `No changes: all ${plans.length} part(s) match.\\n`);\n return total && h.flag('exit-code') === true ? 1 : 0;\n }\n const log: Array<{ part: Part; at: string; result: string }> = [];\n for (const p of plans) {\n if (!p.changes || !p.apply) continue;\n const result = await p.apply();\n log.push({ part: p.part, at: new Date().toISOString(), result });\n if (!json(h)) io.stderr(`${log[log.length - 1]!.at} ${p.part}: ${result}\\n`);\n }\n if (json(h)) print(io, { file: path, cbid, applied: log });\n else if (!log.length) io.stderr('No changes: nothing to apply.\\n');\n return 0;\n}\n"],"mappings":"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","names":["out","out","proposed","out","CookieMunchApiError","r","out","path","str","CookieMunchApiError","out","id","print"]}