@cookiemunch/cli 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  Every published release, newest first. Dates are the day the version was cut.
4
4
 
5
+ ## 0.5.0 (2026-10-23)
6
+
7
+ - Added: `consent-sync status|rotate|remove --site <cbid>` manages the site's hosted consent-sync secret. `rotate` prints it once.
8
+ - Added: `consent-sync token --site <cbid> --subject <id> [--ttl <seconds>]` signs a short-lived sync token for testing.
9
+ - Changed: built on `@cookiemunch/sdk` 0.5.0.
10
+
5
11
  ## 0.4.2 (2026-10-22)
6
12
 
7
13
  - Changed: published from the public [Cookie-Munch/cli](https://github.com/Cookie-Munch/cli) repo with npm provenance, so `npm audit signatures` verifies where the package was built. No code changes.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Cookie Munch
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  run
4
- } from "./chunk-43RTEWFN.js";
4
+ } from "./chunk-2ADK3C47.js";
5
5
 
6
6
  // src/bin.ts
7
7
  import { readFile, writeFile } from "fs/promises";
@@ -167,7 +167,7 @@ then publish again.
167
167
  }
168
168
 
169
169
  // src/cli.ts
170
- import { createCookieMunch, CookieMunchApiError as CookieMunchApiError2 } from "@cookiemunch/sdk";
170
+ import { createCookieMunch, CookieMunchApiError as CookieMunchApiError2, mintConsentSyncToken } from "@cookiemunch/sdk";
171
171
 
172
172
  // src/integrations.ts
173
173
  var out = (io, v) => io.stdout(`${JSON.stringify(v, null, 2)}
@@ -396,6 +396,16 @@ Usage:
396
396
  [--aliases <a,b>] [--dry-run]
397
397
  Rename or move a site. The cbid and consent ledger stay; a domain move clears
398
398
  verification. --dry-run prints the diff and its effects without saving.
399
+ cookiemunch consent-sync status --site <cbid>
400
+ Whether hosted consent sync is set up (the secret's last four characters, when it was minted).
401
+ cookiemunch consent-sync rotate --site <cbid>
402
+ Mint the site's consent-sync signing secret, or replace it (the old one stops at once).
403
+ Prints the secret alone on stdout, so it can be piped into your secret store: it is shown once.
404
+ cookiemunch consent-sync remove --site <cbid> --yes
405
+ Remove it: hosted consent sync stops for every visitor.
406
+ cookiemunch consent-sync token --site <cbid> --subject <id> [--ttl <seconds>]
407
+ Sign a test token locally with COOKIEMUNCH_CONSENT_SYNC_SECRET (nothing is sent), e.g. to try
408
+ GET /api/v1/<cbid>/profile with curl.
399
409
  cookiemunch health [--site <cbid>] [--json]
400
410
  Every link the site's privacy wiring depends on, with a fix hint for each that
401
411
  fails. Exits 1 when a check fails (checks that could not run do not count).
@@ -479,7 +489,7 @@ async function readConfigFile(io, path) {
479
489
  function proposed(current, file, replace, cbid) {
480
490
  return replace ? { ...file, cbid } : mergeLikeServer(current, file);
481
491
  }
482
- var CLI_VERSION = "0.4.2";
492
+ var CLI_VERSION = "0.5.0";
483
493
  function userAgent(io) {
484
494
  return io.env.COOKIEMUNCH_USER_AGENT || `cookiemunch-cli/${CLI_VERSION}`;
485
495
  }
@@ -613,6 +623,43 @@ async function previewCommand(p, io, client) {
613
623
  if (p.flags.open === true && r.previewUrl) await io.openUrl(r.previewUrl);
614
624
  return 0;
615
625
  }
626
+ async function consentSyncCommand(sub, p, io, client) {
627
+ const cbid = requireSite(p, io);
628
+ if (sub === "status") {
629
+ io.stdout(`${JSON.stringify(await client.consentSyncSecret.get(cbid), null, 2)}
630
+ `);
631
+ return 0;
632
+ }
633
+ if (sub === "rotate") {
634
+ const r = await client.consentSyncSecret.rotate(cbid);
635
+ io.stdout(`${r.secret}
636
+ `);
637
+ io.stderr("This secret is shown once: store it on your server (never in a page). A previous secret stopped working.\n");
638
+ return 0;
639
+ }
640
+ if (sub === "remove") {
641
+ if (p.flags.yes !== true) throw new UsageError("consent-sync remove stops hosted consent sync for every visitor: add --yes");
642
+ await client.consentSyncSecret.remove(cbid);
643
+ io.stderr(`Hosted consent sync is off for ${cbid}.
644
+ `);
645
+ return 0;
646
+ }
647
+ if (sub === "token") {
648
+ const secret = io.env.COOKIEMUNCH_CONSENT_SYNC_SECRET;
649
+ if (!secret) throw new UsageError("set COOKIEMUNCH_CONSENT_SYNC_SECRET to the site's consent-sync secret");
650
+ const subject = str(p.flags, "subject");
651
+ if (!subject) throw new UsageError("--subject <id> is required");
652
+ const ttl = str(p.flags, "ttl");
653
+ try {
654
+ io.stdout(`${mintConsentSyncToken({ secret, cbid, subject, ...ttl !== void 0 ? { ttlSeconds: Number(ttl) } : {} })}
655
+ `);
656
+ } catch (e) {
657
+ throw new UsageError(e.message);
658
+ }
659
+ return 0;
660
+ }
661
+ throw new UsageError(`unknown consent-sync command: ${sub ?? "(none)"} \u2014 use status, rotate, remove or token`);
662
+ }
616
663
  async function executorsCommand(sub, p, io, base, key, client) {
617
664
  if (sub === "webhook-test") {
618
665
  const id2 = p.positional[2];
@@ -820,6 +867,7 @@ ${USAGE}`);
820
867
  if (cmd === "config") return await configCommand(sub, p, io, client);
821
868
  if (cmd === "preview") return await previewCommand(p, io, client);
822
869
  if (cmd === "scan") return await scanCommand(p, io, client);
870
+ if (cmd === "consent-sync") return await consentSyncCommand(sub, p, io, client);
823
871
  if (cmd === "cookies") return await cookiesCommand(sub, p, io, client);
824
872
  if (cmd === "executors") return await executorsCommand(sub, p, io, base, key, client);
825
873
  const helpers = {
@@ -870,4 +918,4 @@ export {
870
918
  parseArgs,
871
919
  run
872
920
  };
873
- //# sourceMappingURL=chunk-43RTEWFN.js.map
921
+ //# sourceMappingURL=chunk-2ADK3C47.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/diff.ts","../src/rights-page.ts","../src/cli.ts","../src/integrations.ts","../src/design-warnings.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'] 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 (!changes.length) { io.stderr(`No changes: ${cbid}'s rights page draft already matches.\\n`); return 0; }\n 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` — 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 upgrade-preset <id> [--preset <name>] [--version <n>] [--org-id <id>] [--atlas-id-app-id <id>] [--dry-run]\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 health [--site <cbid>] [--json]\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 *\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, 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';\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 writeFile: (path: string, data: string) => 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 upgrade-preset <id> [--preset <name>] [--version <n>]\n [--org-id <id>] [--atlas-id-app-id <id>] [--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 Prints the diff; --dry-run changes nothing.\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, referally): 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 Referally: [--param cookieDomain=.example.com] [--param cookieDays=60] [--param category=…].\n cookiemunch cookies unpreset <vendor> --site <cbid> [--dry-run]\n Remove every declaration that vendor's preset made.\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 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]\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 do not count).\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 forumulate|atlas]\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.\n\nEnvironment:\n COOKIEMUNCH_API_KEY an API key (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`;\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']);\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' && typeof value === 'string' && typeof flags.param === 'string') flags.param = `${flags.param}\\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.5.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 (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 (changes.length === 0) {\n io.stderr(`No changes: ${cbid}'s config already matches.\\n`);\n return 0;\n }\n 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 (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(`${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 io.stdout(`${mintConsentSyncToken({ secret, cbid, subject, ...(ttl !== undefined ? { ttlSeconds: Number(ttl) } : {}) })}\\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 === '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 input = {\n ...(preset ? { preset: preset as never } : {}),\n ...(version ? { presetVersion: Number(version) } : {}),\n ...(orgId ? { orgId } : {}),\n ...(atlasIdAppId ? { atlasIdAppId } : {}),\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 !== 'test') throw new UsageError(`unknown executors command: ${sub ?? '(none)'} — use test, webhook-test, deliveries, presets or upgrade-preset`);\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\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', 'referally'] as const;\ntype Vendor = (typeof PRESET_VENDORS)[number];\n\nfunction vendorArg(v: string | undefined): Vendor {\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 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 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 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 if (!cmd || p.flags.help === true || cmd === 'help') {\n io.stdout(USAGE);\n return cmd || p.flags.help === true ? 0 : 2;\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 base = io.env.COOKIEMUNCH_BASE_URL || DEFAULT_BASE_URL;\n const client = createCookieMunch({ apiKey: key, baseUrl: base, fetch: io.fetch, userAgent: userAgent(io), ...(io.env.COOKIEMUNCH_STRICT_FIELDS === '1' ? { strictUnknownFields: true } : {}) });\n try {\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);\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): Promise<number> {\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/** `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 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.ok === true ? 'ok ' : c.ok === false ? (c.severity === 'error' ? 'FAIL' : 'WARN') : '-- ';\n io.stdout(`${mark} ${c.check} — ${c.subject}${c.detail ? `: ${c.detail}` : ''}\\n`);\n if (c.ok === false && c.fixHint) io.stdout(` fix: ${c.fixHint}\\n`);\n }\n io.stdout(`${r.counts.error} error(s), ${r.counts.warning} warning(s), ${r.counts.notChecked} not checked\\n`);\n }\n return r.ok ? 0 : 1;\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 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 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 (partner !== 'forumulate' && partner !== 'atlas') throw h.usage('--partner forumulate|atlas is required');\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 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"],"mappings":"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","names":["out","out","proposed","CookieMunchApiError","CookieMunchApiError","out","id"]}
package/dist/index.d.ts CHANGED
@@ -20,6 +20,7 @@ import { CookieMunchClient } from '@cookiemunch/sdk';
20
20
  * cookiemunch health [--site <cbid>] [--json]
21
21
  * cookiemunch provision <file> [--dry-run]
22
22
  * cookiemunch partners list|link|unlink --site <cbid> …
23
+ * cookiemunch consent-sync status|rotate|remove|token --site <cbid> …
23
24
  *
24
25
  * Everything goes through the typed SDK (@cookiemunch/sdk) except where the SDK has no
25
26
  * method yet; those calls go through `rawRequest` with the same key and base URL. All I/O
@@ -41,7 +42,7 @@ interface CliIo {
41
42
  */
42
43
  confirm?: (question: string) => Promise<boolean>;
43
44
  }
44
- 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 upgrade-preset <id> [--preset <name>] [--version <n>]\n [--org-id <id>] [--atlas-id-app-id <id>] [--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 Prints the diff; --dry-run changes nothing.\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, referally): 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 Referally: [--param cookieDomain=.example.com] [--param cookieDays=60] [--param category=\u2026].\n cookiemunch cookies unpreset <vendor> --site <cbid> [--dry-run]\n Remove every declaration that vendor's preset made.\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 health [--site <cbid>] [--json]\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 do not count).\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 forumulate|atlas]\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.\n\nEnvironment:\n COOKIEMUNCH_API_KEY an API key (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";
45
+ 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 upgrade-preset <id> [--preset <name>] [--version <n>]\n [--org-id <id>] [--atlas-id-app-id <id>] [--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 Prints the diff; --dry-run changes nothing.\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, referally): 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 Referally: [--param cookieDomain=.example.com] [--param cookieDays=60] [--param category=\u2026].\n cookiemunch cookies unpreset <vendor> --site <cbid> [--dry-run]\n Remove every declaration that vendor's preset made.\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 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]\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 do not count).\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 forumulate|atlas]\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.\n\nEnvironment:\n COOKIEMUNCH_API_KEY an API key (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";
45
46
  interface Parsed {
46
47
  positional: string[];
47
48
  flags: Record<string, string | true>;
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  parseArgs,
8
8
  rightsPageCommand,
9
9
  run
10
- } from "./chunk-43RTEWFN.js";
10
+ } from "./chunk-2ADK3C47.js";
11
11
  export {
12
12
  DEFAULT_BASE_URL,
13
13
  USAGE,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cookiemunch/cli",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
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.4.1"
38
+ "@cookiemunch/sdk": "^0.5.0"
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/cli.ts","../src/integrations.ts","../src/design-warnings.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'] 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 (!changes.length) { io.stderr(`No changes: ${cbid}'s rights page draft already matches.\\n`); return 0; }\n 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` — 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 upgrade-preset <id> [--preset <name>] [--version <n>] [--org-id <id>] [--atlas-id-app-id <id>] [--dry-run]\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 health [--site <cbid>] [--json]\n * cookiemunch provision <file> [--dry-run]\n * cookiemunch partners list|link|unlink --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, 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';\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 writeFile: (path: string, data: string) => 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 upgrade-preset <id> [--preset <name>] [--version <n>]\n [--org-id <id>] [--atlas-id-app-id <id>] [--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 Prints the diff; --dry-run changes nothing.\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, referally): 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 Referally: [--param cookieDomain=.example.com] [--param cookieDays=60] [--param category=…].\n cookiemunch cookies unpreset <vendor> --site <cbid> [--dry-run]\n Remove every declaration that vendor's preset made.\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 health [--site <cbid>] [--json]\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 do not count).\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 forumulate|atlas]\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.\n\nEnvironment:\n COOKIEMUNCH_API_KEY an API key (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`;\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']);\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' && typeof value === 'string' && typeof flags.param === 'string') flags.param = `${flags.param}\\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.4.2';\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 (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 (changes.length === 0) {\n io.stderr(`No changes: ${cbid}'s config already matches.\\n`);\n return 0;\n }\n 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 (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 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 === '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 input = {\n ...(preset ? { preset: preset as never } : {}),\n ...(version ? { presetVersion: Number(version) } : {}),\n ...(orgId ? { orgId } : {}),\n ...(atlasIdAppId ? { atlasIdAppId } : {}),\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 !== 'test') throw new UsageError(`unknown executors command: ${sub ?? '(none)'} — use test, webhook-test, deliveries, presets or upgrade-preset`);\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\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', 'referally'] as const;\ntype Vendor = (typeof PRESET_VENDORS)[number];\n\nfunction vendorArg(v: string | undefined): Vendor {\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 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 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 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 if (!cmd || p.flags.help === true || cmd === 'help') {\n io.stdout(USAGE);\n return cmd || p.flags.help === true ? 0 : 2;\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 base = io.env.COOKIEMUNCH_BASE_URL || DEFAULT_BASE_URL;\n const client = createCookieMunch({ apiKey: key, baseUrl: base, fetch: io.fetch, userAgent: userAgent(io), ...(io.env.COOKIEMUNCH_STRICT_FIELDS === '1' ? { strictUnknownFields: true } : {}) });\n try {\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 === '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);\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): Promise<number> {\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/** `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 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.ok === true ? 'ok ' : c.ok === false ? (c.severity === 'error' ? 'FAIL' : 'WARN') : '-- ';\n io.stdout(`${mark} ${c.check} — ${c.subject}${c.detail ? `: ${c.detail}` : ''}\\n`);\n if (c.ok === false && c.fixHint) io.stdout(` fix: ${c.fixHint}\\n`);\n }\n io.stdout(`${r.counts.error} error(s), ${r.counts.warning} warning(s), ${r.counts.notChecked} not checked\\n`);\n }\n return r.ok ? 0 : 1;\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 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 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 (partner !== 'forumulate' && partner !== 'atlas') throw h.usage('--partner forumulate|atlas is required');\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 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"],"mappings":"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","names":["out","out","proposed","CookieMunchApiError","CookieMunchApiError","out","id"]}