apiblaze 0.20.31 → 0.20.39

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.
Files changed (2) hide show
  1. package/dist/index.js +923 -690
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -806,7 +806,7 @@ async function createTenantRow(teamId) {
806
806
  const { name } = await inquirer3.prompt([{
807
807
  type: "input",
808
808
  name: "name",
809
- message: `Tenant name ${import_chalk37.default.dim("(lowercase letters/numbers; globally unique \u2014 becomes {name}.portal.apiblaze.com)")}:`,
809
+ message: `Tenant name ${import_chalk38.default.dim("(lowercase letters/numbers; globally unique \u2014 becomes {name}.portal.apiblaze.com)")}:`,
810
810
  validate: (s) => /^[a-z0-9]+$/.test(s.trim()) ? true : "lowercase letters and numbers only"
811
811
  }]);
812
812
  const slug = name.trim();
@@ -821,7 +821,7 @@ async function createTenantRow(teamId) {
821
821
  } catch (err) {
822
822
  const msg = err instanceof Error ? err.message : String(err);
823
823
  if (/taken|unique|exists|reserved|conflict/i.test(msg)) {
824
- console.log(import_chalk37.default.yellow(` "${slug}" is not available (tenant names are global): ${msg}`));
824
+ console.log(import_chalk38.default.yellow(` "${slug}" is not available (tenant names are global): ${msg}`));
825
825
  continue;
826
826
  }
827
827
  throw err;
@@ -838,11 +838,11 @@ async function addApiblazeHostedLogin(teamId, tenant2, opts = {}) {
838
838
  pageSize: 10,
839
839
  choices: [
840
840
  ...PROVIDERS.map((p) => ({ name: p.label, value: p.id })),
841
- ...opts.allowSkip ? [new inquirer3.Separator(), { name: import_chalk37.default.dim("Skip for now \u2014 set up a login method later"), value: null }] : []
841
+ ...opts.allowSkip ? [new inquirer3.Separator(), { name: import_chalk38.default.dim("Skip for now \u2014 set up a login method later"), value: null }] : []
842
842
  ]
843
843
  }]);
844
844
  if (!provider) {
845
- console.log(import_chalk37.default.dim(" No login method yet \u2014 add one later under Login methods."));
845
+ console.log(import_chalk38.default.dim(" No login method yet \u2014 add one later under Login methods."));
846
846
  return false;
847
847
  }
848
848
  const opt = PROVIDERS.find((p) => p.id === provider);
@@ -888,26 +888,26 @@ async function addApiblazeHostedLogin(teamId, tenant2, opts = {}) {
888
888
  async function createTenantInteractive(teamId) {
889
889
  const { default: inquirer3 } = await import("inquirer");
890
890
  const tenant2 = await createTenantRow(teamId);
891
- console.log(import_chalk37.default.green(` Tenant ${import_chalk37.default.bold(tenant2)} created.`));
891
+ console.log(import_chalk38.default.green(` Tenant ${import_chalk38.default.bold(tenant2)} created.`));
892
892
  const { users } = await inquirer3.prompt([{
893
893
  type: "confirm",
894
894
  name: "users",
895
895
  default: false,
896
- message: `Enable Users & groups? ${import_chalk37.default.dim(`(identity/key management at iam.apiblaze.com)`)}`
896
+ message: `Enable Users & groups? ${import_chalk38.default.dim(`(identity/key management at iam.apiblaze.com)`)}`
897
897
  }]);
898
898
  if (users) {
899
899
  await admin({ method: "PATCH", path: `/teams/${encodeURIComponent(teamId)}/tenants/${encodeURIComponent(tenant2)}/iam`, body: { enabled: true }, summary: "Enable Users & groups" }).catch(() => {
900
900
  });
901
- console.log(import_chalk37.default.green(" Users & groups enabled."));
901
+ console.log(import_chalk38.default.green(" Users & groups enabled."));
902
902
  }
903
903
  await addApiblazeHostedLogin(teamId, tenant2, { allowSkip: true });
904
904
  return tenant2;
905
905
  }
906
- var import_chalk37, import_ora14, PROVIDERS, DEFAULT_SCOPES;
906
+ var import_chalk38, import_ora14, PROVIDERS, DEFAULT_SCOPES;
907
907
  var init_tenant_create = __esm({
908
908
  "src/lib/tenant-create.ts"() {
909
909
  "use strict";
910
- import_chalk37 = __toESM(require("chalk"));
910
+ import_chalk38 = __toESM(require("chalk"));
911
911
  import_ora14 = __toESM(require("ora"));
912
912
  init_admin();
913
913
  PROVIDERS = [
@@ -946,10 +946,10 @@ async function fetchPage2(teamId, q) {
946
946
  }
947
947
  function label(t, defaultTenant, active) {
948
948
  const tags = [
949
- t.tenant_name === active ? import_chalk38.default.cyan("active scope") : "",
950
- t.tenant_name === defaultTenant ? import_chalk38.default.dim("team default") : ""
949
+ t.tenant_name === active ? import_chalk39.default.cyan("active scope") : "",
950
+ t.tenant_name === defaultTenant ? import_chalk39.default.dim("team default") : ""
951
951
  ].filter(Boolean).join(", ");
952
- const disp = t.display_name && t.display_name !== t.tenant_name ? import_chalk38.default.dim(` ${t.display_name}`) : "";
952
+ const disp = t.display_name && t.display_name !== t.tenant_name ? import_chalk39.default.dim(` ${t.display_name}`) : "";
953
953
  return `${t.tenant_name}${disp}${tags ? ` (${tags})` : ""}`;
954
954
  }
955
955
  async function pickTenant(teamId, opts = {}) {
@@ -964,7 +964,7 @@ async function pickTenant(teamId, opts = {}) {
964
964
  const { make } = await inquirer3.prompt([{ type: "confirm", name: "make", message: "No tenants yet \u2014 create one?", default: true }]);
965
965
  if (make) return await createTenantInline(teamId);
966
966
  }
967
- console.error(import_chalk38.default.red("This team has no tenants. Create one with `apiblaze tenant create`."));
967
+ console.error(import_chalk39.default.red("This team has no tenants. Create one with `apiblaze tenant create`."));
968
968
  return null;
969
969
  }
970
970
  const truncated = page.total > page.rows.length;
@@ -973,7 +973,7 @@ async function pickTenant(teamId, opts = {}) {
973
973
  value: t.tenant_name
974
974
  }));
975
975
  if (truncated || q) {
976
- choices.push(new inquirer3.Separator(import_chalk38.default.dim(
976
+ choices.push(new inquirer3.Separator(import_chalk39.default.dim(
977
977
  truncated ? `showing ${page.rows.length} of ${page.total}${q ? ` matching "${q}"` : ""} \u2014 search to narrow` : `matches for "${q}"`
978
978
  )));
979
979
  choices.push({ name: `\u{1F50D} Search${q ? " again" : ""}\u2026`, value: "\0search" });
@@ -1007,11 +1007,11 @@ async function createTenantInline(teamId) {
1007
1007
  const { createTenantInteractive: createTenantInteractive2 } = await Promise.resolve().then(() => (init_tenant_create(), tenant_create_exports));
1008
1008
  return createTenantInteractive2(teamId);
1009
1009
  }
1010
- var import_chalk38, import_ora15, PAGE;
1010
+ var import_chalk39, import_ora15, PAGE;
1011
1011
  var init_tenant_pick = __esm({
1012
1012
  "src/lib/tenant-pick.ts"() {
1013
1013
  "use strict";
1014
- import_chalk38 = __toESM(require("chalk"));
1014
+ import_chalk39 = __toESM(require("chalk"));
1015
1015
  import_ora15 = __toESM(require("ora"));
1016
1016
  init_admin();
1017
1017
  init_auth();
@@ -1021,10 +1021,10 @@ var init_tenant_pick = __esm({
1021
1021
 
1022
1022
  // src/index.ts
1023
1023
  var import_commander = require("commander");
1024
- var import_chalk54 = __toESM(require("chalk"));
1024
+ var import_chalk55 = __toESM(require("chalk"));
1025
1025
 
1026
1026
  // package.json
1027
- var version = "0.20.31";
1027
+ var version = "0.20.39";
1028
1028
 
1029
1029
  // src/index.ts
1030
1030
  init_types();
@@ -2102,6 +2102,7 @@ function suggestTenantName(projectSlug, taken) {
2102
2102
  var fs8 = __toESM(require("fs"));
2103
2103
  var path6 = __toESM(require("path"));
2104
2104
  var crypto2 = __toESM(require("crypto"));
2105
+ var import_child_process3 = require("child_process");
2105
2106
  var import_chalk14 = __toESM(require("chalk"));
2106
2107
  var import_ora4 = __toESM(require("ora"));
2107
2108
  var import_yaml2 = require("yaml");
@@ -2573,10 +2574,74 @@ function codexInteractive(_spec, prompt) {
2573
2574
  }
2574
2575
  var shellQuote = (s) => `"${s.replace(/(["\\$`])/g, "\\$1")}"`;
2575
2576
  function directedPrompt(spec2, question) {
2576
- return `Use the "${spec2.name}" MCP server (it exposes this API's tools) to answer: ${question}`;
2577
+ const ctx = spec2.contextNote ? ` ${spec2.contextNote}` : "";
2578
+ return `Use the "${spec2.name}" MCP server (it exposes this API's tools) to answer: ${question}${ctx}`;
2579
+ }
2580
+ function agentInstructionFile(cli, dir = process.cwd()) {
2581
+ return path4.join(dir, cli === "claude" ? "CLAUDE.md" : "AGENTS.md");
2582
+ }
2583
+ var marker = (name) => ({
2584
+ start: `<!-- apiblaze:mcp:${name} -->`,
2585
+ end: `<!-- /apiblaze:mcp:${name} -->`
2586
+ });
2587
+ function stripMarkedBlock(text, name) {
2588
+ const m = marker(name);
2589
+ for (; ; ) {
2590
+ const i = text.indexOf(m.start);
2591
+ if (i < 0) return text;
2592
+ const j = text.indexOf(m.end, i);
2593
+ if (j < 0) return text.slice(0, i);
2594
+ let k = j + m.end.length;
2595
+ if (text[k] === "\n") k++;
2596
+ text = text.slice(0, i) + text.slice(k);
2597
+ }
2598
+ }
2599
+ function writeAgentInstruction(cli, spec2, dir = process.cwd()) {
2600
+ try {
2601
+ const file = agentInstructionFile(cli, dir);
2602
+ const m = marker(spec2.name);
2603
+ const block = [
2604
+ m.start,
2605
+ `## ${spec2.projectLabel} API \u2014 use the "${spec2.name}" MCP server`,
2606
+ "",
2607
+ `This directory is connected to the \`${spec2.name}\` MCP server, which exposes the`,
2608
+ `${spec2.projectLabel} API as tools. For any question about this API \u2014 its data, its`,
2609
+ "records, what it can do \u2014 call those tools rather than answering from memory or",
2610
+ "asking for data the API can provide.",
2611
+ ...spec2.contextNote ? ["", spec2.contextNote] : [],
2612
+ "",
2613
+ `_Added by \`apiblaze apichat\`. Remove this block, or run \`npx apiblaze apichat ${spec2.name} --remove-mcp ${cli}\`._`,
2614
+ m.end,
2615
+ ""
2616
+ ].join("\n");
2617
+ let text = "";
2618
+ try {
2619
+ text = fs5.readFileSync(file, "utf-8");
2620
+ } catch {
2621
+ }
2622
+ const cleaned = stripMarkedBlock(text, spec2.name);
2623
+ const sep = cleaned.length && !cleaned.endsWith("\n\n") ? cleaned.endsWith("\n") ? "\n" : "\n\n" : "";
2624
+ fs5.writeFileSync(file, cleaned + sep + block, "utf-8");
2625
+ return file;
2626
+ } catch {
2627
+ return null;
2628
+ }
2629
+ }
2630
+ function removeAgentInstruction(cli, name, dir = process.cwd()) {
2631
+ try {
2632
+ const file = agentInstructionFile(cli, dir);
2633
+ const text = fs5.readFileSync(file, "utf-8");
2634
+ const cleaned = stripMarkedBlock(text, name);
2635
+ if (cleaned === text) return false;
2636
+ fs5.writeFileSync(file, cleaned.replace(/\n{3,}/g, "\n\n"), "utf-8");
2637
+ return true;
2638
+ } catch {
2639
+ return false;
2640
+ }
2577
2641
  }
2578
2642
  function claudeSystemHint(spec2) {
2579
- return `You are connected to the "${spec2.name}" MCP server, which exposes the ${spec2.projectLabel} API as tools (mcp__${spec2.name}__*). For any question about this API, call those tools rather than answering from memory or asking the user for data the API can provide.`;
2643
+ const ctx = spec2.contextNote ? ` ${spec2.contextNote}` : "";
2644
+ return `You are connected to the "${spec2.name}" MCP server, which exposes the ${spec2.projectLabel} API as tools (mcp__${spec2.name}__*). For any question about this API, call those tools rather than answering from memory or asking the user for data the API can provide.${ctx}`;
2580
2645
  }
2581
2646
  function renderCommand(argv) {
2582
2647
  return argv.map((a, i) => i === 0 || /^[A-Za-z0-9_@%+=:,./-]+$/.test(a) ? a : shellQuote(a)).join(" ");
@@ -2658,8 +2723,20 @@ async function installAndDemo(cli, spec2, getQuestion, log = console.log) {
2658
2723
  if (ans.status !== 0) log(import_chalk12.default.yellow(`
2659
2724
  ${cli.label} exited with ${ans.status ?? "no status"} \u2014 the MCP stays installed.`));
2660
2725
  }
2661
- log(`
2662
- ${import_chalk12.default.bold(`Your ${cli.label} is now able to talk to the ${spec2.projectLabel} API.`)}`);
2726
+ const instructionFile = writeAgentInstruction(cli.kind, spec2);
2727
+ const off = `npx apiblaze apichat ${spec2.name} --remove-mcp ${cli.kind}`;
2728
+ const mdName = cli.kind === "claude" ? "CLAUDE.md" : "AGENTS.md";
2729
+ log("");
2730
+ log(import_chalk12.default.bgRed.white.bold(` ${cli.label} will launch with your MCP to ${spec2.projectLabel} enabled from now on. `));
2731
+ log(import_chalk12.default.red.bold(` Every ${cli.label} session in this directory can call your API's tools.`));
2732
+ if (instructionFile) {
2733
+ log(import_chalk12.default.red(` We added a "use this MCP" block to your ${import_chalk12.default.bold(mdName)} \u2014 that is what makes it stick:`));
2734
+ log(import_chalk12.default.red(` ${instructionFile}`));
2735
+ } else {
2736
+ log(import_chalk12.default.red(` (Could not write ${mdName} here, so this applies only to sessions apichat starts.)`));
2737
+ }
2738
+ log(import_chalk12.default.red(` Turn it off (removes the MCP server AND the ${mdName} block):`));
2739
+ log(import_chalk12.default.red(` ${import_chalk12.default.bold(off)}`));
2663
2740
  return true;
2664
2741
  }
2665
2742
 
@@ -4137,6 +4214,9 @@ function rememberCliOffer(p, cli, state) {
4137
4214
  }
4138
4215
  function buildInstallSpec(p) {
4139
4216
  return {
4217
+ // Control-plane tools take a team_id the model cannot guess; without it the
4218
+ // authorization check runs against `team:` (empty) and every call 403s.
4219
+ contextNote: p.projectId === "externalauth" && p.teamId ? `Your team_id is "${p.teamId}" \u2014 pass it as the team_id argument to any tool that accepts one, and use it wherever a team is required.` : void 0,
4140
4220
  name: p.projectId,
4141
4221
  url: `https://${p.mcpHost}/${p.version}/${p.environment}`,
4142
4222
  // consumerAuth means the door is a login — install bare, the CLI signs in.
@@ -4180,6 +4260,12 @@ async function maybeInstallExternalCli(p, opts) {
4180
4260
  );
4181
4261
  if (!await ensureInstallableDoor(p, opts)) return false;
4182
4262
  if (!await verifyAndHealMcpHost(p)) {
4263
+ if (p.projectId === "externalauth" && p.anon) {
4264
+ fail3(
4265
+ "Chatting with APIblaze needs an account for now.",
4266
+ "Run `apiblaze login` (free, keeps the proxies you already made), then re-run this command."
4267
+ );
4268
+ }
4183
4269
  fail3(`The MCP endpoint https://${p.mcpHost}/${p.version}/${p.environment} is not answering \u2014 not installing it into ${cli.label}.`);
4184
4270
  }
4185
4271
  await authorizeClientRegistration(p, cli.label);
@@ -4334,9 +4420,112 @@ async function startChat(p, messages, opts) {
4334
4420
  }
4335
4421
  await runRepl(p, messages);
4336
4422
  }
4423
+ function isApiblazeControlPlaneTarget(target) {
4424
+ try {
4425
+ const h = new URL(target).hostname.toLowerCase();
4426
+ return h === "api.mcp.apiblaze.com" || /^externalauth(-[a-z0-9]+)?\.mcp\.apiblaze\.com$/.test(h);
4427
+ } catch {
4428
+ return false;
4429
+ }
4430
+ }
4431
+ function opTenantForTeam(teamId) {
4432
+ return ("op" + (teamId || "")).toLowerCase().replace(/[^a-z0-9]/g, "");
4433
+ }
4434
+ async function openControlPlaneChat() {
4435
+ const creds = loadCredentials();
4436
+ const anonCred = creds?.teamId ? null : loadAnonCred();
4437
+ if (!creds?.teamId && !anonCred?.team_id) {
4438
+ fail3(
4439
+ "Chatting with APIblaze needs a workspace \u2014 its tools act on YOUR proxies.",
4440
+ "Make one first (no signup): apiblaze create --target <your api or spec> --auto"
4441
+ );
4442
+ }
4443
+ const teamId = creds?.teamId ?? anonCred.team_id;
4444
+ const tenant2 = opTenantForTeam(teamId);
4445
+ const projectId = "externalauth";
4446
+ const version2 = "1.0.0";
4447
+ const environment = "prod";
4448
+ const saved = loadApichats().find((a) => a.projectId === projectId);
4449
+ let dpKey = saved?.dpKey ?? anonCred?.cp_key;
4450
+ if (!dpKey) {
4451
+ const spinner = (0, import_ora4.default)("Preparing your APIblaze control-plane key\u2026").start();
4452
+ try {
4453
+ const out = await admin({
4454
+ method: "POST",
4455
+ path: `/teams/${encodeURIComponent(teamId)}/developer-keys`,
4456
+ body: { name: "apichat (APIblaze control plane)" },
4457
+ summary: "Mint a control-plane key for chatting with APIblaze"
4458
+ });
4459
+ dpKey = out?.key;
4460
+ spinner.stop();
4461
+ } catch (err) {
4462
+ spinner.fail("Could not mint a control-plane key.");
4463
+ throw err;
4464
+ }
4465
+ if (!dpKey) fail3("The server returned no control-plane key.");
4466
+ }
4467
+ const p = {
4468
+ projectId,
4469
+ version: version2,
4470
+ environment,
4471
+ dpKey,
4472
+ consumerAuth: false,
4473
+ mcpHost: `${projectId}-${tenant2}.mcp.apiblaze.com`,
4474
+ proxyUrl: `https://api.apiblaze.com/${version2}/${environment}`,
4475
+ anon: !creds?.teamId,
4476
+ access: "invite",
4477
+ tenant: tenant2,
4478
+ teamId
4479
+ };
4480
+ const who = creds?.teamName ?? (anonCred ? "your anonymous workspace" : teamId);
4481
+ console.log(` ${import_chalk14.default.dim("Chatting with:")} ${import_chalk14.default.bold("APIblaze itself")} ${import_chalk14.default.dim(`(${who})`)}`);
4482
+ if (anonCred) {
4483
+ console.log(import_chalk14.default.dim(" Anonymous workspace \u2014 `apiblaze login` then `/claim` inside the chat to keep it."));
4484
+ }
4485
+ upsertApichat({
4486
+ name: projectId,
4487
+ target: "https://api.mcp.apiblaze.com",
4488
+ projectId,
4489
+ version: version2,
4490
+ environment,
4491
+ mcpHost: p.mcpHost,
4492
+ teamId,
4493
+ tenant: tenant2,
4494
+ dpKey,
4495
+ consumerAuth: false,
4496
+ anon: false,
4497
+ ownerUserId: creds?.apiblazeUserId,
4498
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4499
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
4500
+ });
4501
+ return { p };
4502
+ }
4503
+ async function removeExternalMcp(projectId, cliKind) {
4504
+ const kind = cliKind.toLowerCase();
4505
+ if (kind !== "claude" && kind !== "codex") fail3(`--remove-mcp takes "claude" or "codex", not "${cliKind}".`);
4506
+ const label3 = kind === "claude" ? "Claude CLI" : "Codex CLI";
4507
+ let removed = false;
4508
+ if (kind === "claude") {
4509
+ const r = (0, import_child_process3.spawnSync)("claude", ["mcp", "remove", projectId], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], timeout: 15e3 });
4510
+ removed = r.status === 0;
4511
+ } else {
4512
+ removed = removeCodexServer(projectId);
4513
+ }
4514
+ console.log(removed ? ` ${import_chalk14.default.green("\u2714")} Removed the ${import_chalk14.default.bold(projectId)} MCP server from ${label3}.` : import_chalk14.default.dim(` ${label3} had no ${projectId} MCP server configured.`));
4515
+ const hadNote = removeAgentInstruction(kind, projectId);
4516
+ console.log(hadNote ? ` ${import_chalk14.default.green("\u2714")} Removed the standing instruction from ${agentInstructionFile(kind)}.` : import_chalk14.default.dim(` No standing instruction found in ${agentInstructionFile(kind)}.`));
4517
+ console.log(import_chalk14.default.dim(`
4518
+ ${label3} will no longer launch with your API's tools in this directory.`));
4519
+ }
4337
4520
  async function runApichat(opts) {
4338
4521
  setVerbose(opts.verbose === true);
4339
4522
  console.log(import_chalk14.default.bold("\napichat \u2014 turn any API into a chat\n"));
4523
+ if (opts.target && isApiblazeControlPlaneTarget(opts.target)) {
4524
+ const cp = await openControlPlaneChat();
4525
+ if (await maybeInstallExternalCli(cp.p, opts)) return;
4526
+ await startChat(cp.p, [], opts);
4527
+ return;
4528
+ }
4340
4529
  if (opts.target && !opts.openapispec) {
4341
4530
  const { classifyTargetInput: classifyTargetInput2 } = await Promise.resolve().then(() => (init_spec_or_target(), spec_or_target_exports));
4342
4531
  const c = await classifyTargetInput2(opts.target, fail3);
@@ -4346,6 +4535,11 @@ async function runApichat(opts) {
4346
4535
  opts.target = void 0;
4347
4536
  }
4348
4537
  }
4538
+ if (opts.removeMcp) {
4539
+ if (!opts.project) fail3("Name the proxy: apiblaze apichat <project> --remove-mcp claude|codex");
4540
+ await removeExternalMcp(opts.project, opts.removeMcp);
4541
+ return;
4542
+ }
4349
4543
  if (opts.project) {
4350
4544
  const opened = await openDirectProject(opts.project, opts);
4351
4545
  if (await maybeInstallExternalCli(opened.p, opts)) return;
@@ -5232,44 +5426,80 @@ async function runTeam(arg, opts = {}) {
5232
5426
  activate(creds, chosen);
5233
5427
  }
5234
5428
 
5429
+ // src/commands/docs.ts
5430
+ var import_chalk21 = __toESM(require("chalk"));
5431
+ var CONTROL_PLANE_TARGET = "https://api.mcp.apiblaze.com/openapi.json";
5432
+ async function runDocs(opts) {
5433
+ console.log("");
5434
+ console.log(import_chalk21.default.bgYellow.black.bold(" This is not a docs search \u2014 the chatbot can CHANGE your account. "));
5435
+ console.log(import_chalk21.default.yellow(` It connects ${import_chalk21.default.bold("Claude Code")} or ${import_chalk21.default.bold("Codex")} to the real APIblaze API, acting as you:`));
5436
+ console.log(import_chalk21.default.yellow(" it can create proxies, add logins, invite teammates and point domains for real."));
5437
+ console.log(import_chalk21.default.yellow(" Destructive actions (deleting proxies, teams or products) are deliberately not exposed."));
5438
+ console.log(import_chalk21.default.dim(' Read-only questions ("what proxies do I have?") are of course fine.'));
5439
+ console.log("");
5440
+ if (!opts.yes && !opts.prompt && process.stdin.isTTY) {
5441
+ const { default: inquirer3 } = await import("inquirer");
5442
+ const { ok } = await inquirer3.prompt([{
5443
+ type: "confirm",
5444
+ name: "ok",
5445
+ default: true,
5446
+ message: "Continue, knowing the chatbot can act on your account?"
5447
+ }]);
5448
+ if (!ok) {
5449
+ console.log(import_chalk21.default.dim("\n Nothing connected. The written docs are at https://www.apiblaze.com/docs"));
5450
+ return;
5451
+ }
5452
+ }
5453
+ const forwarded = {
5454
+ target: CONTROL_PLANE_TARGET,
5455
+ prompt: opts.prompt,
5456
+ installMcp: opts.installMcp,
5457
+ removeMcp: opts.removeMcp,
5458
+ verbose: opts.verbose,
5459
+ // `--remove-mcp` needs the project name; the control-plane proxy is `externalauth`.
5460
+ ...opts.removeMcp ? { project: "externalauth" } : {}
5461
+ };
5462
+ await runApichat(forwarded);
5463
+ }
5464
+
5235
5465
  // src/commands/authz.ts
5236
- var import_chalk23 = __toESM(require("chalk"));
5466
+ var import_chalk24 = __toESM(require("chalk"));
5237
5467
  init_auth();
5238
5468
  init_api();
5239
5469
 
5240
5470
  // src/lib/agent-chat.ts
5241
5471
  var import_readline = __toESM(require("readline"));
5242
- var import_chalk21 = __toESM(require("chalk"));
5472
+ var import_chalk22 = __toESM(require("chalk"));
5243
5473
  init_api();
5244
5474
  init_admin();
5245
5475
  async function runAgentChatRepl(opts) {
5246
5476
  const { title, subtitle, endpoint, buildBody, seedPrompt, summarizeProposal, commands } = opts;
5247
- console.log("\n" + import_chalk21.default.cyan.bold(title));
5248
- if (subtitle) console.log(import_chalk21.default.dim(subtitle));
5477
+ console.log("\n" + import_chalk22.default.cyan.bold(title));
5478
+ if (subtitle) console.log(import_chalk22.default.dim(subtitle));
5249
5479
  const messages = [];
5250
5480
  const ctx = { proposal: null, lastData: null, log: (s) => console.log(s) };
5251
5481
  const cmdByName = new Map(commands.map((c) => [c.name, c]));
5252
5482
  const footer = () => {
5253
5483
  const parts = [
5254
- import_chalk21.default.dim("type to chat/refine"),
5255
- ...commands.map((c) => import_chalk21.default.dim(`/${c.name} ${c.describe}`)),
5256
- import_chalk21.default.dim("/show"),
5257
- import_chalk21.default.dim("/exit when done"),
5258
- import_chalk21.default.dim("/drop discard changes")
5484
+ import_chalk22.default.dim("type to chat/refine"),
5485
+ ...commands.map((c) => import_chalk22.default.dim(`/${c.name} ${c.describe}`)),
5486
+ import_chalk22.default.dim("/show"),
5487
+ import_chalk22.default.dim("/exit when done"),
5488
+ import_chalk22.default.dim("/drop discard changes")
5259
5489
  ];
5260
- return " " + import_chalk21.default.dim("[ ") + parts.join(import_chalk21.default.dim(" \xB7 ")) + import_chalk21.default.dim(" ]");
5490
+ return " " + import_chalk22.default.dim("[ ") + parts.join(import_chalk22.default.dim(" \xB7 ")) + import_chalk22.default.dim(" ]");
5261
5491
  };
5262
5492
  async function turn(content) {
5263
5493
  messages.push({ role: "user", content });
5264
- process.stdout.write(import_chalk21.default.dim(" \u2026thinking\n"));
5494
+ process.stdout.write(import_chalk22.default.dim(" \u2026thinking\n"));
5265
5495
  const { status, data } = await agentCall(endpoint, "POST", { messages, ...buildBody(messages) });
5266
5496
  if (status === 402) {
5267
- console.log(import_chalk21.default.red(" Insufficient credits \u2014 top up to keep using the agents.\n"));
5497
+ console.log(import_chalk22.default.red(" Insufficient credits \u2014 top up to keep using the agents.\n"));
5268
5498
  messages.pop();
5269
5499
  return;
5270
5500
  }
5271
5501
  if (status >= 400 || !data) {
5272
- console.log(import_chalk21.default.red(` Error (${status}): ${(data && data.error) ?? "request failed"}
5502
+ console.log(import_chalk22.default.red(` Error (${status}): ${(data && data.error) ?? "request failed"}
5273
5503
  `));
5274
5504
  messages.pop();
5275
5505
  return;
@@ -5277,24 +5507,24 @@ async function runAgentChatRepl(opts) {
5277
5507
  ctx.lastData = data;
5278
5508
  const reply = data.reply ?? data.message ?? "(no reply)";
5279
5509
  messages.push({ role: "assistant", content: reply });
5280
- console.log("\n" + import_chalk21.default.cyan("agent \u203A ") + reply + "\n");
5510
+ console.log("\n" + import_chalk22.default.cyan("agent \u203A ") + reply + "\n");
5281
5511
  if (data.proposal) {
5282
5512
  ctx.proposal = data.proposal;
5283
5513
  const summary = summarizeProposal?.(data);
5284
- if (summary) console.log(import_chalk21.default.yellow(" " + summary));
5514
+ if (summary) console.log(import_chalk22.default.yellow(" " + summary));
5285
5515
  const applies = commands.filter((c) => c.needsProposal);
5286
5516
  const primary = applies[applies.length - 1];
5287
5517
  if (primary) {
5288
- console.log(import_chalk21.default.bold.green(" \u279C Next: type ") + import_chalk21.default.bold.cyan(`/${primary.name}`) + import_chalk21.default.bold.green(" to apply this, then ") + import_chalk21.default.bold.cyan("/exit") + import_chalk21.default.bold.green(" to leave."));
5518
+ console.log(import_chalk22.default.bold.green(" \u279C Next: type ") + import_chalk22.default.bold.cyan(`/${primary.name}`) + import_chalk22.default.bold.green(" to apply this, then ") + import_chalk22.default.bold.cyan("/exit") + import_chalk22.default.bold.green(" to leave."));
5289
5519
  const rest = applies.slice(0, -1).map((c) => `/${c.name} = ${c.describe}`).join(" \xB7 ");
5290
- console.log(import_chalk21.default.dim(` (or keep chatting to refine${rest ? ` \xB7 ${rest}` : ""} \xB7 /show = inspect)`));
5520
+ console.log(import_chalk22.default.dim(` (or keep chatting to refine${rest ? ` \xB7 ${rest}` : ""} \xB7 /show = inspect)`));
5291
5521
  }
5292
5522
  console.log();
5293
5523
  }
5294
5524
  const line = formatBilling(data.billing);
5295
5525
  if (line) {
5296
5526
  const llm2 = data.llm;
5297
- console.log(import_chalk21.default.dim(` ${line}${llm2?.model ? ` \xB7 ${llm2.model}` : ""}`));
5527
+ console.log(import_chalk22.default.dim(` ${line}${llm2?.model ? ` \xB7 ${llm2.model}` : ""}`));
5298
5528
  }
5299
5529
  }
5300
5530
  const rl = import_readline.default.createInterface({ input: process.stdin, output: process.stdout });
@@ -5302,31 +5532,31 @@ async function runAgentChatRepl(opts) {
5302
5532
  await turn(seedPrompt);
5303
5533
  for (; ; ) {
5304
5534
  console.log(footer());
5305
- const line = (await ask(import_chalk21.default.green("you \u203A "))).trim();
5535
+ const line = (await ask(import_chalk22.default.green("you \u203A "))).trim();
5306
5536
  if (!line) continue;
5307
5537
  const lower = line.toLowerCase();
5308
5538
  if (line === "/exit" || line === "/quit" || lower === "exit" || lower === "quit" || lower === "q") {
5309
- console.log(import_chalk21.default.dim(" Bye \u2014 anything you enabled or published stays in place.\n"));
5539
+ console.log(import_chalk22.default.dim(" Bye \u2014 anything you enabled or published stays in place.\n"));
5310
5540
  break;
5311
5541
  }
5312
5542
  if (line === "/drop") {
5313
- console.log(import_chalk21.default.dim(" Dropped the pending proposal \u2014 rules you already enabled/published are untouched.\n"));
5543
+ console.log(import_chalk22.default.dim(" Dropped the pending proposal \u2014 rules you already enabled/published are untouched.\n"));
5314
5544
  break;
5315
5545
  }
5316
5546
  if (line === "/show") {
5317
- if (!ctx.proposal) console.log(import_chalk21.default.dim(" No proposal yet \u2014 keep chatting until the agent proposes one.\n"));
5547
+ if (!ctx.proposal) console.log(import_chalk22.default.dim(" No proposal yet \u2014 keep chatting until the agent proposes one.\n"));
5318
5548
  else console.log("\n" + JSON.stringify(ctx.proposal, null, 2) + "\n");
5319
5549
  continue;
5320
5550
  }
5321
5551
  if (line.startsWith("/")) {
5322
5552
  const cmd = cmdByName.get(line.slice(1));
5323
5553
  if (!cmd) {
5324
- console.log(import_chalk21.default.red(` Unknown command "${line}". Try one of: ${commands.map((c) => "/" + c.name).join(", ")}, /show, /drop
5554
+ console.log(import_chalk22.default.red(` Unknown command "${line}". Try one of: ${commands.map((c) => "/" + c.name).join(", ")}, /show, /drop
5325
5555
  `));
5326
5556
  continue;
5327
5557
  }
5328
5558
  if (cmd.needsProposal && !ctx.proposal) {
5329
- console.log(import_chalk21.default.yellow(" No proposal yet \u2014 keep chatting until the agent generates one, then try again.\n"));
5559
+ console.log(import_chalk22.default.yellow(" No proposal yet \u2014 keep chatting until the agent generates one, then try again.\n"));
5330
5560
  continue;
5331
5561
  }
5332
5562
  await cmd.run(ctx);
@@ -5338,7 +5568,7 @@ async function runAgentChatRepl(opts) {
5338
5568
  }
5339
5569
 
5340
5570
  // src/lib/authz-apply.ts
5341
- var import_chalk22 = __toESM(require("chalk"));
5571
+ var import_chalk23 = __toESM(require("chalk"));
5342
5572
  init_api();
5343
5573
  async function gatherSampleIds(projectId, apiVersion, cap = 50) {
5344
5574
  try {
@@ -5363,10 +5593,10 @@ async function gatherSampleIds(projectId, apiVersion, cap = 50) {
5363
5593
  }
5364
5594
  function maybeWarnNoTraffic(total, projectArg) {
5365
5595
  if (total >= 3) return;
5366
- console.log(import_chalk22.default.yellow(total === 0 ? " \u26A0 No captured traffic for this API yet." : ` \u26A0 Only ${total} captured request(s) so far.`));
5367
- console.log(import_chalk22.default.dim(" The authorization agent designs much better models & rules from REAL requests"));
5368
- console.log(import_chalk22.default.dim(" (it sees who is allowed vs denied). Send some through your proxy first \u2014"));
5369
- console.log(import_chalk22.default.dim(` curl a few endpoints, or `) + import_chalk22.default.cyan("npx apiblaze dev") + import_chalk22.default.dim(` \u2014 then re-run.
5596
+ console.log(import_chalk23.default.yellow(total === 0 ? " \u26A0 No captured traffic for this API yet." : ` \u26A0 Only ${total} captured request(s) so far.`));
5597
+ console.log(import_chalk23.default.dim(" The authorization agent designs much better models & rules from REAL requests"));
5598
+ console.log(import_chalk23.default.dim(" (it sees who is allowed vs denied). Send some through your proxy first \u2014"));
5599
+ console.log(import_chalk23.default.dim(` curl a few endpoints, or `) + import_chalk23.default.cyan("npx apiblaze dev") + import_chalk23.default.dim(` \u2014 then re-run.
5370
5600
  `));
5371
5601
  }
5372
5602
  async function applyProposal(opts) {
@@ -5375,11 +5605,11 @@ async function applyProposal(opts) {
5375
5605
  {
5376
5606
  const m = await agentCall(`/projects/${projectId}/${apiVersion}/policies/model?tenantId=${encodeURIComponent(tenant2)}`, "POST", proposal.model);
5377
5607
  if (m.status === 404) {
5378
- log(import_chalk22.default.red(" Authorization store not provisioned yet. Open the dashboard Authorization tab for this project once (it auto-provisions the store), then re-run.\n"));
5608
+ log(import_chalk23.default.red(" Authorization store not provisioned yet. Open the dashboard Authorization tab for this project once (it auto-provisions the store), then re-run.\n"));
5379
5609
  return { ok: 0, fail: 0, enabled: false, storeMissing: true };
5380
5610
  }
5381
5611
  if (m.status >= 400) {
5382
- log(import_chalk22.default.red(` Model save failed (${m.status}): ${m.data?.error ?? ""}
5612
+ log(import_chalk23.default.red(` Model save failed (${m.status}): ${m.data?.error ?? ""}
5383
5613
  `));
5384
5614
  return { ok: 0, fail: 0, enabled: false };
5385
5615
  }
@@ -5408,7 +5638,7 @@ async function applyProposal(opts) {
5408
5638
  if (enable) {
5409
5639
  const e = await agentCall(`/projects/${projectId}/${apiVersion}`, "PATCH", { authorization: { enforce_authorization: true }, tenant: tenant2 });
5410
5640
  if (e.status >= 400) {
5411
- log(import_chalk22.default.red(` Enforced ${ok} route(s) but turning on the project-level switch failed (${e.status}). Toggle "Enforce Authorization" on in the dashboard.
5641
+ log(import_chalk23.default.red(` Enforced ${ok} route(s) but turning on the project-level switch failed (${e.status}). Toggle "Enforce Authorization" on in the dashboard.
5412
5642
  `));
5413
5643
  return { ok, fail: fail6, enabled: false };
5414
5644
  }
@@ -5434,10 +5664,10 @@ async function runAuthz(projectArg, apiVersionArg) {
5434
5664
  const r = await applyProposal({ projectId, apiVersion, tenant: tenant2, proposal, enable, log: ctx.log });
5435
5665
  if (r.storeMissing) return;
5436
5666
  if (enable && r.enabled) {
5437
- ctx.log(import_chalk23.default.green(` \u2713 Enforcement ON \u2014 ${r.ok} route(s) + project switch on${r.fail ? `, ${r.fail} failed` : ""}.`));
5438
- ctx.log(import_chalk23.default.dim(" Done here? Type /exit to leave the chat (your rule stays on).\n"));
5667
+ ctx.log(import_chalk24.default.green(` \u2713 Enforcement ON \u2014 ${r.ok} route(s) + project switch on${r.fail ? `, ${r.fail} failed` : ""}.`));
5668
+ ctx.log(import_chalk24.default.dim(" Done here? Type /exit to leave the chat (your rule stays on).\n"));
5439
5669
  } else if (!enable) {
5440
- ctx.log(import_chalk23.default.green(` \u2713 Published (shadow): model + ${r.ok} route(s)${r.fail ? `, ${r.fail} failed` : ""}. Review, then /enable.
5670
+ ctx.log(import_chalk24.default.green(` \u2713 Published (shadow): model + ${r.ok} route(s)${r.fail ? `, ${r.fail} failed` : ""}. Review, then /enable.
5441
5671
  `));
5442
5672
  }
5443
5673
  }
@@ -5464,7 +5694,7 @@ async function runAuthz(projectArg, apiVersionArg) {
5464
5694
  }
5465
5695
 
5466
5696
  // src/commands/rule.ts
5467
- var import_chalk24 = __toESM(require("chalk"));
5697
+ var import_chalk25 = __toESM(require("chalk"));
5468
5698
  var import_ora8 = __toESM(require("ora"));
5469
5699
  init_auth();
5470
5700
  init_api();
@@ -5501,27 +5731,27 @@ async function runRule(ruleText, projectArg, opts) {
5501
5731
  const proposal = data?.proposal;
5502
5732
  if (!proposal || !Array.isArray(proposal.routes) || proposal.routes.length === 0) {
5503
5733
  spinner.fail("The agent couldn\u2019t turn that into a rule in one shot.");
5504
- if (data?.reply) console.log(import_chalk24.default.dim("\n " + String(data.reply).slice(0, 500) + "\n"));
5505
- console.log(import_chalk24.default.dim(" Try an interactive session for anything nuanced: ") + import_chalk24.default.cyan(`apiblaze agent authz ${projectArg}`));
5734
+ if (data?.reply) console.log(import_chalk25.default.dim("\n " + String(data.reply).slice(0, 500) + "\n"));
5735
+ console.log(import_chalk25.default.dim(" Try an interactive session for anything nuanced: ") + import_chalk25.default.cyan(`apiblaze agent authz ${projectArg}`));
5506
5736
  return;
5507
5737
  }
5508
5738
  spinner.succeed(`Rule designed \u2014 ${proposal.routes.length} route(s) affected.`);
5509
- if (data?.reply) console.log(import_chalk24.default.dim(" " + String(data.reply).slice(0, 240)));
5739
+ if (data?.reply) console.log(import_chalk25.default.dim(" " + String(data.reply).slice(0, 240)));
5510
5740
  const pub = await applyProposal({ projectId, apiVersion, tenant: tenant2, proposal, enable: false });
5511
5741
  if (pub.storeMissing) return;
5512
- console.log(import_chalk24.default.green(` \u2713 Published in shadow mode \u2014 model + ${pub.ok} route(s)${pub.fail ? `, ${pub.fail} failed` : ""}.`));
5742
+ console.log(import_chalk25.default.green(` \u2713 Published in shadow mode \u2014 model + ${pub.ok} route(s)${pub.fail ? `, ${pub.fail} failed` : ""}.`));
5513
5743
  if (opts.enforce) {
5514
5744
  const enf = await applyProposal({ projectId, apiVersion, tenant: tenant2, proposal, enable: true });
5515
5745
  if (enf.enabled) {
5516
- console.log(import_chalk24.default.green(` \u2713 Enforcement ON \u2014 ${enf.ok} route(s) + project switch on${enf.fail ? `, ${enf.fail} failed` : ""}.`));
5746
+ console.log(import_chalk25.default.green(` \u2713 Enforcement ON \u2014 ${enf.ok} route(s) + project switch on${enf.fail ? `, ${enf.fail} failed` : ""}.`));
5517
5747
  }
5518
5748
  } else {
5519
- console.log(import_chalk24.default.dim(` Review it (shadow logs), then enforce: `) + import_chalk24.default.cyan(`apiblaze rule "${rule}" ${projectArg} --enforce`));
5749
+ console.log(import_chalk25.default.dim(` Review it (shadow logs), then enforce: `) + import_chalk25.default.cyan(`apiblaze rule "${rule}" ${projectArg} --enforce`));
5520
5750
  }
5521
5751
  }
5522
5752
 
5523
5753
  // src/commands/openapi.ts
5524
- var import_chalk25 = __toESM(require("chalk"));
5754
+ var import_chalk26 = __toESM(require("chalk"));
5525
5755
  init_auth();
5526
5756
  init_api();
5527
5757
  async function runOpenapi(projectArg, apiVersionArg) {
@@ -5532,10 +5762,10 @@ async function runOpenapi(projectArg, apiVersionArg) {
5532
5762
  if (!match) throw new Error(`Project "${projectArg}" not found in your active team. Run \`apiblaze projects\`.`);
5533
5763
  const projectId = match.projectId;
5534
5764
  const apiVersion = apiVersionArg || match.apiVersion;
5535
- console.log(import_chalk25.default.dim("Gathering captured traffic samples\u2026"));
5765
+ console.log(import_chalk26.default.dim("Gathering captured traffic samples\u2026"));
5536
5766
  const routesRes = await agentCall(`/projects/${projectId}/${apiVersion}/samples/routes`, "GET");
5537
5767
  if (routesRes.status >= 400) {
5538
- console.log(import_chalk25.default.red(`Could not list traffic (${routesRes.status}): ${routesRes.data?.error ?? ""}`));
5768
+ console.log(import_chalk26.default.red(`Could not list traffic (${routesRes.status}): ${routesRes.data?.error ?? ""}`));
5539
5769
  return;
5540
5770
  }
5541
5771
  const routes = routesRes.data?.routes ?? (Array.isArray(routesRes.data) ? routesRes.data : []);
@@ -5548,25 +5778,25 @@ async function runOpenapi(projectArg, apiVersionArg) {
5548
5778
  }
5549
5779
  const sampleIds = [...ids];
5550
5780
  if (sampleIds.length === 0) {
5551
- console.log(import_chalk25.default.yellow("No captured traffic samples found. Hit the dev environment of this proxy to capture some traces, then retry."));
5781
+ console.log(import_chalk26.default.yellow("No captured traffic samples found. Hit the dev environment of this proxy to capture some traces, then retry."));
5552
5782
  return;
5553
5783
  }
5554
5784
  async function publish(ctx) {
5555
5785
  const patch = ctx.proposal.patch;
5556
5786
  if (!Array.isArray(patch) || patch.length === 0) {
5557
- ctx.log(import_chalk25.default.green(" Nothing to publish \u2014 the spec already covers the observed traffic.\n"));
5787
+ ctx.log(import_chalk26.default.green(" Nothing to publish \u2014 the spec already covers the observed traffic.\n"));
5558
5788
  return;
5559
5789
  }
5560
5790
  const specSource = ctx.lastData?.spec_source ?? "unknown";
5561
5791
  const endpoint = specSource === "github" ? "open-pr" : "publish-openapi";
5562
5792
  const pub = await agentCall(`/projects/${projectId}/${apiVersion}/samples/${endpoint}`, "POST", { patch, sample_ids_used: sampleIds });
5563
5793
  if (pub.status >= 400) {
5564
- ctx.log(import_chalk25.default.red(` Publish failed (${pub.status}): ${pub.data?.error ?? ""}
5794
+ ctx.log(import_chalk26.default.red(` Publish failed (${pub.status}): ${pub.data?.error ?? ""}
5565
5795
  `));
5566
5796
  return;
5567
5797
  }
5568
5798
  const prUrl = pub.data?.pr_url;
5569
- ctx.log(import_chalk25.default.green(prUrl ? ` \u2713 Pull request opened: ${prUrl}
5799
+ ctx.log(import_chalk26.default.green(prUrl ? ` \u2713 Pull request opened: ${prUrl}
5570
5800
  ` : " \u2713 Published updated OpenAPI spec.\n"));
5571
5801
  }
5572
5802
  await runAgentChatRepl({
@@ -5587,7 +5817,7 @@ async function runOpenapi(projectArg, apiVersionArg) {
5587
5817
  }
5588
5818
 
5589
5819
  // src/commands/mcp.ts
5590
- var import_chalk26 = __toESM(require("chalk"));
5820
+ var import_chalk27 = __toESM(require("chalk"));
5591
5821
  init_auth();
5592
5822
  init_api();
5593
5823
  async function runMcp(projectArg, apiVersionArg, opts) {
@@ -5604,11 +5834,11 @@ async function runMcp(projectArg, apiVersionArg, opts) {
5604
5834
  const spec2 = ctx.proposal;
5605
5835
  const pub = await agentCall(`/projects/${projectId}/${apiVersion}/mcp/spec`, "PUT", { environment, spec: spec2 });
5606
5836
  if (pub.status >= 400) {
5607
- ctx.log(import_chalk26.default.red(` Publish failed (${pub.status}): ${pub.data?.error ?? ""}
5837
+ ctx.log(import_chalk27.default.red(` Publish failed (${pub.status}): ${pub.data?.error ?? ""}
5608
5838
  `));
5609
5839
  return;
5610
5840
  }
5611
- ctx.log(import_chalk26.default.green(` \u2713 Published MCP server \u2014 ${mcpHost}.mcp.apiblaze.com/${apiVersion}/${environment}.
5841
+ ctx.log(import_chalk27.default.green(` \u2713 Published MCP server \u2014 ${mcpHost}.mcp.apiblaze.com/${apiVersion}/${environment}.
5612
5842
  `));
5613
5843
  }
5614
5844
  await runAgentChatRepl({
@@ -5630,7 +5860,7 @@ async function runMcp(projectArg, apiVersionArg, opts) {
5630
5860
  }
5631
5861
 
5632
5862
  // src/commands/delete.ts
5633
- var import_chalk27 = __toESM(require("chalk"));
5863
+ var import_chalk28 = __toESM(require("chalk"));
5634
5864
  var import_ora9 = __toESM(require("ora"));
5635
5865
  init_admin();
5636
5866
  init_resolve();
@@ -5656,10 +5886,10 @@ async function runDelete(project, version2, opts) {
5656
5886
  return;
5657
5887
  }
5658
5888
  } else {
5659
- console.log(`${import_chalk27.default.red.bold("Delete")} ${import_chalk27.default.bold(proj2.projectName)} ${import_chalk27.default.dim("v" + proj2.apiVersion)} ${import_chalk27.default.dim("(" + proj2.projectId + ")")}`);
5889
+ console.log(`${import_chalk28.default.red.bold("Delete")} ${import_chalk28.default.bold(proj2.projectName)} ${import_chalk28.default.dim("v" + proj2.apiVersion)} ${import_chalk28.default.dim("(" + proj2.projectId + ")")}`);
5660
5890
  if (impact && typeof impact === "object") {
5661
5891
  const counts = impact.counts ?? impact.impact ?? impact;
5662
- console.log(import_chalk27.default.dim(" This removes (cascade): ") + import_chalk27.default.yellow(JSON.stringify(counts)));
5892
+ console.log(import_chalk28.default.dim(" This removes (cascade): ") + import_chalk28.default.yellow(JSON.stringify(counts)));
5663
5893
  }
5664
5894
  if (!opts.yes) {
5665
5895
  const { default: inquirer3 } = await import("inquirer");
@@ -5667,7 +5897,7 @@ async function runDelete(project, version2, opts) {
5667
5897
  { type: "confirm", name: "confirm", message: `Permanently delete ${proj2.projectName} v${proj2.apiVersion}? This cannot be undone.`, default: false }
5668
5898
  ]);
5669
5899
  if (!confirm2) {
5670
- console.log(import_chalk27.default.dim("Aborted."));
5900
+ console.log(import_chalk28.default.dim("Aborted."));
5671
5901
  return;
5672
5902
  }
5673
5903
  }
@@ -5688,7 +5918,7 @@ async function runDelete(project, version2, opts) {
5688
5918
  }
5689
5919
 
5690
5920
  // src/commands/export.ts
5691
- var import_chalk28 = __toESM(require("chalk"));
5921
+ var import_chalk29 = __toESM(require("chalk"));
5692
5922
  var import_fs3 = require("fs");
5693
5923
  init_admin();
5694
5924
  init_auth();
@@ -5707,7 +5937,7 @@ async function runExport(projectArg, versionArg, opts) {
5707
5937
  if (opts.noConsumers) q.set("include_consumers", "0");
5708
5938
  if (opts.keys) q.set("keys", opts.keys);
5709
5939
  const qs = q.toString() ? `?${q.toString()}` : "";
5710
- console.log(import_chalk28.default.dim(`Queuing ${target} export of ${projectId}@${version2}\u2026`));
5940
+ console.log(import_chalk29.default.dim(`Queuing ${target} export of ${projectId}@${version2}\u2026`));
5711
5941
  const job = await admin({
5712
5942
  path: `/projects/${projectId}/${version2}/export/${target}${qs}`,
5713
5943
  method: "GET",
@@ -5717,11 +5947,11 @@ async function runExport(projectArg, versionArg, opts) {
5717
5947
  const statusPath = `/projects/${projectId}/${version2}/export/jobs/${job.job_id}`;
5718
5948
  let status = "queued";
5719
5949
  const started = Date.now();
5720
- process.stdout.write(import_chalk28.default.dim("Building bundle"));
5950
+ process.stdout.write(import_chalk29.default.dim("Building bundle"));
5721
5951
  while (status !== "ready" && status !== "failed") {
5722
5952
  if (Date.now() - started > 10 * 6e4) throw new Error("Export timed out after 10 minutes.");
5723
5953
  await new Promise((r) => setTimeout(r, 3e3));
5724
- process.stdout.write(import_chalk28.default.dim("."));
5954
+ process.stdout.write(import_chalk29.default.dim("."));
5725
5955
  const st = await admin({ path: statusPath, method: "GET", summary: "poll export" });
5726
5956
  status = st?.status ?? "queued";
5727
5957
  if (status === "failed") {
@@ -5739,14 +5969,14 @@ async function runExport(projectArg, versionArg, opts) {
5739
5969
  if (!res.ok) throw new Error(`Download failed (${res.status}): ${await res.text().catch(() => "")}`);
5740
5970
  const buf = Buffer.from(await res.arrayBuffer());
5741
5971
  (0, import_fs3.writeFileSync)(outFile, buf);
5742
- console.log(import_chalk28.default.green(`\u2713 Saved ${outFile} (${(buf.length / 1024).toFixed(0)} KB)`));
5743
- if (job.decryption_key) console.log(import_chalk28.default.yellow(`Decryption key (shown once): ${job.decryption_key}`));
5744
- console.log(import_chalk28.default.dim("Read MIGRATION-REPORT.json inside the zip for the full fidelity ledger."));
5745
- if (target === "kong") console.log(import_chalk28.default.dim("Kong: unzip, then `cd kong && docker compose up` (see kong/README.md)."));
5972
+ console.log(import_chalk29.default.green(`\u2713 Saved ${outFile} (${(buf.length / 1024).toFixed(0)} KB)`));
5973
+ if (job.decryption_key) console.log(import_chalk29.default.yellow(`Decryption key (shown once): ${job.decryption_key}`));
5974
+ console.log(import_chalk29.default.dim("Read MIGRATION-REPORT.json inside the zip for the full fidelity ledger."));
5975
+ if (target === "kong") console.log(import_chalk29.default.dim("Kong: unzip, then `cd kong && docker compose up` (see kong/README.md)."));
5746
5976
  }
5747
5977
 
5748
5978
  // src/commands/recipe-search.ts
5749
- var import_chalk29 = __toESM(require("chalk"));
5979
+ var import_chalk30 = __toESM(require("chalk"));
5750
5980
  var import_ora10 = __toESM(require("ora"));
5751
5981
  init_caller();
5752
5982
 
@@ -5947,20 +6177,20 @@ async function runRecipeSearch(query, opts) {
5947
6177
  return;
5948
6178
  }
5949
6179
  if (!hits.length) {
5950
- console.log(import_chalk29.default.yellow(query ? `No public recipes match "${query}".` : "No public recipes yet."));
5951
- console.log(import_chalk29.default.dim(" Publish one with: apiblaze publish <proxy> --as @yourhandle/name"));
6180
+ console.log(import_chalk30.default.yellow(query ? `No public recipes match "${query}".` : "No public recipes yet."));
6181
+ console.log(import_chalk30.default.dim(" Publish one with: apiblaze publish <proxy> --as @yourhandle/name"));
5952
6182
  return;
5953
6183
  }
5954
6184
  console.log();
5955
6185
  for (const h of hits) {
5956
- const pin = h.latest_revision ? import_chalk29.default.dim(`@${h.latest_revision}`) : "";
5957
- const installs = h.install_count ? import_chalk29.default.dim(` ${h.install_count} install${h.install_count === 1 ? "" : "s"}`) : "";
5958
- console.log(` ${import_chalk29.default.bold(h.name)}${pin}${h.display_name ? import_chalk29.default.dim(` \u2014 ${h.display_name}`) : ""}${installs}`);
5959
- if (h.summary) console.log(` ${import_chalk29.default.dim(h.summary)}`);
6186
+ const pin = h.latest_revision ? import_chalk30.default.dim(`@${h.latest_revision}`) : "";
6187
+ const installs = h.install_count ? import_chalk30.default.dim(` ${h.install_count} install${h.install_count === 1 ? "" : "s"}`) : "";
6188
+ console.log(` ${import_chalk30.default.bold(h.name)}${pin}${h.display_name ? import_chalk30.default.dim(` \u2014 ${h.display_name}`) : ""}${installs}`);
6189
+ if (h.summary) console.log(` ${import_chalk30.default.dim(h.summary)}`);
5960
6190
  }
5961
6191
  console.log();
5962
- console.log(import_chalk29.default.dim(` Install one with: ${import_chalk29.default.cyan(`npx apiblaze install ${hits[0].name}`)}`));
5963
- console.log(import_chalk29.default.dim(` Read one first: ${import_chalk29.default.cyan(`npx apiblaze show ${hits[0].name}`)}`));
6192
+ console.log(import_chalk30.default.dim(` Install one with: ${import_chalk30.default.cyan(`npx apiblaze install ${hits[0].name}`)}`));
6193
+ console.log(import_chalk30.default.dim(` Read one first: ${import_chalk30.default.cyan(`npx apiblaze show ${hits[0].name}`)}`));
5964
6194
  console.log();
5965
6195
  }
5966
6196
  async function runRecipeShow(nameArg, opts) {
@@ -5986,8 +6216,8 @@ async function runRecipeShow(nameArg, opts) {
5986
6216
  return;
5987
6217
  }
5988
6218
  console.log();
5989
- console.log(`${import_chalk29.default.bold(`${recipe.name}@${recipe.revision}`)}${import_chalk29.default.dim(` \u2014 by ${ref.handle}`)}`);
5990
- if (recipe.display_name) console.log(` ${import_chalk29.default.bold(recipe.display_name)}`);
6219
+ console.log(`${import_chalk30.default.bold(`${recipe.name}@${recipe.revision}`)}${import_chalk30.default.dim(` \u2014 by ${ref.handle}`)}`);
6220
+ if (recipe.display_name) console.log(` ${import_chalk30.default.bold(recipe.display_name)}`);
5991
6221
  if (recipe.summary) console.log(` ${recipe.summary}`);
5992
6222
  const meta = [
5993
6223
  head?.install_count !== void 0 ? `${head.install_count} install${head.install_count === 1 ? "" : "s"}` : null,
@@ -5995,7 +6225,7 @@ async function runRecipeShow(nameArg, opts) {
5995
6225
  recipe.published_at ? `published ${recipe.published_at.slice(0, 10)}` : null,
5996
6226
  `api version ${recipe.api_version}`
5997
6227
  ].filter(Boolean).join(" \xB7 ");
5998
- console.log(import_chalk29.default.dim(` ${meta}`));
6228
+ console.log(import_chalk30.default.dim(` ${meta}`));
5999
6229
  console.log();
6000
6230
  if (wantsSection) {
6001
6231
  if (opts.settings) printSection("settings", recipe.settings);
@@ -6009,34 +6239,34 @@ async function runRecipeShow(nameArg, opts) {
6009
6239
  const rules = recipe.transformations?.rules?.length ?? 0;
6010
6240
  const tables = recipe.transformations?.mapping_tables?.length ?? 0;
6011
6241
  const keyTypes = recipe.auth?.key_types?.length ?? 0;
6012
- if (hosts.length) console.log(` ${import_chalk29.default.dim("sends requests to")} ${hosts.join(", ")}`);
6013
- console.log(` ${import_chalk29.default.dim("creates ")} ${describeCreates(keyTypes, routes, !!recipe.settings.mcp_enabled)}`);
6014
- console.log(` ${import_chalk29.default.dim("asks you for ")} ${recipe.questions.length} value${recipe.questions.length === 1 ? "" : "s"}`);
6242
+ if (hosts.length) console.log(` ${import_chalk30.default.dim("sends requests to")} ${hosts.join(", ")}`);
6243
+ console.log(` ${import_chalk30.default.dim("creates ")} ${describeCreates(keyTypes, routes, !!recipe.settings.mcp_enabled)}`);
6244
+ console.log(` ${import_chalk30.default.dim("asks you for ")} ${recipe.questions.length} value${recipe.questions.length === 1 ? "" : "s"}`);
6015
6245
  if (rules || tables) {
6016
- console.log(` ${import_chalk29.default.dim("transforms ")} ${rules} rule${rules === 1 ? "" : "s"}${tables ? `, ${tables} mapping table${tables === 1 ? "" : "s"}` : ""}`);
6246
+ console.log(` ${import_chalk30.default.dim("transforms ")} ${rules} rule${rules === 1 ? "" : "s"}${tables ? `, ${tables} mapping table${tables === 1 ? "" : "s"}` : ""}`);
6017
6247
  }
6018
6248
  if (recipe.settings.publish_openapi === true) {
6019
- console.log(` ${import_chalk29.default.dim("makes public ")} this API's spec`);
6249
+ console.log(` ${import_chalk30.default.dim("makes public ")} this API's spec`);
6020
6250
  }
6021
6251
  if (recipe.questions.length) {
6022
6252
  console.log();
6023
- console.log(import_chalk29.default.bold(" It will ask you for"));
6253
+ console.log(import_chalk30.default.bold(" It will ask you for"));
6024
6254
  for (const q of recipe.questions) {
6025
- console.log(` ${q.prompt}${q.secret ? import_chalk29.default.dim(" (hidden while you type)") : ""}`);
6026
- if (q.example) console.log(import_chalk29.default.dim(` e.g. ${q.example}`));
6255
+ console.log(` ${q.prompt}${q.secret ? import_chalk30.default.dim(" (hidden while you type)") : ""}`);
6256
+ if (q.example) console.log(import_chalk30.default.dim(` e.g. ${q.example}`));
6027
6257
  }
6028
6258
  }
6029
6259
  if (recipe.requires_confirmation?.length) {
6030
6260
  console.log();
6031
- console.log(import_chalk29.default.yellow(" Needs your explicit consent at install time"));
6261
+ console.log(import_chalk30.default.yellow(" Needs your explicit consent at install time"));
6032
6262
  for (const c of recipe.requires_confirmation) {
6033
- console.log(` ${import_chalk29.default.bold(c.kind)} ${c.value}`);
6034
- console.log(import_chalk29.default.dim(` ${c.why}`));
6263
+ console.log(` ${import_chalk30.default.bold(c.kind)} ${c.value}`);
6264
+ console.log(import_chalk30.default.dim(` ${c.why}`));
6035
6265
  }
6036
6266
  }
6037
6267
  console.log();
6038
- console.log(import_chalk29.default.dim(` Install: ${import_chalk29.default.cyan(`npx apiblaze install ${recipe.name}`)}`));
6039
- console.log(import_chalk29.default.dim(" Sections: --settings --auth --transforms --openapi"));
6268
+ console.log(import_chalk30.default.dim(` Install: ${import_chalk30.default.cyan(`npx apiblaze install ${recipe.name}`)}`));
6269
+ console.log(import_chalk30.default.dim(" Sections: --settings --auth --transforms --openapi"));
6040
6270
  console.log();
6041
6271
  }
6042
6272
  function describeCreates(keyTypes, routes, mcp, includeProxy = true) {
@@ -6046,45 +6276,45 @@ function describeCreates(keyTypes, routes, mcp, includeProxy = true) {
6046
6276
  return parts.length ? parts.join(", ") : "nothing else";
6047
6277
  }
6048
6278
  function printSection(title, value) {
6049
- console.log(import_chalk29.default.bold(` ${title}`));
6279
+ console.log(import_chalk30.default.bold(` ${title}`));
6050
6280
  console.log(indent(JSON.stringify(value ?? null, null, 2), " "));
6051
6281
  console.log();
6052
6282
  }
6053
6283
  function printAuth(recipe) {
6054
6284
  const a = recipe.auth ?? { app_client: null, provider: null, key_types: [] };
6055
- console.log(import_chalk29.default.bold(" auth"));
6285
+ console.log(import_chalk30.default.bold(" auth"));
6056
6286
  if (a.provider) {
6057
- console.log(` ${import_chalk29.default.dim("provider ")} ${a.provider.type ?? "(unknown)"}`);
6058
- if (a.provider.scopes) console.log(` ${import_chalk29.default.dim("scopes ")} ${a.provider.scopes}`);
6059
- if (a.provider.target_server_token) console.log(` ${import_chalk29.default.dim("sends to API")} ${a.provider.target_server_token}`);
6060
- console.log(import_chalk29.default.dim(" (no credentials travel in a recipe \u2014 install asks you for your own)"));
6287
+ console.log(` ${import_chalk30.default.dim("provider ")} ${a.provider.type ?? "(unknown)"}`);
6288
+ if (a.provider.scopes) console.log(` ${import_chalk30.default.dim("scopes ")} ${a.provider.scopes}`);
6289
+ if (a.provider.target_server_token) console.log(` ${import_chalk30.default.dim("sends to API")} ${a.provider.target_server_token}`);
6290
+ console.log(import_chalk30.default.dim(" (no credentials travel in a recipe \u2014 install asks you for your own)"));
6061
6291
  } else {
6062
- console.log(import_chalk29.default.dim(" no login provider \u2014 consumers call it with an API key"));
6292
+ console.log(import_chalk30.default.dim(" no login provider \u2014 consumers call it with an API key"));
6063
6293
  }
6064
6294
  if (a.app_client) {
6065
- console.log(` ${import_chalk29.default.dim("login app ")} ${a.app_client.name ?? "(unnamed)"}`);
6295
+ console.log(` ${import_chalk30.default.dim("login app ")} ${a.app_client.name ?? "(unnamed)"}`);
6066
6296
  }
6067
6297
  if (a.key_types?.length) {
6068
- console.log(` ${import_chalk29.default.dim("key types ")} ${a.key_types.map((k) => String(k.name)).join(", ")}`);
6298
+ console.log(` ${import_chalk30.default.dim("key types ")} ${a.key_types.map((k) => String(k.name)).join(", ")}`);
6069
6299
  }
6070
6300
  console.log();
6071
6301
  }
6072
6302
  function printTransforms(recipe) {
6073
6303
  const rules = recipe.transformations?.rules ?? [];
6074
6304
  const tables = recipe.transformations?.mapping_tables ?? [];
6075
- console.log(import_chalk29.default.bold(` transforms (${rules.length})`));
6305
+ console.log(import_chalk30.default.bold(` transforms (${rules.length})`));
6076
6306
  for (const r of rules) {
6077
- const off = r.enabled === false ? import_chalk29.default.dim(" (disabled)") : "";
6078
- console.log(` ${import_chalk29.default.bold(String(r.name ?? "(unnamed)"))} ${import_chalk29.default.dim(String(r.phase ?? "request"))}${off}`);
6307
+ const off = r.enabled === false ? import_chalk30.default.dim(" (disabled)") : "";
6308
+ console.log(` ${import_chalk30.default.bold(String(r.name ?? "(unnamed)"))} ${import_chalk30.default.dim(String(r.phase ?? "request"))}${off}`);
6079
6309
  console.log(indent(JSON.stringify(r.action ?? null, null, 2), " "));
6080
6310
  if (r.condition) console.log(indent(`when ${JSON.stringify(r.condition)}`, " "));
6081
6311
  }
6082
6312
  if (tables.length) {
6083
6313
  console.log();
6084
- console.log(import_chalk29.default.bold(` mapping tables (${tables.length})`));
6314
+ console.log(import_chalk30.default.bold(` mapping tables (${tables.length})`));
6085
6315
  for (const t of tables) {
6086
6316
  const entries2 = Array.isArray(t.entries) ? t.entries.length : 0;
6087
- console.log(` ${import_chalk29.default.bold(String(t.name ?? "(unnamed)"))} ${import_chalk29.default.dim(`${entries2} entr${entries2 === 1 ? "y" : "ies"}`)}`);
6317
+ console.log(` ${import_chalk30.default.bold(String(t.name ?? "(unnamed)"))} ${import_chalk30.default.dim(`${entries2} entr${entries2 === 1 ? "y" : "ies"}`)}`);
6088
6318
  }
6089
6319
  }
6090
6320
  console.log();
@@ -6094,7 +6324,7 @@ function indent(text, pad) {
6094
6324
  }
6095
6325
 
6096
6326
  // src/commands/recipe-install.ts
6097
- var import_chalk30 = __toESM(require("chalk"));
6327
+ var import_chalk31 = __toESM(require("chalk"));
6098
6328
  init_types();
6099
6329
  init_caller();
6100
6330
  init_api();
@@ -6111,7 +6341,7 @@ async function runRecipeInstall(nameArg, opts) {
6111
6341
  const chosenTeamId = picked.chosen ? picked.teamId : void 0;
6112
6342
  const teamName = picked.teamName;
6113
6343
  console.log();
6114
- console.log(`${import_chalk30.default.bold(pinned)}${import_chalk30.default.dim(` \u2014 by ${ref.handle}`)}`);
6344
+ console.log(`${import_chalk31.default.bold(pinned)}${import_chalk31.default.dim(` \u2014 by ${ref.handle}`)}`);
6115
6345
  if (recipe.summary) console.log(` ${recipe.summary}`);
6116
6346
  console.log();
6117
6347
  let project;
@@ -6135,7 +6365,7 @@ async function runRecipeInstall(nameArg, opts) {
6135
6365
  reuseTenant = chosenTenant.existing;
6136
6366
  printSummary(recipe, project, tenant2, reuseTenant);
6137
6367
  if (!assumeYes && !await confirmYesNo(" continue?", interactive)) {
6138
- console.log(import_chalk30.default.yellow(" Cancelled \u2014 nothing was created."));
6368
+ console.log(import_chalk31.default.yellow(" Cancelled \u2014 nothing was created."));
6139
6369
  return;
6140
6370
  }
6141
6371
  }
@@ -6154,18 +6384,18 @@ async function runRecipeInstall(nameArg, opts) {
6154
6384
  process.stdout.write(` ${step.label.padEnd(33)}`);
6155
6385
  try {
6156
6386
  const note = await step.run();
6157
- console.log(`${import_chalk30.default.green("\u2713")}${note ? ` ${import_chalk30.default.dim(note)}` : ""}`);
6387
+ console.log(`${import_chalk31.default.green("\u2713")}${note ? ` ${import_chalk31.default.dim(note)}` : ""}`);
6158
6388
  } catch (err) {
6159
- console.log(`${import_chalk30.default.red("\u2717")} ${import_chalk30.default.red(describeError(err))}`);
6389
+ console.log(`${import_chalk31.default.red("\u2717")} ${import_chalk31.default.red(describeError(err))}`);
6160
6390
  console.log();
6161
6391
  if (step.n === 1) {
6162
- console.log(import_chalk30.default.red(`stopped at step 1 of ${steps.length}. Nothing was created.`));
6392
+ console.log(import_chalk31.default.red(`stopped at step 1 of ${steps.length}. Nothing was created.`));
6163
6393
  console.log("run the same command again once the problem above is fixed:");
6164
- console.log(import_chalk30.default.cyan(` npx apiblaze install ${nameArg}`));
6394
+ console.log(import_chalk31.default.cyan(` npx apiblaze install ${nameArg}`));
6165
6395
  } else {
6166
- console.log(import_chalk30.default.red(`stopped at step ${step.n} of ${steps.length}. ${project} exists but is not finished.`));
6396
+ console.log(import_chalk31.default.red(`stopped at step ${step.n} of ${steps.length}. ${project} exists but is not finished.`));
6167
6397
  console.log("continue with:");
6168
- console.log(import_chalk30.default.cyan(` npx apiblaze install ${nameArg} --into ${project}`));
6398
+ console.log(import_chalk31.default.cyan(` npx apiblaze install ${nameArg} --into ${project}`));
6169
6399
  }
6170
6400
  console.log();
6171
6401
  process.exit(1);
@@ -6175,9 +6405,9 @@ async function runRecipeInstall(nameArg, opts) {
6175
6405
  const urls = installUrls(ctx);
6176
6406
  console.log();
6177
6407
  console.log(`done in ${secs}s.`);
6178
- console.log(` ${import_chalk30.default.dim("proxy ")} ${import_chalk30.default.bold(urls.proxy_url)}`);
6179
- if (recipe.settings.mcp_enabled === true) console.log(` ${import_chalk30.default.dim("mcp ")} ${import_chalk30.default.bold(urls.mcp_url)}`);
6180
- if (recipe.settings.enable_portal === true) console.log(` ${import_chalk30.default.dim("portal")} ${import_chalk30.default.bold(urls.portal_url)}`);
6408
+ console.log(` ${import_chalk31.default.dim("proxy ")} ${import_chalk31.default.bold(urls.proxy_url)}`);
6409
+ if (recipe.settings.mcp_enabled === true) console.log(` ${import_chalk31.default.dim("mcp ")} ${import_chalk31.default.bold(urls.mcp_url)}`);
6410
+ if (recipe.settings.enable_portal === true) console.log(` ${import_chalk31.default.dim("portal")} ${import_chalk31.default.bold(urls.portal_url)}`);
6181
6411
  console.log();
6182
6412
  }
6183
6413
  function buildSteps(inp) {
@@ -6493,7 +6723,7 @@ async function nameIsFree(name, teamId) {
6493
6723
  async function chooseProxyName(slug, asOpt, teamId, interactive) {
6494
6724
  if (asOpt !== void 0) {
6495
6725
  const name = normalizeName3(asOpt);
6496
- if (name !== asOpt) console.log(import_chalk30.default.yellow(` Using "${name}" \u2014 names are lowercase letters and digits only.`));
6726
+ if (name !== asOpt) console.log(import_chalk31.default.yellow(` Using "${name}" \u2014 names are lowercase letters and digits only.`));
6497
6727
  if (name.length < 3) throw new Error("A proxy name must be at least 3 characters (lowercase letters and digits only).");
6498
6728
  const free = await nameIsFree(name, teamId);
6499
6729
  if (free === false) throw new Error(`"${name}" is already taken. Pick another with --as.`);
@@ -6510,7 +6740,7 @@ async function chooseProxyName(slug, asOpt, teamId, interactive) {
6510
6740
  }
6511
6741
  if (!interactive) return suggested;
6512
6742
  const { default: inquirer3 } = await import("inquirer");
6513
- console.log(` ${import_chalk30.default.dim("proxy")} ${slug} \u2192 ${import_chalk30.default.bold(suggested)} ${import_chalk30.default.dim("[enter to accept, or type a name]")}`);
6743
+ console.log(` ${import_chalk31.default.dim("proxy")} ${slug} \u2192 ${import_chalk31.default.bold(suggested)} ${import_chalk31.default.dim("[enter to accept, or type a name]")}`);
6514
6744
  for (; ; ) {
6515
6745
  const { raw } = await inquirer3.prompt([{
6516
6746
  type: "input",
@@ -6521,20 +6751,20 @@ async function chooseProxyName(slug, asOpt, teamId, interactive) {
6521
6751
  }]);
6522
6752
  const name = normalizeName3(raw);
6523
6753
  if (name !== String(raw).trim()) {
6524
- console.log(import_chalk30.default.yellow(` \u2192 using ${import_chalk30.default.bold(name)} (lowercase letters and digits only)`));
6754
+ console.log(import_chalk31.default.yellow(` \u2192 using ${import_chalk31.default.bold(name)} (lowercase letters and digits only)`));
6525
6755
  }
6526
6756
  if (name.length < 3) {
6527
- console.log(import_chalk30.default.yellow(" Name must be at least 3 characters.\n"));
6757
+ console.log(import_chalk31.default.yellow(" Name must be at least 3 characters.\n"));
6528
6758
  continue;
6529
6759
  }
6530
6760
  const free = await nameIsFree(name, teamId);
6531
6761
  if (free === false) {
6532
- console.log(import_chalk30.default.yellow(` "${name}" is taken. Try another.
6762
+ console.log(import_chalk31.default.yellow(` "${name}" is taken. Try another.
6533
6763
  `));
6534
6764
  continue;
6535
6765
  }
6536
- if (free === null) console.log(import_chalk30.default.dim(" (could not verify availability; continuing)"));
6537
- console.log(` ${import_chalk30.default.cyan("\u2192")} ${import_chalk30.default.bold(`https://${name}.abz.run`)}`);
6766
+ if (free === null) console.log(import_chalk31.default.dim(" (could not verify availability; continuing)"));
6767
+ console.log(` ${import_chalk31.default.cyan("\u2192")} ${import_chalk31.default.bold(`https://${name}.abz.run`)}`);
6538
6768
  return name;
6539
6769
  }
6540
6770
  }
@@ -6552,20 +6782,20 @@ function printSummary(recipe, project, tenant2, reuseTenant = false) {
6552
6782
  const keyTypes = recipe.auth?.key_types?.length ?? 0;
6553
6783
  const questions = reuseTenant ? 0 : recipe.questions?.length ?? 0;
6554
6784
  const row = (label3, value, note) => {
6555
- console.log(` ${import_chalk30.default.dim(label3.padEnd(21))}${value}${note ? import_chalk30.default.dim(` ${note}`) : ""}`);
6785
+ console.log(` ${import_chalk31.default.dim(label3.padEnd(21))}${value}${note ? import_chalk31.default.dim(` ${note}`) : ""}`);
6556
6786
  };
6557
6787
  console.log();
6558
- console.log(import_chalk30.default.bold(" This will:"));
6788
+ console.log(import_chalk31.default.bold(" This will:"));
6559
6789
  console.log();
6560
- row("create a proxy", import_chalk30.default.bold(project), `at https://${project}.abz.run`);
6561
- row("for its users", import_chalk30.default.bold(tenant2), reuseTenant ? "(one you already have)" : "(a new tenant)");
6790
+ row("create a proxy", import_chalk31.default.bold(project), `at https://${project}.abz.run`);
6791
+ row("for its users", import_chalk31.default.bold(tenant2), reuseTenant ? "(one you already have)" : "(a new tenant)");
6562
6792
  if (hosts.length) row("sending requests to", hosts.join(", "));
6563
6793
  row("and set up", describeCreates(keyTypes, routes, recipe.settings.mcp_enabled === true, false));
6564
6794
  row("asking you for", questions ? `${questions} value${questions === 1 ? "" : "s"}` : "nothing");
6565
6795
  if (reuseTenant) {
6566
6796
  console.log();
6567
- console.log(import_chalk30.default.dim(` ${tenant2} is used exactly as it is \u2014 its existing login stays, and this`));
6568
- console.log(import_chalk30.default.dim(" recipe's own login setup is not applied."));
6797
+ console.log(import_chalk31.default.dim(` ${tenant2} is used exactly as it is \u2014 its existing login stays, and this`));
6798
+ console.log(import_chalk31.default.dim(" recipe's own login setup is not applied."));
6569
6799
  }
6570
6800
  console.log();
6571
6801
  }
@@ -6574,11 +6804,11 @@ function declineAll(items) {
6574
6804
  const upstreams = items.filter((i) => i.kind === "upstream");
6575
6805
  console.log();
6576
6806
  for (const u of upstreams) {
6577
- console.log(import_chalk30.default.yellow(` --yes: this proxy sends every request to ${import_chalk30.default.bold(u.value)}.`));
6807
+ console.log(import_chalk31.default.yellow(` --yes: this proxy sends every request to ${import_chalk31.default.bold(u.value)}.`));
6578
6808
  }
6579
6809
  if (skippable.length) {
6580
- console.log(import_chalk30.default.yellow(` --yes: installing without ${skippable.length} setting${skippable.length === 1 ? "" : "s"} that need consent.`));
6581
- for (const i of skippable) console.log(import_chalk30.default.dim(` skipped ${i.kind} ${i.value}`));
6810
+ console.log(import_chalk31.default.yellow(` --yes: installing without ${skippable.length} setting${skippable.length === 1 ? "" : "s"} that need consent.`));
6811
+ for (const i of skippable) console.log(import_chalk31.default.dim(` skipped ${i.kind} ${i.value}`));
6582
6812
  }
6583
6813
  return new Set(skippable.map((i) => i.kind));
6584
6814
  }
@@ -6596,14 +6826,14 @@ async function askConsent(items, interactive) {
6596
6826
  const count = items.length;
6597
6827
  const word = ["", "it", "both", "all three", "all four", "all five", "all six"][count] ?? `all ${count}`;
6598
6828
  console.log();
6599
- console.log(import_chalk30.default.yellow("\u26A0 This recipe changes who can reach your proxy, what it trusts, and what it can cost."));
6829
+ console.log(import_chalk31.default.yellow("\u26A0 This recipe changes who can reach your proxy, what it trusts, and what it can cost."));
6600
6830
  console.log();
6601
6831
  for (const item of items) {
6602
- console.log(` ${import_chalk30.default.bold(item.kind.padEnd(16))} ${item.value}`);
6603
- for (const line of wrapText(item.why, 62)) console.log(` ${" ".repeat(16)} ${import_chalk30.default.dim(line)}`);
6832
+ console.log(` ${import_chalk31.default.bold(item.kind.padEnd(16))} ${item.value}`);
6833
+ for (const line of wrapText(item.why, 62)) console.log(` ${" ".repeat(16)} ${import_chalk31.default.dim(line)}`);
6604
6834
  }
6605
6835
  console.log();
6606
- console.log(`Type "${import_chalk30.default.bold("yes")}" to accept ${word}.`);
6836
+ console.log(`Type "${import_chalk31.default.bold("yes")}" to accept ${word}.`);
6607
6837
  console.log("Press enter to install the recipe without them.");
6608
6838
  let typed = "";
6609
6839
  if (interactive) {
@@ -6615,7 +6845,7 @@ async function askConsent(items, interactive) {
6615
6845
  for (const item of items) {
6616
6846
  declined.add(item.kind === "transform" ? `transform:${item.value}` : `kind:${item.kind}`);
6617
6847
  }
6618
- console.log(import_chalk30.default.dim(` Installing without ${count} setting${count === 1 ? "" : "s"} \u2014 everything else is applied.`));
6848
+ console.log(import_chalk31.default.dim(` Installing without ${count} setting${count === 1 ? "" : "s"} \u2014 everything else is applied.`));
6619
6849
  return declined;
6620
6850
  }
6621
6851
  async function askQuestions(questions, ctx, interactive) {
@@ -6628,13 +6858,13 @@ async function askQuestions(questions, ctx, interactive) {
6628
6858
  const BOX = 64;
6629
6859
  const title = "\u2500\u2500 from the publisher ";
6630
6860
  console.log();
6631
- console.log(` ${import_chalk30.default.dim(title + "\u2500".repeat(BOX - title.length))}`);
6632
- for (const line of fillContext(q.before, ctx).split("\n")) console.log(` ${import_chalk30.default.dim("\u2502")} ${line}`);
6633
- console.log(` ${import_chalk30.default.dim("\u2500".repeat(BOX))}`);
6861
+ console.log(` ${import_chalk31.default.dim(title + "\u2500".repeat(BOX - title.length))}`);
6862
+ for (const line of fillContext(q.before, ctx).split("\n")) console.log(` ${import_chalk31.default.dim("\u2502")} ${line}`);
6863
+ console.log(` ${import_chalk31.default.dim("\u2500".repeat(BOX))}`);
6634
6864
  }
6635
6865
  if (fromEnv !== void 0 && fromEnv !== "") {
6636
6866
  answers[q.id] = fromEnv;
6637
- console.log(` ${q.prompt}: ${import_chalk30.default.dim(`(from ${envName})`)}`);
6867
+ console.log(` ${q.prompt}: ${import_chalk31.default.dim(`(from ${envName})`)}`);
6638
6868
  continue;
6639
6869
  }
6640
6870
  if (!interactive) {
@@ -6644,7 +6874,7 @@ async function askQuestions(questions, ctx, interactive) {
6644
6874
  );
6645
6875
  }
6646
6876
  const { default: inquirer3 } = await import("inquirer");
6647
- if (q.example && !q.secret) console.log(import_chalk30.default.dim(` e.g. ${q.example}`));
6877
+ if (q.example && !q.secret) console.log(import_chalk31.default.dim(` e.g. ${q.example}`));
6648
6878
  const { value } = await inquirer3.prompt([{
6649
6879
  // `secret: true` masks the input — the Google client secret is typed once,
6650
6880
  // goes to provider creation, and is never echoed or stored.
@@ -6678,30 +6908,30 @@ async function confirmReinstall(recipe, project, tenant2, interactive) {
6678
6908
  const tables = recipe.transformations?.mapping_tables?.length ?? 0;
6679
6909
  const routes = countRoutes(recipe.openapi);
6680
6910
  const keyTypes = recipe.auth?.key_types?.length ?? 0;
6681
- console.log(`This installs ${import_chalk30.default.bold(`${recipe.name}@${recipe.revision}`)} over ${import_chalk30.default.bold(project)}.`);
6911
+ console.log(`This installs ${import_chalk31.default.bold(`${recipe.name}@${recipe.revision}`)} over ${import_chalk31.default.bold(project)}.`);
6682
6912
  console.log();
6683
- console.log(` ${import_chalk30.default.dim("settings ".padEnd(16))}replaced`);
6913
+ console.log(` ${import_chalk31.default.dim("settings ".padEnd(16))}replaced`);
6684
6914
  if (rules || tables) {
6685
- console.log(` ${import_chalk30.default.dim("transforms".padEnd(16))}${rules} rule${rules === 1 ? "" : "s"}${tables ? ` and ${tables} mapping table${tables === 1 ? "" : "s"}` : ""} replaced \u2014 your edits to them are lost`);
6915
+ console.log(` ${import_chalk31.default.dim("transforms".padEnd(16))}${rules} rule${rules === 1 ? "" : "s"}${tables ? ` and ${tables} mapping table${tables === 1 ? "" : "s"}` : ""} replaced \u2014 your edits to them are lost`);
6686
6916
  }
6687
6917
  if (routes) {
6688
- console.log(` ${import_chalk30.default.dim("api spec ".padEnd(16))}replaced, ${routes} routes regenerated${recipe.settings.mcp_enabled === true ? ", MCP rebuilt" : ""}`);
6918
+ console.log(` ${import_chalk31.default.dim("api spec ".padEnd(16))}replaced, ${routes} routes regenerated${recipe.settings.mcp_enabled === true ? ", MCP rebuilt" : ""}`);
6689
6919
  }
6690
6920
  if (keyTypes) {
6691
- console.log(` ${import_chalk30.default.dim("key types ".padEnd(16))}${keyTypes} added if missing; existing types left alone`);
6921
+ console.log(` ${import_chalk31.default.dim("key types ".padEnd(16))}${keyTypes} added if missing; existing types left alone`);
6692
6922
  }
6693
6923
  console.log();
6694
- console.log(` ${import_chalk30.default.dim("unchanged ".padEnd(16))}your API keys, your proxy URL, your users,`);
6924
+ console.log(` ${import_chalk31.default.dim("unchanged ".padEnd(16))}your API keys, your proxy URL, your users,`);
6695
6925
  console.log(` ${" ".repeat(16)}and any tenant other than ${tenant2}`);
6696
6926
  console.log();
6697
- console.log(import_chalk30.default.yellow("This cannot be undone."));
6927
+ console.log(import_chalk31.default.yellow("This cannot be undone."));
6698
6928
  if (!interactive) {
6699
6929
  throw new Error("Reinstall needs a typed confirmation and there is no terminal to ask on.");
6700
6930
  }
6701
6931
  const { default: inquirer3 } = await import("inquirer");
6702
6932
  const { typed } = await inquirer3.prompt([{ type: "input", name: "typed", message: `Type the proxy name (${project}) to continue:` }]);
6703
6933
  if (String(typed ?? "").trim() !== project) {
6704
- console.log(import_chalk30.default.yellow("Cancelled \u2014 nothing was changed."));
6934
+ console.log(import_chalk31.default.yellow("Cancelled \u2014 nothing was changed."));
6705
6935
  process.exit(0);
6706
6936
  }
6707
6937
  }
@@ -6709,7 +6939,7 @@ function requireCallerForInstall() {
6709
6939
  try {
6710
6940
  return requireCaller();
6711
6941
  } catch {
6712
- console.error(import_chalk30.default.red(
6942
+ console.error(import_chalk31.default.red(
6713
6943
  "Installing writes a proxy into an account, so it needs a credential.\n Run `apiblaze login`, or `apiblaze create` first (an anonymous workspace works too)."
6714
6944
  ));
6715
6945
  process.exit(1);
@@ -6745,7 +6975,7 @@ async function chooseTeam(caller, optTeam, interactive) {
6745
6975
  message: " which team should own this proxy?",
6746
6976
  default: active.teamId,
6747
6977
  choices: teams.map((t) => ({
6748
- name: t.teamId === active.teamId ? `${t.name} ${import_chalk30.default.dim("(active)")}` : t.name,
6978
+ name: t.teamId === active.teamId ? `${t.name} ${import_chalk31.default.dim("(active)")}` : t.name,
6749
6979
  value: t.teamId
6750
6980
  }))
6751
6981
  }]);
@@ -6773,10 +7003,10 @@ async function chooseTenant(caller, project, teamId, optTenant, interactive) {
6773
7003
  message: " where should this proxy's users live?",
6774
7004
  default: "__new__",
6775
7005
  choices: [
6776
- { name: `create ${fresh} ${import_chalk30.default.dim("(a fresh tenant, set up by the recipe)")}`, value: "__new__" },
6777
- new inquirer3.Separator(import_chalk30.default.dim(" \u2014 or reuse one you already have \u2014")),
7006
+ { name: `create ${fresh} ${import_chalk31.default.dim("(a fresh tenant, set up by the recipe)")}`, value: "__new__" },
7007
+ new inquirer3.Separator(import_chalk31.default.dim(" \u2014 or reuse one you already have \u2014")),
6778
7008
  ...owned.map((t2) => ({
6779
- name: `${t2} ${import_chalk30.default.dim("(existing \u2014 its own login is kept)")}`,
7009
+ name: `${t2} ${import_chalk31.default.dim("(existing \u2014 its own login is kept)")}`,
6780
7010
  value: t2
6781
7011
  }))
6782
7012
  ]
@@ -6803,7 +7033,7 @@ async function teamTenants(caller, teamId) {
6803
7033
  }
6804
7034
 
6805
7035
  // src/commands/recipe-publish.ts
6806
- var import_chalk31 = __toESM(require("chalk"));
7036
+ var import_chalk32 = __toESM(require("chalk"));
6807
7037
  var import_ora11 = __toESM(require("ora"));
6808
7038
  init_caller();
6809
7039
  init_auth();
@@ -6813,15 +7043,15 @@ async function runRecipePublish(projectArg, opts) {
6813
7043
  try {
6814
7044
  resolved = resolveRecipeName(opts.as, creds?.githubHandle, normalizeName3(projectArg));
6815
7045
  } catch (err) {
6816
- console.error(import_chalk31.default.red(err instanceof Error ? err.message : String(err)));
7046
+ console.error(import_chalk32.default.red(err instanceof Error ? err.message : String(err)));
6817
7047
  process.exitCode = 1;
6818
7048
  return;
6819
7049
  }
6820
7050
  const ref = resolved.ref;
6821
7051
  if (resolved.derivedHandle) {
6822
- console.log(import_chalk31.default.dim(` publishing as ${import_chalk31.default.bold(ref.name)}`));
7052
+ console.log(import_chalk32.default.dim(` publishing as ${import_chalk32.default.bold(ref.name)}`));
6823
7053
  if (resolved.normalizedFrom) {
6824
- console.log(import_chalk31.default.dim(` (your GitHub login is ${resolved.normalizedFrom}; apiblaze names are letters and digits only)`));
7054
+ console.log(import_chalk32.default.dim(` (your GitHub login is ${resolved.normalizedFrom}; apiblaze names are letters and digits only)`));
6825
7055
  }
6826
7056
  }
6827
7057
  const interactive = !!process.stdin.isTTY && !opts.json;
@@ -6840,7 +7070,7 @@ async function runRecipePublish(projectArg, opts) {
6840
7070
  let tenant2 = opts.tenant;
6841
7071
  if (!prep.tenant_used && prep.tenants.length > 1) {
6842
7072
  if (!interactive) {
6843
- console.error(import_chalk31.default.red(
7073
+ console.error(import_chalk32.default.red(
6844
7074
  `${proj2.projectId} has ${prep.tenants.length} tenants (${prep.tenants.join(", ")}). Pass --tenant <slug> to say which auth setup the recipe carries.`
6845
7075
  ));
6846
7076
  process.exit(1);
@@ -6856,7 +7086,7 @@ async function runRecipePublish(projectArg, opts) {
6856
7086
  prep = await prepare(caller, proj2.projectId, proj2.apiVersion, ref.name, tenant2);
6857
7087
  }
6858
7088
  if (!prep.name_available) {
6859
- console.error(import_chalk31.default.red(`${ref.name} belongs to another team, so you cannot publish a revision of it.`));
7089
+ console.error(import_chalk32.default.red(`${ref.name} belongs to another team, so you cannot publish a revision of it.`));
6860
7090
  process.exit(1);
6861
7091
  }
6862
7092
  if (prep.envelope_violations.length) {
@@ -6866,13 +7096,13 @@ async function runRecipePublish(projectArg, opts) {
6866
7096
  if (prep.dropped.length) {
6867
7097
  console.log();
6868
7098
  console.log(`${prep.dropped.length} setting${prep.dropped.length === 1 ? " was" : "s were"} not included, because they are not on the publish list:`);
6869
- for (const d of prep.dropped) console.log(import_chalk31.default.dim(` ${d}`));
7099
+ for (const d of prep.dropped) console.log(import_chalk32.default.dim(` ${d}`));
6870
7100
  if (prep.hidden_tables_excluded) {
6871
- console.log(import_chalk31.default.dim(` (${prep.hidden_tables_excluded} hidden mapping table${prep.hidden_tables_excluded === 1 ? "" : "s"} excluded \u2014 those values belong to your consumers.)`));
7101
+ console.log(import_chalk32.default.dim(` (${prep.hidden_tables_excluded} hidden mapping table${prep.hidden_tables_excluded === 1 ? "" : "s"} excluded \u2014 those values belong to your consumers.)`));
6872
7102
  }
6873
7103
  console.log();
6874
7104
  if (!opts.yes && !await confirm(" continue without them?", interactive)) {
6875
- console.log(import_chalk31.default.yellow("Cancelled."));
7105
+ console.log(import_chalk32.default.yellow("Cancelled."));
6876
7106
  return;
6877
7107
  }
6878
7108
  }
@@ -6885,12 +7115,12 @@ async function runRecipePublish(projectArg, opts) {
6885
7115
  console.log();
6886
7116
  for (const f of prep.findings) printFinding(f);
6887
7117
  console.log();
6888
- console.error(import_chalk31.default.red("--yes cannot accept scanner findings. Fix the value in the proxy, or publish interactively and decide."));
7118
+ console.error(import_chalk32.default.red("--yes cannot accept scanner findings. Fix the value in the proxy, or publish interactively and decide."));
6889
7119
  process.exit(1);
6890
7120
  }
6891
7121
  if (!interactive) {
6892
7122
  for (const f of prep.findings) printFinding(f);
6893
- console.error(import_chalk31.default.red("\nThese need a decision and there is no terminal to ask on."));
7123
+ console.error(import_chalk32.default.red("\nThese need a decision and there is no terminal to ask on."));
6894
7124
  process.exit(1);
6895
7125
  }
6896
7126
  const { default: inquirer3 } = await import("inquirer");
@@ -6911,10 +7141,10 @@ async function runRecipePublish(projectArg, opts) {
6911
7141
  if (verdict === "ask") promotions.push(await askPromotion(f.path));
6912
7142
  }
6913
7143
  }
6914
- console.log(import_chalk31.default.dim(`we cannot judge the other ${prep.unjudged_count} values. run \`apiblaze show ${ref.name}\` after publishing to read the whole recipe.`));
7144
+ console.log(import_chalk32.default.dim(`we cannot judge the other ${prep.unjudged_count} values. run \`apiblaze show ${ref.name}\` after publishing to read the whole recipe.`));
6915
7145
  const totalQuestions = prep.question_ids.length + promotions.length;
6916
7146
  if (totalQuestions > 5) {
6917
- console.log(import_chalk31.default.yellow(`
7147
+ console.log(import_chalk32.default.yellow(`
6918
7148
  \u26A0 installers will have to supply ${totalQuestions} values before this works.`));
6919
7149
  }
6920
7150
  const visibility = opts.private ? "private" : "public";
@@ -6922,11 +7152,11 @@ async function runRecipePublish(projectArg, opts) {
6922
7152
  if (visibility === "public" && prep.spec_will_become_public) {
6923
7153
  console.log();
6924
7154
  console.log("Publishing publicly also makes this API's spec readable at");
6925
- console.log(` ${import_chalk31.default.bold(`https://${proj2.projectId}.abz.run/${proj2.apiVersion}/openapi.json`)}`);
7155
+ console.log(` ${import_chalk32.default.bold(`https://${proj2.projectId}.abz.run/${proj2.apiVersion}/openapi.json`)}`);
6926
7156
  console.log("It is currently private.");
6927
7157
  confirmSpecPublic = opts.yes ? true : await confirm("Continue?", interactive);
6928
7158
  if (!confirmSpecPublic) {
6929
- console.log(import_chalk31.default.yellow("Cancelled \u2014 nothing was published."));
7159
+ console.log(import_chalk32.default.yellow("Cancelled \u2014 nothing was published."));
6930
7160
  return;
6931
7161
  }
6932
7162
  }
@@ -6952,7 +7182,7 @@ async function runRecipePublish(projectArg, opts) {
6952
7182
  },
6953
7183
  summary: `Publish ${proj2.projectId} as ${ref.name} (${visibility})`
6954
7184
  });
6955
- spin2?.succeed(`Published ${import_chalk31.default.bold(`${out.name}@${out.revision}`)} (${out.visibility}).`);
7185
+ spin2?.succeed(`Published ${import_chalk32.default.bold(`${out.name}@${out.revision}`)} (${out.visibility}).`);
6956
7186
  } catch (err) {
6957
7187
  spin2?.fail("Publish failed.");
6958
7188
  throw err;
@@ -6961,15 +7191,15 @@ async function runRecipePublish(projectArg, opts) {
6961
7191
  console.log(JSON.stringify(out));
6962
7192
  return;
6963
7193
  }
6964
- console.log(` ${import_chalk31.default.dim("size ")} ${(out.size_bytes / 1024).toFixed(1)} KB`);
6965
- console.log(` ${import_chalk31.default.dim("checksum")} ${out.sha256.slice(0, 16)}\u2026`);
7194
+ console.log(` ${import_chalk32.default.dim("size ")} ${(out.size_bytes / 1024).toFixed(1)} KB`);
7195
+ console.log(` ${import_chalk32.default.dim("checksum")} ${out.sha256.slice(0, 16)}\u2026`);
6966
7196
  console.log();
6967
7197
  if (out.visibility === "public") {
6968
- console.log(import_chalk31.default.dim(` Anyone can now run: ${import_chalk31.default.cyan(`npx apiblaze install ${out.name}`)}`));
7198
+ console.log(import_chalk32.default.dim(` Anyone can now run: ${import_chalk32.default.cyan(`npx apiblaze install ${out.name}`)}`));
6969
7199
  } else {
6970
- console.log(import_chalk31.default.dim(" Private \u2014 only members of this team can see or install it."));
7200
+ console.log(import_chalk32.default.dim(" Private \u2014 only members of this team can see or install it."));
6971
7201
  }
6972
- console.log(import_chalk31.default.dim(` Pull it back with: ${import_chalk31.default.cyan(`npx apiblaze withdraw ${out.name}@${out.revision}`)}`));
7202
+ console.log(import_chalk32.default.dim(` Pull it back with: ${import_chalk32.default.cyan(`npx apiblaze withdraw ${out.name}@${out.revision}`)}`));
6973
7203
  console.log();
6974
7204
  }
6975
7205
  async function prepare(caller, projectId, apiVersion, name, tenant2) {
@@ -6982,23 +7212,23 @@ async function prepare(caller, projectId, apiVersion, name, tenant2) {
6982
7212
  }
6983
7213
  function printFinding(f) {
6984
7214
  const preview = (f.preview ?? "").replace(/\s+/g, " ").trim();
6985
- console.log(` ${import_chalk31.default.bold(f.path)}`);
6986
- console.log(` ${import_chalk31.default.yellow(preview.padEnd(38))}${import_chalk31.default.dim(f.why)}`);
7215
+ console.log(` ${import_chalk32.default.bold(f.path)}`);
7216
+ console.log(` ${import_chalk32.default.yellow(preview.padEnd(38))}${import_chalk32.default.dim(f.why)}`);
6987
7217
  }
6988
7218
  function printEnvelopeViolations(violations) {
6989
7219
  console.log();
6990
- console.error(import_chalk31.default.red("This proxy has transform rules a recipe cannot carry."));
7220
+ console.error(import_chalk32.default.red("This proxy has transform rules a recipe cannot carry."));
6991
7221
  console.log();
6992
7222
  for (const v of violations) {
6993
- console.log(` ${import_chalk31.default.bold(v.rule)} ${import_chalk31.default.dim(`(${v.kind}s ${v.field})`)}`);
7223
+ console.log(` ${import_chalk32.default.bold(v.rule)} ${import_chalk32.default.dim(`(${v.kind}s ${v.field})`)}`);
6994
7224
  console.log(` ${v.why}`);
6995
7225
  }
6996
7226
  console.log();
6997
7227
  console.log("A recipe runs in a stranger's account, after apiblaze has attached their end user's");
6998
7228
  console.log("real third-party token, so two rules are absolute:");
6999
- console.log(` ${import_chalk31.default.dim("\u2022")} a rule may never READ Authorization, Cookie, or the third-party token headers \u2014`);
7229
+ console.log(` ${import_chalk32.default.dim("\u2022")} a rule may never READ Authorization, Cookie, or the third-party token headers \u2014`);
7000
7230
  console.log(" those hold a live credential that works at the provider without apiblaze;");
7001
- console.log(` ${import_chalk31.default.dim("\u2022")} a rule may never WRITE an identity header (x-end-user-id and friends) \u2014`);
7231
+ console.log(` ${import_chalk32.default.dim("\u2022")} a rule may never WRITE an identity header (x-end-user-id and friends) \u2014`);
7002
7232
  console.log(" those tell the installer's own backend who is calling.");
7003
7233
  console.log();
7004
7234
  console.log("Writing Authorization from a question or a fixed value is fine \u2014 that is the");
@@ -7016,7 +7246,7 @@ async function askPromotion(path9) {
7016
7246
  { type: "input", name: "id", message: " id:", default: suggestedId }
7017
7247
  ]);
7018
7248
  const id = String(answers.id || suggestedId).toLowerCase().replace(/[^a-z0-9_]/g, "_");
7019
- console.log(import_chalk31.default.dim(` \u2192 replaced with {{${id}}}`));
7249
+ console.log(import_chalk32.default.dim(` \u2192 replaced with {{${id}}}`));
7020
7250
  return {
7021
7251
  path: path9,
7022
7252
  id,
@@ -7035,7 +7265,7 @@ async function confirm(message, interactive) {
7035
7265
  async function runRecipeWithdraw(nameArg, opts) {
7036
7266
  const ref = parseRecipeRef(nameArg);
7037
7267
  if (ref.revision === void 0) {
7038
- console.error(import_chalk31.default.red(`Name the revision to withdraw, e.g. ${nameArg}@3. Revisions are withdrawn one at a time.`));
7268
+ console.error(import_chalk32.default.red(`Name the revision to withdraw, e.g. ${nameArg}@3. Revisions are withdrawn one at a time.`));
7039
7269
  process.exit(1);
7040
7270
  }
7041
7271
  const interactive = !!process.stdin.isTTY && !opts.json;
@@ -7055,11 +7285,11 @@ async function runRecipeWithdraw(nameArg, opts) {
7055
7285
  const { default: inquirer3 } = await import("inquirer");
7056
7286
  const { typed } = await inquirer3.prompt([{ type: "input", name: "typed", message: `type the recipe name to confirm (${ref.name}):` }]);
7057
7287
  if (String(typed ?? "").trim() !== ref.name) {
7058
- console.log(import_chalk31.default.yellow("Cancelled \u2014 nothing was withdrawn."));
7288
+ console.log(import_chalk32.default.yellow("Cancelled \u2014 nothing was withdrawn."));
7059
7289
  return;
7060
7290
  }
7061
7291
  } else {
7062
- console.error(import_chalk31.default.red("Withdrawing needs a typed confirmation and there is no terminal to ask on."));
7292
+ console.error(import_chalk32.default.red("Withdrawing needs a typed confirmation and there is no terminal to ask on."));
7063
7293
  process.exit(1);
7064
7294
  }
7065
7295
  const spinner = !opts.json ? (0, import_ora11.default)("Withdrawing...").start() : null;
@@ -7088,33 +7318,33 @@ async function runRecipeWithdraw(nameArg, opts) {
7088
7318
  }
7089
7319
 
7090
7320
  // src/commands/logs.ts
7091
- var import_chalk33 = __toESM(require("chalk"));
7321
+ var import_chalk34 = __toESM(require("chalk"));
7092
7322
  init_admin();
7093
7323
  init_auth();
7094
7324
  init_resolve();
7095
7325
 
7096
7326
  // src/lib/log-view.ts
7097
- var import_chalk32 = __toESM(require("chalk"));
7327
+ var import_chalk33 = __toESM(require("chalk"));
7098
7328
  var readline2 = __toESM(require("readline"));
7099
7329
  function statusColor(status) {
7100
- if (status < 300) return import_chalk32.default.green;
7101
- if (status < 400) return import_chalk32.default.blue;
7102
- if (status < 500) return import_chalk32.default.yellow;
7103
- return import_chalk32.default.red;
7330
+ if (status < 300) return import_chalk33.default.green;
7331
+ if (status < 400) return import_chalk33.default.blue;
7332
+ if (status < 500) return import_chalk33.default.yellow;
7333
+ return import_chalk33.default.red;
7104
7334
  }
7105
7335
  function methodColor(method) {
7106
7336
  switch ((method || "").toUpperCase()) {
7107
7337
  case "GET":
7108
- return import_chalk32.default.green;
7338
+ return import_chalk33.default.green;
7109
7339
  case "POST":
7110
- return import_chalk32.default.blue;
7340
+ return import_chalk33.default.blue;
7111
7341
  case "PUT":
7112
7342
  case "PATCH":
7113
- return import_chalk32.default.yellow;
7343
+ return import_chalk33.default.yellow;
7114
7344
  case "DELETE":
7115
- return import_chalk32.default.red;
7345
+ return import_chalk33.default.red;
7116
7346
  default:
7117
- return import_chalk32.default.white;
7347
+ return import_chalk33.default.white;
7118
7348
  }
7119
7349
  }
7120
7350
  function clock(ts) {
@@ -7126,12 +7356,12 @@ function routeCell(route) {
7126
7356
  return (r.length > ROUTE_W ? `\u2026${r.slice(-(ROUTE_W - 1))}` : r).padEnd(ROUTE_W);
7127
7357
  }
7128
7358
  function formatRow(r) {
7129
- const time = import_chalk32.default.dim(clock(r.ts));
7359
+ const time = import_chalk33.default.dim(clock(r.ts));
7130
7360
  const method = methodColor(r.method)(String(r.method || "\u2014").padEnd(6));
7131
7361
  const route = routeCell(String(r.route || "\u2014"));
7132
7362
  const status = statusColor(r.status)(String(r.status ?? "\u2014").padStart(3));
7133
- const ms = import_chalk32.default.dim(`${r.duration_ms}ms`.padStart(8));
7134
- const step = r.error_step ? import_chalk32.default.dim(` ${r.error_step}`) : "";
7363
+ const ms = import_chalk33.default.dim(`${r.duration_ms}ms`.padStart(8));
7364
+ const step = r.error_step ? import_chalk33.default.dim(` ${r.error_step}`) : "";
7135
7365
  return `${time} ${method} ${route} ${status} ${ms}${step}`;
7136
7366
  }
7137
7367
  function printRow(r, json) {
@@ -7146,15 +7376,15 @@ var WindowNotices = class {
7146
7376
  note(res) {
7147
7377
  if (res.history_unavailable && !this.saidUnavailable) {
7148
7378
  this.saidUnavailable = true;
7149
- console.error(import_chalk32.default.yellow("\u26A0 log history is unreachable right now \u2014 showing the live buffer only, older requests exist but cannot be read."));
7379
+ console.error(import_chalk33.default.yellow("\u26A0 log history is unreachable right now \u2014 showing the live buffer only, older requests exist but cannot be read."));
7150
7380
  }
7151
7381
  if ((res.history_markers?.length ?? 0) > 0 && !this.saidGap) {
7152
7382
  this.saidGap = true;
7153
- console.error(import_chalk32.default.yellow("\u26A0 this range includes a volume-ceiling gap \u2014 some rows were dropped at intake and are gone; counts are incomplete."));
7383
+ console.error(import_chalk33.default.yellow("\u26A0 this range includes a volume-ceiling gap \u2014 some rows were dropped at intake and are gone; counts are incomplete."));
7154
7384
  }
7155
7385
  if ((res.dropped_this_hour ?? 0) > 0 && !this.saidDropped) {
7156
7386
  this.saidDropped = true;
7157
- console.error(import_chalk32.default.yellow(`\u26A0 volume ceiling \u2014 ${res.dropped_this_hour} rows dropped this hour; errors keep logging.`));
7387
+ console.error(import_chalk33.default.yellow(`\u26A0 volume ceiling \u2014 ${res.dropped_this_hour} rows dropped this hour; errors keep logging.`));
7158
7388
  }
7159
7389
  }
7160
7390
  };
@@ -7213,13 +7443,13 @@ async function runTailSession(opts) {
7213
7443
  if (!held.length && !heldRowsDropped && !heldNotesDropped) return;
7214
7444
  const rows = held.filter((h) => h.kind === "row").length;
7215
7445
  const total = rows + heldRowsDropped;
7216
- if (total) console.log(import_chalk32.default.dim(`\u2500\u2500\u2500 ${total} request${total === 1 ? "" : "s"} arrived while paused \u2500\u2500\u2500`));
7446
+ if (total) console.log(import_chalk33.default.dim(`\u2500\u2500\u2500 ${total} request${total === 1 ? "" : "s"} arrived while paused \u2500\u2500\u2500`));
7217
7447
  for (const h of held) {
7218
7448
  if (h.kind === "row") printRow(h.row, opts.json);
7219
7449
  else console.error(h.msg);
7220
7450
  }
7221
7451
  if (heldRowsDropped || heldNotesDropped) {
7222
- console.log(import_chalk32.default.dim(`\u2500\u2500\u2500 ${heldRowsDropped} older one${heldRowsDropped === 1 ? "" : "s"} not shown (pause buffer full) \u2014 browse them with \`logs list\` \u2500\u2500\u2500`));
7452
+ console.log(import_chalk33.default.dim(`\u2500\u2500\u2500 ${heldRowsDropped} older one${heldRowsDropped === 1 ? "" : "s"} not shown (pause buffer full) \u2014 browse them with \`logs list\` \u2500\u2500\u2500`));
7223
7453
  }
7224
7454
  held.length = 0;
7225
7455
  heldRowsDropped = 0;
@@ -7233,7 +7463,7 @@ async function runTailSession(opts) {
7233
7463
  activeSocket?.close();
7234
7464
  } catch {
7235
7465
  }
7236
- if (!opts.json) console.log(import_chalk32.default.dim("\nStopped."));
7466
+ if (!opts.json) console.log(import_chalk33.default.dim("\nStopped."));
7237
7467
  process.exit(0);
7238
7468
  }
7239
7469
  function onKeypress(_s, key) {
@@ -7261,17 +7491,17 @@ async function runTailSession(opts) {
7261
7491
  async function openInspector() {
7262
7492
  if (paused) return;
7263
7493
  if (recent.length === 0) {
7264
- console.log(import_chalk32.default.dim(" nothing captured yet \u2014 waiting for a request\u2026"));
7494
+ console.log(import_chalk33.default.dim(" nothing captured yet \u2014 waiting for a request\u2026"));
7265
7495
  return;
7266
7496
  }
7267
7497
  paused = true;
7268
7498
  unbindKeys();
7269
7499
  try {
7270
7500
  const { default: inquirer3 } = await import("inquirer");
7271
- console.log(import_chalk32.default.dim("\n\u2500\u2500\u2500 paused \xB7 still capturing in the background \u2500\u2500\u2500"));
7501
+ console.log(import_chalk33.default.dim("\n\u2500\u2500\u2500 paused \xB7 still capturing in the background \u2500\u2500\u2500"));
7272
7502
  for (; ; ) {
7273
7503
  const choices = recent.slice(-TAIL_INSPECT_CHOICES).reverse().map((r) => ({ name: formatRow(r), value: r.request_id }));
7274
- choices.push({ name: import_chalk32.default.dim("\u2039resume tail\u203A"), value: "__resume__" });
7504
+ choices.push({ name: import_chalk33.default.dim("\u2039resume tail\u203A"), value: "__resume__" });
7275
7505
  const { picked } = await inquirer3.prompt([{
7276
7506
  type: "list",
7277
7507
  name: "picked",
@@ -7282,12 +7512,12 @@ async function runTailSession(opts) {
7282
7512
  if (picked === "__resume__") break;
7283
7513
  const row = recent.find((r) => r.request_id === picked);
7284
7514
  if (row) printDetail(row, opts.detail);
7285
- else console.log(import_chalk32.default.dim(" that request has scrolled out of the tail buffer \u2014 find it with `logs list`.\n"));
7515
+ else console.log(import_chalk33.default.dim(" that request has scrolled out of the tail buffer \u2014 find it with `logs list`.\n"));
7286
7516
  }
7287
7517
  } finally {
7288
7518
  paused = false;
7289
7519
  flushHeld();
7290
- console.log(import_chalk32.default.dim("\u2500\u2500\u2500 resumed \u2500\u2500\u2500"));
7520
+ console.log(import_chalk33.default.dim("\u2500\u2500\u2500 resumed \u2500\u2500\u2500"));
7291
7521
  bindKeys();
7292
7522
  }
7293
7523
  }
@@ -7297,12 +7527,12 @@ async function runTailSession(opts) {
7297
7527
  if (reconnects >= MAX_RECONNECTS) {
7298
7528
  paused = false;
7299
7529
  flushHeld();
7300
- console.error(import_chalk32.default.red(`Connection lost \u2014 giving up after repeated reconnects${lastFailure ? ` (last error: ${lastFailure})` : ""}.`));
7530
+ console.error(import_chalk33.default.red(`Connection lost \u2014 giving up after repeated reconnects${lastFailure ? ` (last error: ${lastFailure})` : ""}.`));
7301
7531
  process.exit(1);
7302
7532
  }
7303
7533
  const delay = Math.min(1e3 * 2 ** reconnects, 15e3);
7304
7534
  reconnects++;
7305
- diag(import_chalk32.default.dim(`disconnected${lastFailure ? ` (${lastFailure})` : ""} \u2014 reconnecting in ${Math.round(delay / 1e3)}s\u2026`));
7535
+ diag(import_chalk33.default.dim(`disconnected${lastFailure ? ` (${lastFailure})` : ""} \u2014 reconnecting in ${Math.round(delay / 1e3)}s\u2026`));
7306
7536
  setTimeout(() => {
7307
7537
  if (!closed) void connect();
7308
7538
  }, delay);
@@ -7313,7 +7543,7 @@ async function runTailSession(opts) {
7313
7543
  url = await opts.mintTicket();
7314
7544
  } catch (err) {
7315
7545
  if (!everConnected) {
7316
- console.error(import_chalk32.default.red(`Could not start tail: ${err.message}`));
7546
+ console.error(import_chalk33.default.red(`Could not start tail: ${err.message}`));
7317
7547
  process.exit(1);
7318
7548
  }
7319
7549
  lastFailure = `ticket mint failed: ${err.message}`;
@@ -7326,7 +7556,7 @@ async function runTailSession(opts) {
7326
7556
  } catch (err) {
7327
7557
  lastFailure = `bad tail URL: ${err.message}`;
7328
7558
  if (!everConnected) {
7329
- console.error(import_chalk32.default.red(`Could not start tail: ${lastFailure}`));
7559
+ console.error(import_chalk33.default.red(`Could not start tail: ${lastFailure}`));
7330
7560
  process.exit(1);
7331
7561
  }
7332
7562
  scheduleReconnect();
@@ -7341,9 +7571,9 @@ async function runTailSession(opts) {
7341
7571
  lastInbound = Date.now();
7342
7572
  lastFailure = "";
7343
7573
  if (isReconnect) {
7344
- diag(import_chalk32.default.dim("reconnected \u2014 requests during the gap were not replayed (browse them with `logs list`)."));
7574
+ diag(import_chalk33.default.dim("reconnected \u2014 requests during the gap were not replayed (browse them with `logs list`)."));
7345
7575
  } else {
7346
- diag(import_chalk32.default.dim(interactive ? "[Enter] inspect a request \xB7 [Ctrl+C] stop\n" : "Ctrl+C to stop."));
7576
+ diag(import_chalk33.default.dim(interactive ? "[Enter] inspect a request \xB7 [Ctrl+C] stop\n" : "Ctrl+C to stop."));
7347
7577
  }
7348
7578
  bindKeys();
7349
7579
  pingTimer = setInterval(() => {
@@ -7370,7 +7600,7 @@ async function runTailSession(opts) {
7370
7600
  return;
7371
7601
  }
7372
7602
  if (frame?.type === "ceiling") {
7373
- diag(import_chalk32.default.yellow(
7603
+ diag(import_chalk33.default.yellow(
7374
7604
  `\u26A0 volume ceiling \u2014 ${Number(frame.dropped_this_hour) || 0} rows dropped this hour; errors keep streaming.`
7375
7605
  ));
7376
7606
  return;
@@ -7450,10 +7680,10 @@ async function fetchPage(fetchWindow3, params, notices) {
7450
7680
  return { rows, nextCursor: res.next_cursor ?? void 0 };
7451
7681
  }
7452
7682
  if (hop >= MAX_EMPTY_HOPS) {
7453
- console.error(import_chalk32.default.yellow("\u26A0 stopped after scanning a long empty span \u2014 older rows may still exist."));
7683
+ console.error(import_chalk33.default.yellow("\u26A0 stopped after scanning a long empty span \u2014 older rows may still exist."));
7454
7684
  return { rows: [], nextCursor: res.next_cursor, fuseTripped: true };
7455
7685
  }
7456
- if (hop === 0) console.error(import_chalk32.default.dim("searching older history\u2026"));
7686
+ if (hop === 0) console.error(import_chalk33.default.dim("searching older history\u2026"));
7457
7687
  cursor = res.next_cursor;
7458
7688
  }
7459
7689
  }
@@ -7493,18 +7723,18 @@ async function runPlainList(opts, notices) {
7493
7723
  }
7494
7724
  }
7495
7725
  if (rows.length === 0) {
7496
- console.log(import_chalk32.default.dim(fuseTripped ? "Nothing found in the scanned span \u2014 older requests may still exist." : opts.errorsOnly ? "No errors logged yet." : "No requests logged yet."));
7726
+ console.log(import_chalk33.default.dim(fuseTripped ? "Nothing found in the scanned span \u2014 older requests may still exist." : opts.errorsOnly ? "No errors logged yet." : "No requests logged yet."));
7497
7727
  return;
7498
7728
  }
7499
7729
  const now = Date.now();
7500
7730
  for (const d of groupIntoDays(rows)) {
7501
- console.log(import_chalk32.default.bold(dayLabel(d.dayMs, now)));
7731
+ console.log(import_chalk33.default.bold(dayLabel(d.dayMs, now)));
7502
7732
  for (const r of d.rows) console.log(` ${formatRow(r)}`);
7503
7733
  console.log("");
7504
7734
  }
7505
7735
  const errs = rows.filter((r) => r.status >= 400).length;
7506
7736
  const tail = fuseTripped ? " \xB7 stopped early (long empty span) \u2014 older requests may still exist" : more ? " \xB7 showing the most recent \u2014 `--json` streams the rest" : "";
7507
- console.log(import_chalk32.default.dim(
7737
+ console.log(import_chalk33.default.dim(
7508
7738
  `${rows.length} request${rows.length === 1 ? "" : "s"} \xB7 ${errs} error${errs === 1 ? "" : "s"}${tail}`
7509
7739
  ));
7510
7740
  }
@@ -7523,7 +7753,7 @@ async function runHistoryBrowser(opts) {
7523
7753
  for (const r of page.rows) console.log(JSON.stringify(r));
7524
7754
  any = any || page.rows.length > 0;
7525
7755
  if (page.fuseTripped || !page.nextCursor) {
7526
- if (!any && !page.fuseTripped) console.error(import_chalk32.default.dim(opts.errorsOnly ? "No errors logged yet." : "No requests logged yet."));
7756
+ if (!any && !page.fuseTripped) console.error(import_chalk33.default.dim(opts.errorsOnly ? "No errors logged yet." : "No requests logged yet."));
7527
7757
  return;
7528
7758
  }
7529
7759
  cursor2 = page.nextCursor;
@@ -7544,7 +7774,7 @@ async function runHistoryBrowser(opts) {
7544
7774
  scanRows = first.rows;
7545
7775
  scanCursor = first.nextCursor;
7546
7776
  if (scanRows.length === 0) {
7547
- console.log(import_chalk32.default.dim(first.fuseTripped ? "Nothing found in the scanned span \u2014 older rows may exist." : opts.errorsOnly ? "No errors logged yet." : "No requests logged yet."));
7777
+ console.log(import_chalk33.default.dim(first.fuseTripped ? "Nothing found in the scanned span \u2014 older rows may exist." : opts.errorsOnly ? "No errors logged yet." : "No requests logged yet."));
7548
7778
  return;
7549
7779
  }
7550
7780
  }
@@ -7555,10 +7785,10 @@ async function runHistoryBrowser(opts) {
7555
7785
  const now2 = Date.now();
7556
7786
  const oldestKey = days[days.length - 1]?.key;
7557
7787
  const choices = days.map((d) => ({
7558
- name: `${dayLabel(d.dayMs, now2).padEnd(12)} ${String(d.rows.length).padStart(4)}${(scanCursor !== void 0 || scanFloorUnknown) && d.key === oldestKey ? "+" : ""} requests${d.errors ? import_chalk32.default.red(` ${d.errors} errors`) : ""}`,
7788
+ name: `${dayLabel(d.dayMs, now2).padEnd(12)} ${String(d.rows.length).padStart(4)}${(scanCursor !== void 0 || scanFloorUnknown) && d.key === oldestKey ? "+" : ""} requests${d.errors ? import_chalk33.default.red(` ${d.errors} errors`) : ""}`,
7559
7789
  value: d.key
7560
7790
  }));
7561
- if (scanCursor) choices.push({ name: import_chalk32.default.dim("\u2026 older days"), value: "__older__" });
7791
+ if (scanCursor) choices.push({ name: import_chalk33.default.dim("\u2026 older days"), value: "__older__" });
7562
7792
  const { chosenDay } = await inquirer3.prompt([{
7563
7793
  type: "list",
7564
7794
  name: "chosenDay",
@@ -7578,7 +7808,7 @@ async function runHistoryBrowser(opts) {
7578
7808
  scanCursor = void 0;
7579
7809
  } else {
7580
7810
  scanCursor = more.nextCursor;
7581
- if (more.rows.length === 0 && !scanCursor) console.log(import_chalk32.default.dim("That was everything \u2014 no older requests."));
7811
+ if (more.rows.length === 0 && !scanCursor) console.log(import_chalk33.default.dim("That was everything \u2014 no older requests."));
7582
7812
  }
7583
7813
  continue;
7584
7814
  }
@@ -7600,11 +7830,11 @@ async function runHistoryBrowser(opts) {
7600
7830
  cursor
7601
7831
  }, notices);
7602
7832
  if (page.rows.length === 0 && pageRows.length === 0) {
7603
- console.log(import_chalk32.default.dim(page.fuseTripped ? "Stopped scanning this day (long empty span) \u2014 older rows in it may exist." : "No requests for this day."));
7833
+ console.log(import_chalk33.default.dim(page.fuseTripped ? "Stopped scanning this day (long empty span) \u2014 older rows in it may exist." : "No requests for this day."));
7604
7834
  return;
7605
7835
  }
7606
7836
  if (page.rows.length === 0) {
7607
- console.log(import_chalk32.default.dim(page.fuseTripped ? "Stopped scanning further into this day (long empty span) \u2014 older rows in it may exist." : "That was everything for this day."));
7837
+ console.log(import_chalk33.default.dim(page.fuseTripped ? "Stopped scanning further into this day (long empty span) \u2014 older rows in it may exist." : "That was everything for this day."));
7608
7838
  moreCursor = void 0;
7609
7839
  } else {
7610
7840
  pageRows = page.rows;
@@ -7615,8 +7845,8 @@ async function runHistoryBrowser(opts) {
7615
7845
  name: formatRow(r),
7616
7846
  value: r.request_id
7617
7847
  }));
7618
- if (moreCursor) choices.push({ name: import_chalk32.default.dim("\u2026 load more"), value: "__more__" });
7619
- choices.push({ name: import_chalk32.default.dim("quit"), value: "__quit__" });
7848
+ if (moreCursor) choices.push({ name: import_chalk33.default.dim("\u2026 load more"), value: "__more__" });
7849
+ choices.push({ name: import_chalk33.default.dim("quit"), value: "__quit__" });
7620
7850
  for (; ; ) {
7621
7851
  const { picked } = await inquirer3.prompt([{
7622
7852
  type: "list",
@@ -7666,19 +7896,19 @@ function wrapCells(items, width) {
7666
7896
  ${PANE_INDENT}`);
7667
7897
  }
7668
7898
  function renderHeaders(h) {
7669
- if (!h) return import_chalk32.default.dim("\u2014");
7899
+ if (!h) return import_chalk33.default.dim("\u2014");
7670
7900
  const width = process.stdout.columns || 100;
7671
7901
  if (h.values) {
7672
7902
  const e = Object.entries(h.values);
7673
- if (!e.length) return import_chalk32.default.dim("none");
7903
+ if (!e.length) return import_chalk33.default.dim("none");
7674
7904
  const rank = (k) => {
7675
7905
  const i = HEADER_PRIORITY.indexOf(k.toLowerCase());
7676
7906
  return i === -1 ? NOISE_HEADER.test(k) ? 999 : 500 : i;
7677
7907
  };
7678
- return e.sort((a, b) => rank(a[0]) - rank(b[0])).map(([k, v]) => `${import_chalk32.default.dim(k + ":")} ${v}`).join(`
7908
+ return e.sort((a, b) => rank(a[0]) - rank(b[0])).map(([k, v]) => `${import_chalk33.default.dim(k + ":")} ${v}`).join(`
7679
7909
  ${PANE_INDENT}`);
7680
7910
  }
7681
- if (!h.names?.length) return import_chalk32.default.dim("none");
7911
+ if (!h.names?.length) return import_chalk33.default.dim("none");
7682
7912
  const names = [...h.names];
7683
7913
  const noise = names.filter((n) => NOISE_HEADER.test(n));
7684
7914
  const shown = names.filter((n) => !NOISE_HEADER.test(n)).sort((a, b) => {
@@ -7686,70 +7916,70 @@ ${PANE_INDENT}`);
7686
7916
  const ib = HEADER_PRIORITY.indexOf(b.toLowerCase());
7687
7917
  return (ia === -1 ? 500 : ia) - (ib === -1 ? 500 : ib) || a.localeCompare(b);
7688
7918
  });
7689
- const body = shown.length ? wrapCells(shown, width) : import_chalk32.default.dim("(all forwarding headers)");
7919
+ const body = shown.length ? wrapCells(shown, width) : import_chalk33.default.dim("(all forwarding headers)");
7690
7920
  const tail = noise.length ? `
7691
- ${PANE_INDENT}${import_chalk32.default.dim(`+ ${noise.length} forwarding/client-hint header${noise.length === 1 ? "" : "s"} (cf-*, sec-*)`)}` : "";
7692
- return `${body}${tail} ${import_chalk32.default.dim("(names only)")}`;
7921
+ ${PANE_INDENT}${import_chalk33.default.dim(`+ ${noise.length} forwarding/client-hint header${noise.length === 1 ? "" : "s"} (cf-*, sec-*)`)}` : "";
7922
+ return `${body}${tail} ${import_chalk33.default.dim("(names only)")}`;
7693
7923
  }
7694
7924
  function renderBody(b) {
7695
- if (!b) return import_chalk32.default.dim("\u2014");
7925
+ if (!b) return import_chalk33.default.dim("\u2014");
7696
7926
  const meta = [b.content_type, b.size != null ? `${b.size}B` : null, b.truncated ? "truncated" : null].filter(Boolean).join(" \xB7 ");
7697
- if (b.not_captured) return import_chalk32.default.dim(`not captured (${b.not_captured})${meta ? " \xB7 " + meta : ""}`);
7927
+ if (b.not_captured) return import_chalk33.default.dim(`not captured (${b.not_captured})${meta ? " \xB7 " + meta : ""}`);
7698
7928
  const isShape = b.value === void 0 && b.shape !== void 0;
7699
7929
  const content = b.value !== void 0 ? b.value : b.shape;
7700
7930
  if (content === null || content === void 0 || content === "" || content === "empty") {
7701
- return import_chalk32.default.dim(`empty${meta ? " \xB7 " + meta : ""}`);
7931
+ return import_chalk33.default.dim(`empty${meta ? " \xB7 " + meta : ""}`);
7702
7932
  }
7703
7933
  const text = typeof content === "string" ? content : JSON.stringify(content, null, 2);
7704
- const head = isShape ? import_chalk32.default.dim("shape only (values not captured)\n ") : "";
7934
+ const head = isShape ? import_chalk33.default.dim("shape only (values not captured)\n ") : "";
7705
7935
  return head + text.split("\n").join("\n ");
7706
7936
  }
7707
7937
  function pane(title, tone, view, empty) {
7708
7938
  console.log(` ${tone(title)}`);
7709
7939
  if (empty !== void 0) {
7710
- console.log(` ${import_chalk32.default.dim(empty)}`);
7940
+ console.log(` ${import_chalk33.default.dim(empty)}`);
7711
7941
  return;
7712
7942
  }
7713
7943
  const v = view ?? {};
7714
- if (v.url) console.log(` ${import_chalk32.default.dim("target")} ${v.url}`);
7944
+ if (v.url) console.log(` ${import_chalk33.default.dim("target")} ${v.url}`);
7715
7945
  if (v.status != null) {
7716
- console.log(` ${import_chalk32.default.dim("status")} ${statusColor(v.status)(String(v.status))}${v.status_text ? import_chalk32.default.dim(" " + v.status_text) : ""}`);
7946
+ console.log(` ${import_chalk33.default.dim("status")} ${statusColor(v.status)(String(v.status))}${v.status_text ? import_chalk33.default.dim(" " + v.status_text) : ""}`);
7717
7947
  }
7718
- if (v.raw_path) console.log(` ${import_chalk32.default.dim("path")} ${v.raw_path}`);
7948
+ if (v.raw_path) console.log(` ${import_chalk33.default.dim("path")} ${v.raw_path}`);
7719
7949
  if (v.query && Object.keys(v.query).length) {
7720
- console.log(` ${import_chalk32.default.dim("query")} ${Object.entries(v.query).map(([k, q]) => `${k}=${q}`).join(" ")}`);
7950
+ console.log(` ${import_chalk33.default.dim("query")} ${Object.entries(v.query).map(([k, q]) => `${k}=${q}`).join(" ")}`);
7721
7951
  }
7722
- if (v.jwt !== void 0) console.log(` ${import_chalk32.default.dim("jwt")} ${JSON.stringify(v.jwt)}`);
7723
- console.log(` ${import_chalk32.default.dim("headers")} ${renderHeaders(v.headers)}`);
7724
- console.log(` ${import_chalk32.default.dim("body")} ${renderBody(v.body)}`);
7952
+ if (v.jwt !== void 0) console.log(` ${import_chalk33.default.dim("jwt")} ${JSON.stringify(v.jwt)}`);
7953
+ console.log(` ${import_chalk33.default.dim("headers")} ${renderHeaders(v.headers)}`);
7954
+ console.log(` ${import_chalk33.default.dim("body")} ${renderBody(v.body)}`);
7725
7955
  }
7726
7956
  function printDetail(r, mode = "producer") {
7727
7957
  const v = r.views;
7728
7958
  console.log("");
7729
- console.log(import_chalk32.default.bold(`${r.method} ${r.route}`) + " " + statusColor(r.status)(String(r.status)) + import_chalk32.default.dim(` ${r.duration_ms}ms`));
7959
+ console.log(import_chalk33.default.bold(`${r.method} ${r.route}`) + " " + statusColor(r.status)(String(r.status)) + import_chalk33.default.dim(` ${r.duration_ms}ms`));
7730
7960
  const cost = typeof r.cost_cents === "number" && r.cost_cents > 0 ? ` \xB7 ${r.cost_cents}\xA2` : "";
7731
- console.log(import_chalk32.default.dim(` request_id ${r.request_id}${r.environment ? ` \xB7 env ${r.environment}` : ""}${r.consumer_id ? ` \xB7 consumer ${r.consumer_id}` : ""}${cost}`));
7961
+ console.log(import_chalk33.default.dim(` request_id ${r.request_id}${r.environment ? ` \xB7 env ${r.environment}` : ""}${r.consumer_id ? ` \xB7 consumer ${r.consumer_id}` : ""}${cost}`));
7732
7962
  console.log("");
7733
7963
  if (!v) {
7734
- console.log(import_chalk32.default.dim(" No view detail captured for this request.\n"));
7964
+ console.log(import_chalk33.default.dim(" No view detail captured for this request.\n"));
7735
7965
  return;
7736
7966
  }
7737
- pane("Request (before) \u2014 client \u2192 APIblaze", import_chalk32.default.cyan, v.request);
7967
+ pane("Request (before) \u2014 client \u2192 APIblaze", import_chalk33.default.cyan, v.request);
7738
7968
  if (mode === "producer") {
7739
7969
  pane(
7740
7970
  "Request (after) \u2014 APIblaze \u2192 upstream",
7741
- import_chalk32.default.cyan,
7971
+ import_chalk33.default.cyan,
7742
7972
  v.forwarded_request,
7743
7973
  v.forwarded_request ? void 0 : "Request did not reach an upstream."
7744
7974
  );
7745
7975
  pane(
7746
7976
  "Response (before) \u2014 upstream \u2192 APIblaze",
7747
- import_chalk32.default.magenta,
7977
+ import_chalk33.default.magenta,
7748
7978
  v.upstream_response,
7749
7979
  v.upstream_response ? void 0 : "No upstream response."
7750
7980
  );
7751
7981
  }
7752
- pane("Response (after) \u2014 APIblaze \u2192 client", import_chalk32.default.magenta, v.response);
7982
+ pane("Response (after) \u2014 APIblaze \u2192 client", import_chalk33.default.magenta, v.response);
7753
7983
  console.log("");
7754
7984
  }
7755
7985
 
@@ -7798,7 +8028,7 @@ async function resolve(projectArg, versionArg, opts) {
7798
8028
  return { projectId, projectName: match.projectName, version: version2, tenant: tenant2 };
7799
8029
  }
7800
8030
  function otherPlaneHint() {
7801
- if (loadConsumer()) console.log(import_chalk33.default.dim(" \u2039consumer view: apiblaze consumer logs\u203A"));
8031
+ if (loadConsumer()) console.log(import_chalk34.default.dim(" \u2039consumer view: apiblaze consumer logs\u203A"));
7802
8032
  }
7803
8033
  function fetchWindow(projectId, version2, tenant2) {
7804
8034
  return (params) => {
@@ -7817,8 +8047,8 @@ function fetchWindow(projectId, version2, tenant2) {
7817
8047
  async function runLogsTail(projectArg, versionArg, opts) {
7818
8048
  const { projectId, projectName, version: version2, tenant: tenant2 } = await resolve(projectArg, versionArg, opts);
7819
8049
  if (!opts.json) {
7820
- console.log(import_chalk33.default.bold("API Producer logs") + import_chalk33.default.dim(` \xB7 ${projectName}@${version2} \xB7 tenant ${tenant2}${opts.errorsOnly ? " \xB7 errors only" : ""}`));
7821
- console.log(import_chalk33.default.dim("every caller's requests, with cost and upstream detail"));
8050
+ console.log(import_chalk34.default.bold("API Producer logs") + import_chalk34.default.dim(` \xB7 ${projectName}@${version2} \xB7 tenant ${tenant2}${opts.errorsOnly ? " \xB7 errors only" : ""}`));
8051
+ console.log(import_chalk34.default.dim("every caller's requests, with cost and upstream detail"));
7822
8052
  otherPlaneHint();
7823
8053
  }
7824
8054
  await runTailSession({
@@ -7839,8 +8069,8 @@ async function runLogsTail(projectArg, versionArg, opts) {
7839
8069
  async function runLogsList(projectArg, versionArg, opts) {
7840
8070
  const { projectId, projectName, version: version2, tenant: tenant2 } = await resolve(projectArg, versionArg, opts);
7841
8071
  if (!opts.json) {
7842
- console.log(import_chalk33.default.bold("API Producer logs") + import_chalk33.default.dim(` \xB7 ${projectName}@${version2} \xB7 tenant ${tenant2}${opts.errorsOnly ? " \xB7 errors only" : ""}`));
7843
- console.log(import_chalk33.default.dim("every caller's requests, with cost and upstream detail"));
8072
+ console.log(import_chalk34.default.bold("API Producer logs") + import_chalk34.default.dim(` \xB7 ${projectName}@${version2} \xB7 tenant ${tenant2}${opts.errorsOnly ? " \xB7 errors only" : ""}`));
8073
+ console.log(import_chalk34.default.dim("every caller's requests, with cost and upstream detail"));
7844
8074
  otherPlaneHint();
7845
8075
  console.log("");
7846
8076
  }
@@ -7854,15 +8084,15 @@ async function runLogsList(projectArg, versionArg, opts) {
7854
8084
  }
7855
8085
 
7856
8086
  // src/commands/consumer-logs.ts
7857
- var import_chalk34 = __toESM(require("chalk"));
8087
+ var import_chalk35 = __toESM(require("chalk"));
7858
8088
  init_auth();
7859
8089
  var CONSUMER_LOGS_BASE = process.env.APIBLAZE_CONSUMER_LOGS_BASE || "https://logs.apiblaze.com/consumer";
7860
8090
  function requireConsumer() {
7861
8091
  const c = loadConsumer();
7862
8092
  if (!c) {
7863
- console.error(import_chalk34.default.red("Not logged in as an API Consumer. Run `apiblaze consumer login` first."));
8093
+ console.error(import_chalk35.default.red("Not logged in as an API Consumer. Run `apiblaze consumer login` first."));
7864
8094
  if (loadCredentials()) {
7865
- console.error(import_chalk34.default.dim("You're signed in as an API Producer \u2014 for a proxy's full logs run `apiblaze logs <project>`."));
8095
+ console.error(import_chalk35.default.dim("You're signed in as an API Producer \u2014 for a proxy's full logs run `apiblaze logs <project>`."));
7866
8096
  }
7867
8097
  process.exit(1);
7868
8098
  }
@@ -7893,7 +8123,7 @@ async function consumerLogsFetch(session, suffix, init) {
7893
8123
  return data;
7894
8124
  }
7895
8125
  function otherPlaneHint2() {
7896
- if (loadCredentials()) console.log(import_chalk34.default.dim(" \u2039producer view: apiblaze logs <project>\u203A"));
8126
+ if (loadCredentials()) console.log(import_chalk35.default.dim(" \u2039producer view: apiblaze logs <project>\u203A"));
7897
8127
  }
7898
8128
  function fetchWindow2(session, project) {
7899
8129
  return (params) => {
@@ -7909,8 +8139,8 @@ function fetchWindow2(session, project) {
7909
8139
  async function runConsumerLogsTail(opts) {
7910
8140
  const session = requireConsumer();
7911
8141
  if (!opts.json) {
7912
- console.log(import_chalk34.default.bold("API Consumer logs") + import_chalk34.default.dim(` \xB7 your own requests on ${session.creds.tenant}${opts.project ? ` \xB7 ${opts.project}` : ""}${opts.errorsOnly ? " \xB7 errors only" : ""}`));
7913
- console.log(import_chalk34.default.dim("cost and upstream details are producer-only and are not sent"));
8142
+ console.log(import_chalk35.default.bold("API Consumer logs") + import_chalk35.default.dim(` \xB7 your own requests on ${session.creds.tenant}${opts.project ? ` \xB7 ${opts.project}` : ""}${opts.errorsOnly ? " \xB7 errors only" : ""}`));
8143
+ console.log(import_chalk35.default.dim("cost and upstream details are producer-only and are not sent"));
7914
8144
  otherPlaneHint2();
7915
8145
  }
7916
8146
  await runTailSession({
@@ -7928,8 +8158,8 @@ async function runConsumerLogsTail(opts) {
7928
8158
  async function runConsumerLogsList(opts) {
7929
8159
  const session = requireConsumer();
7930
8160
  if (!opts.json) {
7931
- console.log(import_chalk34.default.bold("API Consumer logs") + import_chalk34.default.dim(` \xB7 your own requests on ${session.creds.tenant}${opts.project ? ` \xB7 ${opts.project}` : ""}${opts.errorsOnly ? " \xB7 errors only" : ""}`));
7932
- console.log(import_chalk34.default.dim("cost and upstream details are producer-only and are not sent"));
8161
+ console.log(import_chalk35.default.bold("API Consumer logs") + import_chalk35.default.dim(` \xB7 your own requests on ${session.creds.tenant}${opts.project ? ` \xB7 ${opts.project}` : ""}${opts.errorsOnly ? " \xB7 errors only" : ""}`));
8162
+ console.log(import_chalk35.default.dim("cost and upstream details are producer-only and are not sent"));
7933
8163
  otherPlaneHint2();
7934
8164
  console.log("");
7935
8165
  }
@@ -7943,7 +8173,7 @@ async function runConsumerLogsList(opts) {
7943
8173
  }
7944
8174
 
7945
8175
  // src/commands/config.ts
7946
- var import_chalk35 = __toESM(require("chalk"));
8176
+ var import_chalk36 = __toESM(require("chalk"));
7947
8177
  var import_ora12 = __toESM(require("ora"));
7948
8178
  init_admin();
7949
8179
  init_resolve();
@@ -7967,7 +8197,7 @@ async function patchConfig(project, opts, body, summary) {
7967
8197
  }
7968
8198
  async function runTargetSet(project, opts) {
7969
8199
  if (!opts.url) {
7970
- console.error(import_chalk35.default.red("--url is required."));
8200
+ console.error(import_chalk36.default.red("--url is required."));
7971
8201
  process.exit(1);
7972
8202
  }
7973
8203
  const body = opts.env ? { environments: { [opts.env]: { target: opts.url } } } : { target_url: opts.url };
@@ -7980,40 +8210,40 @@ async function runThrottleSet(project, opts) {
7980
8210
  if (opts.quota !== void 0) throttling.proxyQuota = Number(opts.quota);
7981
8211
  if (opts.period !== void 0) {
7982
8212
  if (!["daily", "weekly", "monthly"].includes(opts.period)) {
7983
- console.error(import_chalk35.default.red("--period must be daily, weekly, or monthly."));
8213
+ console.error(import_chalk36.default.red("--period must be daily, weekly, or monthly."));
7984
8214
  process.exit(1);
7985
8215
  }
7986
8216
  throttling.quotaPeriod = opts.period;
7987
8217
  }
7988
8218
  if (Object.keys(throttling).length === 0) {
7989
- console.error(import_chalk35.default.red("Nothing to set. Pass at least one of --rate, --end-user-rate, --quota, --period."));
8219
+ console.error(import_chalk36.default.red("Nothing to set. Pass at least one of --rate, --end-user-rate, --quota, --period."));
7990
8220
  process.exit(1);
7991
8221
  }
7992
8222
  await patchConfig(project, opts, { throttling }, `Update throttling ${JSON.stringify(throttling)}`);
7993
8223
  }
7994
8224
  async function runRename(project, opts) {
7995
8225
  if (!opts.displayName) {
7996
- console.error(import_chalk35.default.red("--display-name is required."));
8226
+ console.error(import_chalk36.default.red("--display-name is required."));
7997
8227
  process.exit(1);
7998
8228
  }
7999
8229
  await patchConfig(project, opts, { display_name: opts.displayName }, `Rename \u2192 "${opts.displayName}"`);
8000
8230
  }
8001
8231
 
8002
8232
  // src/commands/config-browse.ts
8003
- var import_chalk44 = __toESM(require("chalk"));
8233
+ var import_chalk45 = __toESM(require("chalk"));
8004
8234
  var import_ora20 = __toESM(require("ora"));
8005
8235
  init_admin();
8006
8236
  init_auth();
8007
8237
  init_resolve();
8008
8238
 
8009
8239
  // src/commands/domain.ts
8010
- var import_chalk36 = __toESM(require("chalk"));
8240
+ var import_chalk37 = __toESM(require("chalk"));
8011
8241
  var import_ora13 = __toESM(require("ora"));
8012
8242
  init_admin();
8013
8243
  init_resolve();
8014
8244
  async function runDomainAdd(project, opts) {
8015
8245
  if (!opts.domain) {
8016
- console.error(import_chalk36.default.red("--domain is required."));
8246
+ console.error(import_chalk37.default.red("--domain is required."));
8017
8247
  process.exit(1);
8018
8248
  }
8019
8249
  const { teamId } = await resolveTeam(opts.team);
@@ -8032,9 +8262,9 @@ async function runDomainAdd(project, opts) {
8032
8262
  console.log(JSON.stringify(out));
8033
8263
  return;
8034
8264
  }
8035
- if (out?.cnameRecord) console.log(` ${import_chalk36.default.cyan("CNAME")} ${out.cnameRecord.name ?? opts.domain} \u2192 ${out.cnameRecord.value ?? out.cnameRecord.target}`);
8036
- if (out?.dcv) console.log(` ${import_chalk36.default.cyan("TXT")} ${out.dcv.name} = ${out.dcv.value}`);
8037
- if (out?.id) console.log(import_chalk36.default.dim(` domain id: ${out.id}`));
8265
+ if (out?.cnameRecord) console.log(` ${import_chalk37.default.cyan("CNAME")} ${out.cnameRecord.name ?? opts.domain} \u2192 ${out.cnameRecord.value ?? out.cnameRecord.target}`);
8266
+ if (out?.dcv) console.log(` ${import_chalk37.default.cyan("TXT")} ${out.dcv.name} = ${out.dcv.value}`);
8267
+ if (out?.id) console.log(import_chalk37.default.dim(` domain id: ${out.id}`));
8038
8268
  } catch (err) {
8039
8269
  spinner.fail("Domain registration failed.");
8040
8270
  throw err;
@@ -8054,14 +8284,14 @@ async function runDomainList(project, opts) {
8054
8284
  return;
8055
8285
  }
8056
8286
  if (!domains.length) {
8057
- console.log(import_chalk36.default.yellow("No custom domains."));
8287
+ console.log(import_chalk37.default.yellow("No custom domains."));
8058
8288
  return;
8059
8289
  }
8060
- for (const d of domains) console.log(` ${import_chalk36.default.bold(d.hostname)} ${import_chalk36.default.dim(d.status ?? "")} ${import_chalk36.default.dim(d.id ?? "")}`);
8290
+ for (const d of domains) console.log(` ${import_chalk37.default.bold(d.hostname)} ${import_chalk37.default.dim(d.status ?? "")} ${import_chalk37.default.dim(d.id ?? "")}`);
8061
8291
  }
8062
8292
  async function runDomainStatus(project, opts) {
8063
8293
  if (!opts.id) {
8064
- console.error(import_chalk36.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
8294
+ console.error(import_chalk37.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
8065
8295
  process.exit(1);
8066
8296
  }
8067
8297
  const { teamId } = await resolveTeam(opts.team);
@@ -8071,11 +8301,11 @@ async function runDomainStatus(project, opts) {
8071
8301
  path: `/projects/${proj2.projectId}/domains/${encodeURIComponent(opts.id)}/status`,
8072
8302
  summary: `Check custom-domain status`
8073
8303
  });
8074
- console.log(opts.json ? JSON.stringify(out) : ` ${import_chalk36.default.bold(out?.hostname ?? opts.id)}: ${import_chalk36.default.cyan(out?.status ?? "unknown")}`);
8304
+ console.log(opts.json ? JSON.stringify(out) : ` ${import_chalk37.default.bold(out?.hostname ?? opts.id)}: ${import_chalk37.default.cyan(out?.status ?? "unknown")}`);
8075
8305
  }
8076
8306
  async function runDomainRemove(project, opts) {
8077
8307
  if (!opts.id) {
8078
- console.error(import_chalk36.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
8308
+ console.error(import_chalk37.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
8079
8309
  process.exit(1);
8080
8310
  }
8081
8311
  const { teamId } = await resolveTeam(opts.team);
@@ -8113,7 +8343,7 @@ async function runDomainSetBase(project, opts) {
8113
8343
  }
8114
8344
 
8115
8345
  // src/commands/tenant.ts
8116
- var import_chalk39 = __toESM(require("chalk"));
8346
+ var import_chalk40 = __toESM(require("chalk"));
8117
8347
  var import_ora16 = __toESM(require("ora"));
8118
8348
  init_admin();
8119
8349
  init_resolve();
@@ -8122,20 +8352,20 @@ init_tenant_pick();
8122
8352
  async function runTenantUse(query, opts) {
8123
8353
  const creds = loadCredentials();
8124
8354
  if (!creds) {
8125
- console.error(import_chalk39.default.red("Not logged in. Run `apiblaze login` first."));
8355
+ console.error(import_chalk40.default.red("Not logged in. Run `apiblaze login` first."));
8126
8356
  process.exit(1);
8127
8357
  }
8128
8358
  if (opts.clear) {
8129
8359
  delete creds.activeTenant;
8130
8360
  saveCredentials(creds);
8131
- console.log(import_chalk39.default.green("Tenant scope cleared."));
8361
+ console.log(import_chalk40.default.green("Tenant scope cleared."));
8132
8362
  return;
8133
8363
  }
8134
8364
  const { teamId } = await resolveTeam(opts.team);
8135
8365
  const slug = await pickTenant(teamId, { message: "Scope future commands to which tenant?", initialQuery: query });
8136
8366
  if (!slug) process.exit(1);
8137
8367
  saveCredentials({ ...creds, activeTenant: slug });
8138
- console.log(import_chalk39.default.green(`Tenant scope set to ${import_chalk39.default.bold(slug)}.`) + import_chalk39.default.dim(" (clear with `apiblaze tenant use --clear`)"));
8368
+ console.log(import_chalk40.default.green(`Tenant scope set to ${import_chalk40.default.bold(slug)}.`) + import_chalk40.default.dim(" (clear with `apiblaze tenant use --clear`)"));
8139
8369
  }
8140
8370
  async function runTenantList(opts) {
8141
8371
  const { teamId, teamName } = await resolveTeam(opts.team);
@@ -8152,22 +8382,22 @@ async function runTenantList(opts) {
8152
8382
  return;
8153
8383
  }
8154
8384
  if (!tenants.length) {
8155
- console.log(import_chalk39.default.yellow(opts.q ? `No tenants matching "${opts.q}".` : "No tenants."));
8385
+ console.log(import_chalk40.default.yellow(opts.q ? `No tenants matching "${opts.q}".` : "No tenants."));
8156
8386
  return;
8157
8387
  }
8158
8388
  for (const t of tenants) {
8159
8389
  const name = typeof t === "string" ? t : t.tenant_name;
8160
- const display = typeof t === "string" ? "" : import_chalk39.default.dim(` ${t.display_name ?? ""}`);
8161
- console.log(` ${import_chalk39.default.bold(name)}${display}`);
8390
+ const display = typeof t === "string" ? "" : import_chalk40.default.dim(` ${t.display_name ?? ""}`);
8391
+ console.log(` ${import_chalk40.default.bold(name)}${display}`);
8162
8392
  }
8163
8393
  const total = out?.total ?? tenants.length;
8164
8394
  if (total > tenants.length) {
8165
- console.log(import_chalk39.default.dim(` \u2026 showing ${tenants.length} of ${total} \u2014 narrow with --q <search>`));
8395
+ console.log(import_chalk40.default.dim(` \u2026 showing ${tenants.length} of ${total} \u2014 narrow with --q <search>`));
8166
8396
  }
8167
8397
  }
8168
8398
  async function runTenantCreate(opts) {
8169
8399
  if (!opts.name) {
8170
- console.error(import_chalk39.default.red("--name (display name) is required."));
8400
+ console.error(import_chalk40.default.red("--name (display name) is required."));
8171
8401
  process.exit(1);
8172
8402
  }
8173
8403
  const { teamId } = await resolveTeam(opts.team);
@@ -8179,7 +8409,7 @@ async function runTenantCreate(opts) {
8179
8409
  body: { display_name: opts.name, ...opts.slug ? { tenant_name: opts.slug } : {} },
8180
8410
  summary: `Create tenant "${opts.name}"`
8181
8411
  });
8182
- spinner.succeed(`Created tenant ${import_chalk39.default.bold(out?.tenant_name ?? opts.name)}.`);
8412
+ spinner.succeed(`Created tenant ${import_chalk40.default.bold(out?.tenant_name ?? opts.name)}.`);
8183
8413
  if (opts.json) console.log(JSON.stringify(out));
8184
8414
  } catch (err) {
8185
8415
  spinner.fail("Tenant create failed.");
@@ -8188,7 +8418,7 @@ async function runTenantCreate(opts) {
8188
8418
  }
8189
8419
  async function runTenantAttach(project, opts) {
8190
8420
  if (!opts.tenant) {
8191
- console.error(import_chalk39.default.red("--tenant <slug> is required."));
8421
+ console.error(import_chalk40.default.red("--tenant <slug> is required."));
8192
8422
  process.exit(1);
8193
8423
  }
8194
8424
  const { teamId } = await resolveTeam(opts.team);
@@ -8216,7 +8446,7 @@ async function runTenantDelete(slug, opts) {
8216
8446
  { type: "confirm", name: "confirm", message: `Permanently delete tenant "${slug}" and everything under it? This cannot be undone.`, default: false }
8217
8447
  ]);
8218
8448
  if (!confirm2) {
8219
- console.log(import_chalk39.default.dim("Aborted."));
8449
+ console.log(import_chalk40.default.dim("Aborted."));
8220
8450
  return;
8221
8451
  }
8222
8452
  }
@@ -8235,7 +8465,7 @@ async function runTenantDelete(slug, opts) {
8235
8465
  }
8236
8466
  async function runTenantCors(opts) {
8237
8467
  if (!opts.tenant) {
8238
- console.error(import_chalk39.default.red("--tenant <slug> is required."));
8468
+ console.error(import_chalk40.default.red("--tenant <slug> is required."));
8239
8469
  process.exit(1);
8240
8470
  }
8241
8471
  const { teamId } = await resolveTeam(opts.team);
@@ -8257,7 +8487,7 @@ async function runTenantCors(opts) {
8257
8487
  }
8258
8488
 
8259
8489
  // src/commands/tenant-drill.ts
8260
- var import_chalk40 = __toESM(require("chalk"));
8490
+ var import_chalk41 = __toESM(require("chalk"));
8261
8491
  var import_ora17 = __toESM(require("ora"));
8262
8492
  var import_crypto = require("crypto");
8263
8493
  init_admin();
@@ -8288,15 +8518,15 @@ async function validScopedTenant(teamId, query) {
8288
8518
  const next = { ...creds };
8289
8519
  delete next.activeTenant;
8290
8520
  saveCredentials2(next);
8291
- console.log(import_chalk40.default.yellow(`Tenant scope "${scoped}" no longer exists in this team \u2014 cleared.`));
8521
+ console.log(import_chalk41.default.yellow(`Tenant scope "${scoped}" no longer exists in this team \u2014 cleared.`));
8292
8522
  return void 0;
8293
8523
  }
8294
8524
  async function tenantHome(teamId, tenant2) {
8295
8525
  const { default: inquirer3 } = await import("inquirer");
8296
8526
  const base2 = `/teams/${encodeURIComponent(teamId)}/tenants/${encodeURIComponent(tenant2)}`;
8297
- console.log(import_chalk40.default.bold(`
8527
+ console.log(import_chalk41.default.bold(`
8298
8528
  Tenant ${tenant2}`));
8299
- console.log(import_chalk40.default.dim("Tenant auth/settings are SHARED: changes apply to every proxy this tenant serves.\n"));
8529
+ console.log(import_chalk41.default.dim("Tenant auth/settings are SHARED: changes apply to every proxy this tenant serves.\n"));
8300
8530
  for (; ; ) {
8301
8531
  const spinner = (0, import_ora17.default)("Reading tenant state...").start();
8302
8532
  const [iam, cors, emails, issuers, opaque, clients] = await Promise.all([
@@ -8312,18 +8542,18 @@ Tenant ${tenant2}`));
8312
8542
  const nClients = Array.isArray(clients) ? clients.length : 0;
8313
8543
  const nOpaque = opaque?.opaque?.endpoint ? 1 : 0;
8314
8544
  const nLogin = nClients + nIssuers + nOpaque;
8315
- const onOff = (b) => b ? import_chalk40.default.green("on") : import_chalk40.default.dim("off");
8545
+ const onOff = (b) => b ? import_chalk41.default.green("on") : import_chalk41.default.dim("off");
8316
8546
  const { pick: pick2 } = await inquirer3.prompt([{
8317
8547
  type: "list",
8318
8548
  name: "pick",
8319
8549
  message: `Tenant ${tenant2}:`,
8320
8550
  pageSize: 12,
8321
8551
  choices: [
8322
- { name: `Login methods (${nLogin}) ${import_chalk40.default.dim("how your consumers sign in")}`, value: "login" },
8323
- { name: `Users & groups: ${onOff(iam?.iam_enabled)} ${import_chalk40.default.dim(`identity & key management (iam.apiblaze.com)`)}`, value: "iam" },
8324
- { name: `Portal admins (${nEmails}) ${import_chalk40.default.dim("emails allowed to administer this tenant's portal")}`, value: "emails" },
8325
- new inquirer3.Separator(import_chalk40.default.dim(" Settings")),
8326
- { name: `CORS: ${cors?.cors ? import_chalk40.default.cyan(JSON.stringify(cors.cors)) : import_chalk40.default.dim("(unset)")} ${import_chalk40.default.dim("browser origins allowed to call this tenant")}`, value: "cors" },
8552
+ { name: `Login methods (${nLogin}) ${import_chalk41.default.dim("how your consumers sign in")}`, value: "login" },
8553
+ { name: `Users & groups: ${onOff(iam?.iam_enabled)} ${import_chalk41.default.dim(`identity & key management (iam.apiblaze.com)`)}`, value: "iam" },
8554
+ { name: `Portal admins (${nEmails}) ${import_chalk41.default.dim("emails allowed to administer this tenant's portal")}`, value: "emails" },
8555
+ new inquirer3.Separator(import_chalk41.default.dim(" Settings")),
8556
+ { name: `CORS: ${cors?.cors ? import_chalk41.default.cyan(JSON.stringify(cors.cors)) : import_chalk41.default.dim("(unset)")} ${import_chalk41.default.dim("browser origins allowed to call this tenant")}`, value: "cors" },
8327
8557
  { name: "\u2190 Back", value: "back" }
8328
8558
  ]
8329
8559
  }]);
@@ -8336,7 +8566,7 @@ Tenant ${tenant2}`));
8336
8566
  case "iam": {
8337
8567
  const { v } = await inquirer3.prompt([{ type: "confirm", name: "v", message: "Enable Users & groups?", default: !!iam?.iam_enabled }]);
8338
8568
  await admin({ method: "PATCH", path: `${base2}/iam`, body: { enabled: v }, summary: `IAM enforcement \u2192 ${v ? "on" : "off"}` });
8339
- console.log(import_chalk40.default.green(` Users & groups ${v ? "enabled" : "disabled"}.`));
8569
+ console.log(import_chalk41.default.green(` Users & groups ${v ? "enabled" : "disabled"}.`));
8340
8570
  break;
8341
8571
  }
8342
8572
  case "cors": {
@@ -8349,11 +8579,11 @@ Tenant ${tenant2}`));
8349
8579
  if (v === "") break;
8350
8580
  const parsed = v === "null" ? null : safeJson(v);
8351
8581
  if (parsed === void 0) {
8352
- console.log(import_chalk40.default.yellow(" Not valid JSON \u2014 unchanged."));
8582
+ console.log(import_chalk41.default.yellow(" Not valid JSON \u2014 unchanged."));
8353
8583
  break;
8354
8584
  }
8355
8585
  await admin({ method: "PUT", path: `${base2}/cors`, body: { cors: parsed }, summary: "Set tenant CORS" });
8356
- console.log(import_chalk40.default.green(" CORS updated."));
8586
+ console.log(import_chalk41.default.green(" CORS updated."));
8357
8587
  break;
8358
8588
  }
8359
8589
  case "emails":
@@ -8377,15 +8607,15 @@ async function loginMethodsMenu(teamId, tenant2, base2) {
8377
8607
  const choices = [];
8378
8608
  for (const c of appClients) {
8379
8609
  const nP = (c.providers ?? []).length || c.providers_count || 0;
8380
- choices.push({ name: `${import_chalk40.default.cyan("APIblaze-hosted")} ${import_chalk40.default.bold(c.name ?? c.clientId)} ${import_chalk40.default.dim(`${c.clientId}${nP ? ` \xB7 ${nP} provider${nP === 1 ? "" : "s"}` : import_chalk40.default.yellow(" \xB7 needs a provider")}`)}`, value: { kind: "client", item: c } });
8610
+ choices.push({ name: `${import_chalk41.default.cyan("APIblaze-hosted")} ${import_chalk41.default.bold(c.name ?? c.clientId)} ${import_chalk41.default.dim(`${c.clientId}${nP ? ` \xB7 ${nP} provider${nP === 1 ? "" : "s"}` : import_chalk41.default.yellow(" \xB7 needs a provider")}`)}`, value: { kind: "client", item: c } });
8381
8611
  }
8382
8612
  for (const i of issuers) {
8383
- choices.push({ name: `${import_chalk40.default.cyan("Your own \u2014 JWT ")} ${import_chalk40.default.bold(i.iss)} ${import_chalk40.default.dim(`aud=${i.aud}`)}`, value: { kind: "issuer", item: i } });
8613
+ choices.push({ name: `${import_chalk41.default.cyan("Your own \u2014 JWT ")} ${import_chalk41.default.bold(i.iss)} ${import_chalk41.default.dim(`aud=${i.aud}`)}`, value: { kind: "issuer", item: i } });
8384
8614
  }
8385
8615
  if (opaque?.endpoint) {
8386
- choices.push({ name: `${import_chalk40.default.cyan("Your own \u2014 opaque")} ${import_chalk40.default.bold(opaque.endpoint)}`, value: { kind: "opaque", item: opaque } });
8616
+ choices.push({ name: `${import_chalk41.default.cyan("Your own \u2014 opaque")} ${import_chalk41.default.bold(opaque.endpoint)}`, value: { kind: "opaque", item: opaque } });
8387
8617
  }
8388
- if (!choices.length) console.log(import_chalk40.default.dim("\n No login methods yet \u2014 consumers cannot sign in until you add one."));
8618
+ if (!choices.length) console.log(import_chalk41.default.dim("\n No login methods yet \u2014 consumers cannot sign in until you add one."));
8389
8619
  const { pick: pick2 } = await inquirer3.prompt([{
8390
8620
  type: "list",
8391
8621
  name: "pick",
@@ -8425,9 +8655,9 @@ async function addLoginMethod(teamId, tenant2, base2) {
8425
8655
  message: "How do people log in?",
8426
8656
  pageSize: 8,
8427
8657
  choices: [
8428
- { name: `APIblaze hosted login page ${import_chalk40.default.dim("we host login; pick a provider (GitHub/Google/\u2026) \u2014 easiest")}`, value: "apiblaze" },
8429
- { name: `Your own hosted login \u2014 JWT ${import_chalk40.default.dim("your identity provider issues JWTs; we trust them")}`, value: "jwt" },
8430
- { name: `Your own login \u2014 opaque token ${import_chalk40.default.dim("we validate your opaque tokens via an introspection endpoint")}`, value: "opaque" },
8658
+ { name: `APIblaze hosted login page ${import_chalk41.default.dim("we host login; pick a provider (GitHub/Google/\u2026) \u2014 easiest")}`, value: "apiblaze" },
8659
+ { name: `Your own hosted login \u2014 JWT ${import_chalk41.default.dim("your identity provider issues JWTs; we trust them")}`, value: "jwt" },
8660
+ { name: `Your own login \u2014 opaque token ${import_chalk41.default.dim("we validate your opaque tokens via an introspection endpoint")}`, value: "opaque" },
8431
8661
  { name: "\u2190 Back", value: null }
8432
8662
  ]
8433
8663
  }]);
@@ -8451,8 +8681,8 @@ function safeJson(s) {
8451
8681
  async function emailsMenu(base2, emails) {
8452
8682
  const { default: inquirer3 } = await import("inquirer");
8453
8683
  console.log();
8454
- if (!emails.length) console.log(import_chalk40.default.dim(" No consumer-admin emails."));
8455
- for (const e of emails) console.log(` ${import_chalk40.default.bold(e.email ?? e)} ${import_chalk40.default.dim(e.status ?? "")}`);
8684
+ if (!emails.length) console.log(import_chalk41.default.dim(" No consumer-admin emails."));
8685
+ for (const e of emails) console.log(` ${import_chalk41.default.bold(e.email ?? e)} ${import_chalk41.default.dim(e.status ?? "")}`);
8456
8686
  const { act } = await inquirer3.prompt([{
8457
8687
  type: "list",
8458
8688
  name: "act",
@@ -8467,7 +8697,7 @@ async function emailsMenu(base2, emails) {
8467
8697
  if (act === "add") {
8468
8698
  const { email } = await inquirer3.prompt([{ type: "input", name: "email", message: "Email:", validate: (s) => /.+@.+\..+/.test(s) || "not an email" }]);
8469
8699
  await admin({ method: "POST", path: `${base2}/admin-emails`, body: { email }, summary: `Add consumer-admin ${email}` });
8470
- console.log(import_chalk40.default.green(` ${email} added.`));
8700
+ console.log(import_chalk41.default.green(` ${email} added.`));
8471
8701
  } else {
8472
8702
  const { e } = await inquirer3.prompt([{
8473
8703
  type: "list",
@@ -8477,7 +8707,7 @@ async function emailsMenu(base2, emails) {
8477
8707
  }]);
8478
8708
  if (!e) return;
8479
8709
  await admin({ method: "DELETE", path: `${base2}/admin-emails/${encodeURIComponent(e)}`, summary: `Remove consumer-admin ${e}` });
8480
- console.log(import_chalk40.default.green(` ${e} removed.`));
8710
+ console.log(import_chalk41.default.green(` ${e} removed.`));
8481
8711
  }
8482
8712
  }
8483
8713
  async function addIssuer(base2) {
@@ -8498,19 +8728,19 @@ async function addIssuer(base2) {
8498
8728
  body: { iss: a.iss.trim(), aud: a.aud.trim(), jwks_url: a.jwks.trim() || null, sub_semantics: a.sem, ...claim ? { claim_name: claim } : {} },
8499
8729
  summary: `Add external issuer ${a.iss.trim()}`
8500
8730
  });
8501
- console.log(import_chalk40.default.green(" JWT login method saved."));
8731
+ console.log(import_chalk41.default.green(" JWT login method saved."));
8502
8732
  }
8503
8733
  async function issuerHome(base2, issuer) {
8504
8734
  const { default: inquirer3 } = await import("inquirer");
8505
8735
  console.log(`
8506
- ${import_chalk40.default.bold(issuer.iss)} ${import_chalk40.default.dim(`aud=${issuer.aud} \xB7 ${issuer.sub_semantics ?? ""}`)}`);
8736
+ ${import_chalk41.default.bold(issuer.iss)} ${import_chalk41.default.dim(`aud=${issuer.aud} \xB7 ${issuer.sub_semantics ?? ""}`)}`);
8507
8737
  const { act } = await inquirer3.prompt([{
8508
8738
  type: "list",
8509
8739
  name: "act",
8510
8740
  message: "This JWT login method:",
8511
8741
  choices: [
8512
8742
  { name: "Replace it (re-enter details)", value: "edit" },
8513
- { name: import_chalk40.default.red("Delete it"), value: "rm" },
8743
+ { name: import_chalk41.default.red("Delete it"), value: "rm" },
8514
8744
  { name: "\u2190 Back", value: "back" }
8515
8745
  ]
8516
8746
  }]);
@@ -8526,7 +8756,7 @@ async function issuerHome(base2, issuer) {
8526
8756
  path: `${base2}/external-issuers?iss=${encodeURIComponent(issuer.iss)}&aud=${encodeURIComponent(issuer.aud)}`,
8527
8757
  summary: `Delete issuer ${issuer.iss}`
8528
8758
  });
8529
- console.log(import_chalk40.default.green(" Deleted."));
8759
+ console.log(import_chalk41.default.green(" Deleted."));
8530
8760
  }
8531
8761
  async function setOpaque(base2, cur) {
8532
8762
  const { default: inquirer3 } = await import("inquirer");
@@ -8535,19 +8765,19 @@ async function setOpaque(base2, cur) {
8535
8765
  { type: "list", name: "method", message: "HTTP method:", choices: ["GET", "POST"], default: cur?.method ?? "GET" }
8536
8766
  ]);
8537
8767
  await admin({ method: "PUT", path: `${base2}/opaque`, body: { opaque: { endpoint: a.endpoint, method: a.method } }, summary: "Set opaque validator" });
8538
- console.log(import_chalk40.default.green(" Opaque login method set."));
8768
+ console.log(import_chalk41.default.green(" Opaque login method set."));
8539
8769
  }
8540
8770
  async function opaqueHome(base2, cur) {
8541
8771
  const { default: inquirer3 } = await import("inquirer");
8542
8772
  console.log(`
8543
- ${import_chalk40.default.bold(cur.endpoint)} ${import_chalk40.default.dim(cur.method ?? "GET")}`);
8773
+ ${import_chalk41.default.bold(cur.endpoint)} ${import_chalk41.default.dim(cur.method ?? "GET")}`);
8544
8774
  const { act } = await inquirer3.prompt([{
8545
8775
  type: "list",
8546
8776
  name: "act",
8547
8777
  message: "This opaque login method:",
8548
8778
  choices: [
8549
8779
  { name: "Replace it", value: "edit" },
8550
- { name: import_chalk40.default.red("Delete it"), value: "rm" },
8780
+ { name: import_chalk41.default.red("Delete it"), value: "rm" },
8551
8781
  { name: "\u2190 Back", value: "back" }
8552
8782
  ]
8553
8783
  }]);
@@ -8557,7 +8787,7 @@ async function opaqueHome(base2, cur) {
8557
8787
  return;
8558
8788
  }
8559
8789
  await admin({ method: "PUT", path: `${base2}/opaque`, body: { opaque: null }, summary: "Clear opaque validator" });
8560
- console.log(import_chalk40.default.green(" Deleted."));
8790
+ console.log(import_chalk41.default.green(" Deleted."));
8561
8791
  }
8562
8792
  async function clientHome(base2, summary) {
8563
8793
  const { default: inquirer3 } = await import("inquirer");
@@ -8576,13 +8806,13 @@ async function clientHome(base2, summary) {
8576
8806
  message: `${c.name ?? id}:`,
8577
8807
  pageSize: 12,
8578
8808
  choices: [
8579
- { name: `Login providers${nProviders ? ` (${nProviders})` : ""} ${import_chalk40.default.dim("google/github/microsoft/\u2026 \u2014 how consumers sign in")}`, value: "providers" },
8580
- { name: `Callback URLs: ${cb.length ? import_chalk40.default.cyan(cb.join(", ")) : import_chalk40.default.dim("(none)")}`, value: "callbacks" },
8581
- { name: `Scopes: ${scopes.length ? import_chalk40.default.cyan(scopes.join(" ")) : import_chalk40.default.dim("(defaults)")}`, value: "scopes" },
8809
+ { name: `Login providers${nProviders ? ` (${nProviders})` : ""} ${import_chalk41.default.dim("google/github/microsoft/\u2026 \u2014 how consumers sign in")}`, value: "providers" },
8810
+ { name: `Callback URLs: ${cb.length ? import_chalk41.default.cyan(cb.join(", ")) : import_chalk41.default.dim("(none)")}`, value: "callbacks" },
8811
+ { name: `Scopes: ${scopes.length ? import_chalk41.default.cyan(scopes.join(" ")) : import_chalk41.default.dim("(defaults)")}`, value: "scopes" },
8582
8812
  { name: `Token expiries: access ${c.accessTokenExpiry ?? 3600}s \xB7 id ${c.idTokenExpiry ?? 3600}s \xB7 refresh ${c.refreshTokenExpiry ?? 2592e3}s`, value: "expiries" },
8583
8813
  { name: "Reveal client secret", value: "secret" },
8584
8814
  { name: "Rotate client secret", value: "rotate" },
8585
- { name: import_chalk40.default.red("Delete this app client"), value: "delete" },
8815
+ { name: import_chalk41.default.red("Delete this app client"), value: "delete" },
8586
8816
  { name: "\u2190 Back", value: "back" }
8587
8817
  ]
8588
8818
  }]);
@@ -8595,13 +8825,13 @@ async function clientHome(base2, summary) {
8595
8825
  case "callbacks": {
8596
8826
  const { v } = await inquirer3.prompt([{ type: "input", name: "v", message: "Callback URLs (comma-separated):", default: cb.join(", ") }]);
8597
8827
  await admin({ method: "PATCH", path: cBase, body: { authorizedCallbackUrls: parseList(v) }, summary: "Update callback URLs" });
8598
- console.log(import_chalk40.default.green(" Callbacks updated."));
8828
+ console.log(import_chalk41.default.green(" Callbacks updated."));
8599
8829
  break;
8600
8830
  }
8601
8831
  case "scopes": {
8602
8832
  const { v } = await inquirer3.prompt([{ type: "input", name: "v", message: "Scopes (space/comma-separated):", default: scopes.join(" ") }]);
8603
8833
  await admin({ method: "PATCH", path: cBase, body: { scopes: v.split(/[\s,]+/).filter(Boolean) }, summary: "Update scopes" });
8604
- console.log(import_chalk40.default.green(" Scopes updated."));
8834
+ console.log(import_chalk41.default.green(" Scopes updated."));
8605
8835
  break;
8606
8836
  }
8607
8837
  case "expiries": {
@@ -8616,14 +8846,14 @@ async function clientHome(base2, summary) {
8616
8846
  body: { accessTokenExpiry: Number(a.access), idTokenExpiry: Number(a.id), refreshTokenExpiry: Number(a.refresh) },
8617
8847
  summary: "Update token expiries"
8618
8848
  });
8619
- console.log(import_chalk40.default.green(" Expiries updated."));
8849
+ console.log(import_chalk41.default.green(" Expiries updated."));
8620
8850
  break;
8621
8851
  }
8622
8852
  case "secret": {
8623
8853
  const { sure } = await inquirer3.prompt([{ type: "confirm", name: "sure", message: "Print the client secret to this terminal?", default: false }]);
8624
8854
  if (!sure) break;
8625
8855
  const s = await admin({ method: "GET", path: `${cBase}/secret`, summary: "Reveal client secret" });
8626
- console.log(` ${import_chalk40.default.bold("client_secret")}: ${import_chalk40.default.green(s?.clientSecret ?? s?.client_secret ?? JSON.stringify(s))}`);
8856
+ console.log(` ${import_chalk41.default.bold("client_secret")}: ${import_chalk41.default.green(s?.clientSecret ?? s?.client_secret ?? JSON.stringify(s))}`);
8627
8857
  break;
8628
8858
  }
8629
8859
  case "rotate": {
@@ -8631,14 +8861,14 @@ async function clientHome(base2, summary) {
8631
8861
  if (!sure) break;
8632
8862
  const fresh = randomSecret();
8633
8863
  await admin({ method: "PATCH", path: cBase, body: { clientSecret: fresh }, summary: "Rotate client secret" });
8634
- console.log(` New ${import_chalk40.default.bold("client_secret")}: ${import_chalk40.default.green(fresh)} ${import_chalk40.default.dim("(store it now)")}`);
8864
+ console.log(` New ${import_chalk41.default.bold("client_secret")}: ${import_chalk41.default.green(fresh)} ${import_chalk41.default.dim("(store it now)")}`);
8635
8865
  break;
8636
8866
  }
8637
8867
  case "delete": {
8638
8868
  const { sure } = await inquirer3.prompt([{ type: "confirm", name: "sure", message: `Delete app client "${c.name ?? id}"? Consumers logged in through it will lose access.`, default: false }]);
8639
8869
  if (!sure) break;
8640
8870
  await admin({ method: "DELETE", path: cBase, summary: `Delete app client ${id}` });
8641
- console.log(import_chalk40.default.green(" App client deleted."));
8871
+ console.log(import_chalk41.default.green(" App client deleted."));
8642
8872
  return;
8643
8873
  }
8644
8874
  }
@@ -8665,9 +8895,9 @@ async function providersMenu(cBase, clientLabel) {
8665
8895
  const providers = Array.isArray(raw) ? raw : [];
8666
8896
  console.log();
8667
8897
  for (const p of providers) {
8668
- console.log(` ${import_chalk40.default.bold(p.type)} ${import_chalk40.default.dim(`${p.clientId || "(managed)"} \xB7 identity=${p.tokenType ?? "apiblaze"} \xB7 to-upstream=${p.targetServerToken ?? "apiblaze"}${p.isApiblazeDefault ? " \xB7 apiblaze-managed" : ""}`)}`);
8898
+ console.log(` ${import_chalk41.default.bold(p.type)} ${import_chalk41.default.dim(`${p.clientId || "(managed)"} \xB7 identity=${p.tokenType ?? "apiblaze"} \xB7 to-upstream=${p.targetServerToken ?? "apiblaze"}${p.isApiblazeDefault ? " \xB7 apiblaze-managed" : ""}`)}`);
8669
8899
  }
8670
- if (!providers.length) console.log(import_chalk40.default.dim(" No login providers \u2014 consumers cannot sign in to this client yet."));
8900
+ if (!providers.length) console.log(import_chalk41.default.dim(" No login providers \u2014 consumers cannot sign in to this client yet."));
8671
8901
  const { act } = await inquirer3.prompt([{
8672
8902
  type: "list",
8673
8903
  name: "act",
@@ -8725,23 +8955,23 @@ async function providersMenu(cBase, clientLabel) {
8725
8955
  body.targetServerToken = routing;
8726
8956
  }
8727
8957
  await admin({ method: "POST", path: `${cBase}/providers`, body, summary: `Add ${type} login provider` });
8728
- console.log(import_chalk40.default.green(` ${type} provider added.`));
8958
+ console.log(import_chalk41.default.green(` ${type} provider added.`));
8729
8959
  } else {
8730
8960
  const { p } = await inquirer3.prompt([{
8731
8961
  type: "list",
8732
8962
  name: "p",
8733
8963
  message: act === "rm" ? "Remove which provider?" : "Reveal which secret?",
8734
- choices: [...providers.map((x) => ({ name: `${x.type} ${import_chalk40.default.dim(x.clientId || "(managed)")}`, value: x })), { name: "\u2190 Back", value: null }]
8964
+ choices: [...providers.map((x) => ({ name: `${x.type} ${import_chalk41.default.dim(x.clientId || "(managed)")}`, value: x })), { name: "\u2190 Back", value: null }]
8735
8965
  }]);
8736
8966
  if (!p) continue;
8737
8967
  if (act === "rm") {
8738
8968
  const { sure } = await inquirer3.prompt([{ type: "confirm", name: "sure", message: `Remove the ${p.type} provider? Consumers using it can no longer sign in.`, default: false }]);
8739
8969
  if (!sure) continue;
8740
8970
  await admin({ method: "DELETE", path: `${cBase}/providers/${encodeURIComponent(p.id)}`, summary: `Remove ${p.type} provider` });
8741
- console.log(import_chalk40.default.green(` ${p.type} removed.`));
8971
+ console.log(import_chalk41.default.green(` ${p.type} removed.`));
8742
8972
  } else {
8743
8973
  const s = await admin({ method: "GET", path: `${cBase}/providers/${encodeURIComponent(p.id)}/secret`, summary: `Reveal ${p.type} provider secret` });
8744
- console.log(` ${import_chalk40.default.bold("client_secret")}: ${import_chalk40.default.green(s?.clientSecret ?? s?.client_secret ?? JSON.stringify(s))}`);
8974
+ console.log(` ${import_chalk41.default.bold("client_secret")}: ${import_chalk41.default.green(s?.clientSecret ?? s?.client_secret ?? JSON.stringify(s))}`);
8745
8975
  }
8746
8976
  }
8747
8977
  }
@@ -8749,7 +8979,7 @@ async function providersMenu(cBase, clientLabel) {
8749
8979
 
8750
8980
  // src/commands/spec.ts
8751
8981
  var fs11 = __toESM(require("fs"));
8752
- var import_chalk41 = __toESM(require("chalk"));
8982
+ var import_chalk42 = __toESM(require("chalk"));
8753
8983
  var import_ora18 = __toESM(require("ora"));
8754
8984
  init_admin();
8755
8985
  init_api();
@@ -8766,14 +8996,14 @@ async function runSpecGet(project, opts) {
8766
8996
  }
8767
8997
  async function runSpecSet(project, opts) {
8768
8998
  if (!opts.file) {
8769
- console.error(import_chalk41.default.red("--file <path> is required (OpenAPI JSON or YAML)."));
8999
+ console.error(import_chalk42.default.red("--file <path> is required (OpenAPI JSON or YAML)."));
8770
9000
  process.exit(1);
8771
9001
  }
8772
9002
  let specContent;
8773
9003
  try {
8774
9004
  specContent = fs11.readFileSync(opts.file, "utf-8");
8775
9005
  } catch {
8776
- console.error(import_chalk41.default.red(`Cannot read file: ${opts.file}`));
9006
+ console.error(import_chalk42.default.red(`Cannot read file: ${opts.file}`));
8777
9007
  process.exit(1);
8778
9008
  }
8779
9009
  const { teamId } = await resolveTeam(opts.team);
@@ -8802,23 +9032,23 @@ async function runSpecSet(project, opts) {
8802
9032
  function printSpecChangeReport(report, projectName) {
8803
9033
  const r = report.routes;
8804
9034
  if (r) {
8805
- for (const a of r.added) console.log(import_chalk41.default.green(` + ${a}`));
8806
- for (const d of r.removed) console.log(import_chalk41.default.red(` \u2212 ${d}`));
8807
- for (const rn of r.renamed ?? []) console.log(import_chalk41.default.yellow(` ~ ${rn.from} \u2192 ${rn.to}`));
8808
- for (const m of r.modified ?? []) console.log(import_chalk41.default.dim(` \xB1 ${m} (params/schema changed)`));
9035
+ for (const a of r.added) console.log(import_chalk42.default.green(` + ${a}`));
9036
+ for (const d of r.removed) console.log(import_chalk42.default.red(` \u2212 ${d}`));
9037
+ for (const rn of r.renamed ?? []) console.log(import_chalk42.default.yellow(` ~ ${rn.from} \u2192 ${rn.to}`));
9038
+ for (const m of r.modified ?? []) console.log(import_chalk42.default.dim(` \xB1 ${m} (params/schema changed)`));
8809
9039
  }
8810
- if (report.applied?.mcp_regenerated) console.log(import_chalk41.default.dim(" MCP catalogue regenerated."));
8811
- if (report.applied?.candidates_cleared) console.log(import_chalk41.default.dim(` ${report.applied.candidates_cleared} route candidate(s) now documented \u2014 cleared.`));
9040
+ if (report.applied?.mcp_regenerated) console.log(import_chalk42.default.dim(" MCP catalogue regenerated."));
9041
+ if (report.applied?.candidates_cleared) console.log(import_chalk42.default.dim(` ${report.applied.candidates_cleared} route candidate(s) now documented \u2014 cleared.`));
8812
9042
  for (const item of report.attention ?? []) {
8813
- console.log(import_chalk41.default.yellow(` \u26A0 ${item.detail}`));
9043
+ console.log(import_chalk42.default.yellow(` \u26A0 ${item.detail}`));
8814
9044
  if (item.suggestion?.carry_from && item.suggestion.carry_to) {
8815
- console.log(import_chalk41.default.dim(` Fix: apiblaze spec carry ${projectName} --method ${item.suggestion.method} --from "${item.suggestion.carry_from}" --to "${item.suggestion.carry_to}"`));
9045
+ console.log(import_chalk42.default.dim(` Fix: apiblaze spec carry ${projectName} --method ${item.suggestion.method} --from "${item.suggestion.carry_from}" --to "${item.suggestion.carry_to}"`));
8816
9046
  }
8817
9047
  }
8818
9048
  }
8819
9049
  async function runSpecCarry(project, opts) {
8820
9050
  if (!opts.method || !opts.from || !opts.to) {
8821
- console.error(import_chalk41.default.red("--method, --from and --to are required."));
9051
+ console.error(import_chalk42.default.red("--method, --from and --to are required."));
8822
9052
  process.exit(1);
8823
9053
  }
8824
9054
  const { teamId } = await resolveTeam(opts.team);
@@ -8840,7 +9070,7 @@ async function runSpecCarry(project, opts) {
8840
9070
  }
8841
9071
  async function runSpecDeleteRule(project, opts) {
8842
9072
  if (!opts.method || !opts.route) {
8843
- console.error(import_chalk41.default.red("--method and --route are required."));
9073
+ console.error(import_chalk42.default.red("--method and --route are required."));
8844
9074
  process.exit(1);
8845
9075
  }
8846
9076
  const { teamId } = await resolveTeam(opts.team);
@@ -8860,14 +9090,14 @@ async function runSpecDeleteRule(project, opts) {
8860
9090
  }
8861
9091
 
8862
9092
  // src/commands/agent.ts
8863
- var import_chalk43 = __toESM(require("chalk"));
9093
+ var import_chalk44 = __toESM(require("chalk"));
8864
9094
  var import_ora19 = __toESM(require("ora"));
8865
9095
  init_auth();
8866
9096
  init_admin();
8867
9097
  init_resolve();
8868
9098
 
8869
9099
  // src/lib/tools.ts
8870
- var import_chalk42 = __toESM(require("chalk"));
9100
+ var import_chalk43 = __toESM(require("chalk"));
8871
9101
  init_admin();
8872
9102
  init_api();
8873
9103
  init_resolve();
@@ -8887,15 +9117,15 @@ var TOOLS = [
8887
9117
  const key = keys.dev ?? Object.values(keys)[0];
8888
9118
  const url = `https://${a.name}.abz.run/${version2}/dev`;
8889
9119
  const tryIt = buildTryItCurl(url, auth, key);
8890
- const lines = [` ${import_chalk42.default.dim("Proxy URL:")} ${import_chalk42.default.bold(url)}`];
8891
- if (res.devPortal) lines.push(` ${import_chalk42.default.dim("Dev portal:")} ${res.devPortal}`);
9120
+ const lines = [` ${import_chalk43.default.dim("Proxy URL:")} ${import_chalk43.default.bold(url)}`];
9121
+ if (res.devPortal) lines.push(` ${import_chalk43.default.dim("Dev portal:")} ${res.devPortal}`);
8892
9122
  const envs = Object.keys(keys);
8893
9123
  if (envs.length) {
8894
- lines.push("", ` ${import_chalk42.default.bold("API keys")} ${import_chalk42.default.dim("(bootstrapped \u2014 send as the X-API-Key header; shown once):")}`);
9124
+ lines.push("", ` ${import_chalk43.default.bold("API keys")} ${import_chalk43.default.dim("(bootstrapped \u2014 send as the X-API-Key header; shown once):")}`);
8895
9125
  const w = Math.max(...envs.map((e) => e.length));
8896
- for (const env of envs) lines.push(` ${import_chalk42.default.cyan(env.padEnd(w))} ${import_chalk42.default.green(keys[env])}`);
9126
+ for (const env of envs) lines.push(` ${import_chalk43.default.cyan(env.padEnd(w))} ${import_chalk43.default.green(keys[env])}`);
8897
9127
  }
8898
- if (tryIt) lines.push("", ` ${import_chalk42.default.dim("Try it:")}`, ` ${import_chalk42.default.cyan(tryIt)}`);
9128
+ if (tryIt) lines.push("", ` ${import_chalk43.default.dim("Try it:")}`, ` ${import_chalk43.default.cyan(tryIt)}`);
8899
9129
  return { ...res, proxy_url: url, keys, ...tryIt ? { try_it: tryIt } : {}, display: lines.join("\n") };
8900
9130
  }
8901
9131
  },
@@ -9051,17 +9281,17 @@ function truncate(value, max = 1500) {
9051
9281
  }
9052
9282
  function printCost(resp) {
9053
9283
  const line = formatBilling(resp.billing);
9054
- if (line) console.log(import_chalk43.default.magenta(` ${line}`) + import_chalk43.default.dim(` (${resp.llm.model}, ${resp.llm.total_tokens} tok)`));
9284
+ if (line) console.log(import_chalk44.default.magenta(` ${line}`) + import_chalk44.default.dim(` (${resp.llm.model}, ${resp.llm.total_tokens} tok)`));
9055
9285
  }
9056
9286
  async function runAgent(opts) {
9057
9287
  requireAuth();
9058
9288
  const { teamId, teamName } = await resolveTeam(opts.team);
9059
9289
  const { default: inquirer3 } = await import("inquirer");
9060
- console.log(import_chalk43.default.bold("APIblaze agent") + import_chalk43.default.dim(` \xB7 team ${teamName ?? teamId}`));
9061
- console.log(import_chalk43.default.dim('Ask me to create/delete/configure proxies, tenants, keys, domains, specs. Type "exit" to quit.\n'));
9290
+ console.log(import_chalk44.default.bold("APIblaze agent") + import_chalk44.default.dim(` \xB7 team ${teamName ?? teamId}`));
9291
+ console.log(import_chalk44.default.dim('Ask me to create/delete/configure proxies, tenants, keys, domains, specs. Type "exit" to quit.\n'));
9062
9292
  const history = [];
9063
9293
  while (true) {
9064
- const { input } = await inquirer3.prompt([{ type: "input", name: "input", message: import_chalk43.default.cyan("you") + " \u203A" }]);
9294
+ const { input } = await inquirer3.prompt([{ type: "input", name: "input", message: import_chalk44.default.cyan("you") + " \u203A" }]);
9065
9295
  const text = (input ?? "").trim();
9066
9296
  if (!text) continue;
9067
9297
  if (["exit", "quit", ":q"].includes(text.toLowerCase())) break;
@@ -9075,14 +9305,14 @@ async function runAgent(opts) {
9075
9305
  } catch (err) {
9076
9306
  spinner.stop();
9077
9307
  if (err instanceof ApiError && err.status === 402) {
9078
- console.log(import_chalk43.default.yellow(" Insufficient credits \u2014 top up to keep using the agent."));
9308
+ console.log(import_chalk44.default.yellow(" Insufficient credits \u2014 top up to keep using the agent."));
9079
9309
  break;
9080
9310
  }
9081
9311
  throw err;
9082
9312
  }
9083
9313
  history.push({ role: "assistant", content: resp.raw });
9084
9314
  printCost(resp);
9085
- if (resp.reply) console.log(import_chalk43.default.green("agent") + " \u203A " + resp.reply);
9315
+ if (resp.reply) console.log(import_chalk44.default.green("agent") + " \u203A " + resp.reply);
9086
9316
  if (!resp.action) break;
9087
9317
  const tool = findTool(resp.action.tool);
9088
9318
  if (!tool) {
@@ -9107,11 +9337,11 @@ async function runAgent(opts) {
9107
9337
  }
9108
9338
  renderTrace();
9109
9339
  if (step === MAX_TOOL_STEPS - 1) {
9110
- console.log(import_chalk43.default.dim(" (paused after several steps \u2014 tell me how to continue)"));
9340
+ console.log(import_chalk44.default.dim(" (paused after several steps \u2014 tell me how to continue)"));
9111
9341
  }
9112
9342
  }
9113
9343
  }
9114
- console.log(import_chalk43.default.dim("\nBye."));
9344
+ console.log(import_chalk44.default.dim("\nBye."));
9115
9345
  }
9116
9346
 
9117
9347
  // src/commands/config-browse.ts
@@ -9406,11 +9636,11 @@ function dig(blob, dotted) {
9406
9636
  }
9407
9637
  var readSetting = (s, cfg) => s.read ? s.read(cfg) : dig(cfg, s.key);
9408
9638
  function show(v) {
9409
- if (v === void 0) return import_chalk44.default.dim("(unset)");
9410
- if (v === null) return import_chalk44.default.dim("null");
9411
- if (typeof v === "object") return import_chalk44.default.cyan(JSON.stringify(v));
9412
- if (typeof v === "boolean") return v ? import_chalk44.default.green("on") : import_chalk44.default.red("off");
9413
- return import_chalk44.default.cyan(String(v));
9639
+ if (v === void 0) return import_chalk45.default.dim("(unset)");
9640
+ if (v === null) return import_chalk45.default.dim("null");
9641
+ if (typeof v === "object") return import_chalk45.default.cyan(JSON.stringify(v));
9642
+ if (typeof v === "boolean") return v ? import_chalk45.default.green("on") : import_chalk45.default.red("off");
9643
+ return import_chalk45.default.cyan(String(v));
9414
9644
  }
9415
9645
  function parseValue(raw) {
9416
9646
  if (raw === "true") return true;
@@ -9452,10 +9682,10 @@ async function patchSetting(proj2, s, value, cfg) {
9452
9682
  }
9453
9683
  }
9454
9684
  var loginFirst = (what) => {
9455
- console.log(import_chalk44.default.yellow(`
9685
+ console.log(import_chalk45.default.yellow(`
9456
9686
  Log in first to ${what}.`));
9457
- console.log(import_chalk44.default.dim(" Run `npx apiblaze login` \u2014 or `npx apiblaze claim` if you created this proxy"));
9458
- console.log(import_chalk44.default.dim(" anonymously and want to bring it into your account.\n"));
9687
+ console.log(import_chalk45.default.dim(" Run `npx apiblaze login` \u2014 or `npx apiblaze claim` if you created this proxy"));
9688
+ console.log(import_chalk45.default.dim(" anonymously and want to bring it into your account.\n"));
9459
9689
  };
9460
9690
  async function runConfig(project, key, value, opts) {
9461
9691
  const creds = loadCredentials();
@@ -9472,9 +9702,9 @@ async function runConfig(project, key, value, opts) {
9472
9702
  }
9473
9703
  const setting = SETTINGS.find((s) => s.key === key);
9474
9704
  if (!setting) {
9475
- console.error(import_chalk44.default.red(`Unknown setting "${key}".`));
9476
- console.error(import_chalk44.default.dim(" Known: " + SETTINGS.map((s) => s.key).join(", ")));
9477
- console.error(import_chalk44.default.dim(" (Features like transforms/domains/tenants live in the menu: `apiblaze config <project>`.)"));
9705
+ console.error(import_chalk45.default.red(`Unknown setting "${key}".`));
9706
+ console.error(import_chalk45.default.dim(" Known: " + SETTINGS.map((s) => s.key).join(", ")));
9707
+ console.error(import_chalk45.default.dim(" (Features like transforms/domains/tenants live in the menu: `apiblaze config <project>`.)"));
9478
9708
  process.exit(1);
9479
9709
  }
9480
9710
  if (value === void 0) {
@@ -9489,7 +9719,7 @@ async function pickProject(teamId) {
9489
9719
  const { getProjects: getProjects2 } = await Promise.resolve().then(() => (init_api(), api_exports));
9490
9720
  const projects = await getProjects2(teamId).catch(() => []);
9491
9721
  if (!projects.length) {
9492
- console.error(import_chalk44.default.red("No projects in this team. Create one: `npx apiblaze create`."));
9722
+ console.error(import_chalk45.default.red("No projects in this team. Create one: `npx apiblaze create`."));
9493
9723
  process.exit(1);
9494
9724
  }
9495
9725
  const { default: inquirer3 } = await import("inquirer");
@@ -9497,7 +9727,7 @@ async function pickProject(teamId) {
9497
9727
  type: "list",
9498
9728
  name: "picked",
9499
9729
  message: "Which project?",
9500
- choices: projects.map((p) => ({ name: `${p.projectName} ${import_chalk44.default.dim("v" + p.apiVersion)}`, value: p }))
9730
+ choices: projects.map((p) => ({ name: `${p.projectName} ${import_chalk45.default.dim("v" + p.apiVersion)}`, value: p }))
9501
9731
  }]);
9502
9732
  return { projectId: picked.projectId, projectName: picked.projectName, apiVersion: picked.apiVersion, teamId, tenant: picked.tenant };
9503
9733
  }
@@ -9508,25 +9738,25 @@ function printAll(proj2, cfg, json) {
9508
9738
  console.log(JSON.stringify(out, null, 2));
9509
9739
  return;
9510
9740
  }
9511
- console.log(import_chalk44.default.bold(`
9741
+ console.log(import_chalk45.default.bold(`
9512
9742
  ${proj2.projectName} v${proj2.apiVersion} \u2014 settings
9513
9743
  `));
9514
9744
  for (const group2 of SETTING_GROUPS) {
9515
- console.log(import_chalk44.default.bold(group2));
9745
+ console.log(import_chalk45.default.bold(group2));
9516
9746
  for (const s of SETTINGS.filter((x) => x.group === group2)) {
9517
- console.log(` ${s.key.padEnd(32)} ${show(readSetting(s, cfg))} ${import_chalk44.default.dim(s.desc)}`);
9747
+ console.log(` ${s.key.padEnd(32)} ${show(readSetting(s, cfg))} ${import_chalk45.default.dim(s.desc)}`);
9518
9748
  }
9519
9749
  console.log();
9520
9750
  }
9521
- console.log(import_chalk44.default.dim("Change one: apiblaze config " + proj2.projectName + " <key> <value> (add --verbose for the API call)"));
9751
+ console.log(import_chalk45.default.dim("Change one: apiblaze config " + proj2.projectName + " <key> <value> (add --verbose for the API call)"));
9522
9752
  }
9523
9753
  async function discoveryMenu(project) {
9524
9754
  const { default: inquirer3 } = await import("inquirer");
9525
- console.log(import_chalk44.default.bold(`
9755
+ console.log(import_chalk45.default.bold(`
9526
9756
  APIblaze proxy configuration${project ? ` \u2014 ${project}` : ""}
9527
9757
  `));
9528
- console.log(import_chalk44.default.dim("You are not logged in \u2014 browsing what's configurable. Everything below works"));
9529
- console.log(import_chalk44.default.dim("from this menu once you log in (`npx apiblaze login`).\n"));
9758
+ console.log(import_chalk45.default.dim("You are not logged in \u2014 browsing what's configurable. Everything below works"));
9759
+ console.log(import_chalk45.default.dim("from this menu once you log in (`npx apiblaze login`).\n"));
9530
9760
  for (; ; ) {
9531
9761
  const { pick: pick2 } = await inquirer3.prompt([{
9532
9762
  type: "list",
@@ -9534,13 +9764,13 @@ APIblaze proxy configuration${project ? ` \u2014 ${project}` : ""}
9534
9764
  message: "Explore:",
9535
9765
  pageSize: 20,
9536
9766
  choices: [
9537
- new inquirer3.Separator(import_chalk44.default.bold("\u2014 Settings \u2014")),
9767
+ new inquirer3.Separator(import_chalk45.default.bold("\u2014 Settings \u2014")),
9538
9768
  ...SETTING_GROUPS.map((g) => ({
9539
- name: `${g} ${import_chalk44.default.dim(SETTINGS.filter((s) => s.group === g).map((s) => s.label).join(", "))}`,
9769
+ name: `${g} ${import_chalk45.default.dim(SETTINGS.filter((s) => s.group === g).map((s) => s.label).join(", "))}`,
9540
9770
  value: { kind: "settings", g }
9541
9771
  })),
9542
- new inquirer3.Separator(import_chalk44.default.bold("\u2014 Features \u2014")),
9543
- ...FEATURES.map((f) => ({ name: `${f.label} ${import_chalk44.default.dim(f.desc)}`, value: { kind: "feature", f } })),
9772
+ new inquirer3.Separator(import_chalk45.default.bold("\u2014 Features \u2014")),
9773
+ ...FEATURES.map((f) => ({ name: `${f.label} ${import_chalk45.default.dim(f.desc)}`, value: { kind: "feature", f } })),
9544
9774
  new inquirer3.Separator(),
9545
9775
  { name: "Exit", value: { kind: "exit" } }
9546
9776
  ]
@@ -9549,24 +9779,24 @@ APIblaze proxy configuration${project ? ` \u2014 ${project}` : ""}
9549
9779
  if (pick2.kind === "settings") {
9550
9780
  console.log();
9551
9781
  for (const s of SETTINGS.filter((x) => x.group === pick2.g)) {
9552
- console.log(` ${import_chalk44.default.bold(s.label.padEnd(28))} ${import_chalk44.default.dim(s.desc)}`);
9553
- console.log(` ${import_chalk44.default.dim(" key: " + s.key)}`);
9782
+ console.log(` ${import_chalk45.default.bold(s.label.padEnd(28))} ${import_chalk45.default.dim(s.desc)}`);
9783
+ console.log(` ${import_chalk45.default.dim(" key: " + s.key)}`);
9554
9784
  }
9555
9785
  loginFirst("view or change these settings");
9556
9786
  } else {
9557
9787
  const f = pick2.f;
9558
9788
  console.log(`
9559
- ${import_chalk44.default.bold(f.label)} \u2014 ${f.desc}`);
9789
+ ${import_chalk45.default.bold(f.label)} \u2014 ${f.desc}`);
9560
9790
  loginFirst(`use ${f.label.toLowerCase()}`);
9561
9791
  }
9562
9792
  }
9563
9793
  }
9564
9794
  async function navigator(proj2, cfg, opts) {
9565
9795
  const { default: inquirer3 } = await import("inquirer");
9566
- console.log(import_chalk44.default.bold(`
9796
+ console.log(import_chalk45.default.bold(`
9567
9797
  ${proj2.projectName} v${proj2.apiVersion} \u2014 configuration
9568
9798
  `));
9569
- console.log(import_chalk44.default.dim("Tip: every change is one API call \u2014 add --verbose to see the curl equivalent.\n"));
9799
+ console.log(import_chalk45.default.dim("Tip: every change is one API call \u2014 add --verbose to see the curl equivalent.\n"));
9570
9800
  let blob = cfg;
9571
9801
  for (; ; ) {
9572
9802
  const { pick: pick2 } = await inquirer3.prompt([{
@@ -9575,10 +9805,10 @@ ${proj2.projectName} v${proj2.apiVersion} \u2014 configuration
9575
9805
  message: "Where to?",
9576
9806
  pageSize: 20,
9577
9807
  choices: [
9578
- new inquirer3.Separator(import_chalk44.default.bold("\u2014 Settings \u2014")),
9808
+ new inquirer3.Separator(import_chalk45.default.bold("\u2014 Settings \u2014")),
9579
9809
  ...SETTING_GROUPS.map((g) => ({ name: g, value: { kind: "settings", g } })),
9580
- new inquirer3.Separator(import_chalk44.default.bold("\u2014 Features \u2014")),
9581
- ...FEATURES.map((f) => ({ name: `${f.label} ${import_chalk44.default.dim(f.desc)}`, value: { kind: f.go } })),
9810
+ new inquirer3.Separator(import_chalk45.default.bold("\u2014 Features \u2014")),
9811
+ ...FEATURES.map((f) => ({ name: `${f.label} ${import_chalk45.default.dim(f.desc)}`, value: { kind: f.go } })),
9582
9812
  new inquirer3.Separator(),
9583
9813
  { name: "Show all settings", value: { kind: "list" } },
9584
9814
  { name: "Exit", value: { kind: "exit" } }
@@ -9618,7 +9848,7 @@ ${proj2.projectName} v${proj2.apiVersion} \u2014 configuration
9618
9848
  }
9619
9849
  }
9620
9850
  } catch (err) {
9621
- console.error(import_chalk44.default.red(` ${err instanceof Error ? err.message : String(err)}`));
9851
+ console.error(import_chalk45.default.red(` ${err instanceof Error ? err.message : String(err)}`));
9622
9852
  }
9623
9853
  }
9624
9854
  }
@@ -9632,7 +9862,7 @@ async function settingsGroup(proj2, cfg, group2) {
9632
9862
  message: group2 + ":",
9633
9863
  pageSize: 16,
9634
9864
  choices: [
9635
- ...items.map((s2) => ({ name: `${s2.label.padEnd(30)} ${show(readSetting(s2, cfg))} ${import_chalk44.default.dim(s2.desc)}`, value: s2 })),
9865
+ ...items.map((s2) => ({ name: `${s2.label.padEnd(30)} ${show(readSetting(s2, cfg))} ${import_chalk45.default.dim(s2.desc)}`, value: s2 })),
9636
9866
  new inquirer3.Separator(),
9637
9867
  { name: "\u2190 Back", value: null }
9638
9868
  ]
@@ -9650,7 +9880,7 @@ async function settingsGroup(proj2, cfg, group2) {
9650
9880
  } else if (s.type === "number") {
9651
9881
  const { v } = await inquirer3.prompt([{ type: "input", name: "v", message: `${s.label} (number):`, default: readSetting(s, cfg) }]);
9652
9882
  if (v === "" || Number.isNaN(Number(v))) {
9653
- console.log(import_chalk44.default.yellow(" Not a number \u2014 unchanged."));
9883
+ console.log(import_chalk45.default.yellow(" Not a number \u2014 unchanged."));
9654
9884
  continue;
9655
9885
  }
9656
9886
  value = Number(v);
@@ -9731,7 +9961,7 @@ async function buildCondition(phase) {
9731
9961
  const items = [];
9732
9962
  for (; ; ) {
9733
9963
  const a = await inquirer3.prompt([
9734
- { type: "input", name: "source", message: `Condition field ${import_chalk44.default.dim(srcHint)}:`, validate: (s) => !!s || "required" },
9964
+ { type: "input", name: "source", message: `Condition field ${import_chalk45.default.dim(srcHint)}:`, validate: (s) => !!s || "required" },
9735
9965
  { type: "list", name: "operator", message: "Operator:", choices: [
9736
9966
  "eq",
9737
9967
  "neq",
@@ -9762,7 +9992,7 @@ async function buildCondition(phase) {
9762
9992
  function showCondition(cond) {
9763
9993
  if (!Array.isArray(cond) || !cond.length) return "";
9764
9994
  const s = cond.map((c) => `${c.source} ${c.operator}${c.value !== void 0 ? ` "${c.value}"` : ""}${c.logicOp ? ` ${c.logicOp}` : ""}`).join(" ");
9765
- return import_chalk44.default.dim(` when ${s}`);
9995
+ return import_chalk45.default.dim(` when ${s}`);
9766
9996
  }
9767
9997
  async function transformsMenu(proj2) {
9768
9998
  const { default: inquirer3 } = await import("inquirer");
@@ -9771,12 +10001,12 @@ async function transformsMenu(proj2) {
9771
10001
  const out = await admin({ method: "GET", path: base2, summary: "List transform rules" });
9772
10002
  const rules = out?.rules ?? [];
9773
10003
  console.log();
9774
- if (!rules.length) console.log(import_chalk44.default.dim(" No transform rules yet."));
10004
+ if (!rules.length) console.log(import_chalk45.default.dim(" No transform rules yet."));
9775
10005
  for (const r of rules) {
9776
10006
  const a = r.action ?? {};
9777
10007
  const fns = [...a.source_fns ?? [], ...a.dest_fns ?? []].map((f) => f.fn);
9778
- const what = a.type === "hardcode" ? `${a.destination} = "${a.value}"` : a.type === "remove" ? `remove ${a.field}` : `${a.source} \u2192 ${a.destination}${a.lookup ? " (mapped)" : ""}${fns.length ? import_chalk44.default.dim(` via ${fns.join("\u2192")}`) : ""}`;
9779
- console.log(` ${r.enabled ? import_chalk44.default.green("\u25CF") : import_chalk44.default.dim("\u25CB")} ${import_chalk44.default.bold(r.name)} ${import_chalk44.default.dim(`[${r.phase ?? "request"}]`)} ${what}${showCondition(r.condition)}`);
10008
+ const what = a.type === "hardcode" ? `${a.destination} = "${a.value}"` : a.type === "remove" ? `remove ${a.field}` : `${a.source} \u2192 ${a.destination}${a.lookup ? " (mapped)" : ""}${fns.length ? import_chalk45.default.dim(` via ${fns.join("\u2192")}`) : ""}`;
10009
+ console.log(` ${r.enabled ? import_chalk45.default.green("\u25CF") : import_chalk45.default.dim("\u25CB")} ${import_chalk45.default.bold(r.name)} ${import_chalk45.default.dim(`[${r.phase ?? "request"}]`)} ${what}${showCondition(r.condition)}`);
9780
10010
  }
9781
10011
  const { act } = await inquirer3.prompt([{
9782
10012
  type: "list",
@@ -9788,7 +10018,7 @@ async function transformsMenu(proj2) {
9788
10018
  { name: "Enable/disable a rule", value: "toggle" },
9789
10019
  { name: "Delete a rule", value: "delete" }
9790
10020
  ] : [],
9791
- { name: import_chalk44.default.dim("Add from raw JSON (grouped conditions, lookup tables, \u2026)"), value: "raw" },
10021
+ { name: import_chalk45.default.dim("Add from raw JSON (grouped conditions, lookup tables, \u2026)"), value: "raw" },
9792
10022
  { name: "\u2190 Back", value: "back" }
9793
10023
  ]
9794
10024
  }]);
@@ -9801,11 +10031,11 @@ async function transformsMenu(proj2) {
9801
10031
  }]);
9802
10032
  const body = parseValue(raw);
9803
10033
  if (!body || typeof body !== "object" || Array.isArray(body)) {
9804
- console.log(import_chalk44.default.yellow(" Not a JSON object \u2014 skipped."));
10034
+ console.log(import_chalk45.default.yellow(" Not a JSON object \u2014 skipped."));
9805
10035
  continue;
9806
10036
  }
9807
10037
  await admin({ method: "POST", path: base2, body, summary: "Create transform rule (raw JSON)" });
9808
- console.log(import_chalk44.default.green(" Rule created."));
10038
+ console.log(import_chalk45.default.green(" Rule created."));
9809
10039
  continue;
9810
10040
  }
9811
10041
  if (act === "add") {
@@ -9821,7 +10051,7 @@ async function transformsMenu(proj2) {
9821
10051
  { name: "Remove a field", value: "remove" }
9822
10052
  ] }
9823
10053
  ]);
9824
- const fieldHint = import_chalk44.default.dim("(e.g. header:x-api-version, param:limit, bodyvar:user.id)");
10054
+ const fieldHint = import_chalk45.default.dim("(e.g. header:x-api-version, param:limit, bodyvar:user.id)");
9825
10055
  let action2;
9826
10056
  if (ans.kind === "hardcode") {
9827
10057
  const a = await inquirer3.prompt([
@@ -9868,16 +10098,16 @@ async function transformsMenu(proj2) {
9868
10098
  type: "list",
9869
10099
  name: "rule",
9870
10100
  message: act === "toggle" ? "Which rule?" : "Delete which rule?",
9871
- choices: [...rules.map((r) => ({ name: `${r.name} ${import_chalk44.default.dim(`[${r.phase ?? "request"}]`)}`, value: r })), { name: "\u2190 Back", value: null }]
10101
+ choices: [...rules.map((r) => ({ name: `${r.name} ${import_chalk45.default.dim(`[${r.phase ?? "request"}]`)}`, value: r })), { name: "\u2190 Back", value: null }]
9872
10102
  }]);
9873
10103
  if (!rule) continue;
9874
10104
  if (act === "toggle") {
9875
10105
  const flipped = { ...rule, enabled: rule.enabled === false };
9876
10106
  await admin({ method: "PUT", path: `${base2}/${rule.id}`, body: flipped, summary: `${flipped.enabled ? "Enable" : "Disable"} transform "${rule.name}"` });
9877
- console.log(import_chalk44.default.green(` ${rule.name} \u2192 ${flipped.enabled ? "enabled" : "disabled"}`));
10107
+ console.log(import_chalk45.default.green(` ${rule.name} \u2192 ${flipped.enabled ? "enabled" : "disabled"}`));
9878
10108
  } else {
9879
10109
  await admin({ method: "DELETE", path: `${base2}/${rule.id}`, summary: `Delete transform "${rule.name}"` });
9880
- console.log(import_chalk44.default.green(` ${rule.name} deleted.`));
10110
+ console.log(import_chalk45.default.green(` ${rule.name} deleted.`));
9881
10111
  }
9882
10112
  }
9883
10113
  }
@@ -9889,9 +10119,9 @@ async function mappingsMenu(proj2) {
9889
10119
  const out = await admin({ method: "GET", path: base2, summary: "List mapping tables" });
9890
10120
  const tables = out?.mappings ?? out?.tables ?? [];
9891
10121
  console.log();
9892
- if (!tables.length) console.log(import_chalk44.default.dim(" No mapping tables yet."));
10122
+ if (!tables.length) console.log(import_chalk45.default.dim(" No mapping tables yet."));
9893
10123
  for (const t of tables) {
9894
- console.log(` ${import_chalk44.default.bold(t.name)} ${import_chalk44.default.dim(`${t.entries?.length ?? "?"} entries${t.hide_map_values ? ", hidden" : ""}${t.encrypt_values ? ", encrypted" : ""}`)}`);
10124
+ console.log(` ${import_chalk45.default.bold(t.name)} ${import_chalk45.default.dim(`${t.entries?.length ?? "?"} entries${t.hide_map_values ? ", hidden" : ""}${t.encrypt_values ? ", encrypted" : ""}`)}`);
9895
10125
  }
9896
10126
  const { act } = await inquirer3.prompt([{
9897
10127
  type: "list",
@@ -9911,11 +10141,11 @@ async function mappingsMenu(proj2) {
9911
10141
  ]);
9912
10142
  const entries2 = parseValue(a.entries);
9913
10143
  if (!Array.isArray(entries2)) {
9914
- console.log(import_chalk44.default.yellow(" Entries must be a JSON array \u2014 not created."));
10144
+ console.log(import_chalk45.default.yellow(" Entries must be a JSON array \u2014 not created."));
9915
10145
  continue;
9916
10146
  }
9917
10147
  await admin({ method: "POST", path: base2, body: { name: a.name, entries: entries2 }, summary: `Create mapping table "${a.name}"` });
9918
- console.log(import_chalk44.default.green(` Table "${a.name}" created.`));
10148
+ console.log(import_chalk45.default.green(` Table "${a.name}" created.`));
9919
10149
  } else {
9920
10150
  const { table } = await inquirer3.prompt([{
9921
10151
  type: "list",
@@ -9925,7 +10155,7 @@ async function mappingsMenu(proj2) {
9925
10155
  }]);
9926
10156
  if (!table) continue;
9927
10157
  await admin({ method: "DELETE", path: `${base2}/${table.id}`, summary: `Delete mapping table "${table.name}"` });
9928
- console.log(import_chalk44.default.green(` ${table.name} deleted.`));
10158
+ console.log(import_chalk45.default.green(` ${table.name} deleted.`));
9929
10159
  }
9930
10160
  }
9931
10161
  }
@@ -9936,14 +10166,14 @@ async function tenantsMenu(proj2, opts) {
9936
10166
  const out = await admin({ method: "GET", path: base2, summary: "List attached tenants" });
9937
10167
  const tenants = out?.tenants ?? [];
9938
10168
  console.log();
9939
- if (!tenants.length) console.log(import_chalk44.default.dim(" No tenants attached (consumers use the default tenant)."));
9940
- for (const t of tenants) console.log(` ${import_chalk44.default.bold(t.tenant_name ?? t.name)} ${import_chalk44.default.dim(t.display_name ?? "")}`);
10169
+ if (!tenants.length) console.log(import_chalk45.default.dim(" No tenants attached (consumers use the default tenant)."));
10170
+ for (const t of tenants) console.log(` ${import_chalk45.default.bold(t.tenant_name ?? t.name)} ${import_chalk45.default.dim(t.display_name ?? "")}`);
9941
10171
  const { act } = await inquirer3.prompt([{
9942
10172
  type: "list",
9943
10173
  name: "act",
9944
10174
  message: "Tenants:",
9945
10175
  choices: [
9946
- { name: `Manage a tenant\u2026 ${import_chalk44.default.dim("settings, login app clients, providers, issuers \u2014 affects EVERY proxy the tenant serves")}`, value: "manage" },
10176
+ { name: `Manage a tenant\u2026 ${import_chalk45.default.dim("settings, login app clients, providers, issuers \u2014 affects EVERY proxy the tenant serves")}`, value: "manage" },
9947
10177
  { name: "Attach a tenant to this project", value: "attach" },
9948
10178
  ...tenants.length ? [{ name: "Detach a tenant from this project", value: "detach" }] : [],
9949
10179
  { name: "\u2190 Back", value: "back" }
@@ -9966,7 +10196,7 @@ async function tenantsMenu(proj2, opts) {
9966
10196
  }]);
9967
10197
  if (!t) continue;
9968
10198
  await admin({ method: "DELETE", path: `${base2}/${encodeURIComponent(t.tenant_name ?? t.name)}`, summary: `Detach tenant ${t.tenant_name ?? t.name}` });
9969
- console.log(import_chalk44.default.green(` Detached ${t.tenant_name ?? t.name}.`));
10199
+ console.log(import_chalk45.default.green(` Detached ${t.tenant_name ?? t.name}.`));
9970
10200
  }
9971
10201
  }
9972
10202
  }
@@ -10009,7 +10239,7 @@ async function specMenu(proj2, opts) {
10009
10239
  choices: [
10010
10240
  { name: "Print the stored spec", value: "get" },
10011
10241
  { name: "Refresh the spec from its source", value: "refresh" },
10012
- { name: import_chalk44.default.dim("Build the spec by chatting over real traffic \u2192 agent"), value: "agent" },
10242
+ { name: import_chalk45.default.dim("Build the spec by chatting over real traffic \u2192 agent"), value: "agent" },
10013
10243
  { name: "\u2190 Back", value: "back" }
10014
10244
  ]
10015
10245
  }]);
@@ -10017,7 +10247,7 @@ async function specMenu(proj2, opts) {
10017
10247
  if (act === "get") await runSpecGet(proj2.projectName, { team: opts.team, apiversion: proj2.apiVersion });
10018
10248
  else if (act === "refresh") {
10019
10249
  await admin({ method: "POST", path: `/projects/${proj2.projectId}/${proj2.apiVersion}/refresh-spec`, summary: "Refresh spec from source" });
10020
- console.log(import_chalk44.default.green(" Spec refresh triggered."));
10250
+ console.log(import_chalk45.default.green(" Spec refresh triggered."));
10021
10251
  } else await runOpenapi(proj2.projectName, proj2.apiVersion);
10022
10252
  }
10023
10253
  async function agentsMenu(proj2, opts) {
@@ -10042,7 +10272,7 @@ async function agentsMenu(proj2, opts) {
10042
10272
  }
10043
10273
 
10044
10274
  // src/commands/group.ts
10045
- var import_chalk45 = __toESM(require("chalk"));
10275
+ var import_chalk46 = __toESM(require("chalk"));
10046
10276
  var import_ora21 = __toESM(require("ora"));
10047
10277
  init_auth();
10048
10278
  init_admin();
@@ -10136,7 +10366,7 @@ async function userByRefOrCreate(t, ref) {
10136
10366
  if (!ref.includes("@")) throw e;
10137
10367
  const created = await t.call("/v1/admin/users", "POST", { email: ref.trim().toLowerCase() });
10138
10368
  if (!created?.abz_sub) throw e;
10139
- console.log(import_chalk45.default.dim(` ${ref} wasn't a user yet \u2014 created.`));
10369
+ console.log(import_chalk46.default.dim(` ${ref} wasn't a user yet \u2014 created.`));
10140
10370
  return { abz_sub: created.abz_sub, email: created.email ?? ref, display_name: null };
10141
10371
  }
10142
10372
  }
@@ -10144,11 +10374,11 @@ async function runGroupList(opts) {
10144
10374
  const t = await resolveTransport(opts);
10145
10375
  const groups = await listGroups(t);
10146
10376
  if (opts.json) return void console.log(JSON.stringify(groups));
10147
- if (!groups.length) return void console.log(import_chalk45.default.yellow(`No groups in ${t.tenant}. Create one: apiblaze group create <name>`));
10148
- console.log(import_chalk45.default.dim(`Tenant ${t.tenant}:`));
10377
+ if (!groups.length) return void console.log(import_chalk46.default.yellow(`No groups in ${t.tenant}. Create one: apiblaze group create <name>`));
10378
+ console.log(import_chalk46.default.dim(`Tenant ${t.tenant}:`));
10149
10379
  for (const g of groups) {
10150
- const sealed = g.name === "apiblaze_admins" ? import_chalk45.default.dim(" (admins \u2014 managed by allowlist)") : "";
10151
- console.log(` ${import_chalk45.default.bold(g.name)} ${import_chalk45.default.dim(`${g.member_count ?? 0} member(s)`)}${sealed}`);
10380
+ const sealed = g.name === "apiblaze_admins" ? import_chalk46.default.dim(" (admins \u2014 managed by allowlist)") : "";
10381
+ console.log(` ${import_chalk46.default.bold(g.name)} ${import_chalk46.default.dim(`${g.member_count ?? 0} member(s)`)}${sealed}`);
10152
10382
  }
10153
10383
  }
10154
10384
  async function runGroupCreate(name, opts) {
@@ -10176,7 +10406,7 @@ async function runGroupCreate(name, opts) {
10176
10406
  const spinner = (0, import_ora21.default)(`Creating group ${name}...`).start();
10177
10407
  try {
10178
10408
  await t.call("/v1/admin/groups", "POST", { name, admins: [adminSub] });
10179
- spinner.succeed(`Group ${import_chalk45.default.bold(name)} created in ${t.tenant}.`);
10409
+ spinner.succeed(`Group ${import_chalk46.default.bold(name)} created in ${t.tenant}.`);
10180
10410
  } catch (e) {
10181
10411
  spinner.fail("Create failed.");
10182
10412
  throw e;
@@ -10188,7 +10418,7 @@ async function runGroupDelete(name, opts) {
10188
10418
  const spinner = (0, import_ora21.default)(`Deleting group ${name}...`).start();
10189
10419
  try {
10190
10420
  await t.call(`/v1/admin/groups/${encodeURIComponent(g.id)}`, "DELETE");
10191
- spinner.succeed(`Group ${import_chalk45.default.bold(name)} deleted.`);
10421
+ spinner.succeed(`Group ${import_chalk46.default.bold(name)} deleted.`);
10192
10422
  } catch (e) {
10193
10423
  spinner.fail("Delete failed.");
10194
10424
  throw e;
@@ -10201,11 +10431,11 @@ async function runGroupMembers(name, opts) {
10201
10431
  const subs = await t.call(`/v1/admin/groups/${encodeURIComponent(g.id)}/subgroups`);
10202
10432
  if (opts.json) return void console.log(JSON.stringify({ ...detail, subgroups: subs?.subgroups ?? [] }));
10203
10433
  const members = detail?.members ?? [];
10204
- console.log(import_chalk45.default.bold(`${g.name}`) + import_chalk45.default.dim(` (${t.tenant})`));
10205
- for (const m of members) console.log(` ${label2(m)} ${m.role === "admin" ? import_chalk45.default.cyan("group-admin") : import_chalk45.default.dim("member")}`);
10206
- if (!members.length) console.log(import_chalk45.default.dim(" no members"));
10434
+ console.log(import_chalk46.default.bold(`${g.name}`) + import_chalk46.default.dim(` (${t.tenant})`));
10435
+ for (const m of members) console.log(` ${label2(m)} ${m.role === "admin" ? import_chalk46.default.cyan("group-admin") : import_chalk46.default.dim("member")}`);
10436
+ if (!members.length) console.log(import_chalk46.default.dim(" no members"));
10207
10437
  const sg = subs?.subgroups ?? [];
10208
- if (sg.length) console.log(import_chalk45.default.dim(` subgroups: ${sg.map((s) => s.name).join(", ")}`));
10438
+ if (sg.length) console.log(import_chalk46.default.dim(` subgroups: ${sg.map((s) => s.name).join(", ")}`));
10209
10439
  }
10210
10440
  async function runGroupAddUser(userRef, groupName, opts) {
10211
10441
  const t = await resolveTransport(opts);
@@ -10215,7 +10445,7 @@ async function runGroupAddUser(userRef, groupName, opts) {
10215
10445
  const spinner = (0, import_ora21.default)(`Adding ${label2(u)} to ${g.name}...`).start();
10216
10446
  try {
10217
10447
  await t.call(`/v1/admin/groups/${encodeURIComponent(g.id)}/members`, "POST", { abz_sub: u.abz_sub, role });
10218
- spinner.succeed(`${import_chalk45.default.bold(label2(u))} added to ${import_chalk45.default.bold(g.name)} as ${role}.`);
10448
+ spinner.succeed(`${import_chalk46.default.bold(label2(u))} added to ${import_chalk46.default.bold(g.name)} as ${role}.`);
10219
10449
  } catch (e) {
10220
10450
  spinner.fail("Add failed.");
10221
10451
  throw e;
@@ -10227,7 +10457,7 @@ async function runGroupRemoveUser(userRef, groupName, opts) {
10227
10457
  const spinner = (0, import_ora21.default)(`Removing ${label2(u)} from ${g.name}...`).start();
10228
10458
  try {
10229
10459
  await t.call(`/v1/admin/groups/${encodeURIComponent(g.id)}/members/_?abz_sub=${encodeURIComponent(u.abz_sub)}`, "DELETE");
10230
- spinner.succeed(`${import_chalk45.default.bold(label2(u))} removed from ${import_chalk45.default.bold(g.name)}.`);
10460
+ spinner.succeed(`${import_chalk46.default.bold(label2(u))} removed from ${import_chalk46.default.bold(g.name)}.`);
10231
10461
  } catch (e) {
10232
10462
  spinner.fail("Remove failed.");
10233
10463
  throw e;
@@ -10239,7 +10469,7 @@ async function runGroupAddGroup(childName, parentName, opts) {
10239
10469
  const spinner = (0, import_ora21.default)(`Nesting ${child.name} under ${parent.name}...`).start();
10240
10470
  try {
10241
10471
  await t.call(`/v1/admin/groups/${encodeURIComponent(parent.id)}/subgroups`, "POST", { child_group_id: child.id });
10242
- spinner.succeed(`${import_chalk45.default.bold(child.name)} is now a subgroup of ${import_chalk45.default.bold(parent.name)}.`);
10472
+ spinner.succeed(`${import_chalk46.default.bold(child.name)} is now a subgroup of ${import_chalk46.default.bold(parent.name)}.`);
10243
10473
  } catch (e) {
10244
10474
  spinner.fail("Nest failed.");
10245
10475
  throw e;
@@ -10251,7 +10481,7 @@ async function runGroupRemoveGroup(childName, parentName, opts) {
10251
10481
  const spinner = (0, import_ora21.default)(`Un-nesting ${child.name} from ${parent.name}...`).start();
10252
10482
  try {
10253
10483
  await t.call(`/v1/admin/groups/${encodeURIComponent(parent.id)}/subgroups/${encodeURIComponent(child.id)}`, "DELETE");
10254
- spinner.succeed(`${import_chalk45.default.bold(child.name)} un-nested from ${import_chalk45.default.bold(parent.name)}.`);
10484
+ spinner.succeed(`${import_chalk46.default.bold(child.name)} un-nested from ${import_chalk46.default.bold(parent.name)}.`);
10255
10485
  } catch (e) {
10256
10486
  spinner.fail("Un-nest failed.");
10257
10487
  throw e;
@@ -10262,18 +10492,18 @@ async function runGroupUsers(opts) {
10262
10492
  const users = await listUsers(t);
10263
10493
  const observed = await t.call("/v1/admin/observed-identities").catch(() => ({ identities: [] }));
10264
10494
  if (opts.json) return void console.log(JSON.stringify({ users, observed: observed?.identities ?? [] }));
10265
- console.log(import_chalk45.default.dim(`Tenant ${t.tenant} \u2014 user directory:`));
10266
- for (const u of users) console.log(` ${label2(u)} ${import_chalk45.default.dim(u.abz_sub)}`);
10267
- if (!users.length) console.log(import_chalk45.default.dim(" no users yet"));
10495
+ console.log(import_chalk46.default.dim(`Tenant ${t.tenant} \u2014 user directory:`));
10496
+ for (const u of users) console.log(` ${label2(u)} ${import_chalk46.default.dim(u.abz_sub)}`);
10497
+ if (!users.length) console.log(import_chalk46.default.dim(" no users yet"));
10268
10498
  const fresh = (observed?.identities ?? []).filter((o) => !o.provisioned);
10269
10499
  if (fresh.length) {
10270
- console.log(import_chalk45.default.dim("Seen in traffic (not yet users):"));
10271
- for (const o of fresh) console.log(` ${o.email || o.abz_sub} ${import_chalk45.default.dim(o.source_label ?? "")}`);
10500
+ console.log(import_chalk46.default.dim("Seen in traffic (not yet users):"));
10501
+ for (const o of fresh) console.log(` ${o.email || o.abz_sub} ${import_chalk46.default.dim(o.source_label ?? "")}`);
10272
10502
  }
10273
10503
  }
10274
10504
 
10275
10505
  // src/commands/key.ts
10276
- var import_chalk46 = __toESM(require("chalk"));
10506
+ var import_chalk47 = __toESM(require("chalk"));
10277
10507
  var import_ora22 = __toESM(require("ora"));
10278
10508
  init_caller();
10279
10509
  async function runApikeysMenu(opts) {
@@ -10303,11 +10533,11 @@ async function runKeyList(opts) {
10303
10533
  return;
10304
10534
  }
10305
10535
  if (!keys.length) {
10306
- console.log(import_chalk46.default.yellow("No developer keys."));
10536
+ console.log(import_chalk47.default.yellow("No developer keys."));
10307
10537
  return;
10308
10538
  }
10309
10539
  for (const k of keys) {
10310
- console.log(` ${import_chalk46.default.bold(k.key_id ?? k.id)} ${import_chalk46.default.dim(k.description ?? "")} ${import_chalk46.default.dim(k.expires_at ?? "no expiry")}`);
10540
+ console.log(` ${import_chalk47.default.bold(k.key_id ?? k.id)} ${import_chalk47.default.dim(k.description ?? "")} ${import_chalk47.default.dim(k.expires_at ?? "no expiry")}`);
10311
10541
  }
10312
10542
  }
10313
10543
  async function runKeyMint(opts) {
@@ -10329,9 +10559,9 @@ async function runKeyMint(opts) {
10329
10559
  console.log(JSON.stringify(out));
10330
10560
  return;
10331
10561
  }
10332
- console.log(` ${import_chalk46.default.bold("key_id")}: ${out?.key_id}`);
10333
- console.log(` ${import_chalk46.default.bold("key")}: ${import_chalk46.default.green(out?.key)} ${import_chalk46.default.dim("(shown once \u2014 store it now)")}`);
10334
- if (out?.expires_at) console.log(` ${import_chalk46.default.dim("expires:")} ${out.expires_at}`);
10562
+ console.log(` ${import_chalk47.default.bold("key_id")}: ${out?.key_id}`);
10563
+ console.log(` ${import_chalk47.default.bold("key")}: ${import_chalk47.default.green(out?.key)} ${import_chalk47.default.dim("(shown once \u2014 store it now)")}`);
10564
+ if (out?.expires_at) console.log(` ${import_chalk47.default.dim("expires:")} ${out.expires_at}`);
10335
10565
  } catch (err) {
10336
10566
  spinner.fail("Mint failed.");
10337
10567
  throw err;
@@ -10358,7 +10588,7 @@ async function runKeyRevoke(keyId, opts) {
10358
10588
  init_iam();
10359
10589
 
10360
10590
  // src/commands/admins.ts
10361
- var import_chalk47 = __toESM(require("chalk"));
10591
+ var import_chalk48 = __toESM(require("chalk"));
10362
10592
  var import_ora23 = __toESM(require("ora"));
10363
10593
  init_caller();
10364
10594
  function requireTenant(opts) {
@@ -10386,13 +10616,13 @@ async function runAdminsList(opts) {
10386
10616
  return;
10387
10617
  }
10388
10618
  if (!admins2.length) {
10389
- console.log(import_chalk47.default.yellow(`No tenant admins for ${tenant2} yet.`));
10619
+ console.log(import_chalk48.default.yellow(`No tenant admins for ${tenant2} yet.`));
10390
10620
  return;
10391
10621
  }
10392
10622
  for (const a of admins2) {
10393
10623
  const email = typeof a === "string" ? a : a.email;
10394
10624
  const flags = [a.active === false ? "pending" : null, a.pinned ? "pinned" : null].filter(Boolean).join(", ");
10395
- console.log(` ${import_chalk47.default.bold(email)}${flags ? import_chalk47.default.dim(` (${flags})`) : ""}`);
10625
+ console.log(` ${import_chalk48.default.bold(email)}${flags ? import_chalk48.default.dim(` (${flags})`) : ""}`);
10396
10626
  }
10397
10627
  }
10398
10628
  async function runAdminsAdd(email, opts) {
@@ -10407,9 +10637,9 @@ async function runAdminsAdd(email, opts) {
10407
10637
  body: { email },
10408
10638
  summary: `Add ${email} to tenant ${tenant2} admins`
10409
10639
  });
10410
- spinner?.succeed(`${import_chalk47.default.bold(email)} is now a tenant admin of ${import_chalk47.default.bold(tenant2)}.`);
10640
+ spinner?.succeed(`${import_chalk48.default.bold(email)} is now a tenant admin of ${import_chalk48.default.bold(tenant2)}.`);
10411
10641
  if (opts.json) console.log(JSON.stringify(out ?? { ok: true }));
10412
- else console.log(import_chalk47.default.dim(" Reload the Users & Groups widget \u2014 access flips from \u201Cpending\u201D to ready."));
10642
+ else console.log(import_chalk48.default.dim(" Reload the Users & Groups widget \u2014 access flips from \u201Cpending\u201D to ready."));
10413
10643
  } catch (err) {
10414
10644
  spinner?.fail("Add failed.");
10415
10645
  throw err;
@@ -10426,7 +10656,7 @@ async function runAdminsRemove(email, opts) {
10426
10656
  path: `${base(teamId, tenant2)}/${encodeURIComponent(email)}`,
10427
10657
  summary: `Remove ${email} from tenant ${tenant2} admins`
10428
10658
  });
10429
- spinner?.succeed(`Removed ${import_chalk47.default.bold(email)} from the tenant admins of ${import_chalk47.default.bold(tenant2)}.`);
10659
+ spinner?.succeed(`Removed ${import_chalk48.default.bold(email)} from the tenant admins of ${import_chalk48.default.bold(tenant2)}.`);
10430
10660
  } catch (err) {
10431
10661
  spinner?.fail("Remove failed.");
10432
10662
  throw err;
@@ -10434,7 +10664,7 @@ async function runAdminsRemove(email, opts) {
10434
10664
  }
10435
10665
 
10436
10666
  // src/commands/preapprove.ts
10437
- var import_chalk48 = __toESM(require("chalk"));
10667
+ var import_chalk49 = __toESM(require("chalk"));
10438
10668
  var import_ora24 = __toESM(require("ora"));
10439
10669
  async function runPreapprove(who, opts) {
10440
10670
  const tenant2 = await resolveProducerTenant(opts.tenant);
@@ -10442,14 +10672,14 @@ async function runPreapprove(who, opts) {
10442
10672
  const rules = await listPreapprovalRules(tenant2);
10443
10673
  if (opts.json) return void console.log(JSON.stringify(rules, null, 2));
10444
10674
  if (!rules.length) {
10445
- console.log(import_chalk48.default.dim(`No pre-approval rules in ${tenant2}. Anyone who signs in can access (unless access is restricted).`));
10446
- console.log(import_chalk48.default.dim(`Add one: apiblaze preapprove someone@acme.com`));
10675
+ console.log(import_chalk49.default.dim(`No pre-approval rules in ${tenant2}. Anyone who signs in can access (unless access is restricted).`));
10676
+ console.log(import_chalk49.default.dim(`Add one: apiblaze preapprove someone@acme.com`));
10447
10677
  return;
10448
10678
  }
10449
- console.log(import_chalk48.default.dim(`Pre-approved for ${import_chalk48.default.bold(tenant2)}:`));
10679
+ console.log(import_chalk49.default.dim(`Pre-approved for ${import_chalk49.default.bold(tenant2)}:`));
10450
10680
  for (const r of rules) {
10451
- const tag = r.kind === "domain" ? import_chalk48.default.cyan("@" + r.value + " (whole domain)") : r.value;
10452
- const grp = r.groups?.length ? import_chalk48.default.dim(` \u2192 groups: ${r.groups.join(", ")}`) : "";
10681
+ const tag = r.kind === "domain" ? import_chalk49.default.cyan("@" + r.value + " (whole domain)") : r.value;
10682
+ const grp = r.groups?.length ? import_chalk49.default.dim(` \u2192 groups: ${r.groups.join(", ")}`) : "";
10453
10683
  console.log(` ${tag}${grp}`);
10454
10684
  }
10455
10685
  return;
@@ -10460,17 +10690,17 @@ async function runPreapprove(who, opts) {
10460
10690
  if (opts.remove) {
10461
10691
  const spinner2 = (0, import_ora24.default)(`Removing ${who} from ${tenant2}\u2026`).start();
10462
10692
  const { removed, value } = await removePreapprovalRule(tenant2, who);
10463
- if (removed) spinner2.succeed(`${import_chalk48.default.bold(value)} is no longer pre-approved for ${tenant2}.`);
10464
- else spinner2.warn(`No pre-approval rule for ${import_chalk48.default.bold(value)} in ${tenant2} \u2014 nothing to remove.`);
10693
+ if (removed) spinner2.succeed(`${import_chalk49.default.bold(value)} is no longer pre-approved for ${tenant2}.`);
10694
+ else spinner2.warn(`No pre-approval rule for ${import_chalk49.default.bold(value)} in ${tenant2} \u2014 nothing to remove.`);
10465
10695
  return;
10466
10696
  }
10467
10697
  const spinner = (0, import_ora24.default)(`Pre-approving ${who} for ${tenant2}\u2026`).start();
10468
10698
  try {
10469
10699
  const { kind, value } = await addPreapprovalRule(tenant2, who, opts.group);
10470
10700
  const what = kind === "domain" ? `Anyone @${value}` : value;
10471
- spinner.succeed(`${import_chalk48.default.bold(what)} can now sign in to ${import_chalk48.default.bold(tenant2)}.`);
10472
- if (opts.group?.length) console.log(import_chalk48.default.dim(` They'll join group(s) ${opts.group.join(", ")} on first sign-in.`));
10473
- console.log(import_chalk48.default.dim(` See the full list: apiblaze preapprove --list`));
10701
+ spinner.succeed(`${import_chalk49.default.bold(what)} can now sign in to ${import_chalk49.default.bold(tenant2)}.`);
10702
+ if (opts.group?.length) console.log(import_chalk49.default.dim(` They'll join group(s) ${opts.group.join(", ")} on first sign-in.`));
10703
+ console.log(import_chalk49.default.dim(` See the full list: apiblaze preapprove --list`));
10474
10704
  } catch (err) {
10475
10705
  spinner.fail("Could not add the rule.");
10476
10706
  throw err;
@@ -10478,7 +10708,7 @@ async function runPreapprove(who, opts) {
10478
10708
  }
10479
10709
 
10480
10710
  // src/commands/consumer.ts
10481
- var import_chalk49 = __toESM(require("chalk"));
10711
+ var import_chalk50 = __toESM(require("chalk"));
10482
10712
  var import_ora25 = __toESM(require("ora"));
10483
10713
  init_admin();
10484
10714
  init_resolve();
@@ -10500,7 +10730,7 @@ async function consumerFetch(creds, suffix, init) {
10500
10730
  function requireConsumer2() {
10501
10731
  const c = loadConsumer();
10502
10732
  if (!c) {
10503
- console.error(import_chalk49.default.red("Not logged in as a consumer. Run `apiblaze consumer login` first."));
10733
+ console.error(import_chalk50.default.red("Not logged in as a consumer. Run `apiblaze consumer login` first."));
10504
10734
  process.exit(1);
10505
10735
  }
10506
10736
  return c;
@@ -10511,7 +10741,7 @@ async function runConsumerLogin(opts) {
10511
10741
  let clientId = opts.client;
10512
10742
  if (clientId) {
10513
10743
  if (!tenant2) {
10514
- console.error(import_chalk49.default.red("When using --client, also pass --tenant <slug> (it sets which portal/keys host to use)."));
10744
+ console.error(import_chalk50.default.red("When using --client, also pass --tenant <slug> (it sets which portal/keys host to use)."));
10515
10745
  process.exit(1);
10516
10746
  }
10517
10747
  } else {
@@ -10529,18 +10759,18 @@ async function runConsumerLogin(opts) {
10529
10759
  const usable = (Array.isArray(clients) ? clients : []).filter((c) => c && (c.client_id || c.clientId));
10530
10760
  const pick2 = usable.find((c) => c.is_default || c.default) ?? usable.find((c) => c.verified !== false) ?? usable[0];
10531
10761
  if (!pick2) {
10532
- console.error(import_chalk49.default.red(`Tenant "${tenant2}" has no login app configured. Set one up in the dashboard (or \`apiblaze create\` with auth).`));
10762
+ console.error(import_chalk50.default.red(`Tenant "${tenant2}" has no login app configured. Set one up in the dashboard (or \`apiblaze create\` with auth).`));
10533
10763
  process.exit(1);
10534
10764
  }
10535
10765
  clientId = pick2.client_id ?? pick2.clientId;
10536
10766
  }
10537
- console.log(`${import_chalk49.default.cyan("\u2192")} Logging in to ${import_chalk49.default.bold(tenant2)} as a consumer...`);
10767
+ console.log(`${import_chalk50.default.cyan("\u2192")} Logging in to ${import_chalk50.default.bold(tenant2)} as a consumer...`);
10538
10768
  const result = await deviceLogin(clientId, DEFAULT_SCOPE, ({ verificationUri, userCode }) => {
10539
10769
  console.log(`
10540
- Open: ${import_chalk49.default.underline(verificationUri)}`);
10541
- console.log(` Code: ${import_chalk49.default.bold(userCode)}
10770
+ Open: ${import_chalk50.default.underline(verificationUri)}`);
10771
+ console.log(` Code: ${import_chalk50.default.bold(userCode)}
10542
10772
  `);
10543
- console.log(import_chalk49.default.dim(" (opening your browser\u2026 waiting for you to finish)"));
10773
+ console.log(import_chalk50.default.dim(" (opening your browser\u2026 waiting for you to finish)"));
10544
10774
  });
10545
10775
  const claims = result.idToken && decodeJwt2(result.idToken) || (decodeJwt2(result.accessToken) ?? {});
10546
10776
  const creds = {
@@ -10555,7 +10785,7 @@ async function runConsumerLogin(opts) {
10555
10785
  obtainedAt: Date.now()
10556
10786
  };
10557
10787
  saveConsumer(creds);
10558
- console.log(import_chalk49.default.green(`\u2714 Logged in as consumer${creds.email ? ` ${creds.email}` : ""} on ${tenant2}.`));
10788
+ console.log(import_chalk50.default.green(`\u2714 Logged in as consumer${creds.email ? ` ${creds.email}` : ""} on ${tenant2}.`));
10559
10789
  }
10560
10790
  async function runConsumerTokens(opts) {
10561
10791
  const creds = requireConsumer2();
@@ -10568,18 +10798,18 @@ async function runConsumerTokens(opts) {
10568
10798
  console.log(JSON.stringify({ tenant: fresh.tenant, access_token: fresh.accessToken, refresh_token: fresh.refreshToken, id_token: fresh.idToken, expires_at: new Date(fresh.expiresAt).toISOString() }, null, 2));
10569
10799
  return;
10570
10800
  }
10571
- console.log(`${import_chalk49.default.cyan("Consumer")} ${import_chalk49.default.bold(fresh.email ?? fresh.tenant)} on ${import_chalk49.default.bold(fresh.tenant)}
10801
+ console.log(`${import_chalk50.default.cyan("Consumer")} ${import_chalk50.default.bold(fresh.email ?? fresh.tenant)} on ${import_chalk50.default.bold(fresh.tenant)}
10572
10802
  `);
10573
- console.log(`${import_chalk49.default.bold("access_token")} ${import_chalk49.default.dim("exp " + (exp(fresh.accessToken) ?? "?"))}
10803
+ console.log(`${import_chalk50.default.bold("access_token")} ${import_chalk50.default.dim("exp " + (exp(fresh.accessToken) ?? "?"))}
10574
10804
  ${fresh.accessToken}
10575
10805
  `);
10576
- if (fresh.idToken) console.log(`${import_chalk49.default.bold("id_token")} ${import_chalk49.default.dim("exp " + (exp(fresh.idToken) ?? "?"))}
10806
+ if (fresh.idToken) console.log(`${import_chalk50.default.bold("id_token")} ${import_chalk50.default.dim("exp " + (exp(fresh.idToken) ?? "?"))}
10577
10807
  ${fresh.idToken}
10578
10808
  `);
10579
- if (fresh.refreshToken) console.log(`${import_chalk49.default.bold("refresh_token")}
10809
+ if (fresh.refreshToken) console.log(`${import_chalk50.default.bold("refresh_token")}
10580
10810
  ${fresh.refreshToken}
10581
10811
  `);
10582
- console.log(import_chalk49.default.dim("These are your own tokens \u2014 keep them secret."));
10812
+ console.log(import_chalk50.default.dim("These are your own tokens \u2014 keep them secret."));
10583
10813
  }
10584
10814
  async function runConsumerApikeys(opts) {
10585
10815
  const creds = requireConsumer2();
@@ -10589,8 +10819,8 @@ async function runConsumerApikeys(opts) {
10589
10819
  const revealed = await consumerFetch(list.creds, "/apikeys/reveal").catch(() => ({ status: 0, data: null, creds: list.creds }));
10590
10820
  spinner.stop();
10591
10821
  if (list.status >= 400) {
10592
- console.error(import_chalk49.default.red(`Failed to list keys (${list.status}): ${list.data?.error ?? ""}`));
10593
- if (list.status === 401) console.error(import_chalk49.default.dim("Your consumer session may have expired \u2014 run `apiblaze consumer login` again."));
10822
+ console.error(import_chalk50.default.red(`Failed to list keys (${list.status}): ${list.data?.error ?? ""}`));
10823
+ if (list.status === 401) console.error(import_chalk50.default.dim("Your consumer session may have expired \u2014 run `apiblaze consumer login` again."));
10594
10824
  process.exit(1);
10595
10825
  }
10596
10826
  const keys = list.data?.keys ?? [];
@@ -10598,16 +10828,16 @@ async function runConsumerApikeys(opts) {
10598
10828
  if (opts.json) {
10599
10829
  console.log(JSON.stringify({ keys, revealed: revealMap }, null, 2));
10600
10830
  } else if (!keys.length) {
10601
- console.log(import_chalk49.default.yellow("No API keys yet."));
10831
+ console.log(import_chalk50.default.yellow("No API keys yet."));
10602
10832
  } else {
10603
10833
  for (const k of keys) {
10604
10834
  const clear = revealMap[k.environment]?.key;
10605
- const shown = clear ? import_chalk49.default.green(clear) : import_chalk49.default.dim(`${k.key_prefix ?? ""}\u2026${k.key_suffix ?? ""}`);
10606
- const exp = k.expires_at ? import_chalk49.default.dim(`exp ${k.expires_at}`) : import_chalk49.default.dim("no expiry");
10607
- console.log(` ${import_chalk49.default.bold(k.environment ?? "")} ${shown} ${exp} ${import_chalk49.default.dim(k.description ?? "")}`);
10835
+ const shown = clear ? import_chalk50.default.green(clear) : import_chalk50.default.dim(`${k.key_prefix ?? ""}\u2026${k.key_suffix ?? ""}`);
10836
+ const exp = k.expires_at ? import_chalk50.default.dim(`exp ${k.expires_at}`) : import_chalk50.default.dim("no expiry");
10837
+ console.log(` ${import_chalk50.default.bold(k.environment ?? "")} ${shown} ${exp} ${import_chalk50.default.dim(k.description ?? "")}`);
10608
10838
  }
10609
10839
  if (Object.keys(revealMap).length === 0 && keys.some((k) => !k.expires_at)) {
10610
- console.log(import_chalk49.default.dim("\n(Only expiring keys can be shown in clear; non-expiring keys show a prefix only.)"));
10840
+ console.log(import_chalk50.default.dim("\n(Only expiring keys can be shown in clear; non-expiring keys show a prefix only.)"));
10611
10841
  }
10612
10842
  }
10613
10843
  if (opts.json) return;
@@ -10629,12 +10859,12 @@ async function runConsumerApikeys(opts) {
10629
10859
  }
10630
10860
  s2.succeed("Key created.");
10631
10861
  const key = created.data?.key ?? created.data?.fullKey;
10632
- if (key) console.log(` ${import_chalk49.default.green(key)} ${import_chalk49.default.dim("(shown once \u2014 store it now)")}`);
10633
- else console.log(import_chalk49.default.dim(" Key created; run `apiblaze consumer apikeys` to reveal it if it expires."));
10862
+ if (key) console.log(` ${import_chalk50.default.green(key)} ${import_chalk50.default.dim("(shown once \u2014 store it now)")}`);
10863
+ else console.log(import_chalk50.default.dim(" Key created; run `apiblaze consumer apikeys` to reveal it if it expires."));
10634
10864
  }
10635
10865
 
10636
10866
  // src/commands/sidecar.ts
10637
- var import_chalk50 = __toESM(require("chalk"));
10867
+ var import_chalk51 = __toESM(require("chalk"));
10638
10868
  var import_ora26 = __toESM(require("ora"));
10639
10869
  var fs12 = __toESM(require("fs"));
10640
10870
  var path8 = __toESM(require("path"));
@@ -10677,7 +10907,7 @@ function upsertEnvLocal(root, token) {
10677
10907
  }
10678
10908
  function installSidecarPackage(root) {
10679
10909
  if (fs12.existsSync(path8.join(root, "node_modules", "apiblaze", "package.json"))) {
10680
- console.log(` ${import_chalk50.default.green("\u2713")} apiblaze package already installed`);
10910
+ console.log(` ${import_chalk51.default.green("\u2713")} apiblaze package already installed`);
10681
10911
  return;
10682
10912
  }
10683
10913
  const has = (f) => fs12.existsSync(path8.join(root, f));
@@ -10688,7 +10918,7 @@ function installSidecarPackage(root) {
10688
10918
  execSync(`${pm.cmd} ${pm.add} apiblaze`, { cwd: root, stdio: "ignore" });
10689
10919
  spinner.succeed("Installed apiblaze (the sidecar runtime).");
10690
10920
  } catch {
10691
- spinner.warn(`Couldn't auto-install \u2014 run ${import_chalk50.default.cyan(`${pm.cmd} ${pm.add} apiblaze`)} yourself before ${import_chalk50.default.cyan("npm run dev")}.`);
10921
+ spinner.warn(`Couldn't auto-install \u2014 run ${import_chalk51.default.cyan(`${pm.cmd} ${pm.add} apiblaze`)} yourself before ${import_chalk51.default.cyan("npm run dev")}.`);
10692
10922
  }
10693
10923
  }
10694
10924
  function readEnvKey(root) {
@@ -10839,29 +11069,29 @@ async function runAnonymousInit(root, router, opts) {
10839
11069
  if (out.cp_key && out.team_id) saveAnonCred2(out.cp_key, out.team_id, out.claim_code);
10840
11070
  const envState = upsertEnvLocal(root, out.token);
10841
11071
  ensureGitignored(root);
10842
- console.log(` ${import_chalk50.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
10843
- console.log(` ${import_chalk50.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
11072
+ console.log(` ${import_chalk51.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
11073
+ console.log(` ${import_chalk51.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
10844
11074
  installSidecarPackage(root);
10845
11075
  let inspectorPath = null;
10846
11076
  if (!opts.noInspector) {
10847
11077
  inspectorPath = generateInspector(root, router);
10848
- if (inspectorPath) console.log(` ${import_chalk50.default.green("\u2713")} inspector at ${inspectorPath}`);
11078
+ if (inspectorPath) console.log(` ${import_chalk51.default.green("\u2713")} inspector at ${inspectorPath}`);
10849
11079
  }
10850
11080
  console.log("");
10851
- console.log(import_chalk50.default.bold("Done (no account needed). What happens next:"));
10852
- console.log(` 1. ${import_chalk50.default.cyan("npm run dev")} and use your app.`);
11081
+ console.log(import_chalk51.default.bold("Done (no account needed). What happens next:"));
11082
+ console.log(` 1. ${import_chalk51.default.cyan("npm run dev")} and use your app.`);
10853
11083
  console.log(` 2. Each external origin your app calls is logged in the console \u2014 approve one with:`);
10854
- console.log(` ${import_chalk50.default.cyan("apiblaze sidecar approve api.stripe.com")} (no login needed)`);
11084
+ console.log(` ${import_chalk51.default.cyan("apiblaze sidecar approve api.stripe.com")} (no login needed)`);
10855
11085
  console.log("");
10856
- console.log(import_chalk50.default.bold(" \u{1F511} Keep your setup \u2014 claim it into an account:"));
10857
- console.log(` ${import_chalk50.default.cyan("apiblaze login")} then ${import_chalk50.default.cyan("apiblaze claim")} ${import_chalk50.default.dim("(no code needed here)")}`);
10858
- console.log(import_chalk50.default.dim(` From another machine: apiblaze claim ${out.claim_code} \xB7 expires in 30 days`));
11086
+ console.log(import_chalk51.default.bold(" \u{1F511} Keep your setup \u2014 claim it into an account:"));
11087
+ console.log(` ${import_chalk51.default.cyan("apiblaze login")} then ${import_chalk51.default.cyan("apiblaze claim")} ${import_chalk51.default.dim("(no code needed here)")}`);
11088
+ console.log(import_chalk51.default.dim(` From another machine: apiblaze claim ${out.claim_code} \xB7 expires in 30 days`));
10859
11089
  }
10860
11090
  async function runSidecar(opts) {
10861
11091
  const root = path8.resolve(opts.dir ?? process.cwd());
10862
11092
  const detected2 = detectNextProject(root);
10863
11093
  if (!detected2.found) {
10864
- console.log(import_chalk50.default.yellow(`No Next.js project detected in ${root}.`));
11094
+ console.log(import_chalk51.default.yellow(`No Next.js project detected in ${root}.`));
10865
11095
  console.log("Create one (e.g. `npx create-next-app`) and re-run `apiblaze init` inside it.");
10866
11096
  return;
10867
11097
  }
@@ -10872,10 +11102,10 @@ async function runSidecar(opts) {
10872
11102
  if (!loadCredentials()) {
10873
11103
  upsertEnvLocal(root, readEnvKey(root));
10874
11104
  ensureGitignored(root);
10875
- console.log(` ${import_chalk50.default.green("\u2713")} .env.local present (APIBLAZE_API_KEY) \u2014 reusing`);
10876
- console.log(` ${import_chalk50.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
11105
+ console.log(` ${import_chalk51.default.green("\u2713")} .env.local present (APIBLAZE_API_KEY) \u2014 reusing`);
11106
+ console.log(` ${import_chalk51.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
10877
11107
  installSidecarPackage(root);
10878
- console.log(import_chalk50.default.dim(" Log in and run `apiblaze claim <code>` to keep this setup, or `apiblaze login` to manage it."));
11108
+ console.log(import_chalk51.default.dim(" Log in and run `apiblaze claim <code>` to keep this setup, or `apiblaze login` to manage it."));
10879
11109
  return;
10880
11110
  }
10881
11111
  const { teamId, teamName } = await resolveTeam(opts.team);
@@ -10898,38 +11128,38 @@ async function runSidecar(opts) {
10898
11128
  throw err;
10899
11129
  }
10900
11130
  } else {
10901
- console.log(import_chalk50.default.dim(` Reusing the existing APIBLAZE_API_KEY (run with --rotate to mint a fresh one, or --team <name> to switch teams).`));
11131
+ console.log(import_chalk51.default.dim(` Reusing the existing APIBLAZE_API_KEY (run with --rotate to mint a fresh one, or --team <name> to switch teams).`));
10902
11132
  }
10903
11133
  const envState = upsertEnvLocal(root, token);
10904
11134
  ensureGitignored(root);
10905
- console.log(` ${import_chalk50.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
11135
+ console.log(` ${import_chalk51.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
10906
11136
  const wireState = wireInstrumentation(root);
10907
- console.log(` ${import_chalk50.default.green("\u2713")} instrumentation.ts ${wireState}`);
11137
+ console.log(` ${import_chalk51.default.green("\u2713")} instrumentation.ts ${wireState}`);
10908
11138
  installSidecarPackage(root);
10909
11139
  let inspectorPath = null;
10910
11140
  if (!opts.noInspector) {
10911
11141
  inspectorPath = generateInspector(root, detected2.router);
10912
- if (inspectorPath) console.log(` ${import_chalk50.default.green("\u2713")} inspector at ${inspectorPath}`);
11142
+ if (inspectorPath) console.log(` ${import_chalk51.default.green("\u2713")} inspector at ${inspectorPath}`);
10913
11143
  }
10914
11144
  console.log("");
10915
- console.log(import_chalk50.default.bold("Done. What happens next:"));
10916
- console.log(` 1. ${import_chalk50.default.cyan("npm run dev")} and use your app \u2014 it works exactly as before (all calls go direct).`);
10917
- console.log(` 2. The origins your app calls appear as ${import_chalk50.default.bold("candidates")} \u2014 list them: ${import_chalk50.default.cyan("apiblaze sidecar")}`);
10918
- console.log(` 3. Approve the ones to route: ${import_chalk50.default.cyan("apiblaze sidecar approve api.stripe.com")} (or in the dashboard)`);
11145
+ console.log(import_chalk51.default.bold("Done. What happens next:"));
11146
+ console.log(` 1. ${import_chalk51.default.cyan("npm run dev")} and use your app \u2014 it works exactly as before (all calls go direct).`);
11147
+ console.log(` 2. The origins your app calls appear as ${import_chalk51.default.bold("candidates")} \u2014 list them: ${import_chalk51.default.cyan("apiblaze sidecar")}`);
11148
+ console.log(` 3. Approve the ones to route: ${import_chalk51.default.cyan("apiblaze sidecar approve api.stripe.com")} (or in the dashboard)`);
10919
11149
  console.log(` \u2026within ~5 min your app starts routing that origin through APIblaze.`);
10920
- if (inspectorPath) console.log(` \u2022 Try it now: open ${import_chalk50.default.underline("http://localhost:3000/abz-inspector")} (dev only; rm ${path8.dirname(inspectorPath)} before shipping)`);
10921
- if (switchingTeam) console.log(import_chalk50.default.dim(` \u2022 Approved origins are per-team \u2014 re-approve them on ${teamName ?? teamId} with \`apiblaze sidecar approve <origin>\`.`));
11150
+ if (inspectorPath) console.log(` \u2022 Try it now: open ${import_chalk51.default.underline("http://localhost:3000/abz-inspector")} (dev only; rm ${path8.dirname(inspectorPath)} before shipping)`);
11151
+ if (switchingTeam) console.log(import_chalk51.default.dim(` \u2022 Approved origins are per-team \u2014 re-approve them on ${teamName ?? teamId} with \`apiblaze sidecar approve <origin>\`.`));
10922
11152
  console.log("");
10923
- console.log(import_chalk50.default.dim(" Manage: apiblaze sidecar (list/approve/deny/remove)"));
10924
- console.log(import_chalk50.default.dim(" Rotate: apiblaze init --rotate \xB7 Switch team: apiblaze init --team <name>"));
10925
- console.log(import_chalk50.default.dim(" Turn off: set APIBLAZE_SIDECAR=off in .env.local (flip back to on anytime; key stays put)."));
11153
+ console.log(import_chalk51.default.dim(" Manage: apiblaze sidecar (list/approve/deny/remove)"));
11154
+ console.log(import_chalk51.default.dim(" Rotate: apiblaze init --rotate \xB7 Switch team: apiblaze init --team <name>"));
11155
+ console.log(import_chalk51.default.dim(" Turn off: set APIBLAZE_SIDECAR=off in .env.local (flip back to on anytime; key stays put)."));
10926
11156
  console.log("");
10927
- console.log(import_chalk50.default.yellow(" \u26A0 APIBLAZE_API_KEY is long-lived and lets a holder call your team's proxies. Never commit it."));
10928
- console.log(import_chalk50.default.dim(" Your control-plane login stays in ~/.apiblaze \u2014 it never entered this project."));
11157
+ console.log(import_chalk51.default.yellow(" \u26A0 APIBLAZE_API_KEY is long-lived and lets a holder call your team's proxies. Never commit it."));
11158
+ console.log(import_chalk51.default.dim(" Your control-plane login stays in ~/.apiblaze \u2014 it never entered this project."));
10929
11159
  }
10930
11160
 
10931
11161
  // src/commands/origins.ts
10932
- var import_chalk51 = __toESM(require("chalk"));
11162
+ var import_chalk52 = __toESM(require("chalk"));
10933
11163
  var import_ora27 = __toESM(require("ora"));
10934
11164
  init_admin();
10935
11165
  init_resolve();
@@ -10940,7 +11170,7 @@ async function runOriginsList(opts) {
10940
11170
  if (!loadCredentials()) {
10941
11171
  const cred = loadAnonCred();
10942
11172
  if (!cred) {
10943
- console.log(import_chalk51.default.yellow("No anonymous workspace here. Run `apiblaze init` first."));
11173
+ console.log(import_chalk52.default.yellow("No anonymous workspace here. Run `apiblaze init` first."));
10944
11174
  return;
10945
11175
  }
10946
11176
  out = await cpFetch(cred.cp_key, `/teams/${encodeURIComponent(cred.team_id)}/sidecar/candidates`, { method: "GET" });
@@ -10958,27 +11188,27 @@ async function runOriginsList(opts) {
10958
11188
  }
10959
11189
  const routed = out.routed ?? [];
10960
11190
  const candidates = out.candidates ?? [];
10961
- console.log(import_chalk51.default.bold(`
11191
+ console.log(import_chalk52.default.bold(`
10962
11192
  Routed through APIblaze (${routed.length})`));
10963
- if (!routed.length) console.log(import_chalk51.default.dim(" none yet"));
10964
- for (const r of routed) console.log(` ${import_chalk51.default.green("\u25CF")} ${r.sidecar_origin} ${import_chalk51.default.dim(`\u2192 ${r.project_id}`)}`);
10965
- console.log(import_chalk51.default.bold(`
11193
+ if (!routed.length) console.log(import_chalk52.default.dim(" none yet"));
11194
+ for (const r of routed) console.log(` ${import_chalk52.default.green("\u25CF")} ${r.sidecar_origin} ${import_chalk52.default.dim(`\u2192 ${r.project_id}`)}`);
11195
+ console.log(import_chalk52.default.bold(`
10966
11196
  Candidates \u2014 going direct, not yet approved (${candidates.length})`));
10967
- if (!candidates.length) console.log(import_chalk51.default.dim(" none \u2014 run your app to discover the origins it calls"));
11197
+ if (!candidates.length) console.log(import_chalk52.default.dim(" none \u2014 run your app to discover the origins it calls"));
10968
11198
  for (const c of candidates) {
10969
- console.log(` ${import_chalk51.default.yellow("\u25CB")} ${c.origin} ${import_chalk51.default.dim(`seen ${c.request_count}\xD7, last ${c.last_seen}`)}`);
11199
+ console.log(` ${import_chalk52.default.yellow("\u25CB")} ${c.origin} ${import_chalk52.default.dim(`seen ${c.request_count}\xD7, last ${c.last_seen}`)}`);
10970
11200
  }
10971
11201
  if (candidates.length) {
10972
- console.log(import_chalk51.default.dim(`
11202
+ console.log(import_chalk52.default.dim(`
10973
11203
  Approve: apiblaze sidecar approve ${candidates[0].origin.replace("https://", "")}`));
10974
- console.log(import_chalk51.default.dim(` Dismiss: apiblaze sidecar deny ${candidates[0].origin.replace("https://", "")}`));
11204
+ console.log(import_chalk52.default.dim(` Dismiss: apiblaze sidecar deny ${candidates[0].origin.replace("https://", "")}`));
10975
11205
  }
10976
11206
  }
10977
11207
  async function runOriginsApprove(origin, opts) {
10978
11208
  if (!loadCredentials()) {
10979
11209
  const cred = loadAnonCred();
10980
11210
  if (!cred) {
10981
- console.error(import_chalk51.default.red("Not logged in and no anonymous workspace. Run `apiblaze init` first."));
11211
+ console.error(import_chalk52.default.red("Not logged in and no anonymous workspace. Run `apiblaze init` first."));
10982
11212
  process.exit(1);
10983
11213
  }
10984
11214
  const spinner2 = (0, import_ora27.default)(`Approving ${origin} (anonymous)...`).start();
@@ -11031,13 +11261,13 @@ async function runOriginsRemove(origin, opts) {
11031
11261
  }
11032
11262
 
11033
11263
  // src/commands/op.ts
11034
- var import_chalk53 = __toESM(require("chalk"));
11264
+ var import_chalk54 = __toESM(require("chalk"));
11035
11265
  init_auth();
11036
11266
  init_trace();
11037
11267
  init_types();
11038
11268
 
11039
11269
  // src/commands/op-billing.ts
11040
- var import_chalk52 = __toESM(require("chalk"));
11270
+ var import_chalk53 = __toESM(require("chalk"));
11041
11271
  init_admin();
11042
11272
  var SANDBOX = {
11043
11273
  teamId: "team_1782844865835_zujrf",
@@ -11096,7 +11326,7 @@ async function rowsForRays(project, version2, tenant2, rays) {
11096
11326
  }
11097
11327
  function printDoors(data) {
11098
11328
  const checks = [];
11099
- console.log(import_chalk52.default.bold("\n Doors \u2014 is every way in metered?\n"));
11329
+ console.log(import_chalk53.default.bold("\n Doors \u2014 is every way in metered?\n"));
11100
11330
  const doors = data?.doors ?? [];
11101
11331
  const metered = doors.filter((d) => d.verdict === "metered");
11102
11332
  const allowed = doors.filter((d) => d.verdict === "allowed-free");
@@ -11105,29 +11335,29 @@ function printDoors(data) {
11105
11335
  const errs = data?.errors ?? [];
11106
11336
  const routeAuditBroke = errs.some((e) => e.startsWith("zone "));
11107
11337
  const devAuditBroke = errs.some((e) => e.startsWith("workers.dev audit"));
11108
- console.log(import_chalk52.default.dim(` ${metered.length} route(s) behind main-proxy (metered)`));
11109
- for (const d of metered) console.log(import_chalk52.default.green(` \u2713 ${d.pattern}`));
11110
- console.log(import_chalk52.default.dim(`
11338
+ console.log(import_chalk53.default.dim(` ${metered.length} route(s) behind main-proxy (metered)`));
11339
+ for (const d of metered) console.log(import_chalk53.default.green(` \u2713 ${d.pattern}`));
11340
+ console.log(import_chalk53.default.dim(`
11111
11341
  ${allowed.length} route(s) free ON PURPOSE`));
11112
11342
  for (const d of allowed) {
11113
- console.log(import_chalk52.default.cyan(` \u2022 ${d.pattern}`) + import_chalk52.default.dim(` \u2192 ${d.script}`));
11114
- console.log(import_chalk52.default.dim(` ${d.why}`));
11343
+ console.log(import_chalk53.default.cyan(` \u2022 ${d.pattern}`) + import_chalk53.default.dim(` \u2192 ${d.script}`));
11344
+ console.log(import_chalk53.default.dim(` ${d.why}`));
11115
11345
  }
11116
11346
  if (known.length) {
11117
- console.log(import_chalk52.default.yellow(`
11347
+ console.log(import_chalk53.default.yellow(`
11118
11348
  ${known.length} route(s) KNOWN OPEN \u2014 unmetered, not yet closed`));
11119
11349
  for (const d of known) {
11120
- console.log(import_chalk52.default.yellow(` ! ${d.pattern}`) + import_chalk52.default.dim(` \u2192 ${d.script}`));
11121
- console.log(import_chalk52.default.dim(` ${d.why}`));
11350
+ console.log(import_chalk53.default.yellow(` ! ${d.pattern}`) + import_chalk53.default.dim(` \u2192 ${d.script}`));
11351
+ console.log(import_chalk53.default.dim(` ${d.why}`));
11122
11352
  }
11123
11353
  checks.push({ name: "no known-open doors", status: "KNOWN", detail: `${known.length} unmetered route(s) still open \u2014 see above` });
11124
11354
  }
11125
11355
  if (stray.length) {
11126
- console.log(import_chalk52.default.red(`
11356
+ console.log(import_chalk53.default.red(`
11127
11357
  ${stray.length} STRAY route(s) \u2014 not main-proxy, not on the allowlist`));
11128
11358
  for (const d of stray) {
11129
- console.log(import_chalk52.default.red(` \u2717 ${d.pattern}`) + import_chalk52.default.dim(` \u2192 ${d.script}`));
11130
- console.log(import_chalk52.default.dim(` ${d.why}`));
11359
+ console.log(import_chalk53.default.red(` \u2717 ${d.pattern}`) + import_chalk53.default.dim(` \u2192 ${d.script}`));
11360
+ console.log(import_chalk53.default.dim(` ${d.why}`));
11131
11361
  }
11132
11362
  checks.push({ name: "no stray routes", status: "FAIL", detail: `${stray.length}: ${stray.map((s) => s.pattern).join(", ")}` });
11133
11363
  } else if (routeAuditBroke) {
@@ -11138,22 +11368,22 @@ function printDoors(data) {
11138
11368
  const wd = data?.workers_dev ?? {};
11139
11369
  const open = wd.enabled ?? [];
11140
11370
  if (open.length) {
11141
- console.log(import_chalk52.default.red(`
11371
+ console.log(import_chalk53.default.red(`
11142
11372
  ${open.length} of ${wd.total} worker(s) reachable on *.workers.dev`));
11143
- for (const s of open) console.log(import_chalk52.default.red(` \u2717 ${s.script}.workers.dev`) + import_chalk52.default.dim(` (enabled=${s.enabled} previews=${s.previews})`));
11144
- console.log(import_chalk52.default.dim(" A workers.dev hostname bypasses every CF route, WAF rule and the credit gate."));
11373
+ for (const s of open) console.log(import_chalk53.default.red(` \u2717 ${s.script}.workers.dev`) + import_chalk53.default.dim(` (enabled=${s.enabled} previews=${s.previews})`));
11374
+ console.log(import_chalk53.default.dim(" A workers.dev hostname bypasses every CF route, WAF rule and the credit gate."));
11145
11375
  checks.push({ name: "no workers.dev doors", status: "FAIL", detail: `${open.length} script(s) publicly reachable: ${open.map((s) => s.script).join(", ")}` });
11146
11376
  } else if (devAuditBroke || !wd.total) {
11147
11377
  checks.push({ name: "no workers.dev doors", status: "SKIP", detail: "script enumeration failed \u2014 NOT a pass, no subdomain was ever read. Needs a CF token with Workers Scripts:Read." });
11148
11378
  } else {
11149
- console.log(import_chalk52.default.green(`
11379
+ console.log(import_chalk53.default.green(`
11150
11380
  \u2713 0 of ${wd.total} workers reachable on *.workers.dev`));
11151
11381
  checks.push({ name: "no workers.dev doors", status: "PASS", detail: `all ${wd.total} scripts have workers.dev + previews disabled` });
11152
11382
  }
11153
- if (data?.how_to_fix) console.log(import_chalk52.default.yellow(`
11154
- ${data.reason}`) + import_chalk52.default.dim(`
11383
+ if (data?.how_to_fix) console.log(import_chalk53.default.yellow(`
11384
+ ${data.reason}`) + import_chalk53.default.dim(`
11155
11385
  ${data.how_to_fix}`));
11156
- else for (const e of errs) console.log(import_chalk52.default.red(`
11386
+ else for (const e of errs) console.log(import_chalk53.default.red(`
11157
11387
  audit error: ${e}`));
11158
11388
  if (errs.length) {
11159
11389
  checks.push({ name: "audit completeness", status: "FAIL", detail: `${errs.length} part(s) of the audit could not run \u2014 coverage is INCOMPLETE, and the checks they would have covered are SKIP above` });
@@ -11163,9 +11393,9 @@ function printDoors(data) {
11163
11393
  async function runMeter(readLedger, opts) {
11164
11394
  const checks = [];
11165
11395
  const N = Math.max(1, Math.min(10, opts.count ?? 3));
11166
- console.log(import_chalk52.default.bold("\n Meter \u2014 is 1 request charged exactly 1 request?\n"));
11396
+ console.log(import_chalk53.default.bold("\n Meter \u2014 is 1 request charged exactly 1 request?\n"));
11167
11397
  const snap = await readLedger();
11168
- console.log(import_chalk52.default.dim(` wallet ${snap.billing_account_id} \xB7 band count ${snap.band_count} \xB7 next request ${snap.next_request_cents}\xA2
11398
+ console.log(import_chalk53.default.dim(` wallet ${snap.billing_account_id} \xB7 band count ${snap.band_count} \xB7 next request ${snap.next_request_cents}\xA2
11169
11399
  `));
11170
11400
  const url = `https://${dpHost}/${SANDBOX.version}/${SANDBOX.environment}/`;
11171
11401
  const headers = opts.key ? { "X-API-Key": opts.key } : {};
@@ -11247,22 +11477,22 @@ async function runMeter(readLedger, opts) {
11247
11477
  return checks;
11248
11478
  }
11249
11479
  function printChecks(checks) {
11250
- console.log(import_chalk52.default.bold("\n Results\n"));
11251
- const mark = { PASS: import_chalk52.default.green(" PASS"), FAIL: import_chalk52.default.red(" FAIL"), SKIP: import_chalk52.default.dim(" SKIP"), KNOWN: import_chalk52.default.yellow(" KNOWN") };
11480
+ console.log(import_chalk53.default.bold("\n Results\n"));
11481
+ const mark = { PASS: import_chalk53.default.green(" PASS"), FAIL: import_chalk53.default.red(" FAIL"), SKIP: import_chalk53.default.dim(" SKIP"), KNOWN: import_chalk53.default.yellow(" KNOWN") };
11252
11482
  for (const ch of checks) {
11253
- console.log(` ${mark[ch.status]} ${import_chalk52.default.bold(ch.name)}`);
11254
- console.log(import_chalk52.default.dim(` ${ch.detail}`));
11483
+ console.log(` ${mark[ch.status]} ${import_chalk53.default.bold(ch.name)}`);
11484
+ console.log(import_chalk53.default.dim(` ${ch.detail}`));
11255
11485
  }
11256
11486
  const fails = checks.filter((c) => c.status === "FAIL").length;
11257
11487
  const skips = checks.filter((c) => c.status === "SKIP").length;
11258
11488
  const known = checks.filter((c) => c.status === "KNOWN").length;
11259
11489
  console.log("");
11260
11490
  const passes = checks.filter((c) => c.status === "PASS").length;
11261
- if (fails) console.log(import_chalk52.default.red(` ${fails} check(s) FAILED.`));
11262
- else if (passes) console.log(import_chalk52.default.green(` ${passes} check(s) passed, 0 failed.`));
11263
- else console.log(import_chalk52.default.yellow(" NOTHING WAS VERIFIED \u2014 every check was skipped."));
11264
- if (known) console.log(import_chalk52.default.yellow(` ${known} known-open issue(s) still outstanding.`));
11265
- if (skips) console.log(import_chalk52.default.dim(` ${skips} check(s) NOT RUN (see SKIP above) \u2014 those invariants are unverified.`));
11491
+ if (fails) console.log(import_chalk53.default.red(` ${fails} check(s) FAILED.`));
11492
+ else if (passes) console.log(import_chalk53.default.green(` ${passes} check(s) passed, 0 failed.`));
11493
+ else console.log(import_chalk53.default.yellow(" NOTHING WAS VERIFIED \u2014 every check was skipped."));
11494
+ if (known) console.log(import_chalk53.default.yellow(` ${known} known-open issue(s) still outstanding.`));
11495
+ if (skips) console.log(import_chalk53.default.dim(` ${skips} check(s) NOT RUN (see SKIP above) \u2014 those invariants are unverified.`));
11266
11496
  console.log("");
11267
11497
  }
11268
11498
 
@@ -11309,93 +11539,93 @@ var OP_COMMANDS = [
11309
11539
  function renderOpCommands() {
11310
11540
  const width = Math.max(...OP_COMMANDS.map((c) => c.cmd.length)) + 10;
11311
11541
  const lines = OP_COMMANDS.map((c) => {
11312
- const left = ` ${import_chalk53.default.cyan(`apiblaze ${c.cmd}`)}`;
11542
+ const left = ` ${import_chalk54.default.cyan(`apiblaze ${c.cmd}`)}`;
11313
11543
  const pad = " ".repeat(Math.max(1, width - c.cmd.length));
11314
- return `${left}${pad}${c.blurb}${c.extra ? " " + import_chalk53.default.dim(`(${c.extra})`) : ""}`;
11544
+ return `${left}${pad}${c.blurb}${c.extra ? " " + import_chalk54.default.dim(`(${c.extra})`) : ""}`;
11315
11545
  });
11316
11546
  return [
11317
- import_chalk53.default.bold("Operator commands"),
11547
+ import_chalk54.default.bold("Operator commands"),
11318
11548
  ...lines,
11319
11549
  "",
11320
- import_chalk53.default.dim(" Operators only. The gate is server-side (dashboard /api/cli/op checks the"),
11321
- import_chalk53.default.dim(" signed-in email, admin-api re-checks with operatorGate) \u2014 a patched CLI just"),
11322
- import_chalk53.default.dim(" gets 403s. Every op call is read-only except `op sweep`."),
11550
+ import_chalk54.default.dim(" Operators only. The gate is server-side (dashboard /api/cli/op checks the"),
11551
+ import_chalk54.default.dim(" signed-in email, admin-api re-checks with operatorGate) \u2014 a patched CLI just"),
11552
+ import_chalk54.default.dim(" gets 403s. Every op call is read-only except `op sweep`."),
11323
11553
  "",
11324
- import_chalk53.default.dim(" Not a CLI command: to prune all non-CP data run scripts/nuke-but-cp.sh --apply --sweep"),
11325
- import_chalk53.default.dim(" in the repo. Operator dashboards (dlq, thresholds, throttling, pricing, billing,"),
11326
- import_chalk53.default.dim(" agent-spend, teams, tests, leak-detection, lifecycle) live at /operator/* in the app.")
11554
+ import_chalk54.default.dim(" Not a CLI command: to prune all non-CP data run scripts/nuke-but-cp.sh --apply --sweep"),
11555
+ import_chalk54.default.dim(" in the repo. Operator dashboards (dlq, thresholds, throttling, pricing, billing,"),
11556
+ import_chalk54.default.dim(" agent-spend, teams, tests, leak-detection, lifecycle) live at /operator/* in the app.")
11327
11557
  ].join("\n");
11328
11558
  }
11329
11559
  function printResidue(report, applied) {
11330
11560
  const up = report?.upstash ?? {};
11331
11561
  const fga = report?.fga ?? {};
11332
11562
  const ghosts = report?.ghosts ?? {};
11333
- console.log(import_chalk53.default.bold(applied ? "\nExternal-residue sweep" : "\nExternal residue (dry-run \u2014 nothing deleted)"));
11334
- console.log(import_chalk53.default.bold("\n Upstash"));
11563
+ console.log(import_chalk54.default.bold(applied ? "\nExternal-residue sweep" : "\nExternal residue (dry-run \u2014 nothing deleted)"));
11564
+ console.log(import_chalk54.default.bold("\n Upstash"));
11335
11565
  const orphans = up.orphans ?? [];
11336
- if (orphans.length === 0) console.log(import_chalk53.default.green(" no orphaned keys"));
11337
- for (const o of orphans) console.log(` ${import_chalk53.default.yellow(o.key)} ${import_chalk53.default.dim(`\u2014 ${o.reason}`)}`);
11338
- console.log(import_chalk53.default.dim(` kept (live principals): ${up.kept ?? 0} \xB7 anon wallets (untouched): ${up.anon_wallets ?? 0}`));
11566
+ if (orphans.length === 0) console.log(import_chalk54.default.green(" no orphaned keys"));
11567
+ for (const o of orphans) console.log(` ${import_chalk54.default.yellow(o.key)} ${import_chalk54.default.dim(`\u2014 ${o.reason}`)}`);
11568
+ console.log(import_chalk54.default.dim(` kept (live principals): ${up.kept ?? 0} \xB7 anon wallets (untouched): ${up.anon_wallets ?? 0}`));
11339
11569
  if (up.anon_wallet_detail) {
11340
11570
  const d = up.anon_wallet_detail;
11341
- console.log(import_chalk53.default.dim(` anon wallets: ${d.count} ($${(d.total_cents / 100).toFixed(2)}), ${d.no_ttl} with NO TTL${d.no_ttl ? " \u26A0" : " (all self-expire)"}`));
11571
+ console.log(import_chalk54.default.dim(` anon wallets: ${d.count} ($${(d.total_cents / 100).toFixed(2)}), ${d.no_ttl} with NO TTL${d.no_ttl ? " \u26A0" : " (all self-expire)"}`));
11342
11572
  }
11343
11573
  if (up.keyspace_census) {
11344
11574
  const census = Object.entries(up.keyspace_census).map(([k, v]) => `${k}=${v}`).join(" \xB7 ");
11345
- console.log(import_chalk53.default.dim(` keyspace: ${census}`));
11575
+ console.log(import_chalk54.default.dim(` keyspace: ${census}`));
11346
11576
  }
11347
- if (up.unknown?.length) console.log(import_chalk53.default.dim(` unknown (never deleted): ${up.unknown.join(", ")}`));
11348
- if (applied) console.log(` ${import_chalk53.default.bold(String(up.deleted ?? 0))} key(s) deleted`);
11349
- for (const e of up.errors ?? []) console.log(import_chalk53.default.red(` error: ${e}`));
11350
- console.log(import_chalk53.default.bold("\n OpenFGA / Neon \u2014 orphan stores"));
11577
+ if (up.unknown?.length) console.log(import_chalk54.default.dim(` unknown (never deleted): ${up.unknown.join(", ")}`));
11578
+ if (applied) console.log(` ${import_chalk54.default.bold(String(up.deleted ?? 0))} key(s) deleted`);
11579
+ for (const e of up.errors ?? []) console.log(import_chalk54.default.red(` error: ${e}`));
11580
+ console.log(import_chalk54.default.bold("\n OpenFGA / Neon \u2014 orphan stores"));
11351
11581
  if (applied) {
11352
11582
  const swept = fga?.swept ?? [];
11353
- if (swept.length === 0) console.log(import_chalk53.default.green(" no orphaned stores"));
11583
+ if (swept.length === 0) console.log(import_chalk54.default.green(" no orphaned stores"));
11354
11584
  for (const s of swept) {
11355
11585
  console.log(
11356
- ` ${import_chalk53.default.yellow(s.store_id)} ${import_chalk53.default.dim(`\u2014 store ${s.openfga_deleted ? "deleted" : "DEFERRED"}, ${s.neon_deleted} Neon tuple(s) purged`)}`
11586
+ ` ${import_chalk54.default.yellow(s.store_id)} ${import_chalk54.default.dim(`\u2014 store ${s.openfga_deleted ? "deleted" : "DEFERRED"}, ${s.neon_deleted} Neon tuple(s) purged`)}`
11357
11587
  );
11358
11588
  }
11359
- if (fga?.remaining) console.log(import_chalk53.default.yellow(` ${fga.remaining} more orphan store(s) \u2014 re-run to drain`));
11589
+ if (fga?.remaining) console.log(import_chalk54.default.yellow(` ${fga.remaining} more orphan store(s) \u2014 re-run to drain`));
11360
11590
  const st = fga?.side_tables;
11361
- if (st) console.log(import_chalk53.default.dim(` Neon side-tables purged: ${st.soft_deleted_stores} store records, ${st.orphan_models} models, ${st.orphan_changelog} changelog rows${st.error ? ` (${st.error})` : ""}`));
11591
+ if (st) console.log(import_chalk54.default.dim(` Neon side-tables purged: ${st.soft_deleted_stores} store records, ${st.orphan_models} models, ${st.orphan_changelog} changelog rows${st.error ? ` (${st.error})` : ""}`));
11362
11592
  } else {
11363
11593
  const fgaOrphans = fga?.orphans ?? [];
11364
- if (fgaOrphans.length === 0) console.log(import_chalk53.default.green(" no orphaned stores"));
11594
+ if (fgaOrphans.length === 0) console.log(import_chalk54.default.green(" no orphaned stores"));
11365
11595
  for (const s of fgaOrphans) {
11366
11596
  const src = s.in_openfga ? "live in OpenFGA" : "Neon tuples only";
11367
- console.log(` ${import_chalk53.default.yellow(s.store_id)} ${import_chalk53.default.dim(`\u2014 ${src}${s.name ? ` (${s.name})` : ""}, ${s.neon_tuples} Neon tuple(s)`)}`);
11597
+ console.log(` ${import_chalk54.default.yellow(s.store_id)} ${import_chalk54.default.dim(`\u2014 ${src}${s.name ? ` (${s.name})` : ""}, ${s.neon_tuples} Neon tuple(s)`)}`);
11368
11598
  }
11369
- console.log(import_chalk53.default.dim(` kept stores: ${(fga?.kept_store_ids ?? []).length}`));
11599
+ console.log(import_chalk54.default.dim(` kept stores: ${(fga?.kept_store_ids ?? []).length}`));
11370
11600
  const st = fga?.side_tables;
11371
- if (st) console.log(import_chalk53.default.dim(` Neon side-table residue: ${st.soft_deleted_stores} soft-deleted store records, ${st.orphan_models} orphan models, ${st.orphan_changelog} orphan changelog rows`));
11601
+ if (st) console.log(import_chalk54.default.dim(` Neon side-table residue: ${st.soft_deleted_stores} soft-deleted store records, ${st.orphan_models} orphan models, ${st.orphan_changelog} orphan changelog rows`));
11372
11602
  }
11373
- for (const e of fga?.errors ?? []) console.log(import_chalk53.default.red(` error: ${e}`));
11374
- console.log(import_chalk53.default.bold("\n OpenFGA \u2014 ghost tuples in surviving stores"));
11603
+ for (const e of fga?.errors ?? []) console.log(import_chalk54.default.red(` error: ${e}`));
11604
+ console.log(import_chalk54.default.bold("\n OpenFGA \u2014 ghost tuples in surviving stores"));
11375
11605
  if (applied) {
11376
- if ((ghosts?.ghost_count ?? 0) === 0) console.log(import_chalk53.default.green(" no ghost tuples"));
11377
- else console.log(` ${import_chalk53.default.bold(String(ghosts.deleted ?? 0))} ghost tuple(s) deleted ${import_chalk53.default.dim(`(of ${ghosts.ghost_count} found, ${ghosts.scanned_tuples} scanned across ${ghosts.live_stores} live stores)`)}`);
11606
+ if ((ghosts?.ghost_count ?? 0) === 0) console.log(import_chalk54.default.green(" no ghost tuples"));
11607
+ else console.log(` ${import_chalk54.default.bold(String(ghosts.deleted ?? 0))} ghost tuple(s) deleted ${import_chalk54.default.dim(`(of ${ghosts.ghost_count} found, ${ghosts.scanned_tuples} scanned across ${ghosts.live_stores} live stores)`)}`);
11378
11608
  } else {
11379
11609
  const n = ghosts?.ghost_count ?? 0;
11380
- if (n === 0) console.log(import_chalk53.default.green(` no ghost tuples ${import_chalk53.default.dim(`(${ghosts.scanned_tuples ?? 0} scanned across ${ghosts.live_stores ?? 0} live stores)`)}`));
11610
+ if (n === 0) console.log(import_chalk54.default.green(` no ghost tuples ${import_chalk54.default.dim(`(${ghosts.scanned_tuples ?? 0} scanned across ${ghosts.live_stores ?? 0} live stores)`)}`));
11381
11611
  else {
11382
- console.log(import_chalk53.default.yellow(` ${n} ghost tuple(s) referencing entities absent from D1:`));
11612
+ console.log(import_chalk54.default.yellow(` ${n} ghost tuple(s) referencing entities absent from D1:`));
11383
11613
  for (const g of (ghosts.ghosts ?? []).slice(0, 20)) {
11384
- console.log(import_chalk53.default.dim(` ${g.object_type}:${g.object_id} ${g.relation} ${g._user}`));
11614
+ console.log(import_chalk54.default.dim(` ${g.object_type}:${g.object_id} ${g.relation} ${g._user}`));
11385
11615
  }
11386
- if (n > 20) console.log(import_chalk53.default.dim(` \u2026 and ${n - 20} more`));
11616
+ if (n > 20) console.log(import_chalk54.default.dim(` \u2026 and ${n - 20} more`));
11387
11617
  }
11388
11618
  }
11389
- for (const e of ghosts?.errors ?? []) console.log(import_chalk53.default.red(` error: ${e}`));
11619
+ for (const e of ghosts?.errors ?? []) console.log(import_chalk54.default.red(` error: ${e}`));
11390
11620
  console.log();
11391
11621
  }
11392
11622
  async function runOp(sub, opts = {}, view) {
11393
11623
  if (!loadCredentials()) {
11394
- console.log(import_chalk53.default.dim("Not logged in. Run `apiblaze login`."));
11624
+ console.log(import_chalk54.default.dim("Not logged in. Run `apiblaze login`."));
11395
11625
  return;
11396
11626
  }
11397
11627
  if (!isOperatorLogin()) {
11398
- console.log(import_chalk53.default.dim("`apiblaze op` is only available to platform operators."));
11628
+ console.log(import_chalk54.default.dim("`apiblaze op` is only available to platform operators."));
11399
11629
  return;
11400
11630
  }
11401
11631
  switch (sub) {
@@ -11421,17 +11651,17 @@ async function runOp(sub, opts = {}, view) {
11421
11651
  const nSide = (st.soft_deleted_stores ?? 0) + (st.orphan_models ?? 0) + (st.orphan_changelog ?? 0);
11422
11652
  printResidue(report, false);
11423
11653
  if (nUp + nFga + nGhost + nSide === 0) {
11424
- console.log(import_chalk53.default.green("Nothing to sweep."));
11654
+ console.log(import_chalk54.default.green("Nothing to sweep."));
11425
11655
  return;
11426
11656
  }
11427
11657
  if (!opts.yes) {
11428
11658
  const readline3 = await import("readline/promises");
11429
11659
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
11430
11660
  const answer = await rl.question(
11431
- import_chalk53.default.red(`Delete ${nUp} Upstash key(s) + ${nFga} OpenFGA store(s) + ${nGhost} ghost tuple(s) + ${nSide} Neon side-table row(s)? Type 'sweep' to confirm: `)
11661
+ import_chalk54.default.red(`Delete ${nUp} Upstash key(s) + ${nFga} OpenFGA store(s) + ${nGhost} ghost tuple(s) + ${nSide} Neon side-table row(s)? Type 'sweep' to confirm: `)
11432
11662
  );
11433
11663
  rl.close();
11434
- if (answer.trim() !== "sweep") return void console.log(import_chalk53.default.dim("Aborted."));
11664
+ if (answer.trim() !== "sweep") return void console.log(import_chalk54.default.dim("Aborted."));
11435
11665
  }
11436
11666
  const result = await opCall({ method: "POST", path: "/operator/external-residue/sweep", summary: "external residue sweep" });
11437
11667
  if (opts.json) return void console.log(JSON.stringify(result, null, 2));
@@ -11441,25 +11671,25 @@ async function runOp(sub, opts = {}, view) {
11441
11671
  case "mark": {
11442
11672
  const label3 = (view ?? "").trim();
11443
11673
  if (!label3) {
11444
- console.log(import_chalk53.default.red("Give the change a name:") + import_chalk53.default.cyan(' apiblaze op mark "cached tenant count"'));
11674
+ console.log(import_chalk54.default.red("Give the change a name:") + import_chalk54.default.cyan(' apiblaze op mark "cached tenant count"'));
11445
11675
  return;
11446
11676
  }
11447
11677
  const res = await opCall({ method: "POST", path: "/operator/latency/mark", body: { label: label3 }, summary: "record change marker" });
11448
11678
  const ts = new Date(res?.marker?.ts ?? Date.now()).toISOString();
11449
- console.log(import_chalk53.default.green(`
11450
- Marked: `) + import_chalk53.default.bold(label3));
11451
- console.log(import_chalk53.default.dim(` ${ts}`));
11452
- console.log(import_chalk53.default.dim(` Once traffic has run on both sides, compare with: `) + import_chalk53.default.cyan("apiblaze op latency compare") + "\n");
11679
+ console.log(import_chalk54.default.green(`
11680
+ Marked: `) + import_chalk54.default.bold(label3));
11681
+ console.log(import_chalk54.default.dim(` ${ts}`));
11682
+ console.log(import_chalk54.default.dim(` Once traffic has run on both sides, compare with: `) + import_chalk54.default.cyan("apiblaze op latency compare") + "\n");
11453
11683
  return;
11454
11684
  }
11455
11685
  case "credits": {
11456
11686
  const data = await opCall({ method: "GET", path: "/operator/credits", summary: "list credit wallets" });
11457
11687
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
11458
11688
  const accounts = data?.accounts ?? [];
11459
- if (accounts.length === 0) return void console.log(import_chalk53.default.dim("No credit wallets."));
11689
+ if (accounts.length === 0) return void console.log(import_chalk54.default.dim("No credit wallets."));
11460
11690
  for (const a of accounts) {
11461
11691
  const bal = typeof a.balance_cents === "number" ? `$${(a.balance_cents / 100).toFixed(2)}` : "?";
11462
- console.log(` ${import_chalk53.default.bold(bal.padStart(9))} ${a.walletId}${a.owner_email ? import_chalk53.default.dim(` \u2014 ${a.owner_email}`) : a.anon ? import_chalk53.default.dim(" \u2014 anon") : ""}`);
11692
+ console.log(` ${import_chalk54.default.bold(bal.padStart(9))} ${a.walletId}${a.owner_email ? import_chalk54.default.dim(` \u2014 ${a.owner_email}`) : a.anon ? import_chalk54.default.dim(" \u2014 anon") : ""}`);
11463
11693
  }
11464
11694
  return;
11465
11695
  }
@@ -11470,7 +11700,7 @@ async function runOp(sub, opts = {}, view) {
11470
11700
  case "billing": {
11471
11701
  const which = (view ?? "").trim().toLowerCase();
11472
11702
  if (which && which !== "doors" && which !== "meter") {
11473
- return void console.log(import_chalk53.default.red(`Unknown: apiblaze op billing ${which}. Use 'doors', 'meter', or neither for both.`));
11703
+ return void console.log(import_chalk54.default.red(`Unknown: apiblaze op billing ${which}. Use 'doors', 'meter', or neither for both.`));
11474
11704
  }
11475
11705
  const checks = [];
11476
11706
  let doorsData = null;
@@ -11531,29 +11761,29 @@ async function runOp(sub, opts = {}, view) {
11531
11761
  const data = await opCall({ method: "GET", path: `/operator/latency/grades${q}`, summary: "latency grades" });
11532
11762
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
11533
11763
  const t = data.thresholds_ms;
11534
- console.log(import_chalk53.default.bold("\nHow good was apiblaze itself?") + import_chalk53.default.dim(" (our overhead only \u2014 a slow customer API never counts against us)"));
11535
- console.log(import_chalk53.default.dim(` excellent <${t.excellent.replace("<", "")}ms \xB7 okay ${t.okay}ms \xB7 bad ${t.bad}ms \xB7 terrible ${t.terrible.replace(">=", "")}ms+
11764
+ console.log(import_chalk54.default.bold("\nHow good was apiblaze itself?") + import_chalk54.default.dim(" (our overhead only \u2014 a slow customer API never counts against us)"));
11765
+ console.log(import_chalk54.default.dim(` excellent <${t.excellent.replace("<", "")}ms \xB7 okay ${t.okay}ms \xB7 bad ${t.bad}ms \xB7 terrible ${t.terrible.replace(">=", "")}ms+
11536
11766
  `));
11537
- console.log(import_chalk53.default.dim(" date reqs excellent okay bad terrible"));
11767
+ console.log(import_chalk54.default.dim(" date reqs excellent okay bad terrible"));
11538
11768
  for (const d of data.days ?? []) {
11539
11769
  const p = d.pct;
11540
- const cell = (v, colour) => v > 0 ? colour(`${String(v).padStart(5)}%`) : import_chalk53.default.dim(`${String(v).padStart(5)}%`);
11770
+ const cell = (v, colour) => v > 0 ? colour(`${String(v).padStart(5)}%`) : import_chalk54.default.dim(`${String(v).padStart(5)}%`);
11541
11771
  console.log(
11542
- ` ${d.date} ${String(d.total).padStart(5)} ${cell(p.excellent, import_chalk53.default.green)} ${cell(p.okay, import_chalk53.default.cyan)} ${cell(p.bad, import_chalk53.default.yellow)} ${cell(p.terrible, import_chalk53.default.red)}`
11772
+ ` ${d.date} ${String(d.total).padStart(5)} ${cell(p.excellent, import_chalk54.default.green)} ${cell(p.okay, import_chalk54.default.cyan)} ${cell(p.bad, import_chalk54.default.yellow)} ${cell(p.terrible, import_chalk54.default.red)}`
11543
11773
  );
11544
11774
  }
11545
11775
  const cul = data.culprits ?? [];
11546
11776
  if (cul.length) {
11547
- console.log(import_chalk53.default.bold("\n Who caused the bad and terrible ones\n"));
11548
- console.log(import_chalk53.default.dim(" bad terrible feature \u2192 dependency"));
11777
+ console.log(import_chalk54.default.bold("\n Who caused the bad and terrible ones\n"));
11778
+ console.log(import_chalk54.default.dim(" bad terrible feature \u2192 dependency"));
11549
11779
  for (const r of cul.slice(0, 12)) {
11550
11780
  if (!r.bad && !r.terrible) continue;
11551
11781
  console.log(
11552
- ` ${String(r.bad).padStart(6)} ${import_chalk53.default.red(String(r.terrible).padStart(8))} ${import_chalk53.default.yellow(r.feature)} ${import_chalk53.default.dim("\u2192")} ${import_chalk53.default.cyan(r.dep)}`
11782
+ ` ${String(r.bad).padStart(6)} ${import_chalk54.default.red(String(r.terrible).padStart(8))} ${import_chalk54.default.yellow(r.feature)} ${import_chalk54.default.dim("\u2192")} ${import_chalk54.default.cyan(r.dep)}`
11553
11783
  );
11554
11784
  }
11555
11785
  }
11556
- if (data.caveat) console.log(import_chalk53.default.dim(`
11786
+ if (data.caveat) console.log(import_chalk54.default.dim(`
11557
11787
  \u26A0 ${data.caveat}
11558
11788
  `));
11559
11789
  return;
@@ -11562,24 +11792,24 @@ async function runOp(sub, opts = {}, view) {
11562
11792
  const data = await opCall({ method: "GET", path: `/operator/latency/compare${q}`, summary: "latency before/after" });
11563
11793
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
11564
11794
  const b = data.before, a = data.after, d = data.delta;
11565
- console.log(import_chalk53.default.bold(`
11566
- Before vs after: `) + import_chalk53.default.cyan(data.marker.label));
11567
- console.log(import_chalk53.default.dim(` marked ${new Date(data.marker.ts).toISOString()} \xB7 ${data.window_hours}h either side
11795
+ console.log(import_chalk54.default.bold(`
11796
+ Before vs after: `) + import_chalk54.default.cyan(data.marker.label));
11797
+ console.log(import_chalk54.default.dim(` marked ${new Date(data.marker.ts).toISOString()} \xB7 ${data.window_hours}h either side
11568
11798
  `));
11569
11799
  const row = (name, before, after, delta) => {
11570
11800
  const arrow = delta === 0 ? "=" : delta < 0 ? "\u2193" : "\u2191";
11571
11801
  const txt = `${String(before).padStart(6)}ms \u2192${String(after).padStart(7)}ms ${arrow}${Math.abs(delta)}ms`;
11572
- console.log(` ${name.padEnd(22)}${data.trustworthy ? delta <= 0 ? import_chalk53.default.green(txt) : import_chalk53.default.red(txt) : import_chalk53.default.dim(txt)}`);
11802
+ console.log(` ${name.padEnd(22)}${data.trustworthy ? delta <= 0 ? import_chalk54.default.green(txt) : import_chalk54.default.red(txt) : import_chalk54.default.dim(txt)}`);
11573
11803
  };
11574
- console.log(import_chalk53.default.dim(" metric before after change"));
11804
+ console.log(import_chalk54.default.dim(" metric before after change"));
11575
11805
  row("total p50", b.total_p50, a.total_p50, d.total_p50);
11576
11806
  row("total p95", b.total_p95, a.total_p95, d.total_p95);
11577
11807
  row("apiblaze overhead p50", b.gw_p50, a.gw_p50, d.gw_p50);
11578
11808
  row("apiblaze overhead p95", b.gw_p95, a.gw_p95, d.gw_p95);
11579
- console.log(import_chalk53.default.dim(`
11809
+ console.log(import_chalk54.default.dim(`
11580
11810
  requests: ${b.requests} before \xB7 ${a.requests} after`));
11581
11811
  for (const w of data.warnings ?? []) {
11582
- console.log((data.trustworthy ? import_chalk53.default.dim : import_chalk53.default.yellow)(` ${data.trustworthy ? "\xB7" : "\u26A0"} ${w}`));
11812
+ console.log((data.trustworthy ? import_chalk54.default.dim : import_chalk54.default.yellow)(` ${data.trustworthy ? "\xB7" : "\u26A0"} ${w}`));
11583
11813
  }
11584
11814
  console.log("");
11585
11815
  return;
@@ -11588,19 +11818,19 @@ Before vs after: `) + import_chalk53.default.cyan(data.marker.label));
11588
11818
  const data = await opCall({ method: "GET", path: `/operator/latency/slow${q}`, summary: "slowest requests" });
11589
11819
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
11590
11820
  const rows2 = data?.rows ?? [];
11591
- if (!rows2.length) return void console.log(import_chalk53.default.dim("No requests over the threshold in that window."));
11592
- console.log(import_chalk53.default.bold(`
11821
+ if (!rows2.length) return void console.log(import_chalk54.default.dim("No requests over the threshold in that window."));
11822
+ console.log(import_chalk54.default.bold(`
11593
11823
  Slowest requests \u2014 last ${data.window_hours}h, over ${data.min_ms}ms
11594
11824
  `));
11595
- console.log(import_chalk53.default.dim(" total ours theirs blame request id"));
11825
+ console.log(import_chalk54.default.dim(" total ours theirs blame request id"));
11596
11826
  for (const r of rows2.slice(0, 30)) {
11597
11827
  console.log(
11598
- ` ${String(Math.round(r.duration_ms)).padStart(6)} ${String(Math.round(r.gateway_ms)).padStart(5)} ${String(Math.round(r.upstream_ttfb_ms)).padStart(6)} ${import_chalk53.default.yellow(`${r.slow_gw_feature || "-"}\u2192${r.slow_dep || "-"}`.padEnd(20))} ${import_chalk53.default.dim(r.request_id || "")}`
11828
+ ` ${String(Math.round(r.duration_ms)).padStart(6)} ${String(Math.round(r.gateway_ms)).padStart(5)} ${String(Math.round(r.upstream_ttfb_ms)).padStart(6)} ${import_chalk54.default.yellow(`${r.slow_gw_feature || "-"}\u2192${r.slow_dep || "-"}`.padEnd(20))} ${import_chalk54.default.dim(r.request_id || "")}`
11599
11829
  );
11600
11830
  }
11601
- console.log(import_chalk53.default.dim(`
11831
+ console.log(import_chalk54.default.dim(`
11602
11832
  The last column is the request id (Cloudflare calls it a "cf-ray"). Look one up with`));
11603
- console.log(import_chalk53.default.dim(` \`apiblaze logs\` for that request's exact per-feature breakdown \u2014 unsampled, unlike the table above.
11833
+ console.log(import_chalk54.default.dim(` \`apiblaze logs\` for that request's exact per-feature breakdown \u2014 unsampled, unlike the table above.
11604
11834
  `));
11605
11835
  return;
11606
11836
  }
@@ -11608,18 +11838,18 @@ Slowest requests \u2014 last ${data.window_hours}h, over ${data.min_ms}ms
11608
11838
  const data = await opCall({ method: "GET", path: `/operator/latency/llm${q}`, summary: "llm latency" });
11609
11839
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
11610
11840
  const rows2 = data?.rows ?? [];
11611
- if (!rows2.length) return void console.log(import_chalk53.default.dim("No LLM traffic in that window."));
11612
- console.log(import_chalk53.default.bold(`
11841
+ if (!rows2.length) return void console.log(import_chalk54.default.dim("No LLM traffic in that window."));
11842
+ console.log(import_chalk54.default.bold(`
11613
11843
  LLM timing \u2014 last ${data.window_hours}h
11614
11844
  `));
11615
- console.log(import_chalk53.default.dim(" turns turn p95 ttfc p95 gen p95 reserve p95 in/out tokens p95 model"));
11845
+ console.log(import_chalk54.default.dim(" turns turn p95 ttfc p95 gen p95 reserve p95 in/out tokens p95 model"));
11616
11846
  for (const r of rows2) {
11617
11847
  const n = r.turns ?? r.requests ?? 0;
11618
11848
  console.log(
11619
11849
  ` ${String(Math.round(n)).padStart(8)} ${String(Math.round(r.turn_p95_ms ?? 0)).padStart(6)}ms ${String(Math.round(r.ttfc_p95_ms ?? 0)).padStart(6)}ms ${String(Math.round(r.gen_p95_ms ?? 0)).padStart(6)}ms ${String(Math.round(r.reserve_p95_ms ?? 0)).padStart(9)}ms ${String(Math.round(r.input_tokens_p95 ?? 0)).padStart(6)}/${String(Math.round(r.output_tokens_p95 ?? 0)).padEnd(6)} ${r.model || "-"}`
11620
11850
  );
11621
11851
  }
11622
- console.log(import_chalk53.default.dim(`
11852
+ console.log(import_chalk54.default.dim(`
11623
11853
  ${data.note}
11624
11854
  `));
11625
11855
  return;
@@ -11630,26 +11860,26 @@ LLM timing \u2014 last ${data.window_hours}h
11630
11860
  ]);
11631
11861
  if (opts.json) return void console.log(JSON.stringify({ blame, summary }, null, 2));
11632
11862
  const ov = summary?.apiblaze_overhead_ms ?? {};
11633
- console.log(import_chalk53.default.bold(`
11863
+ console.log(import_chalk54.default.bold(`
11634
11864
  Latency \u2014 last ${summary?.window_hours ?? "?"}h, ${Number(summary?.requests ?? 0).toLocaleString()} requests
11635
11865
  `));
11636
- console.log(` ${import_chalk53.default.bold("apiblaze overhead")} p50 ${String(ov.p50 ?? 0).padStart(5)}ms p95 ${String(ov.p95 ?? 0).padStart(6)}ms p99 ${String(ov.p99 ?? 0).padStart(6)}ms ${import_chalk53.default.dim("\u2190 ours")}`);
11637
- console.log(` ${import_chalk53.default.bold("upstream ttfb ")} ${" ".repeat(24)}p95 ${String(summary?.upstream_ttfb_p95_ms ?? 0).padStart(6)}ms ${import_chalk53.default.dim("\u2190 theirs")}`);
11638
- console.log(import_chalk53.default.dim(` (per-request percentiles \u2014 never subtract one from the other)
11866
+ console.log(` ${import_chalk54.default.bold("apiblaze overhead")} p50 ${String(ov.p50 ?? 0).padStart(5)}ms p95 ${String(ov.p95 ?? 0).padStart(6)}ms p99 ${String(ov.p99 ?? 0).padStart(6)}ms ${import_chalk54.default.dim("\u2190 ours")}`);
11867
+ console.log(` ${import_chalk54.default.bold("upstream ttfb ")} ${" ".repeat(24)}p95 ${String(summary?.upstream_ttfb_p95_ms ?? 0).padStart(6)}ms ${import_chalk54.default.dim("\u2190 theirs")}`);
11868
+ console.log(import_chalk54.default.dim(` (per-request percentiles \u2014 never subtract one from the other)
11639
11869
  `));
11640
11870
  const rows = blame?.blame ?? [];
11641
- if (!rows.length) return void console.log(import_chalk53.default.dim("No latency rows in that window."));
11642
- console.log(import_chalk53.default.bold(" Which feature ate the time, and what inside it\n"));
11643
- console.log(import_chalk53.default.dim(" share p95 feature \u2192 dependency"));
11871
+ if (!rows.length) return void console.log(import_chalk54.default.dim("No latency rows in that window."));
11872
+ console.log(import_chalk54.default.bold(" Which feature ate the time, and what inside it\n"));
11873
+ console.log(import_chalk54.default.dim(" share p95 feature \u2192 dependency"));
11644
11874
  for (const r of rows.slice(0, 15)) {
11645
11875
  const share = `${(r.share * 100).toFixed(1)}%`;
11646
- console.log(` ${share.padStart(6)} ${String(r.p95_ms).padStart(6)}ms ${import_chalk53.default.yellow(r.feature)} ${import_chalk53.default.dim("\u2192")} ${import_chalk53.default.cyan(r.dep)}`);
11876
+ console.log(` ${share.padStart(6)} ${String(r.p95_ms).padStart(6)}ms ${import_chalk54.default.yellow(r.feature)} ${import_chalk54.default.dim("\u2192")} ${import_chalk54.default.cyan(r.dep)}`);
11647
11877
  }
11648
11878
  console.log("");
11649
11879
  return;
11650
11880
  }
11651
11881
  default:
11652
- console.log(import_chalk53.default.red(`Unknown op subcommand '${sub}'. Run \`apiblaze op\` for the menu.`));
11882
+ console.log(import_chalk54.default.red(`Unknown op subcommand '${sub}'. Run \`apiblaze op\` for the menu.`));
11653
11883
  }
11654
11884
  }
11655
11885
 
@@ -11695,7 +11925,7 @@ agent.command("authz").description("Chat to design and turn on access rules for
11695
11925
  program.command("rule").description("Author an object-level access rule in plain English, in one shot (billed per turn)").argument("<rule>", 'The rule in plain English, e.g. "users see only their own rows"').argument("<project>", "Project name or id").option("--enforce", "Turn enforcement on immediately (default: shadow-publish only)").option("--apiversion <version>", "API version (defaults to the project's)").action(action((rule, project, opts) => runRule(rule, project, opts)));
11696
11926
  agent.command("openapi").description("Chat to build your API spec from real traffic").argument("<project>", "Project name or id").argument("[apiVersion]", "API version (defaults to the project's)").action(action((project, apiVersion) => runOpenapi(project, apiVersion)));
11697
11927
  agent.command("mcp").description("Chat to build an MCP server for an API").argument("<project>", "Project name or id").argument("[apiVersion]", "API version (defaults to the project's)").option("--environment <env>", "Environment to publish (default: prod)").action(action((project, apiVersion, opts) => runMcp(project, apiVersion, opts)));
11698
- program.command("apichat [project]").description("Turn any API into a chat: point at an OpenAPI spec \u2014 or chat an EXISTING proxy by name (no login needed)").option("--target <url|file>", "What to chat with \u2014 pass ANY of: a target server base URL (spec auto-discovered at /openapi.json etc.), a local OpenAPI file (./openapi.yaml), or a remote OpenAPI URL (https://acme.com/openapi.yaml)").addOption(new import_commander.Option("--openapi <file|url>", "Deprecated alias \u2014 --target now detects spec files/URLs itself").hideHelp()).addOption(new import_commander.Option("--openapispec <file|url>", "Deprecated alias for --openapi").hideHelp()).option("--name <name>", "Proxy name (defaults to the target host)").option("--apiversion <version>", "API version to create (e.g. 1.0.0)").option("--environment <env>", "Environment to chat against (default: prod anonymous / dev logged-in)").option("--access <mode>", 'Who can call this API once connected (e.g. via Claude): "open" = anyone who signs in, "invite" = only you + emails you pre-approve. Default: invite when logged in, open when anonymous.').option("--target-auth-env <ENV_VAR>", "Read the upstream credential from this env var (CI-safe; required when there is no TTY and the API needs auth)").option("--force", "Proceed even if the API uses oauth2/openIdConnect target auth (you configure target auth yourself later)").option("-y, --yes", "Skip confirmation prompts").option("--tenant <slug>", "Tenant (consumer namespace: portal, login, users) for the new proxy; omit to be asked").option("--apikey <key>", "Use this API key for the proxy's door (api_key proxies). Without it, apichat detects the door and asks \u2014 or runs the consumer login for OAuth doors.").option("--xenduserid <id>", "Assert this end-user id (X-End-User-Id) \u2014 required by proxies with identified/pre-approved enforcement; you are asked for one when the proxy demands it.").option("--verbose", "Show the per-turn proxy curl trace (hidden by default)").option("-p, --prompt <question>", "One-shot question: answered through the external agent CLI after an MCP install, or by apichat itself (exits after answering when there is no TTY)").option("--install-mcp <cli>", "Install this proxy's MCP into an external agent CLI without asking: claude | codex. Also re-offers after an earlier decline.").action(action((project, opts) => runApichat({ ...opts, project, openapispec: opts.openapispec ?? opts.openapi })));
11928
+ program.command("apichat [project]").description("Turn any API into a chat: point at an OpenAPI spec \u2014 or chat an EXISTING proxy by name (no login needed)").option("--target <url|file>", "What to chat with \u2014 pass ANY of: a target server base URL (spec auto-discovered at /openapi.json etc.), a local OpenAPI file (./openapi.yaml), or a remote OpenAPI URL (https://acme.com/openapi.yaml)").addOption(new import_commander.Option("--openapi <file|url>", "Deprecated alias \u2014 --target now detects spec files/URLs itself").hideHelp()).addOption(new import_commander.Option("--openapispec <file|url>", "Deprecated alias for --openapi").hideHelp()).option("--name <name>", "Proxy name (defaults to the target host)").option("--apiversion <version>", "API version to create (e.g. 1.0.0)").option("--environment <env>", "Environment to chat against (default: prod anonymous / dev logged-in)").option("--access <mode>", 'Who can call this API once connected (e.g. via Claude): "open" = anyone who signs in, "invite" = only you + emails you pre-approve. Default: invite when logged in, open when anonymous.').option("--target-auth-env <ENV_VAR>", "Read the upstream credential from this env var (CI-safe; required when there is no TTY and the API needs auth)").option("--force", "Proceed even if the API uses oauth2/openIdConnect target auth (you configure target auth yourself later)").option("-y, --yes", "Skip confirmation prompts").option("--tenant <slug>", "Tenant (consumer namespace: portal, login, users) for the new proxy; omit to be asked").option("--apikey <key>", "Use this API key for the proxy's door (api_key proxies). Without it, apichat detects the door and asks \u2014 or runs the consumer login for OAuth doors.").option("--xenduserid <id>", "Assert this end-user id (X-End-User-Id) \u2014 required by proxies with identified/pre-approved enforcement; you are asked for one when the proxy demands it.").option("--verbose", "Show the per-turn proxy curl trace (hidden by default)").option("-p, --prompt <question>", "One-shot question: answered through the external agent CLI after an MCP install, or by apichat itself (exits after answering when there is no TTY)").option("--install-mcp <cli>", "Install this proxy's MCP into an external agent CLI without asking: claude | codex. Also re-offers after an earlier decline.").option("--remove-mcp <cli>", "Disconnect this proxy from an external agent CLI (claude | codex): removes the MCP server and the standing instruction").action(action((project, opts) => runApichat({ ...opts, project, openapispec: opts.openapispec ?? opts.openapi })));
11699
11929
  var llm = program.command("llm").description("Manage a local LLM provider key for chat (optional \u2014 lifts model quality, bills your key)");
11700
11930
  llm.command("set-key").description("Store an LLM provider key locally (OpenRouter/Anthropic/DeepSeek/OpenAI)").argument("[key]", "The API key (omit to enter it hidden at a prompt)").option("--model <id>", "Model id to use with this key (e.g. anthropic/claude-haiku-4.5)").action(action((key, opts) => runLlmSetKey(key, opts)));
11701
11931
  llm.command("show").description("Show the locally stored LLM key (masked)").action(action(() => runLlmShow()));
@@ -11712,7 +11942,7 @@ program.command("dev").description("Put your localhost behind a public URL (dev
11712
11942
  try {
11713
11943
  const resolved = parseInt(port ?? opts.port, 10);
11714
11944
  if (Number.isNaN(resolved)) {
11715
- console.error(import_chalk54.default.red(`Invalid port: ${port ?? opts.port}`));
11945
+ console.error(import_chalk55.default.red(`Invalid port: ${port ?? opts.port}`));
11716
11946
  process.exit(1);
11717
11947
  }
11718
11948
  await runDev({ port: resolved, project: opts.project, yes: opts.yes, captureFile: opts.captureFile, newSession: opts.newSession });
@@ -11745,6 +11975,7 @@ program.command("claim").description("Claim your anonymous workspace into your a
11745
11975
  process.exit(1);
11746
11976
  }
11747
11977
  });
11978
+ program.command("docs").description("Ask an AI chatbot about APIblaze \u2014 and let it act on your account (it's the real API, not a docs search)").option("-p, --prompt <question>", "Ask one question and exit").option("--install-mcp <cli>", "Wire it straight into an external agent CLI: claude | codex").option("--remove-mcp <cli>", "Disconnect APIblaze from an external agent CLI (claude | codex)").option("--yes", 'Skip the "this can change things" confirmation').option("--verbose", "Show the per-turn proxy curl trace").action(action((opts) => runDocs(opts)));
11748
11979
  program.command("allowoauthregistration").description("Approve the next OAuth client that registers against your tenant (Claude Code, Codex, any MCP client) \u2014 single use").requiredOption("--tenant <slug>", "Tenant the client will register against (see `apiblaze projects`)").option("--team <id|name>", "Team owning the tenant (defaults to your active team)").option("--minutes <n>", "Expire the unused authorization after this many minutes (default 10, max 60)").option("--cancel", "Cancel an unused authorization instead of opening one").action(action((opts) => runAllowOauthRegistration(opts)));
11749
11980
  program.command("team").description("Switch the active team, or create a new one").argument("[team]", "Team name or id to switch to (omit to choose interactively)").option("--new [name]", "Create a new team and make it active (omit the name to be asked)").action(async (team, opts) => {
11750
11981
  try {
@@ -11822,7 +12053,7 @@ spec.command("set").description("Replace the stored OpenAPI spec from a local fi
11822
12053
  spec.command("carry").description("Copy a route's saved rules to the path a spec rename moved traffic to").argument("<project>", "Project name or id").requiredOption("--method <method>", "HTTP method of the route (GET, POST, ...)").requiredOption("--from <path>", "Old route path, e.g. /owners/{ownerId}").requiredOption("--to <path>", "New route path, e.g. /customers/{customerId}").option("--delete-source", "Also delete the old rules after carrying").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runSpecCarry(project, opts)));
11823
12054
  spec.command("delete-rule").description("Delete the saved rules for a route (e.g. an orphan left by a spec change)").argument("<project>", "Project name or id").requiredOption("--method <method>", "HTTP method of the route").requiredOption("--route <path>", "Route path, e.g. /owners/{ownerId}").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").action(action((project, opts) => runSpecDeleteRule(project, opts)));
11824
12055
  var HELP_GROUPS = [
11825
- { title: "Chat", commands: ["apichat", "agent"] },
12056
+ { title: "Chat", commands: ["docs", "apichat", "agent"] },
11826
12057
  { title: "Setup", commands: ["login", "create", "init", "sidecar", "dev", "claim", "team", "whoami", "logout"] },
11827
12058
  { title: "Recipes \u2014 install a working setup, or publish yours", commands: ["search", "show", "install", "publish", "withdraw"] },
11828
12059
  { title: "Control plane commands", commands: ["config", "projects", "logs", "tenant", "group", "admins", "iam", "identified", "preapprove", "rule", "domain", "delete", "target", "throttle", "rename", "spec", "export"] },
@@ -11845,7 +12076,7 @@ function groupedCommandHelp() {
11845
12076
  const sub = byName.get(e.parent)?.commands.find((s) => s.name() === e.sub);
11846
12077
  return sub ? ` ${helpLabel(e).padEnd(width)}${sub.description()}` : "";
11847
12078
  }).filter(Boolean).join("\n");
11848
- return `${import_chalk54.default.bold(g.title)}
12079
+ return `${import_chalk55.default.bold(g.title)}
11849
12080
  ${rows}`;
11850
12081
  }).join("\n\n");
11851
12082
  }
@@ -11856,6 +12087,8 @@ program.configureHelp({
11856
12087
  }
11857
12088
  });
11858
12089
  program.addHelpText("after", () => `
12090
+ ${import_chalk55.default.bold("Don't like reading docs?")} Run ${import_chalk55.default.bgCyan.black.bold(" npx apiblaze docs ")} ${import_chalk55.default.cyan("\u2014 ask an AI chatbot about APIblaze, and let it act on your account.")}
12091
+
11859
12092
  ${groupedCommandHelp()}
11860
12093
 
11861
12094
  Tips:
@@ -11885,14 +12118,14 @@ async function recoverStaleTeam() {
11885
12118
  const { resolveLinkedTeam: resolveLinkedTeam2 } = await Promise.resolve().then(() => (init_team(), team_exports));
11886
12119
  const linked = await resolveLinkedTeam2({ preferredId: creds.teamId, interactive: !!process.stdin.isTTY });
11887
12120
  if (!linked) {
11888
- console.error(import_chalk54.default.yellow("Your account has no teams anymore (deleted?). Run `apiblaze login` or `apiblaze create` to get a workspace."));
12121
+ console.error(import_chalk55.default.yellow("Your account has no teams anymore (deleted?). Run `apiblaze login` or `apiblaze create` to get a workspace."));
11889
12122
  return;
11890
12123
  }
11891
12124
  if (linked.teamId === creds.teamId) return;
11892
12125
  const next = { ...creds, teamId: linked.teamId, teamName: linked.teamName };
11893
12126
  delete next.activeTenant;
11894
12127
  saveCredentials(next);
11895
- console.error(import_chalk54.default.yellow(`Your previous team no longer exists \u2014 relinked to ${import_chalk54.default.bold(linked.teamName ?? linked.teamId)}. Re-run your command.`));
12128
+ console.error(import_chalk55.default.yellow(`Your previous team no longer exists \u2014 relinked to ${import_chalk55.default.bold(linked.teamName ?? linked.teamId)}. Re-run your command.`));
11896
12129
  } catch {
11897
12130
  }
11898
12131
  }
@@ -11900,16 +12133,16 @@ async function printError(err) {
11900
12133
  if (err instanceof ApiError) {
11901
12134
  const data = err.body;
11902
12135
  const extra = [data?.body?.reason, data?.body?.details, data?.details, data?.body?.error].find((x) => typeof x === "string" && x && x !== err.message);
11903
- console.error(import_chalk54.default.red(`
12136
+ console.error(import_chalk55.default.red(`
11904
12137
  API error (${err.status}): ${err.message}${extra ? ` \u2014 ${extra}` : ""}`));
11905
12138
  if (err.status === 403 || err.status === 404) {
11906
12139
  await recoverStaleTeam();
11907
12140
  }
11908
12141
  } else if (err instanceof Error) {
11909
- console.error(import_chalk54.default.red(`
12142
+ console.error(import_chalk55.default.red(`
11910
12143
  Error: ${err.message}`));
11911
12144
  } else {
11912
- console.error(import_chalk54.default.red("\nUnknown error"));
12145
+ console.error(import_chalk55.default.red("\nUnknown error"));
11913
12146
  }
11914
12147
  }
11915
12148
  program.parse(process.argv);