apiblaze 0.20.34 → 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 +824 -687
  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.33";
1027
+ var version = "0.20.39";
1028
1028
 
1029
1029
  // src/index.ts
1030
1030
  init_types();
@@ -2574,7 +2574,8 @@ function codexInteractive(_spec, prompt) {
2574
2574
  }
2575
2575
  var shellQuote = (s) => `"${s.replace(/(["\\$`])/g, "\\$1")}"`;
2576
2576
  function directedPrompt(spec2, question) {
2577
- 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}`;
2578
2579
  }
2579
2580
  function agentInstructionFile(cli, dir = process.cwd()) {
2580
2581
  return path4.join(dir, cli === "claude" ? "CLAUDE.md" : "AGENTS.md");
@@ -2607,6 +2608,7 @@ function writeAgentInstruction(cli, spec2, dir = process.cwd()) {
2607
2608
  `${spec2.projectLabel} API as tools. For any question about this API \u2014 its data, its`,
2608
2609
  "records, what it can do \u2014 call those tools rather than answering from memory or",
2609
2610
  "asking for data the API can provide.",
2611
+ ...spec2.contextNote ? ["", spec2.contextNote] : [],
2610
2612
  "",
2611
2613
  `_Added by \`apiblaze apichat\`. Remove this block, or run \`npx apiblaze apichat ${spec2.name} --remove-mcp ${cli}\`._`,
2612
2614
  m.end,
@@ -2638,7 +2640,8 @@ function removeAgentInstruction(cli, name, dir = process.cwd()) {
2638
2640
  }
2639
2641
  }
2640
2642
  function claudeSystemHint(spec2) {
2641
- 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}`;
2642
2645
  }
2643
2646
  function renderCommand(argv) {
2644
2647
  return argv.map((a, i) => i === 0 || /^[A-Za-z0-9_@%+=:,./-]+$/.test(a) ? a : shellQuote(a)).join(" ");
@@ -4211,6 +4214,9 @@ function rememberCliOffer(p, cli, state) {
4211
4214
  }
4212
4215
  function buildInstallSpec(p) {
4213
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,
4214
4220
  name: p.projectId,
4215
4221
  url: `https://${p.mcpHost}/${p.version}/${p.environment}`,
4216
4222
  // consumerAuth means the door is a login — install bare, the CLI signs in.
@@ -4254,6 +4260,12 @@ async function maybeInstallExternalCli(p, opts) {
4254
4260
  );
4255
4261
  if (!await ensureInstallableDoor(p, opts)) return false;
4256
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
+ }
4257
4269
  fail3(`The MCP endpoint https://${p.mcpHost}/${p.version}/${p.environment} is not answering \u2014 not installing it into ${cli.label}.`);
4258
4270
  }
4259
4271
  await authorizeClientRegistration(p, cli.label);
@@ -4408,6 +4420,86 @@ async function startChat(p, messages, opts) {
4408
4420
  }
4409
4421
  await runRepl(p, messages);
4410
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
+ }
4411
4503
  async function removeExternalMcp(projectId, cliKind) {
4412
4504
  const kind = cliKind.toLowerCase();
4413
4505
  if (kind !== "claude" && kind !== "codex") fail3(`--remove-mcp takes "claude" or "codex", not "${cliKind}".`);
@@ -4428,6 +4520,12 @@ async function removeExternalMcp(projectId, cliKind) {
4428
4520
  async function runApichat(opts) {
4429
4521
  setVerbose(opts.verbose === true);
4430
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
+ }
4431
4529
  if (opts.target && !opts.openapispec) {
4432
4530
  const { classifyTargetInput: classifyTargetInput2 } = await Promise.resolve().then(() => (init_spec_or_target(), spec_or_target_exports));
4433
4531
  const c = await classifyTargetInput2(opts.target, fail3);
@@ -5328,44 +5426,80 @@ async function runTeam(arg, opts = {}) {
5328
5426
  activate(creds, chosen);
5329
5427
  }
5330
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
+
5331
5465
  // src/commands/authz.ts
5332
- var import_chalk23 = __toESM(require("chalk"));
5466
+ var import_chalk24 = __toESM(require("chalk"));
5333
5467
  init_auth();
5334
5468
  init_api();
5335
5469
 
5336
5470
  // src/lib/agent-chat.ts
5337
5471
  var import_readline = __toESM(require("readline"));
5338
- var import_chalk21 = __toESM(require("chalk"));
5472
+ var import_chalk22 = __toESM(require("chalk"));
5339
5473
  init_api();
5340
5474
  init_admin();
5341
5475
  async function runAgentChatRepl(opts) {
5342
5476
  const { title, subtitle, endpoint, buildBody, seedPrompt, summarizeProposal, commands } = opts;
5343
- console.log("\n" + import_chalk21.default.cyan.bold(title));
5344
- 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));
5345
5479
  const messages = [];
5346
5480
  const ctx = { proposal: null, lastData: null, log: (s) => console.log(s) };
5347
5481
  const cmdByName = new Map(commands.map((c) => [c.name, c]));
5348
5482
  const footer = () => {
5349
5483
  const parts = [
5350
- import_chalk21.default.dim("type to chat/refine"),
5351
- ...commands.map((c) => import_chalk21.default.dim(`/${c.name} ${c.describe}`)),
5352
- import_chalk21.default.dim("/show"),
5353
- import_chalk21.default.dim("/exit when done"),
5354
- 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")
5355
5489
  ];
5356
- 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(" ]");
5357
5491
  };
5358
5492
  async function turn(content) {
5359
5493
  messages.push({ role: "user", content });
5360
- process.stdout.write(import_chalk21.default.dim(" \u2026thinking\n"));
5494
+ process.stdout.write(import_chalk22.default.dim(" \u2026thinking\n"));
5361
5495
  const { status, data } = await agentCall(endpoint, "POST", { messages, ...buildBody(messages) });
5362
5496
  if (status === 402) {
5363
- 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"));
5364
5498
  messages.pop();
5365
5499
  return;
5366
5500
  }
5367
5501
  if (status >= 400 || !data) {
5368
- 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"}
5369
5503
  `));
5370
5504
  messages.pop();
5371
5505
  return;
@@ -5373,24 +5507,24 @@ async function runAgentChatRepl(opts) {
5373
5507
  ctx.lastData = data;
5374
5508
  const reply = data.reply ?? data.message ?? "(no reply)";
5375
5509
  messages.push({ role: "assistant", content: reply });
5376
- console.log("\n" + import_chalk21.default.cyan("agent \u203A ") + reply + "\n");
5510
+ console.log("\n" + import_chalk22.default.cyan("agent \u203A ") + reply + "\n");
5377
5511
  if (data.proposal) {
5378
5512
  ctx.proposal = data.proposal;
5379
5513
  const summary = summarizeProposal?.(data);
5380
- if (summary) console.log(import_chalk21.default.yellow(" " + summary));
5514
+ if (summary) console.log(import_chalk22.default.yellow(" " + summary));
5381
5515
  const applies = commands.filter((c) => c.needsProposal);
5382
5516
  const primary = applies[applies.length - 1];
5383
5517
  if (primary) {
5384
- 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."));
5385
5519
  const rest = applies.slice(0, -1).map((c) => `/${c.name} = ${c.describe}`).join(" \xB7 ");
5386
- 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)`));
5387
5521
  }
5388
5522
  console.log();
5389
5523
  }
5390
5524
  const line = formatBilling(data.billing);
5391
5525
  if (line) {
5392
5526
  const llm2 = data.llm;
5393
- 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}` : ""}`));
5394
5528
  }
5395
5529
  }
5396
5530
  const rl = import_readline.default.createInterface({ input: process.stdin, output: process.stdout });
@@ -5398,31 +5532,31 @@ async function runAgentChatRepl(opts) {
5398
5532
  await turn(seedPrompt);
5399
5533
  for (; ; ) {
5400
5534
  console.log(footer());
5401
- const line = (await ask(import_chalk21.default.green("you \u203A "))).trim();
5535
+ const line = (await ask(import_chalk22.default.green("you \u203A "))).trim();
5402
5536
  if (!line) continue;
5403
5537
  const lower = line.toLowerCase();
5404
5538
  if (line === "/exit" || line === "/quit" || lower === "exit" || lower === "quit" || lower === "q") {
5405
- 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"));
5406
5540
  break;
5407
5541
  }
5408
5542
  if (line === "/drop") {
5409
- 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"));
5410
5544
  break;
5411
5545
  }
5412
5546
  if (line === "/show") {
5413
- 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"));
5414
5548
  else console.log("\n" + JSON.stringify(ctx.proposal, null, 2) + "\n");
5415
5549
  continue;
5416
5550
  }
5417
5551
  if (line.startsWith("/")) {
5418
5552
  const cmd = cmdByName.get(line.slice(1));
5419
5553
  if (!cmd) {
5420
- 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
5421
5555
  `));
5422
5556
  continue;
5423
5557
  }
5424
5558
  if (cmd.needsProposal && !ctx.proposal) {
5425
- 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"));
5426
5560
  continue;
5427
5561
  }
5428
5562
  await cmd.run(ctx);
@@ -5434,7 +5568,7 @@ async function runAgentChatRepl(opts) {
5434
5568
  }
5435
5569
 
5436
5570
  // src/lib/authz-apply.ts
5437
- var import_chalk22 = __toESM(require("chalk"));
5571
+ var import_chalk23 = __toESM(require("chalk"));
5438
5572
  init_api();
5439
5573
  async function gatherSampleIds(projectId, apiVersion, cap = 50) {
5440
5574
  try {
@@ -5459,10 +5593,10 @@ async function gatherSampleIds(projectId, apiVersion, cap = 50) {
5459
5593
  }
5460
5594
  function maybeWarnNoTraffic(total, projectArg) {
5461
5595
  if (total >= 3) return;
5462
- console.log(import_chalk22.default.yellow(total === 0 ? " \u26A0 No captured traffic for this API yet." : ` \u26A0 Only ${total} captured request(s) so far.`));
5463
- console.log(import_chalk22.default.dim(" The authorization agent designs much better models & rules from REAL requests"));
5464
- console.log(import_chalk22.default.dim(" (it sees who is allowed vs denied). Send some through your proxy first \u2014"));
5465
- 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.
5466
5600
  `));
5467
5601
  }
5468
5602
  async function applyProposal(opts) {
@@ -5471,11 +5605,11 @@ async function applyProposal(opts) {
5471
5605
  {
5472
5606
  const m = await agentCall(`/projects/${projectId}/${apiVersion}/policies/model?tenantId=${encodeURIComponent(tenant2)}`, "POST", proposal.model);
5473
5607
  if (m.status === 404) {
5474
- 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"));
5475
5609
  return { ok: 0, fail: 0, enabled: false, storeMissing: true };
5476
5610
  }
5477
5611
  if (m.status >= 400) {
5478
- 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 ?? ""}
5479
5613
  `));
5480
5614
  return { ok: 0, fail: 0, enabled: false };
5481
5615
  }
@@ -5504,7 +5638,7 @@ async function applyProposal(opts) {
5504
5638
  if (enable) {
5505
5639
  const e = await agentCall(`/projects/${projectId}/${apiVersion}`, "PATCH", { authorization: { enforce_authorization: true }, tenant: tenant2 });
5506
5640
  if (e.status >= 400) {
5507
- 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.
5508
5642
  `));
5509
5643
  return { ok, fail: fail6, enabled: false };
5510
5644
  }
@@ -5530,10 +5664,10 @@ async function runAuthz(projectArg, apiVersionArg) {
5530
5664
  const r = await applyProposal({ projectId, apiVersion, tenant: tenant2, proposal, enable, log: ctx.log });
5531
5665
  if (r.storeMissing) return;
5532
5666
  if (enable && r.enabled) {
5533
- ctx.log(import_chalk23.default.green(` \u2713 Enforcement ON \u2014 ${r.ok} route(s) + project switch on${r.fail ? `, ${r.fail} failed` : ""}.`));
5534
- 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"));
5535
5669
  } else if (!enable) {
5536
- 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.
5537
5671
  `));
5538
5672
  }
5539
5673
  }
@@ -5560,7 +5694,7 @@ async function runAuthz(projectArg, apiVersionArg) {
5560
5694
  }
5561
5695
 
5562
5696
  // src/commands/rule.ts
5563
- var import_chalk24 = __toESM(require("chalk"));
5697
+ var import_chalk25 = __toESM(require("chalk"));
5564
5698
  var import_ora8 = __toESM(require("ora"));
5565
5699
  init_auth();
5566
5700
  init_api();
@@ -5597,27 +5731,27 @@ async function runRule(ruleText, projectArg, opts) {
5597
5731
  const proposal = data?.proposal;
5598
5732
  if (!proposal || !Array.isArray(proposal.routes) || proposal.routes.length === 0) {
5599
5733
  spinner.fail("The agent couldn\u2019t turn that into a rule in one shot.");
5600
- if (data?.reply) console.log(import_chalk24.default.dim("\n " + String(data.reply).slice(0, 500) + "\n"));
5601
- 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}`));
5602
5736
  return;
5603
5737
  }
5604
5738
  spinner.succeed(`Rule designed \u2014 ${proposal.routes.length} route(s) affected.`);
5605
- 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)));
5606
5740
  const pub = await applyProposal({ projectId, apiVersion, tenant: tenant2, proposal, enable: false });
5607
5741
  if (pub.storeMissing) return;
5608
- 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` : ""}.`));
5609
5743
  if (opts.enforce) {
5610
5744
  const enf = await applyProposal({ projectId, apiVersion, tenant: tenant2, proposal, enable: true });
5611
5745
  if (enf.enabled) {
5612
- 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` : ""}.`));
5613
5747
  }
5614
5748
  } else {
5615
- 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`));
5616
5750
  }
5617
5751
  }
5618
5752
 
5619
5753
  // src/commands/openapi.ts
5620
- var import_chalk25 = __toESM(require("chalk"));
5754
+ var import_chalk26 = __toESM(require("chalk"));
5621
5755
  init_auth();
5622
5756
  init_api();
5623
5757
  async function runOpenapi(projectArg, apiVersionArg) {
@@ -5628,10 +5762,10 @@ async function runOpenapi(projectArg, apiVersionArg) {
5628
5762
  if (!match) throw new Error(`Project "${projectArg}" not found in your active team. Run \`apiblaze projects\`.`);
5629
5763
  const projectId = match.projectId;
5630
5764
  const apiVersion = apiVersionArg || match.apiVersion;
5631
- console.log(import_chalk25.default.dim("Gathering captured traffic samples\u2026"));
5765
+ console.log(import_chalk26.default.dim("Gathering captured traffic samples\u2026"));
5632
5766
  const routesRes = await agentCall(`/projects/${projectId}/${apiVersion}/samples/routes`, "GET");
5633
5767
  if (routesRes.status >= 400) {
5634
- 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 ?? ""}`));
5635
5769
  return;
5636
5770
  }
5637
5771
  const routes = routesRes.data?.routes ?? (Array.isArray(routesRes.data) ? routesRes.data : []);
@@ -5644,25 +5778,25 @@ async function runOpenapi(projectArg, apiVersionArg) {
5644
5778
  }
5645
5779
  const sampleIds = [...ids];
5646
5780
  if (sampleIds.length === 0) {
5647
- 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."));
5648
5782
  return;
5649
5783
  }
5650
5784
  async function publish(ctx) {
5651
5785
  const patch = ctx.proposal.patch;
5652
5786
  if (!Array.isArray(patch) || patch.length === 0) {
5653
- 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"));
5654
5788
  return;
5655
5789
  }
5656
5790
  const specSource = ctx.lastData?.spec_source ?? "unknown";
5657
5791
  const endpoint = specSource === "github" ? "open-pr" : "publish-openapi";
5658
5792
  const pub = await agentCall(`/projects/${projectId}/${apiVersion}/samples/${endpoint}`, "POST", { patch, sample_ids_used: sampleIds });
5659
5793
  if (pub.status >= 400) {
5660
- 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 ?? ""}
5661
5795
  `));
5662
5796
  return;
5663
5797
  }
5664
5798
  const prUrl = pub.data?.pr_url;
5665
- 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}
5666
5800
  ` : " \u2713 Published updated OpenAPI spec.\n"));
5667
5801
  }
5668
5802
  await runAgentChatRepl({
@@ -5683,7 +5817,7 @@ async function runOpenapi(projectArg, apiVersionArg) {
5683
5817
  }
5684
5818
 
5685
5819
  // src/commands/mcp.ts
5686
- var import_chalk26 = __toESM(require("chalk"));
5820
+ var import_chalk27 = __toESM(require("chalk"));
5687
5821
  init_auth();
5688
5822
  init_api();
5689
5823
  async function runMcp(projectArg, apiVersionArg, opts) {
@@ -5700,11 +5834,11 @@ async function runMcp(projectArg, apiVersionArg, opts) {
5700
5834
  const spec2 = ctx.proposal;
5701
5835
  const pub = await agentCall(`/projects/${projectId}/${apiVersion}/mcp/spec`, "PUT", { environment, spec: spec2 });
5702
5836
  if (pub.status >= 400) {
5703
- 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 ?? ""}
5704
5838
  `));
5705
5839
  return;
5706
5840
  }
5707
- 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}.
5708
5842
  `));
5709
5843
  }
5710
5844
  await runAgentChatRepl({
@@ -5726,7 +5860,7 @@ async function runMcp(projectArg, apiVersionArg, opts) {
5726
5860
  }
5727
5861
 
5728
5862
  // src/commands/delete.ts
5729
- var import_chalk27 = __toESM(require("chalk"));
5863
+ var import_chalk28 = __toESM(require("chalk"));
5730
5864
  var import_ora9 = __toESM(require("ora"));
5731
5865
  init_admin();
5732
5866
  init_resolve();
@@ -5752,10 +5886,10 @@ async function runDelete(project, version2, opts) {
5752
5886
  return;
5753
5887
  }
5754
5888
  } else {
5755
- 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 + ")")}`);
5756
5890
  if (impact && typeof impact === "object") {
5757
5891
  const counts = impact.counts ?? impact.impact ?? impact;
5758
- 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)));
5759
5893
  }
5760
5894
  if (!opts.yes) {
5761
5895
  const { default: inquirer3 } = await import("inquirer");
@@ -5763,7 +5897,7 @@ async function runDelete(project, version2, opts) {
5763
5897
  { type: "confirm", name: "confirm", message: `Permanently delete ${proj2.projectName} v${proj2.apiVersion}? This cannot be undone.`, default: false }
5764
5898
  ]);
5765
5899
  if (!confirm2) {
5766
- console.log(import_chalk27.default.dim("Aborted."));
5900
+ console.log(import_chalk28.default.dim("Aborted."));
5767
5901
  return;
5768
5902
  }
5769
5903
  }
@@ -5784,7 +5918,7 @@ async function runDelete(project, version2, opts) {
5784
5918
  }
5785
5919
 
5786
5920
  // src/commands/export.ts
5787
- var import_chalk28 = __toESM(require("chalk"));
5921
+ var import_chalk29 = __toESM(require("chalk"));
5788
5922
  var import_fs3 = require("fs");
5789
5923
  init_admin();
5790
5924
  init_auth();
@@ -5803,7 +5937,7 @@ async function runExport(projectArg, versionArg, opts) {
5803
5937
  if (opts.noConsumers) q.set("include_consumers", "0");
5804
5938
  if (opts.keys) q.set("keys", opts.keys);
5805
5939
  const qs = q.toString() ? `?${q.toString()}` : "";
5806
- 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`));
5807
5941
  const job = await admin({
5808
5942
  path: `/projects/${projectId}/${version2}/export/${target}${qs}`,
5809
5943
  method: "GET",
@@ -5813,11 +5947,11 @@ async function runExport(projectArg, versionArg, opts) {
5813
5947
  const statusPath = `/projects/${projectId}/${version2}/export/jobs/${job.job_id}`;
5814
5948
  let status = "queued";
5815
5949
  const started = Date.now();
5816
- process.stdout.write(import_chalk28.default.dim("Building bundle"));
5950
+ process.stdout.write(import_chalk29.default.dim("Building bundle"));
5817
5951
  while (status !== "ready" && status !== "failed") {
5818
5952
  if (Date.now() - started > 10 * 6e4) throw new Error("Export timed out after 10 minutes.");
5819
5953
  await new Promise((r) => setTimeout(r, 3e3));
5820
- process.stdout.write(import_chalk28.default.dim("."));
5954
+ process.stdout.write(import_chalk29.default.dim("."));
5821
5955
  const st = await admin({ path: statusPath, method: "GET", summary: "poll export" });
5822
5956
  status = st?.status ?? "queued";
5823
5957
  if (status === "failed") {
@@ -5835,14 +5969,14 @@ async function runExport(projectArg, versionArg, opts) {
5835
5969
  if (!res.ok) throw new Error(`Download failed (${res.status}): ${await res.text().catch(() => "")}`);
5836
5970
  const buf = Buffer.from(await res.arrayBuffer());
5837
5971
  (0, import_fs3.writeFileSync)(outFile, buf);
5838
- console.log(import_chalk28.default.green(`\u2713 Saved ${outFile} (${(buf.length / 1024).toFixed(0)} KB)`));
5839
- if (job.decryption_key) console.log(import_chalk28.default.yellow(`Decryption key (shown once): ${job.decryption_key}`));
5840
- console.log(import_chalk28.default.dim("Read MIGRATION-REPORT.json inside the zip for the full fidelity ledger."));
5841
- 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)."));
5842
5976
  }
5843
5977
 
5844
5978
  // src/commands/recipe-search.ts
5845
- var import_chalk29 = __toESM(require("chalk"));
5979
+ var import_chalk30 = __toESM(require("chalk"));
5846
5980
  var import_ora10 = __toESM(require("ora"));
5847
5981
  init_caller();
5848
5982
 
@@ -6043,20 +6177,20 @@ async function runRecipeSearch(query, opts) {
6043
6177
  return;
6044
6178
  }
6045
6179
  if (!hits.length) {
6046
- console.log(import_chalk29.default.yellow(query ? `No public recipes match "${query}".` : "No public recipes yet."));
6047
- 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"));
6048
6182
  return;
6049
6183
  }
6050
6184
  console.log();
6051
6185
  for (const h of hits) {
6052
- const pin = h.latest_revision ? import_chalk29.default.dim(`@${h.latest_revision}`) : "";
6053
- const installs = h.install_count ? import_chalk29.default.dim(` ${h.install_count} install${h.install_count === 1 ? "" : "s"}`) : "";
6054
- console.log(` ${import_chalk29.default.bold(h.name)}${pin}${h.display_name ? import_chalk29.default.dim(` \u2014 ${h.display_name}`) : ""}${installs}`);
6055
- 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)}`);
6056
6190
  }
6057
6191
  console.log();
6058
- console.log(import_chalk29.default.dim(` Install one with: ${import_chalk29.default.cyan(`npx apiblaze install ${hits[0].name}`)}`));
6059
- 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}`)}`));
6060
6194
  console.log();
6061
6195
  }
6062
6196
  async function runRecipeShow(nameArg, opts) {
@@ -6082,8 +6216,8 @@ async function runRecipeShow(nameArg, opts) {
6082
6216
  return;
6083
6217
  }
6084
6218
  console.log();
6085
- console.log(`${import_chalk29.default.bold(`${recipe.name}@${recipe.revision}`)}${import_chalk29.default.dim(` \u2014 by ${ref.handle}`)}`);
6086
- 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)}`);
6087
6221
  if (recipe.summary) console.log(` ${recipe.summary}`);
6088
6222
  const meta = [
6089
6223
  head?.install_count !== void 0 ? `${head.install_count} install${head.install_count === 1 ? "" : "s"}` : null,
@@ -6091,7 +6225,7 @@ async function runRecipeShow(nameArg, opts) {
6091
6225
  recipe.published_at ? `published ${recipe.published_at.slice(0, 10)}` : null,
6092
6226
  `api version ${recipe.api_version}`
6093
6227
  ].filter(Boolean).join(" \xB7 ");
6094
- console.log(import_chalk29.default.dim(` ${meta}`));
6228
+ console.log(import_chalk30.default.dim(` ${meta}`));
6095
6229
  console.log();
6096
6230
  if (wantsSection) {
6097
6231
  if (opts.settings) printSection("settings", recipe.settings);
@@ -6105,34 +6239,34 @@ async function runRecipeShow(nameArg, opts) {
6105
6239
  const rules = recipe.transformations?.rules?.length ?? 0;
6106
6240
  const tables = recipe.transformations?.mapping_tables?.length ?? 0;
6107
6241
  const keyTypes = recipe.auth?.key_types?.length ?? 0;
6108
- if (hosts.length) console.log(` ${import_chalk29.default.dim("sends requests to")} ${hosts.join(", ")}`);
6109
- console.log(` ${import_chalk29.default.dim("creates ")} ${describeCreates(keyTypes, routes, !!recipe.settings.mcp_enabled)}`);
6110
- 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"}`);
6111
6245
  if (rules || tables) {
6112
- 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"}` : ""}`);
6113
6247
  }
6114
6248
  if (recipe.settings.publish_openapi === true) {
6115
- 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`);
6116
6250
  }
6117
6251
  if (recipe.questions.length) {
6118
6252
  console.log();
6119
- console.log(import_chalk29.default.bold(" It will ask you for"));
6253
+ console.log(import_chalk30.default.bold(" It will ask you for"));
6120
6254
  for (const q of recipe.questions) {
6121
- console.log(` ${q.prompt}${q.secret ? import_chalk29.default.dim(" (hidden while you type)") : ""}`);
6122
- 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}`));
6123
6257
  }
6124
6258
  }
6125
6259
  if (recipe.requires_confirmation?.length) {
6126
6260
  console.log();
6127
- 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"));
6128
6262
  for (const c of recipe.requires_confirmation) {
6129
- console.log(` ${import_chalk29.default.bold(c.kind)} ${c.value}`);
6130
- 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}`));
6131
6265
  }
6132
6266
  }
6133
6267
  console.log();
6134
- console.log(import_chalk29.default.dim(` Install: ${import_chalk29.default.cyan(`npx apiblaze install ${recipe.name}`)}`));
6135
- 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"));
6136
6270
  console.log();
6137
6271
  }
6138
6272
  function describeCreates(keyTypes, routes, mcp, includeProxy = true) {
@@ -6142,45 +6276,45 @@ function describeCreates(keyTypes, routes, mcp, includeProxy = true) {
6142
6276
  return parts.length ? parts.join(", ") : "nothing else";
6143
6277
  }
6144
6278
  function printSection(title, value) {
6145
- console.log(import_chalk29.default.bold(` ${title}`));
6279
+ console.log(import_chalk30.default.bold(` ${title}`));
6146
6280
  console.log(indent(JSON.stringify(value ?? null, null, 2), " "));
6147
6281
  console.log();
6148
6282
  }
6149
6283
  function printAuth(recipe) {
6150
6284
  const a = recipe.auth ?? { app_client: null, provider: null, key_types: [] };
6151
- console.log(import_chalk29.default.bold(" auth"));
6285
+ console.log(import_chalk30.default.bold(" auth"));
6152
6286
  if (a.provider) {
6153
- console.log(` ${import_chalk29.default.dim("provider ")} ${a.provider.type ?? "(unknown)"}`);
6154
- if (a.provider.scopes) console.log(` ${import_chalk29.default.dim("scopes ")} ${a.provider.scopes}`);
6155
- if (a.provider.target_server_token) console.log(` ${import_chalk29.default.dim("sends to API")} ${a.provider.target_server_token}`);
6156
- 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)"));
6157
6291
  } else {
6158
- 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"));
6159
6293
  }
6160
6294
  if (a.app_client) {
6161
- 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)"}`);
6162
6296
  }
6163
6297
  if (a.key_types?.length) {
6164
- 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(", ")}`);
6165
6299
  }
6166
6300
  console.log();
6167
6301
  }
6168
6302
  function printTransforms(recipe) {
6169
6303
  const rules = recipe.transformations?.rules ?? [];
6170
6304
  const tables = recipe.transformations?.mapping_tables ?? [];
6171
- console.log(import_chalk29.default.bold(` transforms (${rules.length})`));
6305
+ console.log(import_chalk30.default.bold(` transforms (${rules.length})`));
6172
6306
  for (const r of rules) {
6173
- const off = r.enabled === false ? import_chalk29.default.dim(" (disabled)") : "";
6174
- 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}`);
6175
6309
  console.log(indent(JSON.stringify(r.action ?? null, null, 2), " "));
6176
6310
  if (r.condition) console.log(indent(`when ${JSON.stringify(r.condition)}`, " "));
6177
6311
  }
6178
6312
  if (tables.length) {
6179
6313
  console.log();
6180
- console.log(import_chalk29.default.bold(` mapping tables (${tables.length})`));
6314
+ console.log(import_chalk30.default.bold(` mapping tables (${tables.length})`));
6181
6315
  for (const t of tables) {
6182
6316
  const entries2 = Array.isArray(t.entries) ? t.entries.length : 0;
6183
- 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"}`)}`);
6184
6318
  }
6185
6319
  }
6186
6320
  console.log();
@@ -6190,7 +6324,7 @@ function indent(text, pad) {
6190
6324
  }
6191
6325
 
6192
6326
  // src/commands/recipe-install.ts
6193
- var import_chalk30 = __toESM(require("chalk"));
6327
+ var import_chalk31 = __toESM(require("chalk"));
6194
6328
  init_types();
6195
6329
  init_caller();
6196
6330
  init_api();
@@ -6207,7 +6341,7 @@ async function runRecipeInstall(nameArg, opts) {
6207
6341
  const chosenTeamId = picked.chosen ? picked.teamId : void 0;
6208
6342
  const teamName = picked.teamName;
6209
6343
  console.log();
6210
- 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}`)}`);
6211
6345
  if (recipe.summary) console.log(` ${recipe.summary}`);
6212
6346
  console.log();
6213
6347
  let project;
@@ -6231,7 +6365,7 @@ async function runRecipeInstall(nameArg, opts) {
6231
6365
  reuseTenant = chosenTenant.existing;
6232
6366
  printSummary(recipe, project, tenant2, reuseTenant);
6233
6367
  if (!assumeYes && !await confirmYesNo(" continue?", interactive)) {
6234
- console.log(import_chalk30.default.yellow(" Cancelled \u2014 nothing was created."));
6368
+ console.log(import_chalk31.default.yellow(" Cancelled \u2014 nothing was created."));
6235
6369
  return;
6236
6370
  }
6237
6371
  }
@@ -6250,18 +6384,18 @@ async function runRecipeInstall(nameArg, opts) {
6250
6384
  process.stdout.write(` ${step.label.padEnd(33)}`);
6251
6385
  try {
6252
6386
  const note = await step.run();
6253
- 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)}` : ""}`);
6254
6388
  } catch (err) {
6255
- 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))}`);
6256
6390
  console.log();
6257
6391
  if (step.n === 1) {
6258
- 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.`));
6259
6393
  console.log("run the same command again once the problem above is fixed:");
6260
- console.log(import_chalk30.default.cyan(` npx apiblaze install ${nameArg}`));
6394
+ console.log(import_chalk31.default.cyan(` npx apiblaze install ${nameArg}`));
6261
6395
  } else {
6262
- 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.`));
6263
6397
  console.log("continue with:");
6264
- 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}`));
6265
6399
  }
6266
6400
  console.log();
6267
6401
  process.exit(1);
@@ -6271,9 +6405,9 @@ async function runRecipeInstall(nameArg, opts) {
6271
6405
  const urls = installUrls(ctx);
6272
6406
  console.log();
6273
6407
  console.log(`done in ${secs}s.`);
6274
- console.log(` ${import_chalk30.default.dim("proxy ")} ${import_chalk30.default.bold(urls.proxy_url)}`);
6275
- if (recipe.settings.mcp_enabled === true) console.log(` ${import_chalk30.default.dim("mcp ")} ${import_chalk30.default.bold(urls.mcp_url)}`);
6276
- 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)}`);
6277
6411
  console.log();
6278
6412
  }
6279
6413
  function buildSteps(inp) {
@@ -6589,7 +6723,7 @@ async function nameIsFree(name, teamId) {
6589
6723
  async function chooseProxyName(slug, asOpt, teamId, interactive) {
6590
6724
  if (asOpt !== void 0) {
6591
6725
  const name = normalizeName3(asOpt);
6592
- 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.`));
6593
6727
  if (name.length < 3) throw new Error("A proxy name must be at least 3 characters (lowercase letters and digits only).");
6594
6728
  const free = await nameIsFree(name, teamId);
6595
6729
  if (free === false) throw new Error(`"${name}" is already taken. Pick another with --as.`);
@@ -6606,7 +6740,7 @@ async function chooseProxyName(slug, asOpt, teamId, interactive) {
6606
6740
  }
6607
6741
  if (!interactive) return suggested;
6608
6742
  const { default: inquirer3 } = await import("inquirer");
6609
- 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]")}`);
6610
6744
  for (; ; ) {
6611
6745
  const { raw } = await inquirer3.prompt([{
6612
6746
  type: "input",
@@ -6617,20 +6751,20 @@ async function chooseProxyName(slug, asOpt, teamId, interactive) {
6617
6751
  }]);
6618
6752
  const name = normalizeName3(raw);
6619
6753
  if (name !== String(raw).trim()) {
6620
- 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)`));
6621
6755
  }
6622
6756
  if (name.length < 3) {
6623
- 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"));
6624
6758
  continue;
6625
6759
  }
6626
6760
  const free = await nameIsFree(name, teamId);
6627
6761
  if (free === false) {
6628
- console.log(import_chalk30.default.yellow(` "${name}" is taken. Try another.
6762
+ console.log(import_chalk31.default.yellow(` "${name}" is taken. Try another.
6629
6763
  `));
6630
6764
  continue;
6631
6765
  }
6632
- if (free === null) console.log(import_chalk30.default.dim(" (could not verify availability; continuing)"));
6633
- 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`)}`);
6634
6768
  return name;
6635
6769
  }
6636
6770
  }
@@ -6648,20 +6782,20 @@ function printSummary(recipe, project, tenant2, reuseTenant = false) {
6648
6782
  const keyTypes = recipe.auth?.key_types?.length ?? 0;
6649
6783
  const questions = reuseTenant ? 0 : recipe.questions?.length ?? 0;
6650
6784
  const row = (label3, value, note) => {
6651
- 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}`) : ""}`);
6652
6786
  };
6653
6787
  console.log();
6654
- console.log(import_chalk30.default.bold(" This will:"));
6788
+ console.log(import_chalk31.default.bold(" This will:"));
6655
6789
  console.log();
6656
- row("create a proxy", import_chalk30.default.bold(project), `at https://${project}.abz.run`);
6657
- 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)");
6658
6792
  if (hosts.length) row("sending requests to", hosts.join(", "));
6659
6793
  row("and set up", describeCreates(keyTypes, routes, recipe.settings.mcp_enabled === true, false));
6660
6794
  row("asking you for", questions ? `${questions} value${questions === 1 ? "" : "s"}` : "nothing");
6661
6795
  if (reuseTenant) {
6662
6796
  console.log();
6663
- console.log(import_chalk30.default.dim(` ${tenant2} is used exactly as it is \u2014 its existing login stays, and this`));
6664
- 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."));
6665
6799
  }
6666
6800
  console.log();
6667
6801
  }
@@ -6670,11 +6804,11 @@ function declineAll(items) {
6670
6804
  const upstreams = items.filter((i) => i.kind === "upstream");
6671
6805
  console.log();
6672
6806
  for (const u of upstreams) {
6673
- 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)}.`));
6674
6808
  }
6675
6809
  if (skippable.length) {
6676
- console.log(import_chalk30.default.yellow(` --yes: installing without ${skippable.length} setting${skippable.length === 1 ? "" : "s"} that need consent.`));
6677
- 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}`));
6678
6812
  }
6679
6813
  return new Set(skippable.map((i) => i.kind));
6680
6814
  }
@@ -6692,14 +6826,14 @@ async function askConsent(items, interactive) {
6692
6826
  const count = items.length;
6693
6827
  const word = ["", "it", "both", "all three", "all four", "all five", "all six"][count] ?? `all ${count}`;
6694
6828
  console.log();
6695
- 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."));
6696
6830
  console.log();
6697
6831
  for (const item of items) {
6698
- console.log(` ${import_chalk30.default.bold(item.kind.padEnd(16))} ${item.value}`);
6699
- 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)}`);
6700
6834
  }
6701
6835
  console.log();
6702
- console.log(`Type "${import_chalk30.default.bold("yes")}" to accept ${word}.`);
6836
+ console.log(`Type "${import_chalk31.default.bold("yes")}" to accept ${word}.`);
6703
6837
  console.log("Press enter to install the recipe without them.");
6704
6838
  let typed = "";
6705
6839
  if (interactive) {
@@ -6711,7 +6845,7 @@ async function askConsent(items, interactive) {
6711
6845
  for (const item of items) {
6712
6846
  declined.add(item.kind === "transform" ? `transform:${item.value}` : `kind:${item.kind}`);
6713
6847
  }
6714
- 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.`));
6715
6849
  return declined;
6716
6850
  }
6717
6851
  async function askQuestions(questions, ctx, interactive) {
@@ -6724,13 +6858,13 @@ async function askQuestions(questions, ctx, interactive) {
6724
6858
  const BOX = 64;
6725
6859
  const title = "\u2500\u2500 from the publisher ";
6726
6860
  console.log();
6727
- console.log(` ${import_chalk30.default.dim(title + "\u2500".repeat(BOX - title.length))}`);
6728
- for (const line of fillContext(q.before, ctx).split("\n")) console.log(` ${import_chalk30.default.dim("\u2502")} ${line}`);
6729
- 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))}`);
6730
6864
  }
6731
6865
  if (fromEnv !== void 0 && fromEnv !== "") {
6732
6866
  answers[q.id] = fromEnv;
6733
- console.log(` ${q.prompt}: ${import_chalk30.default.dim(`(from ${envName})`)}`);
6867
+ console.log(` ${q.prompt}: ${import_chalk31.default.dim(`(from ${envName})`)}`);
6734
6868
  continue;
6735
6869
  }
6736
6870
  if (!interactive) {
@@ -6740,7 +6874,7 @@ async function askQuestions(questions, ctx, interactive) {
6740
6874
  );
6741
6875
  }
6742
6876
  const { default: inquirer3 } = await import("inquirer");
6743
- 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}`));
6744
6878
  const { value } = await inquirer3.prompt([{
6745
6879
  // `secret: true` masks the input — the Google client secret is typed once,
6746
6880
  // goes to provider creation, and is never echoed or stored.
@@ -6774,30 +6908,30 @@ async function confirmReinstall(recipe, project, tenant2, interactive) {
6774
6908
  const tables = recipe.transformations?.mapping_tables?.length ?? 0;
6775
6909
  const routes = countRoutes(recipe.openapi);
6776
6910
  const keyTypes = recipe.auth?.key_types?.length ?? 0;
6777
- 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)}.`);
6778
6912
  console.log();
6779
- console.log(` ${import_chalk30.default.dim("settings ".padEnd(16))}replaced`);
6913
+ console.log(` ${import_chalk31.default.dim("settings ".padEnd(16))}replaced`);
6780
6914
  if (rules || tables) {
6781
- 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`);
6782
6916
  }
6783
6917
  if (routes) {
6784
- 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" : ""}`);
6785
6919
  }
6786
6920
  if (keyTypes) {
6787
- 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`);
6788
6922
  }
6789
6923
  console.log();
6790
- 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,`);
6791
6925
  console.log(` ${" ".repeat(16)}and any tenant other than ${tenant2}`);
6792
6926
  console.log();
6793
- console.log(import_chalk30.default.yellow("This cannot be undone."));
6927
+ console.log(import_chalk31.default.yellow("This cannot be undone."));
6794
6928
  if (!interactive) {
6795
6929
  throw new Error("Reinstall needs a typed confirmation and there is no terminal to ask on.");
6796
6930
  }
6797
6931
  const { default: inquirer3 } = await import("inquirer");
6798
6932
  const { typed } = await inquirer3.prompt([{ type: "input", name: "typed", message: `Type the proxy name (${project}) to continue:` }]);
6799
6933
  if (String(typed ?? "").trim() !== project) {
6800
- console.log(import_chalk30.default.yellow("Cancelled \u2014 nothing was changed."));
6934
+ console.log(import_chalk31.default.yellow("Cancelled \u2014 nothing was changed."));
6801
6935
  process.exit(0);
6802
6936
  }
6803
6937
  }
@@ -6805,7 +6939,7 @@ function requireCallerForInstall() {
6805
6939
  try {
6806
6940
  return requireCaller();
6807
6941
  } catch {
6808
- console.error(import_chalk30.default.red(
6942
+ console.error(import_chalk31.default.red(
6809
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)."
6810
6944
  ));
6811
6945
  process.exit(1);
@@ -6841,7 +6975,7 @@ async function chooseTeam(caller, optTeam, interactive) {
6841
6975
  message: " which team should own this proxy?",
6842
6976
  default: active.teamId,
6843
6977
  choices: teams.map((t) => ({
6844
- 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,
6845
6979
  value: t.teamId
6846
6980
  }))
6847
6981
  }]);
@@ -6869,10 +7003,10 @@ async function chooseTenant(caller, project, teamId, optTenant, interactive) {
6869
7003
  message: " where should this proxy's users live?",
6870
7004
  default: "__new__",
6871
7005
  choices: [
6872
- { name: `create ${fresh} ${import_chalk30.default.dim("(a fresh tenant, set up by the recipe)")}`, value: "__new__" },
6873
- 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")),
6874
7008
  ...owned.map((t2) => ({
6875
- 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)")}`,
6876
7010
  value: t2
6877
7011
  }))
6878
7012
  ]
@@ -6899,7 +7033,7 @@ async function teamTenants(caller, teamId) {
6899
7033
  }
6900
7034
 
6901
7035
  // src/commands/recipe-publish.ts
6902
- var import_chalk31 = __toESM(require("chalk"));
7036
+ var import_chalk32 = __toESM(require("chalk"));
6903
7037
  var import_ora11 = __toESM(require("ora"));
6904
7038
  init_caller();
6905
7039
  init_auth();
@@ -6909,15 +7043,15 @@ async function runRecipePublish(projectArg, opts) {
6909
7043
  try {
6910
7044
  resolved = resolveRecipeName(opts.as, creds?.githubHandle, normalizeName3(projectArg));
6911
7045
  } catch (err) {
6912
- 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)));
6913
7047
  process.exitCode = 1;
6914
7048
  return;
6915
7049
  }
6916
7050
  const ref = resolved.ref;
6917
7051
  if (resolved.derivedHandle) {
6918
- 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)}`));
6919
7053
  if (resolved.normalizedFrom) {
6920
- 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)`));
6921
7055
  }
6922
7056
  }
6923
7057
  const interactive = !!process.stdin.isTTY && !opts.json;
@@ -6936,7 +7070,7 @@ async function runRecipePublish(projectArg, opts) {
6936
7070
  let tenant2 = opts.tenant;
6937
7071
  if (!prep.tenant_used && prep.tenants.length > 1) {
6938
7072
  if (!interactive) {
6939
- console.error(import_chalk31.default.red(
7073
+ console.error(import_chalk32.default.red(
6940
7074
  `${proj2.projectId} has ${prep.tenants.length} tenants (${prep.tenants.join(", ")}). Pass --tenant <slug> to say which auth setup the recipe carries.`
6941
7075
  ));
6942
7076
  process.exit(1);
@@ -6952,7 +7086,7 @@ async function runRecipePublish(projectArg, opts) {
6952
7086
  prep = await prepare(caller, proj2.projectId, proj2.apiVersion, ref.name, tenant2);
6953
7087
  }
6954
7088
  if (!prep.name_available) {
6955
- 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.`));
6956
7090
  process.exit(1);
6957
7091
  }
6958
7092
  if (prep.envelope_violations.length) {
@@ -6962,13 +7096,13 @@ async function runRecipePublish(projectArg, opts) {
6962
7096
  if (prep.dropped.length) {
6963
7097
  console.log();
6964
7098
  console.log(`${prep.dropped.length} setting${prep.dropped.length === 1 ? " was" : "s were"} not included, because they are not on the publish list:`);
6965
- 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}`));
6966
7100
  if (prep.hidden_tables_excluded) {
6967
- 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.)`));
6968
7102
  }
6969
7103
  console.log();
6970
7104
  if (!opts.yes && !await confirm(" continue without them?", interactive)) {
6971
- console.log(import_chalk31.default.yellow("Cancelled."));
7105
+ console.log(import_chalk32.default.yellow("Cancelled."));
6972
7106
  return;
6973
7107
  }
6974
7108
  }
@@ -6981,12 +7115,12 @@ async function runRecipePublish(projectArg, opts) {
6981
7115
  console.log();
6982
7116
  for (const f of prep.findings) printFinding(f);
6983
7117
  console.log();
6984
- 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."));
6985
7119
  process.exit(1);
6986
7120
  }
6987
7121
  if (!interactive) {
6988
7122
  for (const f of prep.findings) printFinding(f);
6989
- 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."));
6990
7124
  process.exit(1);
6991
7125
  }
6992
7126
  const { default: inquirer3 } = await import("inquirer");
@@ -7007,10 +7141,10 @@ async function runRecipePublish(projectArg, opts) {
7007
7141
  if (verdict === "ask") promotions.push(await askPromotion(f.path));
7008
7142
  }
7009
7143
  }
7010
- 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.`));
7011
7145
  const totalQuestions = prep.question_ids.length + promotions.length;
7012
7146
  if (totalQuestions > 5) {
7013
- console.log(import_chalk31.default.yellow(`
7147
+ console.log(import_chalk32.default.yellow(`
7014
7148
  \u26A0 installers will have to supply ${totalQuestions} values before this works.`));
7015
7149
  }
7016
7150
  const visibility = opts.private ? "private" : "public";
@@ -7018,11 +7152,11 @@ async function runRecipePublish(projectArg, opts) {
7018
7152
  if (visibility === "public" && prep.spec_will_become_public) {
7019
7153
  console.log();
7020
7154
  console.log("Publishing publicly also makes this API's spec readable at");
7021
- 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`)}`);
7022
7156
  console.log("It is currently private.");
7023
7157
  confirmSpecPublic = opts.yes ? true : await confirm("Continue?", interactive);
7024
7158
  if (!confirmSpecPublic) {
7025
- console.log(import_chalk31.default.yellow("Cancelled \u2014 nothing was published."));
7159
+ console.log(import_chalk32.default.yellow("Cancelled \u2014 nothing was published."));
7026
7160
  return;
7027
7161
  }
7028
7162
  }
@@ -7048,7 +7182,7 @@ async function runRecipePublish(projectArg, opts) {
7048
7182
  },
7049
7183
  summary: `Publish ${proj2.projectId} as ${ref.name} (${visibility})`
7050
7184
  });
7051
- 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}).`);
7052
7186
  } catch (err) {
7053
7187
  spin2?.fail("Publish failed.");
7054
7188
  throw err;
@@ -7057,15 +7191,15 @@ async function runRecipePublish(projectArg, opts) {
7057
7191
  console.log(JSON.stringify(out));
7058
7192
  return;
7059
7193
  }
7060
- console.log(` ${import_chalk31.default.dim("size ")} ${(out.size_bytes / 1024).toFixed(1)} KB`);
7061
- 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`);
7062
7196
  console.log();
7063
7197
  if (out.visibility === "public") {
7064
- 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}`)}`));
7065
7199
  } else {
7066
- 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."));
7067
7201
  }
7068
- 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}`)}`));
7069
7203
  console.log();
7070
7204
  }
7071
7205
  async function prepare(caller, projectId, apiVersion, name, tenant2) {
@@ -7078,23 +7212,23 @@ async function prepare(caller, projectId, apiVersion, name, tenant2) {
7078
7212
  }
7079
7213
  function printFinding(f) {
7080
7214
  const preview = (f.preview ?? "").replace(/\s+/g, " ").trim();
7081
- console.log(` ${import_chalk31.default.bold(f.path)}`);
7082
- 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)}`);
7083
7217
  }
7084
7218
  function printEnvelopeViolations(violations) {
7085
7219
  console.log();
7086
- 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."));
7087
7221
  console.log();
7088
7222
  for (const v of violations) {
7089
- 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})`)}`);
7090
7224
  console.log(` ${v.why}`);
7091
7225
  }
7092
7226
  console.log();
7093
7227
  console.log("A recipe runs in a stranger's account, after apiblaze has attached their end user's");
7094
7228
  console.log("real third-party token, so two rules are absolute:");
7095
- 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`);
7096
7230
  console.log(" those hold a live credential that works at the provider without apiblaze;");
7097
- 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`);
7098
7232
  console.log(" those tell the installer's own backend who is calling.");
7099
7233
  console.log();
7100
7234
  console.log("Writing Authorization from a question or a fixed value is fine \u2014 that is the");
@@ -7112,7 +7246,7 @@ async function askPromotion(path9) {
7112
7246
  { type: "input", name: "id", message: " id:", default: suggestedId }
7113
7247
  ]);
7114
7248
  const id = String(answers.id || suggestedId).toLowerCase().replace(/[^a-z0-9_]/g, "_");
7115
- console.log(import_chalk31.default.dim(` \u2192 replaced with {{${id}}}`));
7249
+ console.log(import_chalk32.default.dim(` \u2192 replaced with {{${id}}}`));
7116
7250
  return {
7117
7251
  path: path9,
7118
7252
  id,
@@ -7131,7 +7265,7 @@ async function confirm(message, interactive) {
7131
7265
  async function runRecipeWithdraw(nameArg, opts) {
7132
7266
  const ref = parseRecipeRef(nameArg);
7133
7267
  if (ref.revision === void 0) {
7134
- 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.`));
7135
7269
  process.exit(1);
7136
7270
  }
7137
7271
  const interactive = !!process.stdin.isTTY && !opts.json;
@@ -7151,11 +7285,11 @@ async function runRecipeWithdraw(nameArg, opts) {
7151
7285
  const { default: inquirer3 } = await import("inquirer");
7152
7286
  const { typed } = await inquirer3.prompt([{ type: "input", name: "typed", message: `type the recipe name to confirm (${ref.name}):` }]);
7153
7287
  if (String(typed ?? "").trim() !== ref.name) {
7154
- console.log(import_chalk31.default.yellow("Cancelled \u2014 nothing was withdrawn."));
7288
+ console.log(import_chalk32.default.yellow("Cancelled \u2014 nothing was withdrawn."));
7155
7289
  return;
7156
7290
  }
7157
7291
  } else {
7158
- 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."));
7159
7293
  process.exit(1);
7160
7294
  }
7161
7295
  const spinner = !opts.json ? (0, import_ora11.default)("Withdrawing...").start() : null;
@@ -7184,33 +7318,33 @@ async function runRecipeWithdraw(nameArg, opts) {
7184
7318
  }
7185
7319
 
7186
7320
  // src/commands/logs.ts
7187
- var import_chalk33 = __toESM(require("chalk"));
7321
+ var import_chalk34 = __toESM(require("chalk"));
7188
7322
  init_admin();
7189
7323
  init_auth();
7190
7324
  init_resolve();
7191
7325
 
7192
7326
  // src/lib/log-view.ts
7193
- var import_chalk32 = __toESM(require("chalk"));
7327
+ var import_chalk33 = __toESM(require("chalk"));
7194
7328
  var readline2 = __toESM(require("readline"));
7195
7329
  function statusColor(status) {
7196
- if (status < 300) return import_chalk32.default.green;
7197
- if (status < 400) return import_chalk32.default.blue;
7198
- if (status < 500) return import_chalk32.default.yellow;
7199
- 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;
7200
7334
  }
7201
7335
  function methodColor(method) {
7202
7336
  switch ((method || "").toUpperCase()) {
7203
7337
  case "GET":
7204
- return import_chalk32.default.green;
7338
+ return import_chalk33.default.green;
7205
7339
  case "POST":
7206
- return import_chalk32.default.blue;
7340
+ return import_chalk33.default.blue;
7207
7341
  case "PUT":
7208
7342
  case "PATCH":
7209
- return import_chalk32.default.yellow;
7343
+ return import_chalk33.default.yellow;
7210
7344
  case "DELETE":
7211
- return import_chalk32.default.red;
7345
+ return import_chalk33.default.red;
7212
7346
  default:
7213
- return import_chalk32.default.white;
7347
+ return import_chalk33.default.white;
7214
7348
  }
7215
7349
  }
7216
7350
  function clock(ts) {
@@ -7222,12 +7356,12 @@ function routeCell(route) {
7222
7356
  return (r.length > ROUTE_W ? `\u2026${r.slice(-(ROUTE_W - 1))}` : r).padEnd(ROUTE_W);
7223
7357
  }
7224
7358
  function formatRow(r) {
7225
- const time = import_chalk32.default.dim(clock(r.ts));
7359
+ const time = import_chalk33.default.dim(clock(r.ts));
7226
7360
  const method = methodColor(r.method)(String(r.method || "\u2014").padEnd(6));
7227
7361
  const route = routeCell(String(r.route || "\u2014"));
7228
7362
  const status = statusColor(r.status)(String(r.status ?? "\u2014").padStart(3));
7229
- const ms = import_chalk32.default.dim(`${r.duration_ms}ms`.padStart(8));
7230
- 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}`) : "";
7231
7365
  return `${time} ${method} ${route} ${status} ${ms}${step}`;
7232
7366
  }
7233
7367
  function printRow(r, json) {
@@ -7242,15 +7376,15 @@ var WindowNotices = class {
7242
7376
  note(res) {
7243
7377
  if (res.history_unavailable && !this.saidUnavailable) {
7244
7378
  this.saidUnavailable = true;
7245
- 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."));
7246
7380
  }
7247
7381
  if ((res.history_markers?.length ?? 0) > 0 && !this.saidGap) {
7248
7382
  this.saidGap = true;
7249
- 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."));
7250
7384
  }
7251
7385
  if ((res.dropped_this_hour ?? 0) > 0 && !this.saidDropped) {
7252
7386
  this.saidDropped = true;
7253
- 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.`));
7254
7388
  }
7255
7389
  }
7256
7390
  };
@@ -7309,13 +7443,13 @@ async function runTailSession(opts) {
7309
7443
  if (!held.length && !heldRowsDropped && !heldNotesDropped) return;
7310
7444
  const rows = held.filter((h) => h.kind === "row").length;
7311
7445
  const total = rows + heldRowsDropped;
7312
- 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`));
7313
7447
  for (const h of held) {
7314
7448
  if (h.kind === "row") printRow(h.row, opts.json);
7315
7449
  else console.error(h.msg);
7316
7450
  }
7317
7451
  if (heldRowsDropped || heldNotesDropped) {
7318
- 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`));
7319
7453
  }
7320
7454
  held.length = 0;
7321
7455
  heldRowsDropped = 0;
@@ -7329,7 +7463,7 @@ async function runTailSession(opts) {
7329
7463
  activeSocket?.close();
7330
7464
  } catch {
7331
7465
  }
7332
- if (!opts.json) console.log(import_chalk32.default.dim("\nStopped."));
7466
+ if (!opts.json) console.log(import_chalk33.default.dim("\nStopped."));
7333
7467
  process.exit(0);
7334
7468
  }
7335
7469
  function onKeypress(_s, key) {
@@ -7357,17 +7491,17 @@ async function runTailSession(opts) {
7357
7491
  async function openInspector() {
7358
7492
  if (paused) return;
7359
7493
  if (recent.length === 0) {
7360
- 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"));
7361
7495
  return;
7362
7496
  }
7363
7497
  paused = true;
7364
7498
  unbindKeys();
7365
7499
  try {
7366
7500
  const { default: inquirer3 } = await import("inquirer");
7367
- 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"));
7368
7502
  for (; ; ) {
7369
7503
  const choices = recent.slice(-TAIL_INSPECT_CHOICES).reverse().map((r) => ({ name: formatRow(r), value: r.request_id }));
7370
- 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__" });
7371
7505
  const { picked } = await inquirer3.prompt([{
7372
7506
  type: "list",
7373
7507
  name: "picked",
@@ -7378,12 +7512,12 @@ async function runTailSession(opts) {
7378
7512
  if (picked === "__resume__") break;
7379
7513
  const row = recent.find((r) => r.request_id === picked);
7380
7514
  if (row) printDetail(row, opts.detail);
7381
- 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"));
7382
7516
  }
7383
7517
  } finally {
7384
7518
  paused = false;
7385
7519
  flushHeld();
7386
- 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"));
7387
7521
  bindKeys();
7388
7522
  }
7389
7523
  }
@@ -7393,12 +7527,12 @@ async function runTailSession(opts) {
7393
7527
  if (reconnects >= MAX_RECONNECTS) {
7394
7528
  paused = false;
7395
7529
  flushHeld();
7396
- 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})` : ""}.`));
7397
7531
  process.exit(1);
7398
7532
  }
7399
7533
  const delay = Math.min(1e3 * 2 ** reconnects, 15e3);
7400
7534
  reconnects++;
7401
- 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`));
7402
7536
  setTimeout(() => {
7403
7537
  if (!closed) void connect();
7404
7538
  }, delay);
@@ -7409,7 +7543,7 @@ async function runTailSession(opts) {
7409
7543
  url = await opts.mintTicket();
7410
7544
  } catch (err) {
7411
7545
  if (!everConnected) {
7412
- 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}`));
7413
7547
  process.exit(1);
7414
7548
  }
7415
7549
  lastFailure = `ticket mint failed: ${err.message}`;
@@ -7422,7 +7556,7 @@ async function runTailSession(opts) {
7422
7556
  } catch (err) {
7423
7557
  lastFailure = `bad tail URL: ${err.message}`;
7424
7558
  if (!everConnected) {
7425
- console.error(import_chalk32.default.red(`Could not start tail: ${lastFailure}`));
7559
+ console.error(import_chalk33.default.red(`Could not start tail: ${lastFailure}`));
7426
7560
  process.exit(1);
7427
7561
  }
7428
7562
  scheduleReconnect();
@@ -7437,9 +7571,9 @@ async function runTailSession(opts) {
7437
7571
  lastInbound = Date.now();
7438
7572
  lastFailure = "";
7439
7573
  if (isReconnect) {
7440
- 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`)."));
7441
7575
  } else {
7442
- 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."));
7443
7577
  }
7444
7578
  bindKeys();
7445
7579
  pingTimer = setInterval(() => {
@@ -7466,7 +7600,7 @@ async function runTailSession(opts) {
7466
7600
  return;
7467
7601
  }
7468
7602
  if (frame?.type === "ceiling") {
7469
- diag(import_chalk32.default.yellow(
7603
+ diag(import_chalk33.default.yellow(
7470
7604
  `\u26A0 volume ceiling \u2014 ${Number(frame.dropped_this_hour) || 0} rows dropped this hour; errors keep streaming.`
7471
7605
  ));
7472
7606
  return;
@@ -7546,10 +7680,10 @@ async function fetchPage(fetchWindow3, params, notices) {
7546
7680
  return { rows, nextCursor: res.next_cursor ?? void 0 };
7547
7681
  }
7548
7682
  if (hop >= MAX_EMPTY_HOPS) {
7549
- 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."));
7550
7684
  return { rows: [], nextCursor: res.next_cursor, fuseTripped: true };
7551
7685
  }
7552
- 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"));
7553
7687
  cursor = res.next_cursor;
7554
7688
  }
7555
7689
  }
@@ -7589,18 +7723,18 @@ async function runPlainList(opts, notices) {
7589
7723
  }
7590
7724
  }
7591
7725
  if (rows.length === 0) {
7592
- 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."));
7593
7727
  return;
7594
7728
  }
7595
7729
  const now = Date.now();
7596
7730
  for (const d of groupIntoDays(rows)) {
7597
- console.log(import_chalk32.default.bold(dayLabel(d.dayMs, now)));
7731
+ console.log(import_chalk33.default.bold(dayLabel(d.dayMs, now)));
7598
7732
  for (const r of d.rows) console.log(` ${formatRow(r)}`);
7599
7733
  console.log("");
7600
7734
  }
7601
7735
  const errs = rows.filter((r) => r.status >= 400).length;
7602
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" : "";
7603
- console.log(import_chalk32.default.dim(
7737
+ console.log(import_chalk33.default.dim(
7604
7738
  `${rows.length} request${rows.length === 1 ? "" : "s"} \xB7 ${errs} error${errs === 1 ? "" : "s"}${tail}`
7605
7739
  ));
7606
7740
  }
@@ -7619,7 +7753,7 @@ async function runHistoryBrowser(opts) {
7619
7753
  for (const r of page.rows) console.log(JSON.stringify(r));
7620
7754
  any = any || page.rows.length > 0;
7621
7755
  if (page.fuseTripped || !page.nextCursor) {
7622
- 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."));
7623
7757
  return;
7624
7758
  }
7625
7759
  cursor2 = page.nextCursor;
@@ -7640,7 +7774,7 @@ async function runHistoryBrowser(opts) {
7640
7774
  scanRows = first.rows;
7641
7775
  scanCursor = first.nextCursor;
7642
7776
  if (scanRows.length === 0) {
7643
- 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."));
7644
7778
  return;
7645
7779
  }
7646
7780
  }
@@ -7651,10 +7785,10 @@ async function runHistoryBrowser(opts) {
7651
7785
  const now2 = Date.now();
7652
7786
  const oldestKey = days[days.length - 1]?.key;
7653
7787
  const choices = days.map((d) => ({
7654
- 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`) : ""}`,
7655
7789
  value: d.key
7656
7790
  }));
7657
- 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__" });
7658
7792
  const { chosenDay } = await inquirer3.prompt([{
7659
7793
  type: "list",
7660
7794
  name: "chosenDay",
@@ -7674,7 +7808,7 @@ async function runHistoryBrowser(opts) {
7674
7808
  scanCursor = void 0;
7675
7809
  } else {
7676
7810
  scanCursor = more.nextCursor;
7677
- 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."));
7678
7812
  }
7679
7813
  continue;
7680
7814
  }
@@ -7696,11 +7830,11 @@ async function runHistoryBrowser(opts) {
7696
7830
  cursor
7697
7831
  }, notices);
7698
7832
  if (page.rows.length === 0 && pageRows.length === 0) {
7699
- 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."));
7700
7834
  return;
7701
7835
  }
7702
7836
  if (page.rows.length === 0) {
7703
- 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."));
7704
7838
  moreCursor = void 0;
7705
7839
  } else {
7706
7840
  pageRows = page.rows;
@@ -7711,8 +7845,8 @@ async function runHistoryBrowser(opts) {
7711
7845
  name: formatRow(r),
7712
7846
  value: r.request_id
7713
7847
  }));
7714
- if (moreCursor) choices.push({ name: import_chalk32.default.dim("\u2026 load more"), value: "__more__" });
7715
- 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__" });
7716
7850
  for (; ; ) {
7717
7851
  const { picked } = await inquirer3.prompt([{
7718
7852
  type: "list",
@@ -7762,19 +7896,19 @@ function wrapCells(items, width) {
7762
7896
  ${PANE_INDENT}`);
7763
7897
  }
7764
7898
  function renderHeaders(h) {
7765
- if (!h) return import_chalk32.default.dim("\u2014");
7899
+ if (!h) return import_chalk33.default.dim("\u2014");
7766
7900
  const width = process.stdout.columns || 100;
7767
7901
  if (h.values) {
7768
7902
  const e = Object.entries(h.values);
7769
- if (!e.length) return import_chalk32.default.dim("none");
7903
+ if (!e.length) return import_chalk33.default.dim("none");
7770
7904
  const rank = (k) => {
7771
7905
  const i = HEADER_PRIORITY.indexOf(k.toLowerCase());
7772
7906
  return i === -1 ? NOISE_HEADER.test(k) ? 999 : 500 : i;
7773
7907
  };
7774
- 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(`
7775
7909
  ${PANE_INDENT}`);
7776
7910
  }
7777
- if (!h.names?.length) return import_chalk32.default.dim("none");
7911
+ if (!h.names?.length) return import_chalk33.default.dim("none");
7778
7912
  const names = [...h.names];
7779
7913
  const noise = names.filter((n) => NOISE_HEADER.test(n));
7780
7914
  const shown = names.filter((n) => !NOISE_HEADER.test(n)).sort((a, b) => {
@@ -7782,70 +7916,70 @@ ${PANE_INDENT}`);
7782
7916
  const ib = HEADER_PRIORITY.indexOf(b.toLowerCase());
7783
7917
  return (ia === -1 ? 500 : ia) - (ib === -1 ? 500 : ib) || a.localeCompare(b);
7784
7918
  });
7785
- 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)");
7786
7920
  const tail = noise.length ? `
7787
- ${PANE_INDENT}${import_chalk32.default.dim(`+ ${noise.length} forwarding/client-hint header${noise.length === 1 ? "" : "s"} (cf-*, sec-*)`)}` : "";
7788
- 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)")}`;
7789
7923
  }
7790
7924
  function renderBody(b) {
7791
- if (!b) return import_chalk32.default.dim("\u2014");
7925
+ if (!b) return import_chalk33.default.dim("\u2014");
7792
7926
  const meta = [b.content_type, b.size != null ? `${b.size}B` : null, b.truncated ? "truncated" : null].filter(Boolean).join(" \xB7 ");
7793
- 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 : ""}`);
7794
7928
  const isShape = b.value === void 0 && b.shape !== void 0;
7795
7929
  const content = b.value !== void 0 ? b.value : b.shape;
7796
7930
  if (content === null || content === void 0 || content === "" || content === "empty") {
7797
- return import_chalk32.default.dim(`empty${meta ? " \xB7 " + meta : ""}`);
7931
+ return import_chalk33.default.dim(`empty${meta ? " \xB7 " + meta : ""}`);
7798
7932
  }
7799
7933
  const text = typeof content === "string" ? content : JSON.stringify(content, null, 2);
7800
- 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 ") : "";
7801
7935
  return head + text.split("\n").join("\n ");
7802
7936
  }
7803
7937
  function pane(title, tone, view, empty) {
7804
7938
  console.log(` ${tone(title)}`);
7805
7939
  if (empty !== void 0) {
7806
- console.log(` ${import_chalk32.default.dim(empty)}`);
7940
+ console.log(` ${import_chalk33.default.dim(empty)}`);
7807
7941
  return;
7808
7942
  }
7809
7943
  const v = view ?? {};
7810
- 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}`);
7811
7945
  if (v.status != null) {
7812
- 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) : ""}`);
7813
7947
  }
7814
- 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}`);
7815
7949
  if (v.query && Object.keys(v.query).length) {
7816
- 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(" ")}`);
7817
7951
  }
7818
- if (v.jwt !== void 0) console.log(` ${import_chalk32.default.dim("jwt")} ${JSON.stringify(v.jwt)}`);
7819
- console.log(` ${import_chalk32.default.dim("headers")} ${renderHeaders(v.headers)}`);
7820
- 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)}`);
7821
7955
  }
7822
7956
  function printDetail(r, mode = "producer") {
7823
7957
  const v = r.views;
7824
7958
  console.log("");
7825
- 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`));
7826
7960
  const cost = typeof r.cost_cents === "number" && r.cost_cents > 0 ? ` \xB7 ${r.cost_cents}\xA2` : "";
7827
- 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}`));
7828
7962
  console.log("");
7829
7963
  if (!v) {
7830
- 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"));
7831
7965
  return;
7832
7966
  }
7833
- 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);
7834
7968
  if (mode === "producer") {
7835
7969
  pane(
7836
7970
  "Request (after) \u2014 APIblaze \u2192 upstream",
7837
- import_chalk32.default.cyan,
7971
+ import_chalk33.default.cyan,
7838
7972
  v.forwarded_request,
7839
7973
  v.forwarded_request ? void 0 : "Request did not reach an upstream."
7840
7974
  );
7841
7975
  pane(
7842
7976
  "Response (before) \u2014 upstream \u2192 APIblaze",
7843
- import_chalk32.default.magenta,
7977
+ import_chalk33.default.magenta,
7844
7978
  v.upstream_response,
7845
7979
  v.upstream_response ? void 0 : "No upstream response."
7846
7980
  );
7847
7981
  }
7848
- 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);
7849
7983
  console.log("");
7850
7984
  }
7851
7985
 
@@ -7894,7 +8028,7 @@ async function resolve(projectArg, versionArg, opts) {
7894
8028
  return { projectId, projectName: match.projectName, version: version2, tenant: tenant2 };
7895
8029
  }
7896
8030
  function otherPlaneHint() {
7897
- 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"));
7898
8032
  }
7899
8033
  function fetchWindow(projectId, version2, tenant2) {
7900
8034
  return (params) => {
@@ -7913,8 +8047,8 @@ function fetchWindow(projectId, version2, tenant2) {
7913
8047
  async function runLogsTail(projectArg, versionArg, opts) {
7914
8048
  const { projectId, projectName, version: version2, tenant: tenant2 } = await resolve(projectArg, versionArg, opts);
7915
8049
  if (!opts.json) {
7916
- console.log(import_chalk33.default.bold("API Producer logs") + import_chalk33.default.dim(` \xB7 ${projectName}@${version2} \xB7 tenant ${tenant2}${opts.errorsOnly ? " \xB7 errors only" : ""}`));
7917
- 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"));
7918
8052
  otherPlaneHint();
7919
8053
  }
7920
8054
  await runTailSession({
@@ -7935,8 +8069,8 @@ async function runLogsTail(projectArg, versionArg, opts) {
7935
8069
  async function runLogsList(projectArg, versionArg, opts) {
7936
8070
  const { projectId, projectName, version: version2, tenant: tenant2 } = await resolve(projectArg, versionArg, opts);
7937
8071
  if (!opts.json) {
7938
- console.log(import_chalk33.default.bold("API Producer logs") + import_chalk33.default.dim(` \xB7 ${projectName}@${version2} \xB7 tenant ${tenant2}${opts.errorsOnly ? " \xB7 errors only" : ""}`));
7939
- 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"));
7940
8074
  otherPlaneHint();
7941
8075
  console.log("");
7942
8076
  }
@@ -7950,15 +8084,15 @@ async function runLogsList(projectArg, versionArg, opts) {
7950
8084
  }
7951
8085
 
7952
8086
  // src/commands/consumer-logs.ts
7953
- var import_chalk34 = __toESM(require("chalk"));
8087
+ var import_chalk35 = __toESM(require("chalk"));
7954
8088
  init_auth();
7955
8089
  var CONSUMER_LOGS_BASE = process.env.APIBLAZE_CONSUMER_LOGS_BASE || "https://logs.apiblaze.com/consumer";
7956
8090
  function requireConsumer() {
7957
8091
  const c = loadConsumer();
7958
8092
  if (!c) {
7959
- 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."));
7960
8094
  if (loadCredentials()) {
7961
- 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>`."));
7962
8096
  }
7963
8097
  process.exit(1);
7964
8098
  }
@@ -7989,7 +8123,7 @@ async function consumerLogsFetch(session, suffix, init) {
7989
8123
  return data;
7990
8124
  }
7991
8125
  function otherPlaneHint2() {
7992
- 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"));
7993
8127
  }
7994
8128
  function fetchWindow2(session, project) {
7995
8129
  return (params) => {
@@ -8005,8 +8139,8 @@ function fetchWindow2(session, project) {
8005
8139
  async function runConsumerLogsTail(opts) {
8006
8140
  const session = requireConsumer();
8007
8141
  if (!opts.json) {
8008
- 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" : ""}`));
8009
- 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"));
8010
8144
  otherPlaneHint2();
8011
8145
  }
8012
8146
  await runTailSession({
@@ -8024,8 +8158,8 @@ async function runConsumerLogsTail(opts) {
8024
8158
  async function runConsumerLogsList(opts) {
8025
8159
  const session = requireConsumer();
8026
8160
  if (!opts.json) {
8027
- 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" : ""}`));
8028
- 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"));
8029
8163
  otherPlaneHint2();
8030
8164
  console.log("");
8031
8165
  }
@@ -8039,7 +8173,7 @@ async function runConsumerLogsList(opts) {
8039
8173
  }
8040
8174
 
8041
8175
  // src/commands/config.ts
8042
- var import_chalk35 = __toESM(require("chalk"));
8176
+ var import_chalk36 = __toESM(require("chalk"));
8043
8177
  var import_ora12 = __toESM(require("ora"));
8044
8178
  init_admin();
8045
8179
  init_resolve();
@@ -8063,7 +8197,7 @@ async function patchConfig(project, opts, body, summary) {
8063
8197
  }
8064
8198
  async function runTargetSet(project, opts) {
8065
8199
  if (!opts.url) {
8066
- console.error(import_chalk35.default.red("--url is required."));
8200
+ console.error(import_chalk36.default.red("--url is required."));
8067
8201
  process.exit(1);
8068
8202
  }
8069
8203
  const body = opts.env ? { environments: { [opts.env]: { target: opts.url } } } : { target_url: opts.url };
@@ -8076,40 +8210,40 @@ async function runThrottleSet(project, opts) {
8076
8210
  if (opts.quota !== void 0) throttling.proxyQuota = Number(opts.quota);
8077
8211
  if (opts.period !== void 0) {
8078
8212
  if (!["daily", "weekly", "monthly"].includes(opts.period)) {
8079
- 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."));
8080
8214
  process.exit(1);
8081
8215
  }
8082
8216
  throttling.quotaPeriod = opts.period;
8083
8217
  }
8084
8218
  if (Object.keys(throttling).length === 0) {
8085
- 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."));
8086
8220
  process.exit(1);
8087
8221
  }
8088
8222
  await patchConfig(project, opts, { throttling }, `Update throttling ${JSON.stringify(throttling)}`);
8089
8223
  }
8090
8224
  async function runRename(project, opts) {
8091
8225
  if (!opts.displayName) {
8092
- console.error(import_chalk35.default.red("--display-name is required."));
8226
+ console.error(import_chalk36.default.red("--display-name is required."));
8093
8227
  process.exit(1);
8094
8228
  }
8095
8229
  await patchConfig(project, opts, { display_name: opts.displayName }, `Rename \u2192 "${opts.displayName}"`);
8096
8230
  }
8097
8231
 
8098
8232
  // src/commands/config-browse.ts
8099
- var import_chalk44 = __toESM(require("chalk"));
8233
+ var import_chalk45 = __toESM(require("chalk"));
8100
8234
  var import_ora20 = __toESM(require("ora"));
8101
8235
  init_admin();
8102
8236
  init_auth();
8103
8237
  init_resolve();
8104
8238
 
8105
8239
  // src/commands/domain.ts
8106
- var import_chalk36 = __toESM(require("chalk"));
8240
+ var import_chalk37 = __toESM(require("chalk"));
8107
8241
  var import_ora13 = __toESM(require("ora"));
8108
8242
  init_admin();
8109
8243
  init_resolve();
8110
8244
  async function runDomainAdd(project, opts) {
8111
8245
  if (!opts.domain) {
8112
- console.error(import_chalk36.default.red("--domain is required."));
8246
+ console.error(import_chalk37.default.red("--domain is required."));
8113
8247
  process.exit(1);
8114
8248
  }
8115
8249
  const { teamId } = await resolveTeam(opts.team);
@@ -8128,9 +8262,9 @@ async function runDomainAdd(project, opts) {
8128
8262
  console.log(JSON.stringify(out));
8129
8263
  return;
8130
8264
  }
8131
- if (out?.cnameRecord) console.log(` ${import_chalk36.default.cyan("CNAME")} ${out.cnameRecord.name ?? opts.domain} \u2192 ${out.cnameRecord.value ?? out.cnameRecord.target}`);
8132
- if (out?.dcv) console.log(` ${import_chalk36.default.cyan("TXT")} ${out.dcv.name} = ${out.dcv.value}`);
8133
- 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}`));
8134
8268
  } catch (err) {
8135
8269
  spinner.fail("Domain registration failed.");
8136
8270
  throw err;
@@ -8150,14 +8284,14 @@ async function runDomainList(project, opts) {
8150
8284
  return;
8151
8285
  }
8152
8286
  if (!domains.length) {
8153
- console.log(import_chalk36.default.yellow("No custom domains."));
8287
+ console.log(import_chalk37.default.yellow("No custom domains."));
8154
8288
  return;
8155
8289
  }
8156
- 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 ?? "")}`);
8157
8291
  }
8158
8292
  async function runDomainStatus(project, opts) {
8159
8293
  if (!opts.id) {
8160
- 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`)."));
8161
8295
  process.exit(1);
8162
8296
  }
8163
8297
  const { teamId } = await resolveTeam(opts.team);
@@ -8167,11 +8301,11 @@ async function runDomainStatus(project, opts) {
8167
8301
  path: `/projects/${proj2.projectId}/domains/${encodeURIComponent(opts.id)}/status`,
8168
8302
  summary: `Check custom-domain status`
8169
8303
  });
8170
- 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")}`);
8171
8305
  }
8172
8306
  async function runDomainRemove(project, opts) {
8173
8307
  if (!opts.id) {
8174
- 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`)."));
8175
8309
  process.exit(1);
8176
8310
  }
8177
8311
  const { teamId } = await resolveTeam(opts.team);
@@ -8209,7 +8343,7 @@ async function runDomainSetBase(project, opts) {
8209
8343
  }
8210
8344
 
8211
8345
  // src/commands/tenant.ts
8212
- var import_chalk39 = __toESM(require("chalk"));
8346
+ var import_chalk40 = __toESM(require("chalk"));
8213
8347
  var import_ora16 = __toESM(require("ora"));
8214
8348
  init_admin();
8215
8349
  init_resolve();
@@ -8218,20 +8352,20 @@ init_tenant_pick();
8218
8352
  async function runTenantUse(query, opts) {
8219
8353
  const creds = loadCredentials();
8220
8354
  if (!creds) {
8221
- 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."));
8222
8356
  process.exit(1);
8223
8357
  }
8224
8358
  if (opts.clear) {
8225
8359
  delete creds.activeTenant;
8226
8360
  saveCredentials(creds);
8227
- console.log(import_chalk39.default.green("Tenant scope cleared."));
8361
+ console.log(import_chalk40.default.green("Tenant scope cleared."));
8228
8362
  return;
8229
8363
  }
8230
8364
  const { teamId } = await resolveTeam(opts.team);
8231
8365
  const slug = await pickTenant(teamId, { message: "Scope future commands to which tenant?", initialQuery: query });
8232
8366
  if (!slug) process.exit(1);
8233
8367
  saveCredentials({ ...creds, activeTenant: slug });
8234
- 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`)"));
8235
8369
  }
8236
8370
  async function runTenantList(opts) {
8237
8371
  const { teamId, teamName } = await resolveTeam(opts.team);
@@ -8248,22 +8382,22 @@ async function runTenantList(opts) {
8248
8382
  return;
8249
8383
  }
8250
8384
  if (!tenants.length) {
8251
- 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."));
8252
8386
  return;
8253
8387
  }
8254
8388
  for (const t of tenants) {
8255
8389
  const name = typeof t === "string" ? t : t.tenant_name;
8256
- const display = typeof t === "string" ? "" : import_chalk39.default.dim(` ${t.display_name ?? ""}`);
8257
- 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}`);
8258
8392
  }
8259
8393
  const total = out?.total ?? tenants.length;
8260
8394
  if (total > tenants.length) {
8261
- 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>`));
8262
8396
  }
8263
8397
  }
8264
8398
  async function runTenantCreate(opts) {
8265
8399
  if (!opts.name) {
8266
- console.error(import_chalk39.default.red("--name (display name) is required."));
8400
+ console.error(import_chalk40.default.red("--name (display name) is required."));
8267
8401
  process.exit(1);
8268
8402
  }
8269
8403
  const { teamId } = await resolveTeam(opts.team);
@@ -8275,7 +8409,7 @@ async function runTenantCreate(opts) {
8275
8409
  body: { display_name: opts.name, ...opts.slug ? { tenant_name: opts.slug } : {} },
8276
8410
  summary: `Create tenant "${opts.name}"`
8277
8411
  });
8278
- 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)}.`);
8279
8413
  if (opts.json) console.log(JSON.stringify(out));
8280
8414
  } catch (err) {
8281
8415
  spinner.fail("Tenant create failed.");
@@ -8284,7 +8418,7 @@ async function runTenantCreate(opts) {
8284
8418
  }
8285
8419
  async function runTenantAttach(project, opts) {
8286
8420
  if (!opts.tenant) {
8287
- console.error(import_chalk39.default.red("--tenant <slug> is required."));
8421
+ console.error(import_chalk40.default.red("--tenant <slug> is required."));
8288
8422
  process.exit(1);
8289
8423
  }
8290
8424
  const { teamId } = await resolveTeam(opts.team);
@@ -8312,7 +8446,7 @@ async function runTenantDelete(slug, opts) {
8312
8446
  { type: "confirm", name: "confirm", message: `Permanently delete tenant "${slug}" and everything under it? This cannot be undone.`, default: false }
8313
8447
  ]);
8314
8448
  if (!confirm2) {
8315
- console.log(import_chalk39.default.dim("Aborted."));
8449
+ console.log(import_chalk40.default.dim("Aborted."));
8316
8450
  return;
8317
8451
  }
8318
8452
  }
@@ -8331,7 +8465,7 @@ async function runTenantDelete(slug, opts) {
8331
8465
  }
8332
8466
  async function runTenantCors(opts) {
8333
8467
  if (!opts.tenant) {
8334
- console.error(import_chalk39.default.red("--tenant <slug> is required."));
8468
+ console.error(import_chalk40.default.red("--tenant <slug> is required."));
8335
8469
  process.exit(1);
8336
8470
  }
8337
8471
  const { teamId } = await resolveTeam(opts.team);
@@ -8353,7 +8487,7 @@ async function runTenantCors(opts) {
8353
8487
  }
8354
8488
 
8355
8489
  // src/commands/tenant-drill.ts
8356
- var import_chalk40 = __toESM(require("chalk"));
8490
+ var import_chalk41 = __toESM(require("chalk"));
8357
8491
  var import_ora17 = __toESM(require("ora"));
8358
8492
  var import_crypto = require("crypto");
8359
8493
  init_admin();
@@ -8384,15 +8518,15 @@ async function validScopedTenant(teamId, query) {
8384
8518
  const next = { ...creds };
8385
8519
  delete next.activeTenant;
8386
8520
  saveCredentials2(next);
8387
- 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.`));
8388
8522
  return void 0;
8389
8523
  }
8390
8524
  async function tenantHome(teamId, tenant2) {
8391
8525
  const { default: inquirer3 } = await import("inquirer");
8392
8526
  const base2 = `/teams/${encodeURIComponent(teamId)}/tenants/${encodeURIComponent(tenant2)}`;
8393
- console.log(import_chalk40.default.bold(`
8527
+ console.log(import_chalk41.default.bold(`
8394
8528
  Tenant ${tenant2}`));
8395
- 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"));
8396
8530
  for (; ; ) {
8397
8531
  const spinner = (0, import_ora17.default)("Reading tenant state...").start();
8398
8532
  const [iam, cors, emails, issuers, opaque, clients] = await Promise.all([
@@ -8408,18 +8542,18 @@ Tenant ${tenant2}`));
8408
8542
  const nClients = Array.isArray(clients) ? clients.length : 0;
8409
8543
  const nOpaque = opaque?.opaque?.endpoint ? 1 : 0;
8410
8544
  const nLogin = nClients + nIssuers + nOpaque;
8411
- 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");
8412
8546
  const { pick: pick2 } = await inquirer3.prompt([{
8413
8547
  type: "list",
8414
8548
  name: "pick",
8415
8549
  message: `Tenant ${tenant2}:`,
8416
8550
  pageSize: 12,
8417
8551
  choices: [
8418
- { name: `Login methods (${nLogin}) ${import_chalk40.default.dim("how your consumers sign in")}`, value: "login" },
8419
- { name: `Users & groups: ${onOff(iam?.iam_enabled)} ${import_chalk40.default.dim(`identity & key management (iam.apiblaze.com)`)}`, value: "iam" },
8420
- { name: `Portal admins (${nEmails}) ${import_chalk40.default.dim("emails allowed to administer this tenant's portal")}`, value: "emails" },
8421
- new inquirer3.Separator(import_chalk40.default.dim(" Settings")),
8422
- { 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" },
8423
8557
  { name: "\u2190 Back", value: "back" }
8424
8558
  ]
8425
8559
  }]);
@@ -8432,7 +8566,7 @@ Tenant ${tenant2}`));
8432
8566
  case "iam": {
8433
8567
  const { v } = await inquirer3.prompt([{ type: "confirm", name: "v", message: "Enable Users & groups?", default: !!iam?.iam_enabled }]);
8434
8568
  await admin({ method: "PATCH", path: `${base2}/iam`, body: { enabled: v }, summary: `IAM enforcement \u2192 ${v ? "on" : "off"}` });
8435
- console.log(import_chalk40.default.green(` Users & groups ${v ? "enabled" : "disabled"}.`));
8569
+ console.log(import_chalk41.default.green(` Users & groups ${v ? "enabled" : "disabled"}.`));
8436
8570
  break;
8437
8571
  }
8438
8572
  case "cors": {
@@ -8445,11 +8579,11 @@ Tenant ${tenant2}`));
8445
8579
  if (v === "") break;
8446
8580
  const parsed = v === "null" ? null : safeJson(v);
8447
8581
  if (parsed === void 0) {
8448
- console.log(import_chalk40.default.yellow(" Not valid JSON \u2014 unchanged."));
8582
+ console.log(import_chalk41.default.yellow(" Not valid JSON \u2014 unchanged."));
8449
8583
  break;
8450
8584
  }
8451
8585
  await admin({ method: "PUT", path: `${base2}/cors`, body: { cors: parsed }, summary: "Set tenant CORS" });
8452
- console.log(import_chalk40.default.green(" CORS updated."));
8586
+ console.log(import_chalk41.default.green(" CORS updated."));
8453
8587
  break;
8454
8588
  }
8455
8589
  case "emails":
@@ -8473,15 +8607,15 @@ async function loginMethodsMenu(teamId, tenant2, base2) {
8473
8607
  const choices = [];
8474
8608
  for (const c of appClients) {
8475
8609
  const nP = (c.providers ?? []).length || c.providers_count || 0;
8476
- 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 } });
8477
8611
  }
8478
8612
  for (const i of issuers) {
8479
- 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 } });
8480
8614
  }
8481
8615
  if (opaque?.endpoint) {
8482
- 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 } });
8483
8617
  }
8484
- 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."));
8485
8619
  const { pick: pick2 } = await inquirer3.prompt([{
8486
8620
  type: "list",
8487
8621
  name: "pick",
@@ -8521,9 +8655,9 @@ async function addLoginMethod(teamId, tenant2, base2) {
8521
8655
  message: "How do people log in?",
8522
8656
  pageSize: 8,
8523
8657
  choices: [
8524
- { name: `APIblaze hosted login page ${import_chalk40.default.dim("we host login; pick a provider (GitHub/Google/\u2026) \u2014 easiest")}`, value: "apiblaze" },
8525
- { name: `Your own hosted login \u2014 JWT ${import_chalk40.default.dim("your identity provider issues JWTs; we trust them")}`, value: "jwt" },
8526
- { 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" },
8527
8661
  { name: "\u2190 Back", value: null }
8528
8662
  ]
8529
8663
  }]);
@@ -8547,8 +8681,8 @@ function safeJson(s) {
8547
8681
  async function emailsMenu(base2, emails) {
8548
8682
  const { default: inquirer3 } = await import("inquirer");
8549
8683
  console.log();
8550
- if (!emails.length) console.log(import_chalk40.default.dim(" No consumer-admin emails."));
8551
- 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 ?? "")}`);
8552
8686
  const { act } = await inquirer3.prompt([{
8553
8687
  type: "list",
8554
8688
  name: "act",
@@ -8563,7 +8697,7 @@ async function emailsMenu(base2, emails) {
8563
8697
  if (act === "add") {
8564
8698
  const { email } = await inquirer3.prompt([{ type: "input", name: "email", message: "Email:", validate: (s) => /.+@.+\..+/.test(s) || "not an email" }]);
8565
8699
  await admin({ method: "POST", path: `${base2}/admin-emails`, body: { email }, summary: `Add consumer-admin ${email}` });
8566
- console.log(import_chalk40.default.green(` ${email} added.`));
8700
+ console.log(import_chalk41.default.green(` ${email} added.`));
8567
8701
  } else {
8568
8702
  const { e } = await inquirer3.prompt([{
8569
8703
  type: "list",
@@ -8573,7 +8707,7 @@ async function emailsMenu(base2, emails) {
8573
8707
  }]);
8574
8708
  if (!e) return;
8575
8709
  await admin({ method: "DELETE", path: `${base2}/admin-emails/${encodeURIComponent(e)}`, summary: `Remove consumer-admin ${e}` });
8576
- console.log(import_chalk40.default.green(` ${e} removed.`));
8710
+ console.log(import_chalk41.default.green(` ${e} removed.`));
8577
8711
  }
8578
8712
  }
8579
8713
  async function addIssuer(base2) {
@@ -8594,19 +8728,19 @@ async function addIssuer(base2) {
8594
8728
  body: { iss: a.iss.trim(), aud: a.aud.trim(), jwks_url: a.jwks.trim() || null, sub_semantics: a.sem, ...claim ? { claim_name: claim } : {} },
8595
8729
  summary: `Add external issuer ${a.iss.trim()}`
8596
8730
  });
8597
- console.log(import_chalk40.default.green(" JWT login method saved."));
8731
+ console.log(import_chalk41.default.green(" JWT login method saved."));
8598
8732
  }
8599
8733
  async function issuerHome(base2, issuer) {
8600
8734
  const { default: inquirer3 } = await import("inquirer");
8601
8735
  console.log(`
8602
- ${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 ?? ""}`)}`);
8603
8737
  const { act } = await inquirer3.prompt([{
8604
8738
  type: "list",
8605
8739
  name: "act",
8606
8740
  message: "This JWT login method:",
8607
8741
  choices: [
8608
8742
  { name: "Replace it (re-enter details)", value: "edit" },
8609
- { name: import_chalk40.default.red("Delete it"), value: "rm" },
8743
+ { name: import_chalk41.default.red("Delete it"), value: "rm" },
8610
8744
  { name: "\u2190 Back", value: "back" }
8611
8745
  ]
8612
8746
  }]);
@@ -8622,7 +8756,7 @@ async function issuerHome(base2, issuer) {
8622
8756
  path: `${base2}/external-issuers?iss=${encodeURIComponent(issuer.iss)}&aud=${encodeURIComponent(issuer.aud)}`,
8623
8757
  summary: `Delete issuer ${issuer.iss}`
8624
8758
  });
8625
- console.log(import_chalk40.default.green(" Deleted."));
8759
+ console.log(import_chalk41.default.green(" Deleted."));
8626
8760
  }
8627
8761
  async function setOpaque(base2, cur) {
8628
8762
  const { default: inquirer3 } = await import("inquirer");
@@ -8631,19 +8765,19 @@ async function setOpaque(base2, cur) {
8631
8765
  { type: "list", name: "method", message: "HTTP method:", choices: ["GET", "POST"], default: cur?.method ?? "GET" }
8632
8766
  ]);
8633
8767
  await admin({ method: "PUT", path: `${base2}/opaque`, body: { opaque: { endpoint: a.endpoint, method: a.method } }, summary: "Set opaque validator" });
8634
- console.log(import_chalk40.default.green(" Opaque login method set."));
8768
+ console.log(import_chalk41.default.green(" Opaque login method set."));
8635
8769
  }
8636
8770
  async function opaqueHome(base2, cur) {
8637
8771
  const { default: inquirer3 } = await import("inquirer");
8638
8772
  console.log(`
8639
- ${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")}`);
8640
8774
  const { act } = await inquirer3.prompt([{
8641
8775
  type: "list",
8642
8776
  name: "act",
8643
8777
  message: "This opaque login method:",
8644
8778
  choices: [
8645
8779
  { name: "Replace it", value: "edit" },
8646
- { name: import_chalk40.default.red("Delete it"), value: "rm" },
8780
+ { name: import_chalk41.default.red("Delete it"), value: "rm" },
8647
8781
  { name: "\u2190 Back", value: "back" }
8648
8782
  ]
8649
8783
  }]);
@@ -8653,7 +8787,7 @@ async function opaqueHome(base2, cur) {
8653
8787
  return;
8654
8788
  }
8655
8789
  await admin({ method: "PUT", path: `${base2}/opaque`, body: { opaque: null }, summary: "Clear opaque validator" });
8656
- console.log(import_chalk40.default.green(" Deleted."));
8790
+ console.log(import_chalk41.default.green(" Deleted."));
8657
8791
  }
8658
8792
  async function clientHome(base2, summary) {
8659
8793
  const { default: inquirer3 } = await import("inquirer");
@@ -8672,13 +8806,13 @@ async function clientHome(base2, summary) {
8672
8806
  message: `${c.name ?? id}:`,
8673
8807
  pageSize: 12,
8674
8808
  choices: [
8675
- { name: `Login providers${nProviders ? ` (${nProviders})` : ""} ${import_chalk40.default.dim("google/github/microsoft/\u2026 \u2014 how consumers sign in")}`, value: "providers" },
8676
- { name: `Callback URLs: ${cb.length ? import_chalk40.default.cyan(cb.join(", ")) : import_chalk40.default.dim("(none)")}`, value: "callbacks" },
8677
- { 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" },
8678
8812
  { name: `Token expiries: access ${c.accessTokenExpiry ?? 3600}s \xB7 id ${c.idTokenExpiry ?? 3600}s \xB7 refresh ${c.refreshTokenExpiry ?? 2592e3}s`, value: "expiries" },
8679
8813
  { name: "Reveal client secret", value: "secret" },
8680
8814
  { name: "Rotate client secret", value: "rotate" },
8681
- { name: import_chalk40.default.red("Delete this app client"), value: "delete" },
8815
+ { name: import_chalk41.default.red("Delete this app client"), value: "delete" },
8682
8816
  { name: "\u2190 Back", value: "back" }
8683
8817
  ]
8684
8818
  }]);
@@ -8691,13 +8825,13 @@ async function clientHome(base2, summary) {
8691
8825
  case "callbacks": {
8692
8826
  const { v } = await inquirer3.prompt([{ type: "input", name: "v", message: "Callback URLs (comma-separated):", default: cb.join(", ") }]);
8693
8827
  await admin({ method: "PATCH", path: cBase, body: { authorizedCallbackUrls: parseList(v) }, summary: "Update callback URLs" });
8694
- console.log(import_chalk40.default.green(" Callbacks updated."));
8828
+ console.log(import_chalk41.default.green(" Callbacks updated."));
8695
8829
  break;
8696
8830
  }
8697
8831
  case "scopes": {
8698
8832
  const { v } = await inquirer3.prompt([{ type: "input", name: "v", message: "Scopes (space/comma-separated):", default: scopes.join(" ") }]);
8699
8833
  await admin({ method: "PATCH", path: cBase, body: { scopes: v.split(/[\s,]+/).filter(Boolean) }, summary: "Update scopes" });
8700
- console.log(import_chalk40.default.green(" Scopes updated."));
8834
+ console.log(import_chalk41.default.green(" Scopes updated."));
8701
8835
  break;
8702
8836
  }
8703
8837
  case "expiries": {
@@ -8712,14 +8846,14 @@ async function clientHome(base2, summary) {
8712
8846
  body: { accessTokenExpiry: Number(a.access), idTokenExpiry: Number(a.id), refreshTokenExpiry: Number(a.refresh) },
8713
8847
  summary: "Update token expiries"
8714
8848
  });
8715
- console.log(import_chalk40.default.green(" Expiries updated."));
8849
+ console.log(import_chalk41.default.green(" Expiries updated."));
8716
8850
  break;
8717
8851
  }
8718
8852
  case "secret": {
8719
8853
  const { sure } = await inquirer3.prompt([{ type: "confirm", name: "sure", message: "Print the client secret to this terminal?", default: false }]);
8720
8854
  if (!sure) break;
8721
8855
  const s = await admin({ method: "GET", path: `${cBase}/secret`, summary: "Reveal client secret" });
8722
- 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))}`);
8723
8857
  break;
8724
8858
  }
8725
8859
  case "rotate": {
@@ -8727,14 +8861,14 @@ async function clientHome(base2, summary) {
8727
8861
  if (!sure) break;
8728
8862
  const fresh = randomSecret();
8729
8863
  await admin({ method: "PATCH", path: cBase, body: { clientSecret: fresh }, summary: "Rotate client secret" });
8730
- 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)")}`);
8731
8865
  break;
8732
8866
  }
8733
8867
  case "delete": {
8734
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 }]);
8735
8869
  if (!sure) break;
8736
8870
  await admin({ method: "DELETE", path: cBase, summary: `Delete app client ${id}` });
8737
- console.log(import_chalk40.default.green(" App client deleted."));
8871
+ console.log(import_chalk41.default.green(" App client deleted."));
8738
8872
  return;
8739
8873
  }
8740
8874
  }
@@ -8761,9 +8895,9 @@ async function providersMenu(cBase, clientLabel) {
8761
8895
  const providers = Array.isArray(raw) ? raw : [];
8762
8896
  console.log();
8763
8897
  for (const p of providers) {
8764
- 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" : ""}`)}`);
8765
8899
  }
8766
- 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."));
8767
8901
  const { act } = await inquirer3.prompt([{
8768
8902
  type: "list",
8769
8903
  name: "act",
@@ -8821,23 +8955,23 @@ async function providersMenu(cBase, clientLabel) {
8821
8955
  body.targetServerToken = routing;
8822
8956
  }
8823
8957
  await admin({ method: "POST", path: `${cBase}/providers`, body, summary: `Add ${type} login provider` });
8824
- console.log(import_chalk40.default.green(` ${type} provider added.`));
8958
+ console.log(import_chalk41.default.green(` ${type} provider added.`));
8825
8959
  } else {
8826
8960
  const { p } = await inquirer3.prompt([{
8827
8961
  type: "list",
8828
8962
  name: "p",
8829
8963
  message: act === "rm" ? "Remove which provider?" : "Reveal which secret?",
8830
- 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 }]
8831
8965
  }]);
8832
8966
  if (!p) continue;
8833
8967
  if (act === "rm") {
8834
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 }]);
8835
8969
  if (!sure) continue;
8836
8970
  await admin({ method: "DELETE", path: `${cBase}/providers/${encodeURIComponent(p.id)}`, summary: `Remove ${p.type} provider` });
8837
- console.log(import_chalk40.default.green(` ${p.type} removed.`));
8971
+ console.log(import_chalk41.default.green(` ${p.type} removed.`));
8838
8972
  } else {
8839
8973
  const s = await admin({ method: "GET", path: `${cBase}/providers/${encodeURIComponent(p.id)}/secret`, summary: `Reveal ${p.type} provider secret` });
8840
- 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))}`);
8841
8975
  }
8842
8976
  }
8843
8977
  }
@@ -8845,7 +8979,7 @@ async function providersMenu(cBase, clientLabel) {
8845
8979
 
8846
8980
  // src/commands/spec.ts
8847
8981
  var fs11 = __toESM(require("fs"));
8848
- var import_chalk41 = __toESM(require("chalk"));
8982
+ var import_chalk42 = __toESM(require("chalk"));
8849
8983
  var import_ora18 = __toESM(require("ora"));
8850
8984
  init_admin();
8851
8985
  init_api();
@@ -8862,14 +8996,14 @@ async function runSpecGet(project, opts) {
8862
8996
  }
8863
8997
  async function runSpecSet(project, opts) {
8864
8998
  if (!opts.file) {
8865
- 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)."));
8866
9000
  process.exit(1);
8867
9001
  }
8868
9002
  let specContent;
8869
9003
  try {
8870
9004
  specContent = fs11.readFileSync(opts.file, "utf-8");
8871
9005
  } catch {
8872
- console.error(import_chalk41.default.red(`Cannot read file: ${opts.file}`));
9006
+ console.error(import_chalk42.default.red(`Cannot read file: ${opts.file}`));
8873
9007
  process.exit(1);
8874
9008
  }
8875
9009
  const { teamId } = await resolveTeam(opts.team);
@@ -8898,23 +9032,23 @@ async function runSpecSet(project, opts) {
8898
9032
  function printSpecChangeReport(report, projectName) {
8899
9033
  const r = report.routes;
8900
9034
  if (r) {
8901
- for (const a of r.added) console.log(import_chalk41.default.green(` + ${a}`));
8902
- for (const d of r.removed) console.log(import_chalk41.default.red(` \u2212 ${d}`));
8903
- for (const rn of r.renamed ?? []) console.log(import_chalk41.default.yellow(` ~ ${rn.from} \u2192 ${rn.to}`));
8904
- 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)`));
8905
9039
  }
8906
- if (report.applied?.mcp_regenerated) console.log(import_chalk41.default.dim(" MCP catalogue regenerated."));
8907
- 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.`));
8908
9042
  for (const item of report.attention ?? []) {
8909
- console.log(import_chalk41.default.yellow(` \u26A0 ${item.detail}`));
9043
+ console.log(import_chalk42.default.yellow(` \u26A0 ${item.detail}`));
8910
9044
  if (item.suggestion?.carry_from && item.suggestion.carry_to) {
8911
- 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}"`));
8912
9046
  }
8913
9047
  }
8914
9048
  }
8915
9049
  async function runSpecCarry(project, opts) {
8916
9050
  if (!opts.method || !opts.from || !opts.to) {
8917
- 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."));
8918
9052
  process.exit(1);
8919
9053
  }
8920
9054
  const { teamId } = await resolveTeam(opts.team);
@@ -8936,7 +9070,7 @@ async function runSpecCarry(project, opts) {
8936
9070
  }
8937
9071
  async function runSpecDeleteRule(project, opts) {
8938
9072
  if (!opts.method || !opts.route) {
8939
- console.error(import_chalk41.default.red("--method and --route are required."));
9073
+ console.error(import_chalk42.default.red("--method and --route are required."));
8940
9074
  process.exit(1);
8941
9075
  }
8942
9076
  const { teamId } = await resolveTeam(opts.team);
@@ -8956,14 +9090,14 @@ async function runSpecDeleteRule(project, opts) {
8956
9090
  }
8957
9091
 
8958
9092
  // src/commands/agent.ts
8959
- var import_chalk43 = __toESM(require("chalk"));
9093
+ var import_chalk44 = __toESM(require("chalk"));
8960
9094
  var import_ora19 = __toESM(require("ora"));
8961
9095
  init_auth();
8962
9096
  init_admin();
8963
9097
  init_resolve();
8964
9098
 
8965
9099
  // src/lib/tools.ts
8966
- var import_chalk42 = __toESM(require("chalk"));
9100
+ var import_chalk43 = __toESM(require("chalk"));
8967
9101
  init_admin();
8968
9102
  init_api();
8969
9103
  init_resolve();
@@ -8983,15 +9117,15 @@ var TOOLS = [
8983
9117
  const key = keys.dev ?? Object.values(keys)[0];
8984
9118
  const url = `https://${a.name}.abz.run/${version2}/dev`;
8985
9119
  const tryIt = buildTryItCurl(url, auth, key);
8986
- const lines = [` ${import_chalk42.default.dim("Proxy URL:")} ${import_chalk42.default.bold(url)}`];
8987
- 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}`);
8988
9122
  const envs = Object.keys(keys);
8989
9123
  if (envs.length) {
8990
- 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):")}`);
8991
9125
  const w = Math.max(...envs.map((e) => e.length));
8992
- 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])}`);
8993
9127
  }
8994
- 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)}`);
8995
9129
  return { ...res, proxy_url: url, keys, ...tryIt ? { try_it: tryIt } : {}, display: lines.join("\n") };
8996
9130
  }
8997
9131
  },
@@ -9147,17 +9281,17 @@ function truncate(value, max = 1500) {
9147
9281
  }
9148
9282
  function printCost(resp) {
9149
9283
  const line = formatBilling(resp.billing);
9150
- 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)`));
9151
9285
  }
9152
9286
  async function runAgent(opts) {
9153
9287
  requireAuth();
9154
9288
  const { teamId, teamName } = await resolveTeam(opts.team);
9155
9289
  const { default: inquirer3 } = await import("inquirer");
9156
- console.log(import_chalk43.default.bold("APIblaze agent") + import_chalk43.default.dim(` \xB7 team ${teamName ?? teamId}`));
9157
- 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'));
9158
9292
  const history = [];
9159
9293
  while (true) {
9160
- 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" }]);
9161
9295
  const text = (input ?? "").trim();
9162
9296
  if (!text) continue;
9163
9297
  if (["exit", "quit", ":q"].includes(text.toLowerCase())) break;
@@ -9171,14 +9305,14 @@ async function runAgent(opts) {
9171
9305
  } catch (err) {
9172
9306
  spinner.stop();
9173
9307
  if (err instanceof ApiError && err.status === 402) {
9174
- 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."));
9175
9309
  break;
9176
9310
  }
9177
9311
  throw err;
9178
9312
  }
9179
9313
  history.push({ role: "assistant", content: resp.raw });
9180
9314
  printCost(resp);
9181
- 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);
9182
9316
  if (!resp.action) break;
9183
9317
  const tool = findTool(resp.action.tool);
9184
9318
  if (!tool) {
@@ -9203,11 +9337,11 @@ async function runAgent(opts) {
9203
9337
  }
9204
9338
  renderTrace();
9205
9339
  if (step === MAX_TOOL_STEPS - 1) {
9206
- 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)"));
9207
9341
  }
9208
9342
  }
9209
9343
  }
9210
- console.log(import_chalk43.default.dim("\nBye."));
9344
+ console.log(import_chalk44.default.dim("\nBye."));
9211
9345
  }
9212
9346
 
9213
9347
  // src/commands/config-browse.ts
@@ -9502,11 +9636,11 @@ function dig(blob, dotted) {
9502
9636
  }
9503
9637
  var readSetting = (s, cfg) => s.read ? s.read(cfg) : dig(cfg, s.key);
9504
9638
  function show(v) {
9505
- if (v === void 0) return import_chalk44.default.dim("(unset)");
9506
- if (v === null) return import_chalk44.default.dim("null");
9507
- if (typeof v === "object") return import_chalk44.default.cyan(JSON.stringify(v));
9508
- if (typeof v === "boolean") return v ? import_chalk44.default.green("on") : import_chalk44.default.red("off");
9509
- 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));
9510
9644
  }
9511
9645
  function parseValue(raw) {
9512
9646
  if (raw === "true") return true;
@@ -9548,10 +9682,10 @@ async function patchSetting(proj2, s, value, cfg) {
9548
9682
  }
9549
9683
  }
9550
9684
  var loginFirst = (what) => {
9551
- console.log(import_chalk44.default.yellow(`
9685
+ console.log(import_chalk45.default.yellow(`
9552
9686
  Log in first to ${what}.`));
9553
- console.log(import_chalk44.default.dim(" Run `npx apiblaze login` \u2014 or `npx apiblaze claim` if you created this proxy"));
9554
- 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"));
9555
9689
  };
9556
9690
  async function runConfig(project, key, value, opts) {
9557
9691
  const creds = loadCredentials();
@@ -9568,9 +9702,9 @@ async function runConfig(project, key, value, opts) {
9568
9702
  }
9569
9703
  const setting = SETTINGS.find((s) => s.key === key);
9570
9704
  if (!setting) {
9571
- console.error(import_chalk44.default.red(`Unknown setting "${key}".`));
9572
- console.error(import_chalk44.default.dim(" Known: " + SETTINGS.map((s) => s.key).join(", ")));
9573
- 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>`.)"));
9574
9708
  process.exit(1);
9575
9709
  }
9576
9710
  if (value === void 0) {
@@ -9585,7 +9719,7 @@ async function pickProject(teamId) {
9585
9719
  const { getProjects: getProjects2 } = await Promise.resolve().then(() => (init_api(), api_exports));
9586
9720
  const projects = await getProjects2(teamId).catch(() => []);
9587
9721
  if (!projects.length) {
9588
- 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`."));
9589
9723
  process.exit(1);
9590
9724
  }
9591
9725
  const { default: inquirer3 } = await import("inquirer");
@@ -9593,7 +9727,7 @@ async function pickProject(teamId) {
9593
9727
  type: "list",
9594
9728
  name: "picked",
9595
9729
  message: "Which project?",
9596
- 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 }))
9597
9731
  }]);
9598
9732
  return { projectId: picked.projectId, projectName: picked.projectName, apiVersion: picked.apiVersion, teamId, tenant: picked.tenant };
9599
9733
  }
@@ -9604,25 +9738,25 @@ function printAll(proj2, cfg, json) {
9604
9738
  console.log(JSON.stringify(out, null, 2));
9605
9739
  return;
9606
9740
  }
9607
- console.log(import_chalk44.default.bold(`
9741
+ console.log(import_chalk45.default.bold(`
9608
9742
  ${proj2.projectName} v${proj2.apiVersion} \u2014 settings
9609
9743
  `));
9610
9744
  for (const group2 of SETTING_GROUPS) {
9611
- console.log(import_chalk44.default.bold(group2));
9745
+ console.log(import_chalk45.default.bold(group2));
9612
9746
  for (const s of SETTINGS.filter((x) => x.group === group2)) {
9613
- 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)}`);
9614
9748
  }
9615
9749
  console.log();
9616
9750
  }
9617
- 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)"));
9618
9752
  }
9619
9753
  async function discoveryMenu(project) {
9620
9754
  const { default: inquirer3 } = await import("inquirer");
9621
- console.log(import_chalk44.default.bold(`
9755
+ console.log(import_chalk45.default.bold(`
9622
9756
  APIblaze proxy configuration${project ? ` \u2014 ${project}` : ""}
9623
9757
  `));
9624
- console.log(import_chalk44.default.dim("You are not logged in \u2014 browsing what's configurable. Everything below works"));
9625
- 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"));
9626
9760
  for (; ; ) {
9627
9761
  const { pick: pick2 } = await inquirer3.prompt([{
9628
9762
  type: "list",
@@ -9630,13 +9764,13 @@ APIblaze proxy configuration${project ? ` \u2014 ${project}` : ""}
9630
9764
  message: "Explore:",
9631
9765
  pageSize: 20,
9632
9766
  choices: [
9633
- new inquirer3.Separator(import_chalk44.default.bold("\u2014 Settings \u2014")),
9767
+ new inquirer3.Separator(import_chalk45.default.bold("\u2014 Settings \u2014")),
9634
9768
  ...SETTING_GROUPS.map((g) => ({
9635
- 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(", "))}`,
9636
9770
  value: { kind: "settings", g }
9637
9771
  })),
9638
- new inquirer3.Separator(import_chalk44.default.bold("\u2014 Features \u2014")),
9639
- ...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 } })),
9640
9774
  new inquirer3.Separator(),
9641
9775
  { name: "Exit", value: { kind: "exit" } }
9642
9776
  ]
@@ -9645,24 +9779,24 @@ APIblaze proxy configuration${project ? ` \u2014 ${project}` : ""}
9645
9779
  if (pick2.kind === "settings") {
9646
9780
  console.log();
9647
9781
  for (const s of SETTINGS.filter((x) => x.group === pick2.g)) {
9648
- console.log(` ${import_chalk44.default.bold(s.label.padEnd(28))} ${import_chalk44.default.dim(s.desc)}`);
9649
- 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)}`);
9650
9784
  }
9651
9785
  loginFirst("view or change these settings");
9652
9786
  } else {
9653
9787
  const f = pick2.f;
9654
9788
  console.log(`
9655
- ${import_chalk44.default.bold(f.label)} \u2014 ${f.desc}`);
9789
+ ${import_chalk45.default.bold(f.label)} \u2014 ${f.desc}`);
9656
9790
  loginFirst(`use ${f.label.toLowerCase()}`);
9657
9791
  }
9658
9792
  }
9659
9793
  }
9660
9794
  async function navigator(proj2, cfg, opts) {
9661
9795
  const { default: inquirer3 } = await import("inquirer");
9662
- console.log(import_chalk44.default.bold(`
9796
+ console.log(import_chalk45.default.bold(`
9663
9797
  ${proj2.projectName} v${proj2.apiVersion} \u2014 configuration
9664
9798
  `));
9665
- 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"));
9666
9800
  let blob = cfg;
9667
9801
  for (; ; ) {
9668
9802
  const { pick: pick2 } = await inquirer3.prompt([{
@@ -9671,10 +9805,10 @@ ${proj2.projectName} v${proj2.apiVersion} \u2014 configuration
9671
9805
  message: "Where to?",
9672
9806
  pageSize: 20,
9673
9807
  choices: [
9674
- new inquirer3.Separator(import_chalk44.default.bold("\u2014 Settings \u2014")),
9808
+ new inquirer3.Separator(import_chalk45.default.bold("\u2014 Settings \u2014")),
9675
9809
  ...SETTING_GROUPS.map((g) => ({ name: g, value: { kind: "settings", g } })),
9676
- new inquirer3.Separator(import_chalk44.default.bold("\u2014 Features \u2014")),
9677
- ...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 } })),
9678
9812
  new inquirer3.Separator(),
9679
9813
  { name: "Show all settings", value: { kind: "list" } },
9680
9814
  { name: "Exit", value: { kind: "exit" } }
@@ -9714,7 +9848,7 @@ ${proj2.projectName} v${proj2.apiVersion} \u2014 configuration
9714
9848
  }
9715
9849
  }
9716
9850
  } catch (err) {
9717
- 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)}`));
9718
9852
  }
9719
9853
  }
9720
9854
  }
@@ -9728,7 +9862,7 @@ async function settingsGroup(proj2, cfg, group2) {
9728
9862
  message: group2 + ":",
9729
9863
  pageSize: 16,
9730
9864
  choices: [
9731
- ...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 })),
9732
9866
  new inquirer3.Separator(),
9733
9867
  { name: "\u2190 Back", value: null }
9734
9868
  ]
@@ -9746,7 +9880,7 @@ async function settingsGroup(proj2, cfg, group2) {
9746
9880
  } else if (s.type === "number") {
9747
9881
  const { v } = await inquirer3.prompt([{ type: "input", name: "v", message: `${s.label} (number):`, default: readSetting(s, cfg) }]);
9748
9882
  if (v === "" || Number.isNaN(Number(v))) {
9749
- console.log(import_chalk44.default.yellow(" Not a number \u2014 unchanged."));
9883
+ console.log(import_chalk45.default.yellow(" Not a number \u2014 unchanged."));
9750
9884
  continue;
9751
9885
  }
9752
9886
  value = Number(v);
@@ -9827,7 +9961,7 @@ async function buildCondition(phase) {
9827
9961
  const items = [];
9828
9962
  for (; ; ) {
9829
9963
  const a = await inquirer3.prompt([
9830
- { 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" },
9831
9965
  { type: "list", name: "operator", message: "Operator:", choices: [
9832
9966
  "eq",
9833
9967
  "neq",
@@ -9858,7 +9992,7 @@ async function buildCondition(phase) {
9858
9992
  function showCondition(cond) {
9859
9993
  if (!Array.isArray(cond) || !cond.length) return "";
9860
9994
  const s = cond.map((c) => `${c.source} ${c.operator}${c.value !== void 0 ? ` "${c.value}"` : ""}${c.logicOp ? ` ${c.logicOp}` : ""}`).join(" ");
9861
- return import_chalk44.default.dim(` when ${s}`);
9995
+ return import_chalk45.default.dim(` when ${s}`);
9862
9996
  }
9863
9997
  async function transformsMenu(proj2) {
9864
9998
  const { default: inquirer3 } = await import("inquirer");
@@ -9867,12 +10001,12 @@ async function transformsMenu(proj2) {
9867
10001
  const out = await admin({ method: "GET", path: base2, summary: "List transform rules" });
9868
10002
  const rules = out?.rules ?? [];
9869
10003
  console.log();
9870
- 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."));
9871
10005
  for (const r of rules) {
9872
10006
  const a = r.action ?? {};
9873
10007
  const fns = [...a.source_fns ?? [], ...a.dest_fns ?? []].map((f) => f.fn);
9874
- 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")}`) : ""}`;
9875
- 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)}`);
9876
10010
  }
9877
10011
  const { act } = await inquirer3.prompt([{
9878
10012
  type: "list",
@@ -9884,7 +10018,7 @@ async function transformsMenu(proj2) {
9884
10018
  { name: "Enable/disable a rule", value: "toggle" },
9885
10019
  { name: "Delete a rule", value: "delete" }
9886
10020
  ] : [],
9887
- { 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" },
9888
10022
  { name: "\u2190 Back", value: "back" }
9889
10023
  ]
9890
10024
  }]);
@@ -9897,11 +10031,11 @@ async function transformsMenu(proj2) {
9897
10031
  }]);
9898
10032
  const body = parseValue(raw);
9899
10033
  if (!body || typeof body !== "object" || Array.isArray(body)) {
9900
- 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."));
9901
10035
  continue;
9902
10036
  }
9903
10037
  await admin({ method: "POST", path: base2, body, summary: "Create transform rule (raw JSON)" });
9904
- console.log(import_chalk44.default.green(" Rule created."));
10038
+ console.log(import_chalk45.default.green(" Rule created."));
9905
10039
  continue;
9906
10040
  }
9907
10041
  if (act === "add") {
@@ -9917,7 +10051,7 @@ async function transformsMenu(proj2) {
9917
10051
  { name: "Remove a field", value: "remove" }
9918
10052
  ] }
9919
10053
  ]);
9920
- 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)");
9921
10055
  let action2;
9922
10056
  if (ans.kind === "hardcode") {
9923
10057
  const a = await inquirer3.prompt([
@@ -9964,16 +10098,16 @@ async function transformsMenu(proj2) {
9964
10098
  type: "list",
9965
10099
  name: "rule",
9966
10100
  message: act === "toggle" ? "Which rule?" : "Delete which rule?",
9967
- 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 }]
9968
10102
  }]);
9969
10103
  if (!rule) continue;
9970
10104
  if (act === "toggle") {
9971
10105
  const flipped = { ...rule, enabled: rule.enabled === false };
9972
10106
  await admin({ method: "PUT", path: `${base2}/${rule.id}`, body: flipped, summary: `${flipped.enabled ? "Enable" : "Disable"} transform "${rule.name}"` });
9973
- 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"}`));
9974
10108
  } else {
9975
10109
  await admin({ method: "DELETE", path: `${base2}/${rule.id}`, summary: `Delete transform "${rule.name}"` });
9976
- console.log(import_chalk44.default.green(` ${rule.name} deleted.`));
10110
+ console.log(import_chalk45.default.green(` ${rule.name} deleted.`));
9977
10111
  }
9978
10112
  }
9979
10113
  }
@@ -9985,9 +10119,9 @@ async function mappingsMenu(proj2) {
9985
10119
  const out = await admin({ method: "GET", path: base2, summary: "List mapping tables" });
9986
10120
  const tables = out?.mappings ?? out?.tables ?? [];
9987
10121
  console.log();
9988
- 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."));
9989
10123
  for (const t of tables) {
9990
- 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" : ""}`)}`);
9991
10125
  }
9992
10126
  const { act } = await inquirer3.prompt([{
9993
10127
  type: "list",
@@ -10007,11 +10141,11 @@ async function mappingsMenu(proj2) {
10007
10141
  ]);
10008
10142
  const entries2 = parseValue(a.entries);
10009
10143
  if (!Array.isArray(entries2)) {
10010
- 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."));
10011
10145
  continue;
10012
10146
  }
10013
10147
  await admin({ method: "POST", path: base2, body: { name: a.name, entries: entries2 }, summary: `Create mapping table "${a.name}"` });
10014
- console.log(import_chalk44.default.green(` Table "${a.name}" created.`));
10148
+ console.log(import_chalk45.default.green(` Table "${a.name}" created.`));
10015
10149
  } else {
10016
10150
  const { table } = await inquirer3.prompt([{
10017
10151
  type: "list",
@@ -10021,7 +10155,7 @@ async function mappingsMenu(proj2) {
10021
10155
  }]);
10022
10156
  if (!table) continue;
10023
10157
  await admin({ method: "DELETE", path: `${base2}/${table.id}`, summary: `Delete mapping table "${table.name}"` });
10024
- console.log(import_chalk44.default.green(` ${table.name} deleted.`));
10158
+ console.log(import_chalk45.default.green(` ${table.name} deleted.`));
10025
10159
  }
10026
10160
  }
10027
10161
  }
@@ -10032,14 +10166,14 @@ async function tenantsMenu(proj2, opts) {
10032
10166
  const out = await admin({ method: "GET", path: base2, summary: "List attached tenants" });
10033
10167
  const tenants = out?.tenants ?? [];
10034
10168
  console.log();
10035
- if (!tenants.length) console.log(import_chalk44.default.dim(" No tenants attached (consumers use the default tenant)."));
10036
- 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 ?? "")}`);
10037
10171
  const { act } = await inquirer3.prompt([{
10038
10172
  type: "list",
10039
10173
  name: "act",
10040
10174
  message: "Tenants:",
10041
10175
  choices: [
10042
- { 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" },
10043
10177
  { name: "Attach a tenant to this project", value: "attach" },
10044
10178
  ...tenants.length ? [{ name: "Detach a tenant from this project", value: "detach" }] : [],
10045
10179
  { name: "\u2190 Back", value: "back" }
@@ -10062,7 +10196,7 @@ async function tenantsMenu(proj2, opts) {
10062
10196
  }]);
10063
10197
  if (!t) continue;
10064
10198
  await admin({ method: "DELETE", path: `${base2}/${encodeURIComponent(t.tenant_name ?? t.name)}`, summary: `Detach tenant ${t.tenant_name ?? t.name}` });
10065
- 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}.`));
10066
10200
  }
10067
10201
  }
10068
10202
  }
@@ -10105,7 +10239,7 @@ async function specMenu(proj2, opts) {
10105
10239
  choices: [
10106
10240
  { name: "Print the stored spec", value: "get" },
10107
10241
  { name: "Refresh the spec from its source", value: "refresh" },
10108
- { 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" },
10109
10243
  { name: "\u2190 Back", value: "back" }
10110
10244
  ]
10111
10245
  }]);
@@ -10113,7 +10247,7 @@ async function specMenu(proj2, opts) {
10113
10247
  if (act === "get") await runSpecGet(proj2.projectName, { team: opts.team, apiversion: proj2.apiVersion });
10114
10248
  else if (act === "refresh") {
10115
10249
  await admin({ method: "POST", path: `/projects/${proj2.projectId}/${proj2.apiVersion}/refresh-spec`, summary: "Refresh spec from source" });
10116
- console.log(import_chalk44.default.green(" Spec refresh triggered."));
10250
+ console.log(import_chalk45.default.green(" Spec refresh triggered."));
10117
10251
  } else await runOpenapi(proj2.projectName, proj2.apiVersion);
10118
10252
  }
10119
10253
  async function agentsMenu(proj2, opts) {
@@ -10138,7 +10272,7 @@ async function agentsMenu(proj2, opts) {
10138
10272
  }
10139
10273
 
10140
10274
  // src/commands/group.ts
10141
- var import_chalk45 = __toESM(require("chalk"));
10275
+ var import_chalk46 = __toESM(require("chalk"));
10142
10276
  var import_ora21 = __toESM(require("ora"));
10143
10277
  init_auth();
10144
10278
  init_admin();
@@ -10232,7 +10366,7 @@ async function userByRefOrCreate(t, ref) {
10232
10366
  if (!ref.includes("@")) throw e;
10233
10367
  const created = await t.call("/v1/admin/users", "POST", { email: ref.trim().toLowerCase() });
10234
10368
  if (!created?.abz_sub) throw e;
10235
- 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.`));
10236
10370
  return { abz_sub: created.abz_sub, email: created.email ?? ref, display_name: null };
10237
10371
  }
10238
10372
  }
@@ -10240,11 +10374,11 @@ async function runGroupList(opts) {
10240
10374
  const t = await resolveTransport(opts);
10241
10375
  const groups = await listGroups(t);
10242
10376
  if (opts.json) return void console.log(JSON.stringify(groups));
10243
- if (!groups.length) return void console.log(import_chalk45.default.yellow(`No groups in ${t.tenant}. Create one: apiblaze group create <name>`));
10244
- 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}:`));
10245
10379
  for (const g of groups) {
10246
- const sealed = g.name === "apiblaze_admins" ? import_chalk45.default.dim(" (admins \u2014 managed by allowlist)") : "";
10247
- 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}`);
10248
10382
  }
10249
10383
  }
10250
10384
  async function runGroupCreate(name, opts) {
@@ -10272,7 +10406,7 @@ async function runGroupCreate(name, opts) {
10272
10406
  const spinner = (0, import_ora21.default)(`Creating group ${name}...`).start();
10273
10407
  try {
10274
10408
  await t.call("/v1/admin/groups", "POST", { name, admins: [adminSub] });
10275
- 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}.`);
10276
10410
  } catch (e) {
10277
10411
  spinner.fail("Create failed.");
10278
10412
  throw e;
@@ -10284,7 +10418,7 @@ async function runGroupDelete(name, opts) {
10284
10418
  const spinner = (0, import_ora21.default)(`Deleting group ${name}...`).start();
10285
10419
  try {
10286
10420
  await t.call(`/v1/admin/groups/${encodeURIComponent(g.id)}`, "DELETE");
10287
- spinner.succeed(`Group ${import_chalk45.default.bold(name)} deleted.`);
10421
+ spinner.succeed(`Group ${import_chalk46.default.bold(name)} deleted.`);
10288
10422
  } catch (e) {
10289
10423
  spinner.fail("Delete failed.");
10290
10424
  throw e;
@@ -10297,11 +10431,11 @@ async function runGroupMembers(name, opts) {
10297
10431
  const subs = await t.call(`/v1/admin/groups/${encodeURIComponent(g.id)}/subgroups`);
10298
10432
  if (opts.json) return void console.log(JSON.stringify({ ...detail, subgroups: subs?.subgroups ?? [] }));
10299
10433
  const members = detail?.members ?? [];
10300
- console.log(import_chalk45.default.bold(`${g.name}`) + import_chalk45.default.dim(` (${t.tenant})`));
10301
- for (const m of members) console.log(` ${label2(m)} ${m.role === "admin" ? import_chalk45.default.cyan("group-admin") : import_chalk45.default.dim("member")}`);
10302
- 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"));
10303
10437
  const sg = subs?.subgroups ?? [];
10304
- 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(", ")}`));
10305
10439
  }
10306
10440
  async function runGroupAddUser(userRef, groupName, opts) {
10307
10441
  const t = await resolveTransport(opts);
@@ -10311,7 +10445,7 @@ async function runGroupAddUser(userRef, groupName, opts) {
10311
10445
  const spinner = (0, import_ora21.default)(`Adding ${label2(u)} to ${g.name}...`).start();
10312
10446
  try {
10313
10447
  await t.call(`/v1/admin/groups/${encodeURIComponent(g.id)}/members`, "POST", { abz_sub: u.abz_sub, role });
10314
- 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}.`);
10315
10449
  } catch (e) {
10316
10450
  spinner.fail("Add failed.");
10317
10451
  throw e;
@@ -10323,7 +10457,7 @@ async function runGroupRemoveUser(userRef, groupName, opts) {
10323
10457
  const spinner = (0, import_ora21.default)(`Removing ${label2(u)} from ${g.name}...`).start();
10324
10458
  try {
10325
10459
  await t.call(`/v1/admin/groups/${encodeURIComponent(g.id)}/members/_?abz_sub=${encodeURIComponent(u.abz_sub)}`, "DELETE");
10326
- 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)}.`);
10327
10461
  } catch (e) {
10328
10462
  spinner.fail("Remove failed.");
10329
10463
  throw e;
@@ -10335,7 +10469,7 @@ async function runGroupAddGroup(childName, parentName, opts) {
10335
10469
  const spinner = (0, import_ora21.default)(`Nesting ${child.name} under ${parent.name}...`).start();
10336
10470
  try {
10337
10471
  await t.call(`/v1/admin/groups/${encodeURIComponent(parent.id)}/subgroups`, "POST", { child_group_id: child.id });
10338
- 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)}.`);
10339
10473
  } catch (e) {
10340
10474
  spinner.fail("Nest failed.");
10341
10475
  throw e;
@@ -10347,7 +10481,7 @@ async function runGroupRemoveGroup(childName, parentName, opts) {
10347
10481
  const spinner = (0, import_ora21.default)(`Un-nesting ${child.name} from ${parent.name}...`).start();
10348
10482
  try {
10349
10483
  await t.call(`/v1/admin/groups/${encodeURIComponent(parent.id)}/subgroups/${encodeURIComponent(child.id)}`, "DELETE");
10350
- 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)}.`);
10351
10485
  } catch (e) {
10352
10486
  spinner.fail("Un-nest failed.");
10353
10487
  throw e;
@@ -10358,18 +10492,18 @@ async function runGroupUsers(opts) {
10358
10492
  const users = await listUsers(t);
10359
10493
  const observed = await t.call("/v1/admin/observed-identities").catch(() => ({ identities: [] }));
10360
10494
  if (opts.json) return void console.log(JSON.stringify({ users, observed: observed?.identities ?? [] }));
10361
- console.log(import_chalk45.default.dim(`Tenant ${t.tenant} \u2014 user directory:`));
10362
- for (const u of users) console.log(` ${label2(u)} ${import_chalk45.default.dim(u.abz_sub)}`);
10363
- 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"));
10364
10498
  const fresh = (observed?.identities ?? []).filter((o) => !o.provisioned);
10365
10499
  if (fresh.length) {
10366
- console.log(import_chalk45.default.dim("Seen in traffic (not yet users):"));
10367
- 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 ?? "")}`);
10368
10502
  }
10369
10503
  }
10370
10504
 
10371
10505
  // src/commands/key.ts
10372
- var import_chalk46 = __toESM(require("chalk"));
10506
+ var import_chalk47 = __toESM(require("chalk"));
10373
10507
  var import_ora22 = __toESM(require("ora"));
10374
10508
  init_caller();
10375
10509
  async function runApikeysMenu(opts) {
@@ -10399,11 +10533,11 @@ async function runKeyList(opts) {
10399
10533
  return;
10400
10534
  }
10401
10535
  if (!keys.length) {
10402
- console.log(import_chalk46.default.yellow("No developer keys."));
10536
+ console.log(import_chalk47.default.yellow("No developer keys."));
10403
10537
  return;
10404
10538
  }
10405
10539
  for (const k of keys) {
10406
- 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")}`);
10407
10541
  }
10408
10542
  }
10409
10543
  async function runKeyMint(opts) {
@@ -10425,9 +10559,9 @@ async function runKeyMint(opts) {
10425
10559
  console.log(JSON.stringify(out));
10426
10560
  return;
10427
10561
  }
10428
- console.log(` ${import_chalk46.default.bold("key_id")}: ${out?.key_id}`);
10429
- console.log(` ${import_chalk46.default.bold("key")}: ${import_chalk46.default.green(out?.key)} ${import_chalk46.default.dim("(shown once \u2014 store it now)")}`);
10430
- 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}`);
10431
10565
  } catch (err) {
10432
10566
  spinner.fail("Mint failed.");
10433
10567
  throw err;
@@ -10454,7 +10588,7 @@ async function runKeyRevoke(keyId, opts) {
10454
10588
  init_iam();
10455
10589
 
10456
10590
  // src/commands/admins.ts
10457
- var import_chalk47 = __toESM(require("chalk"));
10591
+ var import_chalk48 = __toESM(require("chalk"));
10458
10592
  var import_ora23 = __toESM(require("ora"));
10459
10593
  init_caller();
10460
10594
  function requireTenant(opts) {
@@ -10482,13 +10616,13 @@ async function runAdminsList(opts) {
10482
10616
  return;
10483
10617
  }
10484
10618
  if (!admins2.length) {
10485
- 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.`));
10486
10620
  return;
10487
10621
  }
10488
10622
  for (const a of admins2) {
10489
10623
  const email = typeof a === "string" ? a : a.email;
10490
10624
  const flags = [a.active === false ? "pending" : null, a.pinned ? "pinned" : null].filter(Boolean).join(", ");
10491
- 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})`) : ""}`);
10492
10626
  }
10493
10627
  }
10494
10628
  async function runAdminsAdd(email, opts) {
@@ -10503,9 +10637,9 @@ async function runAdminsAdd(email, opts) {
10503
10637
  body: { email },
10504
10638
  summary: `Add ${email} to tenant ${tenant2} admins`
10505
10639
  });
10506
- 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)}.`);
10507
10641
  if (opts.json) console.log(JSON.stringify(out ?? { ok: true }));
10508
- 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."));
10509
10643
  } catch (err) {
10510
10644
  spinner?.fail("Add failed.");
10511
10645
  throw err;
@@ -10522,7 +10656,7 @@ async function runAdminsRemove(email, opts) {
10522
10656
  path: `${base(teamId, tenant2)}/${encodeURIComponent(email)}`,
10523
10657
  summary: `Remove ${email} from tenant ${tenant2} admins`
10524
10658
  });
10525
- 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)}.`);
10526
10660
  } catch (err) {
10527
10661
  spinner?.fail("Remove failed.");
10528
10662
  throw err;
@@ -10530,7 +10664,7 @@ async function runAdminsRemove(email, opts) {
10530
10664
  }
10531
10665
 
10532
10666
  // src/commands/preapprove.ts
10533
- var import_chalk48 = __toESM(require("chalk"));
10667
+ var import_chalk49 = __toESM(require("chalk"));
10534
10668
  var import_ora24 = __toESM(require("ora"));
10535
10669
  async function runPreapprove(who, opts) {
10536
10670
  const tenant2 = await resolveProducerTenant(opts.tenant);
@@ -10538,14 +10672,14 @@ async function runPreapprove(who, opts) {
10538
10672
  const rules = await listPreapprovalRules(tenant2);
10539
10673
  if (opts.json) return void console.log(JSON.stringify(rules, null, 2));
10540
10674
  if (!rules.length) {
10541
- console.log(import_chalk48.default.dim(`No pre-approval rules in ${tenant2}. Anyone who signs in can access (unless access is restricted).`));
10542
- 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`));
10543
10677
  return;
10544
10678
  }
10545
- 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)}:`));
10546
10680
  for (const r of rules) {
10547
- const tag = r.kind === "domain" ? import_chalk48.default.cyan("@" + r.value + " (whole domain)") : r.value;
10548
- 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(", ")}`) : "";
10549
10683
  console.log(` ${tag}${grp}`);
10550
10684
  }
10551
10685
  return;
@@ -10556,17 +10690,17 @@ async function runPreapprove(who, opts) {
10556
10690
  if (opts.remove) {
10557
10691
  const spinner2 = (0, import_ora24.default)(`Removing ${who} from ${tenant2}\u2026`).start();
10558
10692
  const { removed, value } = await removePreapprovalRule(tenant2, who);
10559
- if (removed) spinner2.succeed(`${import_chalk48.default.bold(value)} is no longer pre-approved for ${tenant2}.`);
10560
- 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.`);
10561
10695
  return;
10562
10696
  }
10563
10697
  const spinner = (0, import_ora24.default)(`Pre-approving ${who} for ${tenant2}\u2026`).start();
10564
10698
  try {
10565
10699
  const { kind, value } = await addPreapprovalRule(tenant2, who, opts.group);
10566
10700
  const what = kind === "domain" ? `Anyone @${value}` : value;
10567
- spinner.succeed(`${import_chalk48.default.bold(what)} can now sign in to ${import_chalk48.default.bold(tenant2)}.`);
10568
- if (opts.group?.length) console.log(import_chalk48.default.dim(` They'll join group(s) ${opts.group.join(", ")} on first sign-in.`));
10569
- 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`));
10570
10704
  } catch (err) {
10571
10705
  spinner.fail("Could not add the rule.");
10572
10706
  throw err;
@@ -10574,7 +10708,7 @@ async function runPreapprove(who, opts) {
10574
10708
  }
10575
10709
 
10576
10710
  // src/commands/consumer.ts
10577
- var import_chalk49 = __toESM(require("chalk"));
10711
+ var import_chalk50 = __toESM(require("chalk"));
10578
10712
  var import_ora25 = __toESM(require("ora"));
10579
10713
  init_admin();
10580
10714
  init_resolve();
@@ -10596,7 +10730,7 @@ async function consumerFetch(creds, suffix, init) {
10596
10730
  function requireConsumer2() {
10597
10731
  const c = loadConsumer();
10598
10732
  if (!c) {
10599
- 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."));
10600
10734
  process.exit(1);
10601
10735
  }
10602
10736
  return c;
@@ -10607,7 +10741,7 @@ async function runConsumerLogin(opts) {
10607
10741
  let clientId = opts.client;
10608
10742
  if (clientId) {
10609
10743
  if (!tenant2) {
10610
- 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)."));
10611
10745
  process.exit(1);
10612
10746
  }
10613
10747
  } else {
@@ -10625,18 +10759,18 @@ async function runConsumerLogin(opts) {
10625
10759
  const usable = (Array.isArray(clients) ? clients : []).filter((c) => c && (c.client_id || c.clientId));
10626
10760
  const pick2 = usable.find((c) => c.is_default || c.default) ?? usable.find((c) => c.verified !== false) ?? usable[0];
10627
10761
  if (!pick2) {
10628
- 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).`));
10629
10763
  process.exit(1);
10630
10764
  }
10631
10765
  clientId = pick2.client_id ?? pick2.clientId;
10632
10766
  }
10633
- 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...`);
10634
10768
  const result = await deviceLogin(clientId, DEFAULT_SCOPE, ({ verificationUri, userCode }) => {
10635
10769
  console.log(`
10636
- Open: ${import_chalk49.default.underline(verificationUri)}`);
10637
- console.log(` Code: ${import_chalk49.default.bold(userCode)}
10770
+ Open: ${import_chalk50.default.underline(verificationUri)}`);
10771
+ console.log(` Code: ${import_chalk50.default.bold(userCode)}
10638
10772
  `);
10639
- 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)"));
10640
10774
  });
10641
10775
  const claims = result.idToken && decodeJwt2(result.idToken) || (decodeJwt2(result.accessToken) ?? {});
10642
10776
  const creds = {
@@ -10651,7 +10785,7 @@ async function runConsumerLogin(opts) {
10651
10785
  obtainedAt: Date.now()
10652
10786
  };
10653
10787
  saveConsumer(creds);
10654
- 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}.`));
10655
10789
  }
10656
10790
  async function runConsumerTokens(opts) {
10657
10791
  const creds = requireConsumer2();
@@ -10664,18 +10798,18 @@ async function runConsumerTokens(opts) {
10664
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));
10665
10799
  return;
10666
10800
  }
10667
- 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)}
10668
10802
  `);
10669
- 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) ?? "?"))}
10670
10804
  ${fresh.accessToken}
10671
10805
  `);
10672
- 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) ?? "?"))}
10673
10807
  ${fresh.idToken}
10674
10808
  `);
10675
- if (fresh.refreshToken) console.log(`${import_chalk49.default.bold("refresh_token")}
10809
+ if (fresh.refreshToken) console.log(`${import_chalk50.default.bold("refresh_token")}
10676
10810
  ${fresh.refreshToken}
10677
10811
  `);
10678
- 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."));
10679
10813
  }
10680
10814
  async function runConsumerApikeys(opts) {
10681
10815
  const creds = requireConsumer2();
@@ -10685,8 +10819,8 @@ async function runConsumerApikeys(opts) {
10685
10819
  const revealed = await consumerFetch(list.creds, "/apikeys/reveal").catch(() => ({ status: 0, data: null, creds: list.creds }));
10686
10820
  spinner.stop();
10687
10821
  if (list.status >= 400) {
10688
- console.error(import_chalk49.default.red(`Failed to list keys (${list.status}): ${list.data?.error ?? ""}`));
10689
- 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."));
10690
10824
  process.exit(1);
10691
10825
  }
10692
10826
  const keys = list.data?.keys ?? [];
@@ -10694,16 +10828,16 @@ async function runConsumerApikeys(opts) {
10694
10828
  if (opts.json) {
10695
10829
  console.log(JSON.stringify({ keys, revealed: revealMap }, null, 2));
10696
10830
  } else if (!keys.length) {
10697
- console.log(import_chalk49.default.yellow("No API keys yet."));
10831
+ console.log(import_chalk50.default.yellow("No API keys yet."));
10698
10832
  } else {
10699
10833
  for (const k of keys) {
10700
10834
  const clear = revealMap[k.environment]?.key;
10701
- const shown = clear ? import_chalk49.default.green(clear) : import_chalk49.default.dim(`${k.key_prefix ?? ""}\u2026${k.key_suffix ?? ""}`);
10702
- const exp = k.expires_at ? import_chalk49.default.dim(`exp ${k.expires_at}`) : import_chalk49.default.dim("no expiry");
10703
- 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 ?? "")}`);
10704
10838
  }
10705
10839
  if (Object.keys(revealMap).length === 0 && keys.some((k) => !k.expires_at)) {
10706
- 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.)"));
10707
10841
  }
10708
10842
  }
10709
10843
  if (opts.json) return;
@@ -10725,12 +10859,12 @@ async function runConsumerApikeys(opts) {
10725
10859
  }
10726
10860
  s2.succeed("Key created.");
10727
10861
  const key = created.data?.key ?? created.data?.fullKey;
10728
- if (key) console.log(` ${import_chalk49.default.green(key)} ${import_chalk49.default.dim("(shown once \u2014 store it now)")}`);
10729
- 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."));
10730
10864
  }
10731
10865
 
10732
10866
  // src/commands/sidecar.ts
10733
- var import_chalk50 = __toESM(require("chalk"));
10867
+ var import_chalk51 = __toESM(require("chalk"));
10734
10868
  var import_ora26 = __toESM(require("ora"));
10735
10869
  var fs12 = __toESM(require("fs"));
10736
10870
  var path8 = __toESM(require("path"));
@@ -10773,7 +10907,7 @@ function upsertEnvLocal(root, token) {
10773
10907
  }
10774
10908
  function installSidecarPackage(root) {
10775
10909
  if (fs12.existsSync(path8.join(root, "node_modules", "apiblaze", "package.json"))) {
10776
- console.log(` ${import_chalk50.default.green("\u2713")} apiblaze package already installed`);
10910
+ console.log(` ${import_chalk51.default.green("\u2713")} apiblaze package already installed`);
10777
10911
  return;
10778
10912
  }
10779
10913
  const has = (f) => fs12.existsSync(path8.join(root, f));
@@ -10784,7 +10918,7 @@ function installSidecarPackage(root) {
10784
10918
  execSync(`${pm.cmd} ${pm.add} apiblaze`, { cwd: root, stdio: "ignore" });
10785
10919
  spinner.succeed("Installed apiblaze (the sidecar runtime).");
10786
10920
  } catch {
10787
- 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")}.`);
10788
10922
  }
10789
10923
  }
10790
10924
  function readEnvKey(root) {
@@ -10935,29 +11069,29 @@ async function runAnonymousInit(root, router, opts) {
10935
11069
  if (out.cp_key && out.team_id) saveAnonCred2(out.cp_key, out.team_id, out.claim_code);
10936
11070
  const envState = upsertEnvLocal(root, out.token);
10937
11071
  ensureGitignored(root);
10938
- console.log(` ${import_chalk50.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
10939
- 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)}`);
10940
11074
  installSidecarPackage(root);
10941
11075
  let inspectorPath = null;
10942
11076
  if (!opts.noInspector) {
10943
11077
  inspectorPath = generateInspector(root, router);
10944
- 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}`);
10945
11079
  }
10946
11080
  console.log("");
10947
- console.log(import_chalk50.default.bold("Done (no account needed). What happens next:"));
10948
- 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.`);
10949
11083
  console.log(` 2. Each external origin your app calls is logged in the console \u2014 approve one with:`);
10950
- 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)`);
10951
11085
  console.log("");
10952
- console.log(import_chalk50.default.bold(" \u{1F511} Keep your setup \u2014 claim it into an account:"));
10953
- console.log(` ${import_chalk50.default.cyan("apiblaze login")} then ${import_chalk50.default.cyan("apiblaze claim")} ${import_chalk50.default.dim("(no code needed here)")}`);
10954
- 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`));
10955
11089
  }
10956
11090
  async function runSidecar(opts) {
10957
11091
  const root = path8.resolve(opts.dir ?? process.cwd());
10958
11092
  const detected2 = detectNextProject(root);
10959
11093
  if (!detected2.found) {
10960
- 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}.`));
10961
11095
  console.log("Create one (e.g. `npx create-next-app`) and re-run `apiblaze init` inside it.");
10962
11096
  return;
10963
11097
  }
@@ -10968,10 +11102,10 @@ async function runSidecar(opts) {
10968
11102
  if (!loadCredentials()) {
10969
11103
  upsertEnvLocal(root, readEnvKey(root));
10970
11104
  ensureGitignored(root);
10971
- console.log(` ${import_chalk50.default.green("\u2713")} .env.local present (APIBLAZE_API_KEY) \u2014 reusing`);
10972
- 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)}`);
10973
11107
  installSidecarPackage(root);
10974
- 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."));
10975
11109
  return;
10976
11110
  }
10977
11111
  const { teamId, teamName } = await resolveTeam(opts.team);
@@ -10994,38 +11128,38 @@ async function runSidecar(opts) {
10994
11128
  throw err;
10995
11129
  }
10996
11130
  } else {
10997
- 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).`));
10998
11132
  }
10999
11133
  const envState = upsertEnvLocal(root, token);
11000
11134
  ensureGitignored(root);
11001
- 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`);
11002
11136
  const wireState = wireInstrumentation(root);
11003
- console.log(` ${import_chalk50.default.green("\u2713")} instrumentation.ts ${wireState}`);
11137
+ console.log(` ${import_chalk51.default.green("\u2713")} instrumentation.ts ${wireState}`);
11004
11138
  installSidecarPackage(root);
11005
11139
  let inspectorPath = null;
11006
11140
  if (!opts.noInspector) {
11007
11141
  inspectorPath = generateInspector(root, detected2.router);
11008
- 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}`);
11009
11143
  }
11010
11144
  console.log("");
11011
- console.log(import_chalk50.default.bold("Done. What happens next:"));
11012
- console.log(` 1. ${import_chalk50.default.cyan("npm run dev")} and use your app \u2014 it works exactly as before (all calls go direct).`);
11013
- console.log(` 2. The origins your app calls appear as ${import_chalk50.default.bold("candidates")} \u2014 list them: ${import_chalk50.default.cyan("apiblaze sidecar")}`);
11014
- 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)`);
11015
11149
  console.log(` \u2026within ~5 min your app starts routing that origin through APIblaze.`);
11016
- 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)`);
11017
- 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>\`.`));
11018
11152
  console.log("");
11019
- console.log(import_chalk50.default.dim(" Manage: apiblaze sidecar (list/approve/deny/remove)"));
11020
- console.log(import_chalk50.default.dim(" Rotate: apiblaze init --rotate \xB7 Switch team: apiblaze init --team <name>"));
11021
- 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)."));
11022
11156
  console.log("");
11023
- 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."));
11024
- 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."));
11025
11159
  }
11026
11160
 
11027
11161
  // src/commands/origins.ts
11028
- var import_chalk51 = __toESM(require("chalk"));
11162
+ var import_chalk52 = __toESM(require("chalk"));
11029
11163
  var import_ora27 = __toESM(require("ora"));
11030
11164
  init_admin();
11031
11165
  init_resolve();
@@ -11036,7 +11170,7 @@ async function runOriginsList(opts) {
11036
11170
  if (!loadCredentials()) {
11037
11171
  const cred = loadAnonCred();
11038
11172
  if (!cred) {
11039
- 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."));
11040
11174
  return;
11041
11175
  }
11042
11176
  out = await cpFetch(cred.cp_key, `/teams/${encodeURIComponent(cred.team_id)}/sidecar/candidates`, { method: "GET" });
@@ -11054,27 +11188,27 @@ async function runOriginsList(opts) {
11054
11188
  }
11055
11189
  const routed = out.routed ?? [];
11056
11190
  const candidates = out.candidates ?? [];
11057
- console.log(import_chalk51.default.bold(`
11191
+ console.log(import_chalk52.default.bold(`
11058
11192
  Routed through APIblaze (${routed.length})`));
11059
- if (!routed.length) console.log(import_chalk51.default.dim(" none yet"));
11060
- for (const r of routed) console.log(` ${import_chalk51.default.green("\u25CF")} ${r.sidecar_origin} ${import_chalk51.default.dim(`\u2192 ${r.project_id}`)}`);
11061
- 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(`
11062
11196
  Candidates \u2014 going direct, not yet approved (${candidates.length})`));
11063
- 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"));
11064
11198
  for (const c of candidates) {
11065
- 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}`)}`);
11066
11200
  }
11067
11201
  if (candidates.length) {
11068
- console.log(import_chalk51.default.dim(`
11202
+ console.log(import_chalk52.default.dim(`
11069
11203
  Approve: apiblaze sidecar approve ${candidates[0].origin.replace("https://", "")}`));
11070
- 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://", "")}`));
11071
11205
  }
11072
11206
  }
11073
11207
  async function runOriginsApprove(origin, opts) {
11074
11208
  if (!loadCredentials()) {
11075
11209
  const cred = loadAnonCred();
11076
11210
  if (!cred) {
11077
- 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."));
11078
11212
  process.exit(1);
11079
11213
  }
11080
11214
  const spinner2 = (0, import_ora27.default)(`Approving ${origin} (anonymous)...`).start();
@@ -11127,13 +11261,13 @@ async function runOriginsRemove(origin, opts) {
11127
11261
  }
11128
11262
 
11129
11263
  // src/commands/op.ts
11130
- var import_chalk53 = __toESM(require("chalk"));
11264
+ var import_chalk54 = __toESM(require("chalk"));
11131
11265
  init_auth();
11132
11266
  init_trace();
11133
11267
  init_types();
11134
11268
 
11135
11269
  // src/commands/op-billing.ts
11136
- var import_chalk52 = __toESM(require("chalk"));
11270
+ var import_chalk53 = __toESM(require("chalk"));
11137
11271
  init_admin();
11138
11272
  var SANDBOX = {
11139
11273
  teamId: "team_1782844865835_zujrf",
@@ -11192,7 +11326,7 @@ async function rowsForRays(project, version2, tenant2, rays) {
11192
11326
  }
11193
11327
  function printDoors(data) {
11194
11328
  const checks = [];
11195
- 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"));
11196
11330
  const doors = data?.doors ?? [];
11197
11331
  const metered = doors.filter((d) => d.verdict === "metered");
11198
11332
  const allowed = doors.filter((d) => d.verdict === "allowed-free");
@@ -11201,29 +11335,29 @@ function printDoors(data) {
11201
11335
  const errs = data?.errors ?? [];
11202
11336
  const routeAuditBroke = errs.some((e) => e.startsWith("zone "));
11203
11337
  const devAuditBroke = errs.some((e) => e.startsWith("workers.dev audit"));
11204
- console.log(import_chalk52.default.dim(` ${metered.length} route(s) behind main-proxy (metered)`));
11205
- for (const d of metered) console.log(import_chalk52.default.green(` \u2713 ${d.pattern}`));
11206
- 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(`
11207
11341
  ${allowed.length} route(s) free ON PURPOSE`));
11208
11342
  for (const d of allowed) {
11209
- console.log(import_chalk52.default.cyan(` \u2022 ${d.pattern}`) + import_chalk52.default.dim(` \u2192 ${d.script}`));
11210
- 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}`));
11211
11345
  }
11212
11346
  if (known.length) {
11213
- console.log(import_chalk52.default.yellow(`
11347
+ console.log(import_chalk53.default.yellow(`
11214
11348
  ${known.length} route(s) KNOWN OPEN \u2014 unmetered, not yet closed`));
11215
11349
  for (const d of known) {
11216
- console.log(import_chalk52.default.yellow(` ! ${d.pattern}`) + import_chalk52.default.dim(` \u2192 ${d.script}`));
11217
- 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}`));
11218
11352
  }
11219
11353
  checks.push({ name: "no known-open doors", status: "KNOWN", detail: `${known.length} unmetered route(s) still open \u2014 see above` });
11220
11354
  }
11221
11355
  if (stray.length) {
11222
- console.log(import_chalk52.default.red(`
11356
+ console.log(import_chalk53.default.red(`
11223
11357
  ${stray.length} STRAY route(s) \u2014 not main-proxy, not on the allowlist`));
11224
11358
  for (const d of stray) {
11225
- console.log(import_chalk52.default.red(` \u2717 ${d.pattern}`) + import_chalk52.default.dim(` \u2192 ${d.script}`));
11226
- 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}`));
11227
11361
  }
11228
11362
  checks.push({ name: "no stray routes", status: "FAIL", detail: `${stray.length}: ${stray.map((s) => s.pattern).join(", ")}` });
11229
11363
  } else if (routeAuditBroke) {
@@ -11234,22 +11368,22 @@ function printDoors(data) {
11234
11368
  const wd = data?.workers_dev ?? {};
11235
11369
  const open = wd.enabled ?? [];
11236
11370
  if (open.length) {
11237
- console.log(import_chalk52.default.red(`
11371
+ console.log(import_chalk53.default.red(`
11238
11372
  ${open.length} of ${wd.total} worker(s) reachable on *.workers.dev`));
11239
- 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})`));
11240
- 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."));
11241
11375
  checks.push({ name: "no workers.dev doors", status: "FAIL", detail: `${open.length} script(s) publicly reachable: ${open.map((s) => s.script).join(", ")}` });
11242
11376
  } else if (devAuditBroke || !wd.total) {
11243
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." });
11244
11378
  } else {
11245
- console.log(import_chalk52.default.green(`
11379
+ console.log(import_chalk53.default.green(`
11246
11380
  \u2713 0 of ${wd.total} workers reachable on *.workers.dev`));
11247
11381
  checks.push({ name: "no workers.dev doors", status: "PASS", detail: `all ${wd.total} scripts have workers.dev + previews disabled` });
11248
11382
  }
11249
- if (data?.how_to_fix) console.log(import_chalk52.default.yellow(`
11250
- ${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(`
11251
11385
  ${data.how_to_fix}`));
11252
- 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(`
11253
11387
  audit error: ${e}`));
11254
11388
  if (errs.length) {
11255
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` });
@@ -11259,9 +11393,9 @@ function printDoors(data) {
11259
11393
  async function runMeter(readLedger, opts) {
11260
11394
  const checks = [];
11261
11395
  const N = Math.max(1, Math.min(10, opts.count ?? 3));
11262
- 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"));
11263
11397
  const snap = await readLedger();
11264
- 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
11265
11399
  `));
11266
11400
  const url = `https://${dpHost}/${SANDBOX.version}/${SANDBOX.environment}/`;
11267
11401
  const headers = opts.key ? { "X-API-Key": opts.key } : {};
@@ -11343,22 +11477,22 @@ async function runMeter(readLedger, opts) {
11343
11477
  return checks;
11344
11478
  }
11345
11479
  function printChecks(checks) {
11346
- console.log(import_chalk52.default.bold("\n Results\n"));
11347
- 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") };
11348
11482
  for (const ch of checks) {
11349
- console.log(` ${mark[ch.status]} ${import_chalk52.default.bold(ch.name)}`);
11350
- 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}`));
11351
11485
  }
11352
11486
  const fails = checks.filter((c) => c.status === "FAIL").length;
11353
11487
  const skips = checks.filter((c) => c.status === "SKIP").length;
11354
11488
  const known = checks.filter((c) => c.status === "KNOWN").length;
11355
11489
  console.log("");
11356
11490
  const passes = checks.filter((c) => c.status === "PASS").length;
11357
- if (fails) console.log(import_chalk52.default.red(` ${fails} check(s) FAILED.`));
11358
- else if (passes) console.log(import_chalk52.default.green(` ${passes} check(s) passed, 0 failed.`));
11359
- else console.log(import_chalk52.default.yellow(" NOTHING WAS VERIFIED \u2014 every check was skipped."));
11360
- if (known) console.log(import_chalk52.default.yellow(` ${known} known-open issue(s) still outstanding.`));
11361
- 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.`));
11362
11496
  console.log("");
11363
11497
  }
11364
11498
 
@@ -11405,93 +11539,93 @@ var OP_COMMANDS = [
11405
11539
  function renderOpCommands() {
11406
11540
  const width = Math.max(...OP_COMMANDS.map((c) => c.cmd.length)) + 10;
11407
11541
  const lines = OP_COMMANDS.map((c) => {
11408
- const left = ` ${import_chalk53.default.cyan(`apiblaze ${c.cmd}`)}`;
11542
+ const left = ` ${import_chalk54.default.cyan(`apiblaze ${c.cmd}`)}`;
11409
11543
  const pad = " ".repeat(Math.max(1, width - c.cmd.length));
11410
- 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})`) : ""}`;
11411
11545
  });
11412
11546
  return [
11413
- import_chalk53.default.bold("Operator commands"),
11547
+ import_chalk54.default.bold("Operator commands"),
11414
11548
  ...lines,
11415
11549
  "",
11416
- import_chalk53.default.dim(" Operators only. The gate is server-side (dashboard /api/cli/op checks the"),
11417
- import_chalk53.default.dim(" signed-in email, admin-api re-checks with operatorGate) \u2014 a patched CLI just"),
11418
- 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`."),
11419
11553
  "",
11420
- import_chalk53.default.dim(" Not a CLI command: to prune all non-CP data run scripts/nuke-but-cp.sh --apply --sweep"),
11421
- import_chalk53.default.dim(" in the repo. Operator dashboards (dlq, thresholds, throttling, pricing, billing,"),
11422
- 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.")
11423
11557
  ].join("\n");
11424
11558
  }
11425
11559
  function printResidue(report, applied) {
11426
11560
  const up = report?.upstash ?? {};
11427
11561
  const fga = report?.fga ?? {};
11428
11562
  const ghosts = report?.ghosts ?? {};
11429
- console.log(import_chalk53.default.bold(applied ? "\nExternal-residue sweep" : "\nExternal residue (dry-run \u2014 nothing deleted)"));
11430
- 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"));
11431
11565
  const orphans = up.orphans ?? [];
11432
- if (orphans.length === 0) console.log(import_chalk53.default.green(" no orphaned keys"));
11433
- for (const o of orphans) console.log(` ${import_chalk53.default.yellow(o.key)} ${import_chalk53.default.dim(`\u2014 ${o.reason}`)}`);
11434
- 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}`));
11435
11569
  if (up.anon_wallet_detail) {
11436
11570
  const d = up.anon_wallet_detail;
11437
- 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)"}`));
11438
11572
  }
11439
11573
  if (up.keyspace_census) {
11440
11574
  const census = Object.entries(up.keyspace_census).map(([k, v]) => `${k}=${v}`).join(" \xB7 ");
11441
- console.log(import_chalk53.default.dim(` keyspace: ${census}`));
11575
+ console.log(import_chalk54.default.dim(` keyspace: ${census}`));
11442
11576
  }
11443
- if (up.unknown?.length) console.log(import_chalk53.default.dim(` unknown (never deleted): ${up.unknown.join(", ")}`));
11444
- if (applied) console.log(` ${import_chalk53.default.bold(String(up.deleted ?? 0))} key(s) deleted`);
11445
- for (const e of up.errors ?? []) console.log(import_chalk53.default.red(` error: ${e}`));
11446
- 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"));
11447
11581
  if (applied) {
11448
11582
  const swept = fga?.swept ?? [];
11449
- 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"));
11450
11584
  for (const s of swept) {
11451
11585
  console.log(
11452
- ` ${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`)}`
11453
11587
  );
11454
11588
  }
11455
- 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`));
11456
11590
  const st = fga?.side_tables;
11457
- 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})` : ""}`));
11458
11592
  } else {
11459
11593
  const fgaOrphans = fga?.orphans ?? [];
11460
- 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"));
11461
11595
  for (const s of fgaOrphans) {
11462
11596
  const src = s.in_openfga ? "live in OpenFGA" : "Neon tuples only";
11463
- 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)`)}`);
11464
11598
  }
11465
- 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}`));
11466
11600
  const st = fga?.side_tables;
11467
- 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`));
11468
11602
  }
11469
- for (const e of fga?.errors ?? []) console.log(import_chalk53.default.red(` error: ${e}`));
11470
- 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"));
11471
11605
  if (applied) {
11472
- if ((ghosts?.ghost_count ?? 0) === 0) console.log(import_chalk53.default.green(" no ghost tuples"));
11473
- 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)`)}`);
11474
11608
  } else {
11475
11609
  const n = ghosts?.ghost_count ?? 0;
11476
- 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)`)}`));
11477
11611
  else {
11478
- 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:`));
11479
11613
  for (const g of (ghosts.ghosts ?? []).slice(0, 20)) {
11480
- 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}`));
11481
11615
  }
11482
- 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`));
11483
11617
  }
11484
11618
  }
11485
- 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}`));
11486
11620
  console.log();
11487
11621
  }
11488
11622
  async function runOp(sub, opts = {}, view) {
11489
11623
  if (!loadCredentials()) {
11490
- 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`."));
11491
11625
  return;
11492
11626
  }
11493
11627
  if (!isOperatorLogin()) {
11494
- 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."));
11495
11629
  return;
11496
11630
  }
11497
11631
  switch (sub) {
@@ -11517,17 +11651,17 @@ async function runOp(sub, opts = {}, view) {
11517
11651
  const nSide = (st.soft_deleted_stores ?? 0) + (st.orphan_models ?? 0) + (st.orphan_changelog ?? 0);
11518
11652
  printResidue(report, false);
11519
11653
  if (nUp + nFga + nGhost + nSide === 0) {
11520
- console.log(import_chalk53.default.green("Nothing to sweep."));
11654
+ console.log(import_chalk54.default.green("Nothing to sweep."));
11521
11655
  return;
11522
11656
  }
11523
11657
  if (!opts.yes) {
11524
11658
  const readline3 = await import("readline/promises");
11525
11659
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
11526
11660
  const answer = await rl.question(
11527
- 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: `)
11528
11662
  );
11529
11663
  rl.close();
11530
- 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."));
11531
11665
  }
11532
11666
  const result = await opCall({ method: "POST", path: "/operator/external-residue/sweep", summary: "external residue sweep" });
11533
11667
  if (opts.json) return void console.log(JSON.stringify(result, null, 2));
@@ -11537,25 +11671,25 @@ async function runOp(sub, opts = {}, view) {
11537
11671
  case "mark": {
11538
11672
  const label3 = (view ?? "").trim();
11539
11673
  if (!label3) {
11540
- 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"'));
11541
11675
  return;
11542
11676
  }
11543
11677
  const res = await opCall({ method: "POST", path: "/operator/latency/mark", body: { label: label3 }, summary: "record change marker" });
11544
11678
  const ts = new Date(res?.marker?.ts ?? Date.now()).toISOString();
11545
- console.log(import_chalk53.default.green(`
11546
- Marked: `) + import_chalk53.default.bold(label3));
11547
- console.log(import_chalk53.default.dim(` ${ts}`));
11548
- 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");
11549
11683
  return;
11550
11684
  }
11551
11685
  case "credits": {
11552
11686
  const data = await opCall({ method: "GET", path: "/operator/credits", summary: "list credit wallets" });
11553
11687
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
11554
11688
  const accounts = data?.accounts ?? [];
11555
- 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."));
11556
11690
  for (const a of accounts) {
11557
11691
  const bal = typeof a.balance_cents === "number" ? `$${(a.balance_cents / 100).toFixed(2)}` : "?";
11558
- 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") : ""}`);
11559
11693
  }
11560
11694
  return;
11561
11695
  }
@@ -11566,7 +11700,7 @@ async function runOp(sub, opts = {}, view) {
11566
11700
  case "billing": {
11567
11701
  const which = (view ?? "").trim().toLowerCase();
11568
11702
  if (which && which !== "doors" && which !== "meter") {
11569
- 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.`));
11570
11704
  }
11571
11705
  const checks = [];
11572
11706
  let doorsData = null;
@@ -11627,29 +11761,29 @@ async function runOp(sub, opts = {}, view) {
11627
11761
  const data = await opCall({ method: "GET", path: `/operator/latency/grades${q}`, summary: "latency grades" });
11628
11762
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
11629
11763
  const t = data.thresholds_ms;
11630
- 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)"));
11631
- 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+
11632
11766
  `));
11633
- 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"));
11634
11768
  for (const d of data.days ?? []) {
11635
11769
  const p = d.pct;
11636
- 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)}%`);
11637
11771
  console.log(
11638
- ` ${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)}`
11639
11773
  );
11640
11774
  }
11641
11775
  const cul = data.culprits ?? [];
11642
11776
  if (cul.length) {
11643
- console.log(import_chalk53.default.bold("\n Who caused the bad and terrible ones\n"));
11644
- 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"));
11645
11779
  for (const r of cul.slice(0, 12)) {
11646
11780
  if (!r.bad && !r.terrible) continue;
11647
11781
  console.log(
11648
- ` ${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)}`
11649
11783
  );
11650
11784
  }
11651
11785
  }
11652
- if (data.caveat) console.log(import_chalk53.default.dim(`
11786
+ if (data.caveat) console.log(import_chalk54.default.dim(`
11653
11787
  \u26A0 ${data.caveat}
11654
11788
  `));
11655
11789
  return;
@@ -11658,24 +11792,24 @@ async function runOp(sub, opts = {}, view) {
11658
11792
  const data = await opCall({ method: "GET", path: `/operator/latency/compare${q}`, summary: "latency before/after" });
11659
11793
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
11660
11794
  const b = data.before, a = data.after, d = data.delta;
11661
- console.log(import_chalk53.default.bold(`
11662
- Before vs after: `) + import_chalk53.default.cyan(data.marker.label));
11663
- 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
11664
11798
  `));
11665
11799
  const row = (name, before, after, delta) => {
11666
11800
  const arrow = delta === 0 ? "=" : delta < 0 ? "\u2193" : "\u2191";
11667
11801
  const txt = `${String(before).padStart(6)}ms \u2192${String(after).padStart(7)}ms ${arrow}${Math.abs(delta)}ms`;
11668
- 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)}`);
11669
11803
  };
11670
- console.log(import_chalk53.default.dim(" metric before after change"));
11804
+ console.log(import_chalk54.default.dim(" metric before after change"));
11671
11805
  row("total p50", b.total_p50, a.total_p50, d.total_p50);
11672
11806
  row("total p95", b.total_p95, a.total_p95, d.total_p95);
11673
11807
  row("apiblaze overhead p50", b.gw_p50, a.gw_p50, d.gw_p50);
11674
11808
  row("apiblaze overhead p95", b.gw_p95, a.gw_p95, d.gw_p95);
11675
- console.log(import_chalk53.default.dim(`
11809
+ console.log(import_chalk54.default.dim(`
11676
11810
  requests: ${b.requests} before \xB7 ${a.requests} after`));
11677
11811
  for (const w of data.warnings ?? []) {
11678
- 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}`));
11679
11813
  }
11680
11814
  console.log("");
11681
11815
  return;
@@ -11684,19 +11818,19 @@ Before vs after: `) + import_chalk53.default.cyan(data.marker.label));
11684
11818
  const data = await opCall({ method: "GET", path: `/operator/latency/slow${q}`, summary: "slowest requests" });
11685
11819
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
11686
11820
  const rows2 = data?.rows ?? [];
11687
- if (!rows2.length) return void console.log(import_chalk53.default.dim("No requests over the threshold in that window."));
11688
- 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(`
11689
11823
  Slowest requests \u2014 last ${data.window_hours}h, over ${data.min_ms}ms
11690
11824
  `));
11691
- 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"));
11692
11826
  for (const r of rows2.slice(0, 30)) {
11693
11827
  console.log(
11694
- ` ${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 || "")}`
11695
11829
  );
11696
11830
  }
11697
- console.log(import_chalk53.default.dim(`
11831
+ console.log(import_chalk54.default.dim(`
11698
11832
  The last column is the request id (Cloudflare calls it a "cf-ray"). Look one up with`));
11699
- 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.
11700
11834
  `));
11701
11835
  return;
11702
11836
  }
@@ -11704,18 +11838,18 @@ Slowest requests \u2014 last ${data.window_hours}h, over ${data.min_ms}ms
11704
11838
  const data = await opCall({ method: "GET", path: `/operator/latency/llm${q}`, summary: "llm latency" });
11705
11839
  if (opts.json) return void console.log(JSON.stringify(data, null, 2));
11706
11840
  const rows2 = data?.rows ?? [];
11707
- if (!rows2.length) return void console.log(import_chalk53.default.dim("No LLM traffic in that window."));
11708
- 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(`
11709
11843
  LLM timing \u2014 last ${data.window_hours}h
11710
11844
  `));
11711
- 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"));
11712
11846
  for (const r of rows2) {
11713
11847
  const n = r.turns ?? r.requests ?? 0;
11714
11848
  console.log(
11715
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 || "-"}`
11716
11850
  );
11717
11851
  }
11718
- console.log(import_chalk53.default.dim(`
11852
+ console.log(import_chalk54.default.dim(`
11719
11853
  ${data.note}
11720
11854
  `));
11721
11855
  return;
@@ -11726,26 +11860,26 @@ LLM timing \u2014 last ${data.window_hours}h
11726
11860
  ]);
11727
11861
  if (opts.json) return void console.log(JSON.stringify({ blame, summary }, null, 2));
11728
11862
  const ov = summary?.apiblaze_overhead_ms ?? {};
11729
- console.log(import_chalk53.default.bold(`
11863
+ console.log(import_chalk54.default.bold(`
11730
11864
  Latency \u2014 last ${summary?.window_hours ?? "?"}h, ${Number(summary?.requests ?? 0).toLocaleString()} requests
11731
11865
  `));
11732
- 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")}`);
11733
- 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")}`);
11734
- 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)
11735
11869
  `));
11736
11870
  const rows = blame?.blame ?? [];
11737
- if (!rows.length) return void console.log(import_chalk53.default.dim("No latency rows in that window."));
11738
- console.log(import_chalk53.default.bold(" Which feature ate the time, and what inside it\n"));
11739
- 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"));
11740
11874
  for (const r of rows.slice(0, 15)) {
11741
11875
  const share = `${(r.share * 100).toFixed(1)}%`;
11742
- 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)}`);
11743
11877
  }
11744
11878
  console.log("");
11745
11879
  return;
11746
11880
  }
11747
11881
  default:
11748
- 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.`));
11749
11883
  }
11750
11884
  }
11751
11885
 
@@ -11808,7 +11942,7 @@ program.command("dev").description("Put your localhost behind a public URL (dev
11808
11942
  try {
11809
11943
  const resolved = parseInt(port ?? opts.port, 10);
11810
11944
  if (Number.isNaN(resolved)) {
11811
- console.error(import_chalk54.default.red(`Invalid port: ${port ?? opts.port}`));
11945
+ console.error(import_chalk55.default.red(`Invalid port: ${port ?? opts.port}`));
11812
11946
  process.exit(1);
11813
11947
  }
11814
11948
  await runDev({ port: resolved, project: opts.project, yes: opts.yes, captureFile: opts.captureFile, newSession: opts.newSession });
@@ -11841,6 +11975,7 @@ program.command("claim").description("Claim your anonymous workspace into your a
11841
11975
  process.exit(1);
11842
11976
  }
11843
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)));
11844
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)));
11845
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) => {
11846
11981
  try {
@@ -11918,7 +12053,7 @@ spec.command("set").description("Replace the stored OpenAPI spec from a local fi
11918
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)));
11919
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)));
11920
12055
  var HELP_GROUPS = [
11921
- { title: "Chat", commands: ["apichat", "agent"] },
12056
+ { title: "Chat", commands: ["docs", "apichat", "agent"] },
11922
12057
  { title: "Setup", commands: ["login", "create", "init", "sidecar", "dev", "claim", "team", "whoami", "logout"] },
11923
12058
  { title: "Recipes \u2014 install a working setup, or publish yours", commands: ["search", "show", "install", "publish", "withdraw"] },
11924
12059
  { title: "Control plane commands", commands: ["config", "projects", "logs", "tenant", "group", "admins", "iam", "identified", "preapprove", "rule", "domain", "delete", "target", "throttle", "rename", "spec", "export"] },
@@ -11941,7 +12076,7 @@ function groupedCommandHelp() {
11941
12076
  const sub = byName.get(e.parent)?.commands.find((s) => s.name() === e.sub);
11942
12077
  return sub ? ` ${helpLabel(e).padEnd(width)}${sub.description()}` : "";
11943
12078
  }).filter(Boolean).join("\n");
11944
- return `${import_chalk54.default.bold(g.title)}
12079
+ return `${import_chalk55.default.bold(g.title)}
11945
12080
  ${rows}`;
11946
12081
  }).join("\n\n");
11947
12082
  }
@@ -11952,6 +12087,8 @@ program.configureHelp({
11952
12087
  }
11953
12088
  });
11954
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
+
11955
12092
  ${groupedCommandHelp()}
11956
12093
 
11957
12094
  Tips:
@@ -11981,14 +12118,14 @@ async function recoverStaleTeam() {
11981
12118
  const { resolveLinkedTeam: resolveLinkedTeam2 } = await Promise.resolve().then(() => (init_team(), team_exports));
11982
12119
  const linked = await resolveLinkedTeam2({ preferredId: creds.teamId, interactive: !!process.stdin.isTTY });
11983
12120
  if (!linked) {
11984
- 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."));
11985
12122
  return;
11986
12123
  }
11987
12124
  if (linked.teamId === creds.teamId) return;
11988
12125
  const next = { ...creds, teamId: linked.teamId, teamName: linked.teamName };
11989
12126
  delete next.activeTenant;
11990
12127
  saveCredentials(next);
11991
- 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.`));
11992
12129
  } catch {
11993
12130
  }
11994
12131
  }
@@ -11996,16 +12133,16 @@ async function printError(err) {
11996
12133
  if (err instanceof ApiError) {
11997
12134
  const data = err.body;
11998
12135
  const extra = [data?.body?.reason, data?.body?.details, data?.details, data?.body?.error].find((x) => typeof x === "string" && x && x !== err.message);
11999
- console.error(import_chalk54.default.red(`
12136
+ console.error(import_chalk55.default.red(`
12000
12137
  API error (${err.status}): ${err.message}${extra ? ` \u2014 ${extra}` : ""}`));
12001
12138
  if (err.status === 403 || err.status === 404) {
12002
12139
  await recoverStaleTeam();
12003
12140
  }
12004
12141
  } else if (err instanceof Error) {
12005
- console.error(import_chalk54.default.red(`
12142
+ console.error(import_chalk55.default.red(`
12006
12143
  Error: ${err.message}`));
12007
12144
  } else {
12008
- console.error(import_chalk54.default.red("\nUnknown error"));
12145
+ console.error(import_chalk55.default.red("\nUnknown error"));
12009
12146
  }
12010
12147
  }
12011
12148
  program.parse(process.argv);