@delegance/cli 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -64,10 +64,10 @@ module.exports = __toCommonJS(index_exports);
64
64
 
65
65
  // src/commands/auth.ts
66
66
  var os4 = __toESM(require("os"));
67
- var import_commander2 = require("commander");
68
- var import_inquirer2 = __toESM(require("inquirer"));
67
+ var import_commander3 = require("commander");
68
+ var import_inquirer3 = __toESM(require("inquirer"));
69
69
  var import_ora2 = __toESM(require("ora"));
70
- var import_sdk3 = require("@delegance/sdk");
70
+ var import_sdk4 = require("@delegance/sdk");
71
71
 
72
72
  // src/utils/config.ts
73
73
  var import_conf = __toESM(require("conf"));
@@ -76,7 +76,7 @@ var path = __toESM(require("path"));
76
76
  var os = __toESM(require("os"));
77
77
 
78
78
  // src/version.ts
79
- var CLI_VERSION = "0.2.2";
79
+ var CLI_VERSION = "0.3.0";
80
80
 
81
81
  // src/utils/config.ts
82
82
  var CONFIG_DIR = path.join(os.homedir(), ".delegance");
@@ -542,10 +542,10 @@ function openInBrowser(url, platform = process.platform) {
542
542
 
543
543
  // src/commands/signup.ts
544
544
  var import_crypto = require("crypto");
545
- var import_commander = require("commander");
546
- var import_inquirer = __toESM(require("inquirer"));
545
+ var import_commander2 = require("commander");
546
+ var import_inquirer2 = __toESM(require("inquirer"));
547
547
  var import_ora = __toESM(require("ora"));
548
- var import_sdk2 = require("@delegance/sdk");
548
+ var import_sdk3 = require("@delegance/sdk");
549
549
 
550
550
  // src/utils/pending-signup.ts
551
551
  var fs3 = __toESM(require("fs"));
@@ -586,6 +586,82 @@ function clearPendingSignup(home) {
586
586
  }
587
587
  }
588
588
 
589
+ // src/commands/terms.ts
590
+ var import_commander = require("commander");
591
+ var import_inquirer = __toESM(require("inquirer"));
592
+ var import_sdk2 = require("@delegance/sdk");
593
+ function termsAcceptRefusal(prompted) {
594
+ if (!prompted) {
595
+ return { kind: "error", message: `No prompt to answer. Read the Terms, then run "${cliCommand("terms accept --yes")}".` };
596
+ }
597
+ return { kind: "warn", message: "Not accepted. You can still quote; binding needs the current Terms." };
598
+ }
599
+ function termsLines(t) {
600
+ return [
601
+ `Delegance Terms of Service (version ${t.version}): ${t.termsUrl}`,
602
+ `Privacy Policy: ${t.privacyUrl}`,
603
+ ...t.summaries
604
+ ];
605
+ }
606
+ async function confirmTerms(t, opts) {
607
+ termsLines(t).forEach((l) => (opts.print ?? info)(l));
608
+ if (opts.flag) return true;
609
+ if (!opts.interactive) return false;
610
+ const ask = opts.ask ?? (async () => {
611
+ const a = await import_inquirer.default.prompt([{
612
+ type: "confirm",
613
+ name: "ok",
614
+ message: "Do you accept the Terms of Service and Privacy Policy?",
615
+ default: false
616
+ }]);
617
+ return a.ok === true;
618
+ });
619
+ return ask();
620
+ }
621
+ function createTermsCommand() {
622
+ const cmd = new import_commander.Command("terms").description("Show the Delegance Terms of Service, or accept the current version").option("--json", "Output as JSON").action(async (options) => {
623
+ try {
624
+ const t = await (0, import_sdk2.createSignup)({ baseUrl: getBaseUrl() }).getTerms();
625
+ if (options.json) {
626
+ json(t);
627
+ return;
628
+ }
629
+ termsLines(t).forEach((l) => info(l));
630
+ info(`Broker review before you bind: ${t.brokerReview.command}, or email ${t.brokerReview.email}`);
631
+ } catch (err) {
632
+ failWith("Could not load the Terms", err);
633
+ }
634
+ });
635
+ cmd.command("accept").description("Accept the current Terms of Service for your account (a bind can require it)").option("-y, --yes", "Accept without the prompt (you have read the Terms)").option("--json", "Output as JSON").action(async (options) => {
636
+ const client = getClient();
637
+ try {
638
+ const t = await client.terms.get();
639
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY) && !options.json;
640
+ const ok = await confirmTerms(t, {
641
+ flag: options.yes === true,
642
+ interactive,
643
+ // --json keeps stdout to one JSON document; the Terms still print, on stderr.
644
+ ...options.json ? { print: (l) => console.error(l) } : {}
645
+ });
646
+ if (!ok) {
647
+ const refusal = termsAcceptRefusal(interactive);
648
+ if (refusal.kind === "error") error(refusal.message);
649
+ else warn(refusal.message);
650
+ process.exit(1);
651
+ }
652
+ const r = await client.terms.accept(t.version);
653
+ if (options.json) {
654
+ json(r);
655
+ return;
656
+ }
657
+ success(`Accepted the Terms of Service, version ${r.version}.`);
658
+ } catch (err) {
659
+ failWith("Could not record your acceptance", err);
660
+ }
661
+ });
662
+ return cmd;
663
+ }
664
+
589
665
  // src/commands/signup.ts
590
666
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
591
667
  var COMPANY_SIZES = ["0", "1", "2-10", "11-25", "26-50", "51-100", "100-499", "500+"];
@@ -610,8 +686,44 @@ function addressProblem(a) {
610
686
  if (!/^\d{5}(-\d{4})?$/.test(a.zip.trim())) return "ZIP must be 5 digits (or ZIP+4).";
611
687
  return null;
612
688
  }
689
+ var TERMS_REASONS = /* @__PURE__ */ new Set(["terms_not_accepted", "terms_version_outdated"]);
690
+ function isTermsRefusal(err) {
691
+ return err instanceof import_sdk3.DeleganceError && TERMS_REASONS.has(String(err.reason ?? ""));
692
+ }
693
+ async function loadSignupTerms(get) {
694
+ try {
695
+ return await get();
696
+ } catch (err) {
697
+ if (err instanceof import_sdk3.DeleganceError && err.statusCode === 404) return null;
698
+ throw err;
699
+ }
700
+ }
701
+ async function loadSignupTermsOrExit(baseUrl) {
702
+ try {
703
+ return await loadSignupTerms(() => (0, import_sdk3.createSignup)({ baseUrl }).getTerms());
704
+ } catch (err) {
705
+ failWith("Could not load the Terms of Service", err);
706
+ }
707
+ }
708
+ function nonInteractiveMissing(options, terms) {
709
+ const missing = missingSignupFields(options);
710
+ if (terms && options.acceptTerms !== true) missing.push("--accept-terms");
711
+ return missing;
712
+ }
713
+ async function acceptTermsOrExit(baseUrl, flag, preloaded) {
714
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
715
+ const terms = preloaded === void 0 ? await loadSignupTermsOrExit(baseUrl) : preloaded;
716
+ if (!terms) return "";
717
+ const ok = await confirmTerms(terms, { flag, interactive });
718
+ if (!ok) {
719
+ if (interactive) warn("Not signed up. Delegance needs your acceptance of the Terms and Privacy Policy to open an account.");
720
+ else error("No terminal to ask in. Read the Terms and Privacy Policy above, then pass --accept-terms.");
721
+ process.exit(1);
722
+ }
723
+ return terms.version;
724
+ }
613
725
  function exchangeRefusal(err) {
614
- if (!(err instanceof import_sdk2.DeleganceError)) return null;
726
+ if (!(err instanceof import_sdk3.DeleganceError)) return null;
615
727
  switch (err.reason) {
616
728
  case "account_exists":
617
729
  return `This email already has a Delegance account, so signup did not attach it to a new one. Sign in and create a key at ${PORTAL_URL}/portal/settings/api-keys`;
@@ -625,19 +737,21 @@ function exchangeRefusal(err) {
625
737
  }
626
738
  async function ensureEnrolled(pending) {
627
739
  if (pending.enrollmentId) return pending;
628
- const signup = (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl });
740
+ const signup = (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl });
629
741
  const hash = (0, import_crypto.createHash)("sha256").update(pending.deviceSecret).digest("hex");
630
742
  const enrollment = await signup.enroll(pending.bootstrapKey, {
631
743
  deviceSecretHash: hash,
632
744
  firstName: pending.firstName ?? "",
633
- lastName: pending.lastName ?? ""
745
+ lastName: pending.lastName ?? "",
746
+ termsAccepted: true,
747
+ termsVersion: pending.termsVersion ?? ""
634
748
  });
635
749
  const next = { ...pending, enrollmentId: enrollment.enrollmentId, verificationSent: false };
636
750
  savePendingSignup(next);
637
751
  return sendVerification(next);
638
752
  }
639
753
  async function sendVerification(pending) {
640
- await (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
754
+ await (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
641
755
  const next = { ...pending, verificationSent: true };
642
756
  savePendingSignup(next);
643
757
  return next;
@@ -654,7 +768,7 @@ function storeOrPrintKey(apiKey, store = storeApiKey) {
654
768
  }
655
769
  }
656
770
  async function waitAndStore(pending, timeoutMs) {
657
- const signup = (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl });
771
+ const signup = (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl });
658
772
  const spinner = (0, import_ora.default)(`Waiting for you to click the link sent to ${pending.email} (Ctrl-C is safe: resume with "${cliInvocation()} verify")`).start();
659
773
  const started = Date.now();
660
774
  try {
@@ -705,21 +819,24 @@ function signupPrompts(options, interactive) {
705
819
  return all.filter((q) => q.when !== false).map(({ when: _when, ...q }) => q);
706
820
  }
707
821
  function createSignupCommand() {
708
- return new import_commander.Command("signup").description("Create a Delegance account and get an API key, from the terminal").option("-e, --email <email>", "Your work email (the confirm link goes here)").option("-b, --business <name>", "Business name").option("--first <name>", "Your first name").option("--last <name>", "Your last name").option("-i, --industry <industry>", 'What the business does, e.g. "commercial bakery"').option("--size <size>", `Employees: ${COMPANY_SIZES.join(", ")}`).option("-w, --website <url>", "Website (full URL)").option("--street <street>", "Business street address").option("--city <city>", "City").option("--state <state>", "State, 2-letter code (carriers quote by state)").option("--zip <zip>", "ZIP code").option("-d, --description <text>", "A sentence on what the business does (helps carriers classify it)").option("--timeout <minutes>", "How long to wait for the email click", "15").option("--no-wait", 'Send the email and exit; collect later with "delegance verify"').action(async (options) => {
822
+ return new import_commander2.Command("signup").description("Create a Delegance account and get an API key, from the terminal").option("-e, --email <email>", "Your work email (the confirm link goes here)").option("-b, --business <name>", "Business name").option("--first <name>", "Your first name").option("--last <name>", "Your last name").option("-i, --industry <industry>", 'What the business does, e.g. "commercial bakery"').option("--size <size>", `Employees: ${COMPANY_SIZES.join(", ")}`).option("-w, --website <url>", "Website (full URL)").option("--street <street>", "Business street address").option("--city <city>", "City").option("--state <state>", "State, 2-letter code (carriers quote by state)").option("--zip <zip>", "ZIP code").option("-d, --description <text>", "A sentence on what the business does (helps carriers classify it)").option("--accept-terms", "Accept the Terms of Service and Privacy Policy (shown before the account is created)").option("--timeout <minutes>", "How long to wait for the email click", "15").option("--no-wait", 'Send the email and exit; collect later with "delegance verify"').action(async (options) => {
709
823
  const existing = loadPendingSignup();
710
824
  if (existing) {
711
825
  warn(`A signup for ${existing.email} is already waiting for its email confirmation.`);
712
826
  info(`Run "${cliInvocation()} verify" to finish it, or "${cliInvocation()} verify --cancel" to start over.`);
713
827
  process.exit(1);
714
828
  }
829
+ const baseUrl = getBaseUrl();
830
+ let preloadedTerms;
715
831
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
716
- const missing = missingSignupFields(options);
832
+ preloadedTerms = await loadSignupTermsOrExit(baseUrl);
833
+ const missing = nonInteractiveMissing(options, preloadedTerms);
717
834
  if (missing.length) {
718
835
  error(`No terminal to ask in. Missing: ${missing.join(" ")}`);
719
836
  process.exit(1);
720
837
  }
721
838
  }
722
- const answers = await import_inquirer.default.prompt(signupPrompts(options, Boolean(process.stdin.isTTY && process.stdout.isTTY)));
839
+ const answers = await import_inquirer2.default.prompt(signupPrompts(options, Boolean(process.stdin.isTTY && process.stdout.isTTY)));
723
840
  const address = {
724
841
  street: String(options.street ?? answers.street).trim(),
725
842
  city: String(options.city ?? answers.city).trim(),
@@ -742,8 +859,8 @@ function createSignupCommand() {
742
859
  error(`--size must be one of: ${COMPANY_SIZES.join(", ")}`);
743
860
  process.exit(1);
744
861
  }
745
- const baseUrl = getBaseUrl();
746
- const signup = (0, import_sdk2.createSignup)({ baseUrl });
862
+ const termsVersion = await acceptTermsOrExit(baseUrl, options.acceptTerms === true, preloadedTerms);
863
+ const signup = (0, import_sdk3.createSignup)({ baseUrl });
747
864
  const spinner = (0, import_ora.default)("Creating your account...").start();
748
865
  try {
749
866
  const account = await signup.createAccount({
@@ -755,7 +872,7 @@ function createSignupCommand() {
755
872
  ...description ? { description } : {},
756
873
  ...options.website ? { website: options.website } : {}
757
874
  });
758
- const device = (0, import_sdk2.newDeviceSecret)();
875
+ const device = (0, import_sdk3.newDeviceSecret)();
759
876
  let pending = {
760
877
  enrollmentId: "",
761
878
  deviceSecret: device.secret,
@@ -764,6 +881,7 @@ function createSignupCommand() {
764
881
  email,
765
882
  firstName: String(options.first ?? answers.first).trim(),
766
883
  lastName: String(options.last ?? answers.last).trim(),
884
+ termsVersion,
767
885
  baseUrl,
768
886
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
769
887
  };
@@ -785,14 +903,14 @@ function createSignupCommand() {
785
903
  });
786
904
  }
787
905
  function resendFailureMessage(err) {
788
- if (err instanceof import_sdk2.DeleganceError && (err.statusCode === 401 || err.statusCode === 403)) {
906
+ if (err instanceof import_sdk3.DeleganceError && (err.statusCode === 401 || err.statusCode === 403)) {
789
907
  return "Your email is already confirmed, so there is nothing to re-send. Collecting your key now.";
790
908
  }
791
909
  const why = err instanceof Error ? err.message : String(err);
792
910
  return `Could not re-send the email (${why}). Still waiting for the link you already have.`;
793
911
  }
794
912
  function createVerifyCommand() {
795
- return new import_commander.Command("verify").description("Finish a signup: wait for the email click and store your API key").option("--resend", "Send the confirm email again").option("--cancel", "Forget the in-progress signup on this machine").option("--timeout <minutes>", "How long to wait", "15").action(async (options) => {
913
+ return new import_commander2.Command("verify").description("Finish a signup: wait for the email click and store your API key").option("--resend", "Send the confirm email again").option("--cancel", "Forget the in-progress signup on this machine").option("--accept-terms", "Accept the Terms of Service, if this signup has not recorded an acceptance yet").option("--timeout <minutes>", "How long to wait", "15").action(async (options) => {
796
914
  const pending = loadPendingSignup();
797
915
  if (!pending) {
798
916
  info(`No signup is waiting on this machine. Start one with "${cliInvocation()} signup".`);
@@ -812,8 +930,21 @@ function createVerifyCommand() {
812
930
  failWith("Could not send the confirm email", err);
813
931
  }
814
932
  } else if (!pending.enrollmentId) {
933
+ let toEnroll = pending;
934
+ if (!pending.termsVersion) {
935
+ toEnroll = { ...pending, termsVersion: await acceptTermsOrExit(pending.baseUrl, options.acceptTerms === true) };
936
+ savePendingSignup(toEnroll);
937
+ }
815
938
  try {
816
- resumed = await ensureEnrolled(pending);
939
+ try {
940
+ resumed = await ensureEnrolled(toEnroll);
941
+ } catch (err) {
942
+ if (!isTermsRefusal(err)) throw err;
943
+ warn("The Terms of Service changed since this signup started. Review them again.");
944
+ toEnroll = { ...toEnroll, termsVersion: await acceptTermsOrExit(pending.baseUrl, options.acceptTerms === true) };
945
+ savePendingSignup(toEnroll);
946
+ resumed = await ensureEnrolled(toEnroll);
947
+ }
817
948
  success(`Finished setting up the signup. We emailed a confirm link to ${pending.email}.`);
818
949
  } catch (err) {
819
950
  failWith("Could not finish the signup", err);
@@ -821,7 +952,7 @@ function createVerifyCommand() {
821
952
  }
822
953
  if (options.resend && resumed === pending) {
823
954
  try {
824
- await (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
955
+ await (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
825
956
  success(`Sent the confirm link to ${pending.email} again.`);
826
957
  } catch (err) {
827
958
  info(resendFailureMessage(err));
@@ -852,7 +983,7 @@ function describeExpiry(expiresAt, now = /* @__PURE__ */ new Date()) {
852
983
  return `${date} (in ${days} day${days === 1 ? "" : "s"})`;
853
984
  }
854
985
  function deviceLoginRefusal(err) {
855
- if (!(err instanceof import_sdk3.DeleganceError)) return null;
986
+ if (!(err instanceof import_sdk4.DeleganceError)) return null;
856
987
  switch (err.reason) {
857
988
  case "access_denied":
858
989
  return "The request was denied in the portal. Nothing was stored.";
@@ -865,14 +996,14 @@ function deviceLoginRefusal(err) {
865
996
  }
866
997
  }
867
998
  function notAvailable(err) {
868
- return err instanceof import_sdk3.DeleganceError && (err.statusCode === 404 || err.reason === "not_available");
999
+ return err instanceof import_sdk4.DeleganceError && (err.statusCode === 404 || err.reason === "not_available");
869
1000
  }
870
1001
  function pasteFallbackHint() {
871
1002
  info(`Create a key at ${PORTAL_URL}/portal/settings/api-keys, then run "${cliInvocation()} auth login --key <key>".`);
872
1003
  }
873
1004
  async function readKeyInfo(apiKey, timeoutMs = 5e3) {
874
1005
  try {
875
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: timeoutMs, retries: 0 });
1006
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: timeoutMs, retries: 0 });
876
1007
  return await client.auth.keyInfo();
877
1008
  } catch {
878
1009
  return null;
@@ -893,7 +1024,7 @@ async function loginWithKey(apiKey, skipVerify) {
893
1024
  }
894
1025
  const spinner = (0, import_ora2.default)("Verifying API key...").start();
895
1026
  try {
896
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
1027
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
897
1028
  const isValid = await client.verifyApiKey();
898
1029
  if (!isValid) {
899
1030
  spinner.fail("API key verification failed");
@@ -914,8 +1045,8 @@ async function loginWithKey(apiKey, skipVerify) {
914
1045
  }
915
1046
  }
916
1047
  async function loginWithBrowser(openBrowser) {
917
- const login = (0, import_sdk3.createDeviceLogin)({ baseUrl: getBaseUrl() });
918
- const device = (0, import_sdk3.newDeviceSecret)();
1048
+ const login = (0, import_sdk4.createDeviceLogin)({ baseUrl: getBaseUrl() });
1049
+ const device = (0, import_sdk4.newDeviceSecret)();
919
1050
  let start;
920
1051
  try {
921
1052
  start = await login.start({ deviceSecretHash: device.hash, deviceName: defaultDeviceName() });
@@ -969,7 +1100,7 @@ async function loginWithBrowser(openBrowser) {
969
1100
  }
970
1101
  }
971
1102
  function createAuthCommand() {
972
- const auth = new import_commander2.Command("auth").description("Manage authentication");
1103
+ const auth = new import_commander3.Command("auth").description("Manage authentication");
973
1104
  auth.command("login").description("Sign in: approve this terminal in the portal, or store an API key").option("-k, --key <apiKey>", "Store this API key instead of signing in with the browser").option("--paste", "Prompt for an API key instead of signing in with the browser").option("--no-browser", "Print the approval link without opening a browser").option("--skip-verify", "With --key or --paste: store without verification (useful when API is not reachable)").action(async (options) => {
974
1105
  try {
975
1106
  if (options.key) {
@@ -977,7 +1108,7 @@ function createAuthCommand() {
977
1108
  return;
978
1109
  }
979
1110
  if (options.paste) {
980
- const answers = await import_inquirer2.default.prompt([
1111
+ const answers = await import_inquirer3.default.prompt([
981
1112
  {
982
1113
  type: "password",
983
1114
  name: "apiKey",
@@ -1012,13 +1143,13 @@ function createAuthCommand() {
1012
1143
  let origin = null;
1013
1144
  let refused = null;
1014
1145
  try {
1015
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: 5e3, retries: 0 });
1146
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: 5e3, retries: 0 });
1016
1147
  const keyInfo = await client.auth.keyInfo();
1017
1148
  origin = keyInfo.origin;
1018
1149
  expiryLine = describeExpiry(keyInfo.expiresAt);
1019
1150
  if (!fromEnv) setStoredKeyExpiry(keyInfo.expiresAt);
1020
1151
  } catch (err) {
1021
- if (err instanceof import_sdk3.DeleganceError && err.statusCode === 401) {
1152
+ if (err instanceof import_sdk4.DeleganceError && err.statusCode === 401) {
1022
1153
  refused = err.reason === "key_expired" ? "Your API key expired" : err.reason === "key_membership_revoked" ? "Your API key was revoked: its user is no longer an active member of the company" : "Your API key was rejected by the server";
1023
1154
  expiryLine = err.reason === "key_expired" ? "Expired" : "Not valid";
1024
1155
  }
@@ -1048,13 +1179,13 @@ function createAuthCommand() {
1048
1179
  }
1049
1180
  const spinner = (0, import_ora2.default)("Refreshing your key...").start();
1050
1181
  try {
1051
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
1182
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
1052
1183
  const { expiresAt } = await client.auth.refresh();
1053
1184
  if (!process.env.DELEGANCE_API_KEY) setStoredKeyExpiry(expiresAt);
1054
1185
  spinner.succeed(`Key refreshed. Expires ${describeExpiry(expiresAt)}.`);
1055
1186
  } catch (err) {
1056
1187
  spinner.stop();
1057
- if (err instanceof import_sdk3.DeleganceError && err.reason === "not_refreshable") {
1188
+ if (err instanceof import_sdk4.DeleganceError && err.reason === "not_refreshable") {
1058
1189
  info("This key came from the portal and keeps the expiry it was created with. Nothing changed.");
1059
1190
  return;
1060
1191
  }
@@ -1071,7 +1202,7 @@ function createAuthCommand() {
1071
1202
  return;
1072
1203
  }
1073
1204
  if (!options.force) {
1074
- const { confirm } = await import_inquirer2.default.prompt([
1205
+ const { confirm } = await import_inquirer3.default.prompt([
1075
1206
  {
1076
1207
  type: "confirm",
1077
1208
  name: "confirm",
@@ -1101,7 +1232,7 @@ function createAuthCommand() {
1101
1232
  }
1102
1233
  const spinner = (0, import_ora2.default)("Fetching account info...").start();
1103
1234
  try {
1104
- const client = new import_sdk3.DeleganceClient({
1235
+ const client = new import_sdk4.DeleganceClient({
1105
1236
  apiKey,
1106
1237
  baseUrl: getBaseUrl()
1107
1238
  });
@@ -1129,11 +1260,11 @@ function createAuthCommand() {
1129
1260
  }
1130
1261
 
1131
1262
  // src/commands/company.ts
1132
- var import_commander3 = require("commander");
1133
- var import_inquirer3 = __toESM(require("inquirer"));
1263
+ var import_commander4 = require("commander");
1264
+ var import_inquirer4 = __toESM(require("inquirer"));
1134
1265
  var import_ora3 = __toESM(require("ora"));
1135
1266
  function createCompanyCommand() {
1136
- const company = new import_commander3.Command("company").alias("companies").description("Manage companies");
1267
+ const company = new import_commander4.Command("company").alias("companies").description("Manage companies");
1137
1268
  company.command("list").description("List companies").option("--include-created", "Include companies created via this API key").option("--json", "Output as JSON").action(async (options) => {
1138
1269
  const client = getClient();
1139
1270
  const spinner = (0, import_ora3.default)("Fetching companies...").start();
@@ -1169,7 +1300,7 @@ function createCompanyCommand() {
1169
1300
  company.command("create").description("Create a new company").option("-n, --name <name>", "Company name").option("-i, --industry <industry>", "Industry").option("-s, --size <size>", "Company size (1, 2-10, 11-25, 26-50, 51-100, 100-499, 500+)").option("-e, --email <email>", "Contact email").option("--fein <fein>", "FEIN (XX-XXXXXXX)").option("--website <url>", "Website URL").option("--external-id <id>", "External ID for deduplication").option("--interactive", "Interactive mode with prompts").option("--json", "Output as JSON").action(async (options) => {
1170
1301
  let companyData;
1171
1302
  if (options.interactive || !options.name && !options.industry) {
1172
- const answers = await import_inquirer3.default.prompt([
1303
+ const answers = await import_inquirer4.default.prompt([
1173
1304
  {
1174
1305
  type: "input",
1175
1306
  name: "name",
@@ -1315,7 +1446,7 @@ function createCompanyCommand() {
1315
1446
  }
1316
1447
 
1317
1448
  // src/commands/document.ts
1318
- var import_commander4 = require("commander");
1449
+ var import_commander5 = require("commander");
1319
1450
  var import_ora4 = __toESM(require("ora"));
1320
1451
  var fs4 = __toESM(require("fs"));
1321
1452
  var path4 = __toESM(require("path"));
@@ -1326,7 +1457,7 @@ function extractionOutcome(status) {
1326
1457
  return "pending";
1327
1458
  }
1328
1459
  function createDocumentCommand() {
1329
- const doc = new import_commander4.Command("doc").alias("docs").alias("document").alias("documents").description("Manage documents");
1460
+ const doc = new import_commander5.Command("doc").alias("docs").alias("document").alias("documents").description("Manage documents");
1330
1461
  doc.command("upload <files...>").description("Upload one or more documents").option("-c, --company <id>", "Company ID (or use default)").option("-t, --type <type>", "Document type (policy, loss_run, financial_statement, sov, application, certificate, endorsement, bor, other)").option("--external-id <id>", "External ID for reference").option("-w, --wait", "Wait for extraction to complete").option("--timeout <ms>", "Timeout for waiting (default: 120000)", "120000").option("--json", "Output as JSON").action(async (filePatterns, options) => {
1331
1462
  const companyId = getCompanyId(options);
1332
1463
  const client = getClient();
@@ -1604,11 +1735,11 @@ function createDocumentCommand() {
1604
1735
  }
1605
1736
 
1606
1737
  // src/commands/chat.ts
1607
- var import_commander5 = require("commander");
1738
+ var import_commander6 = require("commander");
1608
1739
  var import_ora5 = __toESM(require("ora"));
1609
- var import_inquirer4 = __toESM(require("inquirer"));
1740
+ var import_inquirer5 = __toESM(require("inquirer"));
1610
1741
  function createChatCommand() {
1611
- const chat = new import_commander5.Command("ask").alias("chat").description("Ask the Orin insurance assistant a question");
1742
+ const chat = new import_commander6.Command("ask").alias("chat").description("Ask the Orin insurance assistant a question");
1612
1743
  chat.command("query <question...>").alias("q").description("Ask a single question").option("-c, --conversation <id>", "Continue a previous conversation").option("--json", "Output as JSON").action(async (questionParts, options) => {
1613
1744
  const question = questionParts.join(" ");
1614
1745
  const client = getClient();
@@ -1644,7 +1775,7 @@ function createChatCommand() {
1644
1775
  console.log('Type your questions. Enter "exit" or "quit" to end the session.');
1645
1776
  console.log();
1646
1777
  while (true) {
1647
- const { question } = await import_inquirer4.default.prompt([
1778
+ const { question } = await import_inquirer5.default.prompt([
1648
1779
  {
1649
1780
  type: "input",
1650
1781
  name: "question",
@@ -1704,18 +1835,18 @@ function createChatCommand() {
1704
1835
  }
1705
1836
 
1706
1837
  // src/commands/quote.ts
1707
- var import_commander6 = require("commander");
1838
+ var import_commander7 = require("commander");
1708
1839
  var import_ora7 = __toESM(require("ora"));
1709
- var import_inquirer6 = __toESM(require("inquirer"));
1710
- var import_sdk5 = require("@delegance/sdk");
1840
+ var import_inquirer7 = __toESM(require("inquirer"));
1841
+ var import_sdk6 = require("@delegance/sdk");
1711
1842
 
1712
1843
  // src/commands/instant-quote.ts
1713
1844
  var fs5 = __toESM(require("fs"));
1714
1845
  var import_crypto2 = require("crypto");
1715
1846
  var import_chalk2 = __toESM(require("chalk"));
1716
- var import_inquirer5 = __toESM(require("inquirer"));
1847
+ var import_inquirer6 = __toESM(require("inquirer"));
1717
1848
  var import_ora6 = __toESM(require("ora"));
1718
- var import_sdk4 = require("@delegance/sdk");
1849
+ var import_sdk5 = require("@delegance/sdk");
1719
1850
 
1720
1851
  // src/utils/coverage-names.ts
1721
1852
  var NAMES = {
@@ -2054,16 +2185,11 @@ var DEMO_STATUS = {
2054
2185
  };
2055
2186
 
2056
2187
  // src/commands/instant-quote.ts
2057
- function shellArg(value) {
2058
- return /^[\w@%+=:,./-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\\''`)}'`;
2059
- }
2060
- function activeRequestLines(err, coverageFlag, ctx = {}) {
2061
- if (!(err instanceof import_sdk4.DeleganceError) || err.statusCode !== 409 || !err.body) return null;
2188
+ function activeRequestLines(err, coverageFlag) {
2189
+ if (!(err instanceof import_sdk5.DeleganceError) || err.statusCode !== 409 || !err.body) return null;
2062
2190
  const { body } = err;
2063
2191
  const code = body.message;
2064
- const answersArg = ctx.answersFile ? ` --answers ${shellArg(ctx.answersFile)}` : "";
2065
- const requote = `${cliInvocation()} quote start --coverage ${coverageFlag}${answersArg} --replace`;
2066
- const replaceCmd = ctx.submit ? `${cliInvocation()} quote submit ${shellArg(ctx.submit.submissionId)} --session-version ${shellArg(ctx.submit.sessionVersion)} --answers ${ctx.answersFile ? shellArg(ctx.answersFile) : "<file>"} --replace` : requote;
2192
+ const requote = `${cliInvocation()} quote start --coverage ${coverageFlag} --replace`;
2067
2193
  if (code === "active_request_exists") {
2068
2194
  const active = Array.isArray(body.active) ? body.active : [];
2069
2195
  const first = active[0];
@@ -2071,7 +2197,7 @@ function activeRequestLines(err, coverageFlag, ctx = {}) {
2071
2197
  const carriers = Array.isArray(first?.carriers) ? first.carriers.map((c) => `${c.carrierId}${c.state ? ` (${c.state.toLowerCase()})` : ""}`).join(", ") : "";
2072
2198
  return [
2073
2199
  `Already with carriers${id ? `: ${id}` : ""}${carriers ? `, ${carriers}` : ""}.`,
2074
- `Check it: ${id ? `${cliInvocation()} quote status ${id}` : `${cliInvocation()} quote status <id>`} Replace it: ${replaceCmd}`
2200
+ `Check it: ${id ? `${cliInvocation()} quote status ${id}` : `${cliInvocation()} quote status <id>`} Replace it: ${requote}`
2075
2201
  ];
2076
2202
  }
2077
2203
  if (code === "replace_conflict") {
@@ -2123,7 +2249,7 @@ async function askOne(q, answers, fallback) {
2123
2249
  }
2124
2250
  };
2125
2251
  }
2126
- const { v } = await import_inquirer5.default.prompt([prompt]);
2252
+ const { v } = await import_inquirer6.default.prompt([prompt]);
2127
2253
  const c = coerceAnswer(q, v);
2128
2254
  if (c.ok && c.value !== void 0) answers[q.id] = c.value;
2129
2255
  }
@@ -2134,7 +2260,7 @@ async function askQuestions(questions, answers = {}) {
2134
2260
  const round = planQuestionRound(questions, answers, handled);
2135
2261
  if (round.confirm.length + round.checklist.length + round.ask.length === 0) break;
2136
2262
  if (round.confirm.length) {
2137
- const { keep } = await import_inquirer5.default.prompt([
2263
+ const { keep } = await import_inquirer6.default.prompt([
2138
2264
  {
2139
2265
  type: "checkbox",
2140
2266
  name: "keep",
@@ -2163,7 +2289,7 @@ async function askQuestions(questions, answers = {}) {
2163
2289
  }
2164
2290
  }
2165
2291
  if (round.checklist.length) {
2166
- const { yes } = await import_inquirer5.default.prompt([
2292
+ const { yes } = await import_inquirer6.default.prompt([
2167
2293
  {
2168
2294
  type: "checkbox",
2169
2295
  name: "yes",
@@ -2174,7 +2300,7 @@ async function askQuestions(questions, answers = {}) {
2174
2300
  ]);
2175
2301
  const yn = checklistAnswers(round.checklist, yes);
2176
2302
  const yesCount = Object.values(yn).filter((v) => v === "yes").length;
2177
- const { ok } = await import_inquirer5.default.prompt([
2303
+ const { ok } = await import_inquirer6.default.prompt([
2178
2304
  { type: "confirm", name: "ok", message: `Yes to ${yesCount}, No to ${round.checklist.length - yesCount}. Correct?`, default: true }
2179
2305
  ]);
2180
2306
  if (ok) {
@@ -2208,7 +2334,7 @@ async function runBrokerHandoff(submissionId, instantAnswers, opts) {
2208
2334
  try {
2209
2335
  plan = await client.instantQuotes.brokerHandoffQuestions(submissionId, instantAnswers);
2210
2336
  } catch (err) {
2211
- if (err instanceof import_sdk4.DeleganceError && err.statusCode === 503) {
2337
+ if (err instanceof import_sdk5.DeleganceError && err.statusCode === 503) {
2212
2338
  say("A broker can still market it: reply to the confirmation email, or start in the portal.");
2213
2339
  return;
2214
2340
  }
@@ -2474,7 +2600,7 @@ function addInstantQuoteCommands(quote) {
2474
2600
  ...options.replace ? { replace: true } : {}
2475
2601
  });
2476
2602
  } catch (err) {
2477
- const guardLines = activeRequestLines(err, String(options.coverage), { answersFile: options.answers });
2603
+ const guardLines = activeRequestLines(err, String(options.coverage));
2478
2604
  if (guardLines) {
2479
2605
  submitSpinner.fail("Nothing was sent.");
2480
2606
  guardLines.forEach((l) => options.json ? console.error(l) : info(l));
@@ -2542,10 +2668,7 @@ function addInstantQuoteCommands(quote) {
2542
2668
  }
2543
2669
  await waitAndPrint(submissionId, Number(options.timeout) * 6e4 || 6e5, !!options.json);
2544
2670
  } catch (err) {
2545
- const guardLines = activeRequestLines(err, "<list>", {
2546
- answersFile: options.answers,
2547
- submit: { submissionId, sessionVersion: String(options.sessionVersion) }
2548
- });
2671
+ const guardLines = activeRequestLines(err, "<list>");
2549
2672
  if (guardLines) {
2550
2673
  error("Nothing was sent.");
2551
2674
  guardLines.forEach((l) => options.json ? console.error(l) : info(l));
@@ -2597,7 +2720,7 @@ async function waitAndPrint(submissionId, timeoutMs, asJson) {
2597
2720
  // src/commands/quote.ts
2598
2721
  var QUOTE_SUBMISSION_UNAVAILABLE = "Quote submission via API isn't available yet";
2599
2722
  function createQuoteCommand() {
2600
- const quote = new import_commander6.Command("quote").alias("quotes").description("Request and manage insurance quotes");
2723
+ const quote = new import_commander7.Command("quote").alias("quotes").description("Request and manage insurance quotes");
2601
2724
  quote.command("carriers").description("List available carriers for quoting").option("--json", "Output as JSON").action(async (options) => {
2602
2725
  const client = getClient();
2603
2726
  const spinner = (0, import_ora7.default)("Fetching carriers...").start();
@@ -2644,7 +2767,7 @@ function createQuoteCommand() {
2644
2767
  process.exit(1);
2645
2768
  }
2646
2769
  if (options.interactive || carrierIds.length === 0 && !options.all) {
2647
- const { selectedCarriers } = await import_inquirer6.default.prompt([
2770
+ const { selectedCarriers } = await import_inquirer7.default.prompt([
2648
2771
  {
2649
2772
  type: "checkbox",
2650
2773
  name: "selectedCarriers",
@@ -2704,7 +2827,7 @@ function createQuoteCommand() {
2704
2827
  }
2705
2828
  } catch (err) {
2706
2829
  spinner.fail("Failed to submit quote request");
2707
- if (err instanceof import_sdk5.NotImplementedError) {
2830
+ if (err instanceof import_sdk6.NotImplementedError) {
2708
2831
  error(QUOTE_SUBMISSION_UNAVAILABLE);
2709
2832
  info(`For an instant quote from the terminal: ${cliInvocation()} quote start --coverage gl`);
2710
2833
  info(`Or start a quote at ${PORTAL_URL}`);
@@ -2837,11 +2960,11 @@ function formatQuoteStatus(status) {
2837
2960
  }
2838
2961
 
2839
2962
  // src/commands/policy.ts
2840
- var import_commander7 = require("commander");
2841
- var import_inquirer7 = __toESM(require("inquirer"));
2963
+ var import_commander8 = require("commander");
2964
+ var import_inquirer8 = __toESM(require("inquirer"));
2842
2965
  var import_ora8 = __toESM(require("ora"));
2843
2966
  function createPolicyCommand() {
2844
- const policy = new import_commander7.Command("policy").alias("policies").description("Manage insurance policies");
2967
+ const policy = new import_commander8.Command("policy").alias("policies").description("Manage insurance policies");
2845
2968
  policy.command("list").alias("ls").description("List all policies").option("-s, --status <status>", "Filter by status (active, expired, all)", "active").option("-t, --type <type>", "Filter by policy type").option("-l, --limit <n>", "Maximum results", "50").option("--json", "Output as JSON").action(async (options) => {
2846
2969
  const client = getClient();
2847
2970
  const spinner = (0, import_ora8.default)("Fetching policies...").start();
@@ -3093,7 +3216,7 @@ async function signWithStepUp(client, requestId, sig, stepUpId, presetCode) {
3093
3216
  warn(`No terminal to type the code in. Finish with: ${cliInvocation()} policy sign ${requestId} --signer-name "${sig.signerName}" --signer-title "${sig.signerTitle}" --attest --step-up ${id} --code <code>`);
3094
3217
  return;
3095
3218
  }
3096
- const answer = await import_inquirer7.default.prompt([{
3219
+ const answer = await import_inquirer8.default.prompt([{
3097
3220
  type: "input",
3098
3221
  name: "code",
3099
3222
  message: "Code from your email:",
@@ -3120,11 +3243,11 @@ function formatPolicyStatus(isActive, daysUntilExpiry) {
3120
3243
  }
3121
3244
 
3122
3245
  // src/commands/coi.ts
3123
- var import_commander8 = require("commander");
3246
+ var import_commander9 = require("commander");
3124
3247
  var import_ora9 = __toESM(require("ora"));
3125
- var import_inquirer8 = __toESM(require("inquirer"));
3248
+ var import_inquirer9 = __toESM(require("inquirer"));
3126
3249
  function createCOICommand() {
3127
- const coi = new import_commander8.Command("coi").description("Generate and manage Certificates of Insurance");
3250
+ const coi = new import_commander9.Command("coi").description("Generate and manage Certificates of Insurance");
3128
3251
  coi.command("generate").alias("create").description("Generate a Certificate of Insurance").option("-p, --policies <ids...>", "Policy IDs to include").option("-n, --holder-name <name>", "Certificate holder name").option("-a, --holder-address <address>", "Certificate holder address").option("--city <city>", "Certificate holder city").option("--state <state>", "Certificate holder state (2-letter)").option("--zip <zip>", "Certificate holder ZIP").option("-t, --type <type>", "Certificate type (additional_insured, certificate_holder)", "certificate_holder").option("-i, --interactive", "Interactive mode").option("--json", "Output as JSON").action(async (options) => {
3129
3252
  const client = getClient();
3130
3253
  let policyIds = options.policies || [];
@@ -3143,7 +3266,7 @@ function createCOICommand() {
3143
3266
  info(`Upload policy documents first with "${cliInvocation()} doc upload"`);
3144
3267
  process.exit(1);
3145
3268
  }
3146
- const answers = await import_inquirer8.default.prompt([
3269
+ const answers = await import_inquirer9.default.prompt([
3147
3270
  {
3148
3271
  type: "checkbox",
3149
3272
  name: "selectedPolicies",
@@ -3279,12 +3402,12 @@ function createCOICommand() {
3279
3402
  }
3280
3403
 
3281
3404
  // src/commands/sov.ts
3282
- var import_commander9 = require("commander");
3405
+ var import_commander10 = require("commander");
3283
3406
  var import_ora10 = __toESM(require("ora"));
3284
3407
  var import_fs = __toESM(require("fs"));
3285
3408
  var import_path = __toESM(require("path"));
3286
3409
  function createSOVCommand() {
3287
- const sov = new import_commander9.Command("sov").description("Manage Schedules of Values (property schedules)");
3410
+ const sov = new import_commander10.Command("sov").description("Manage Schedules of Values (property schedules)");
3288
3411
  sov.command("upload <file>").description("Upload a Schedule of Values file").option("-l, --line <line>", "Line of business (property, inland_marine, etc)", "property").option("--effective <date>", "Effective date (YYYY-MM-DD)").option("--expiration <date>", "Expiration date (YYYY-MM-DD)").option("-w, --wait", "Wait for parsing to complete").option("--json", "Output as JSON").action(async (file, options) => {
3289
3412
  const client = getClient();
3290
3413
  const filePath = import_path.default.resolve(file);
@@ -3442,7 +3565,7 @@ function showSOVDetails(s) {
3442
3565
  }
3443
3566
 
3444
3567
  // src/commands/appetite.ts
3445
- var import_commander10 = require("commander");
3568
+ var import_commander11 = require("commander");
3446
3569
  var import_ora11 = __toESM(require("ora"));
3447
3570
  function num(value) {
3448
3571
  if (value === void 0) return void 0;
@@ -3490,7 +3613,7 @@ function printResult(result) {
3490
3613
  for (const w of result.warnings) warn(w);
3491
3614
  }
3492
3615
  function createAppetiteCommand() {
3493
- const appetite = new import_commander10.Command("appetite").description("Check which carriers will write a risk");
3616
+ const appetite = new import_commander11.Command("appetite").description("Check which carriers will write a risk");
3494
3617
  appetite.command("match").description("Match a business to carrier appetite").requiredOption("-s, --state <state>", "Two-letter state code").option("-i, --industry <industry>", 'Industry, e.g. "bakery"').option("-d, --description <text>", "What the business does").option("--naics <code>", "NAICS code").option("--sic <code>", "SIC code").option("-c, --coverage <types>", "Comma-separated coverage types, e.g. general_liability,workers_comp").option("--carriers <names>", "Comma-separated carriers to limit the match to").option("--market-size <size>", '"Small Business" or "Middle Market"').option("--revenue <usd>", "Annual revenue").option("--payroll <usd>", "Annual payroll").option("--property-value <usd>", "Total property value").option("--min-fit <fit>", "Raise the quality floor: possible or strong").option("--top <n>", "Maximum matches (1-50)").option("--no-wait", "Return the job id instead of waiting for a cold match").option("--timeout <ms>", "How long to wait for a cold match", "120000").option("--json", "Output as JSON").action(async (options) => {
3495
3618
  const input = buildMatchInput(options);
3496
3619
  const timeoutMs = positiveInt(options.timeout, "--timeout");
@@ -3551,7 +3674,7 @@ function createAppetiteCommand() {
3551
3674
  }
3552
3675
 
3553
3676
  // src/commands/lead.ts
3554
- var import_commander11 = require("commander");
3677
+ var import_commander12 = require("commander");
3555
3678
  var import_ora12 = __toESM(require("ora"));
3556
3679
  function buildLeadInput(options) {
3557
3680
  const input = {
@@ -3582,7 +3705,7 @@ function buildLeadInput(options) {
3582
3705
  return input;
3583
3706
  }
3584
3707
  function createLeadCommand() {
3585
- const lead = new import_commander11.Command("lead").alias("leads").description("Send prospect businesses to Delegance");
3708
+ const lead = new import_commander12.Command("lead").alias("leads").description("Send prospect businesses to Delegance");
3586
3709
  lead.command("create").description("Create a lead (idempotent on --external-id and contact email)").requiredOption("-n, --name <name>", "Business name").requiredOption("-e, --email <email>", "Contact email").option("--legal-name <name>", "Legal name, if different").option("-i, --industry <industry>", "Industry").option("-p, --phone <phone>", "Contact phone").option("-w, --website <url>", "Website (full URL)").option("--size <size>", "Company size").option("-d, --description <text>", "What the business does").option("--naics <code>", "NAICS code").option("--sic <code>", "SIC code").option("-s, --state <state>", "Two-letter state code").option("--street <street>", "Street address").option("--suite <suite>", "Suite").option("--city <city>", "City").option("--address-state <state>", "Address state (defaults to --state)").option("--zip <zip>", "ZIP code").option("--external-id <id>", "Your id for this lead").option("--source <source>", "Lead source label").option("--notes <notes>", "Notes for the broker").option("--json", "Output as JSON").action(async (options) => {
3587
3710
  const input = buildLeadInput(options);
3588
3711
  if (input.address && (!input.address.street || !input.address.city || !input.address.state || !input.address.zip)) {
@@ -3605,11 +3728,11 @@ function createLeadCommand() {
3605
3728
  }
3606
3729
 
3607
3730
  // src/commands/knowledge.ts
3608
- var import_commander12 = require("commander");
3731
+ var import_commander13 = require("commander");
3609
3732
  var import_ora13 = __toESM(require("ora"));
3610
3733
  var SEARCH_TYPES = ["notecard", "document_chunk"];
3611
3734
  function createKnowledgeCommand() {
3612
- const knowledge = new import_commander12.Command("knowledge").alias("kb").description("Search notecards and document facts");
3735
+ const knowledge = new import_commander13.Command("knowledge").alias("kb").description("Search notecards and document facts");
3613
3736
  knowledge.command("search <query...>").description("Search notecards and document text").option("-t, --type <type>", `Limit to one result type (${SEARCH_TYPES.join(", ")})`).option("-l, --limit <n>", "Maximum results", "10").option("--json", "Output as JSON").action(async (queryParts, options) => {
3614
3737
  const client = getClient();
3615
3738
  const query = queryParts.join(" ");
@@ -3711,7 +3834,7 @@ function createKnowledgeCommand() {
3711
3834
  }
3712
3835
 
3713
3836
  // src/commands/onboarding.ts
3714
- var import_commander13 = require("commander");
3837
+ var import_commander14 = require("commander");
3715
3838
  var import_ora14 = __toESM(require("ora"));
3716
3839
  var ONBOARDING_STATES = [
3717
3840
  "created",
@@ -3721,7 +3844,7 @@ var ONBOARDING_STATES = [
3721
3844
  "ready"
3722
3845
  ];
3723
3846
  function createOnboardingCommand() {
3724
- const onboarding = new import_commander13.Command("onboarding").alias("onboard").description("Check account setup and onboarding state");
3847
+ const onboarding = new import_commander14.Command("onboarding").alias("onboard").description("Check account setup and onboarding state");
3725
3848
  onboarding.command("status").description("Show the setup checklist and the next step").option("--json", "Output as JSON").action(async (options) => {
3726
3849
  const client = getClient();
3727
3850
  const spinner = (0, import_ora14.default)("Fetching onboarding status...").start();
@@ -3812,7 +3935,7 @@ function createOnboardingCommand() {
3812
3935
  }
3813
3936
 
3814
3937
  // src/commands/usage.ts
3815
- var import_commander14 = require("commander");
3938
+ var import_commander15 = require("commander");
3816
3939
  var import_ora15 = __toESM(require("ora"));
3817
3940
  function isoDay(daysAgo, now = /* @__PURE__ */ new Date()) {
3818
3941
  const d = new Date(now.getTime() - daysAgo * 24 * 60 * 60 * 1e3);
@@ -3822,7 +3945,7 @@ function cents(n) {
3822
3945
  return `$${(n / 100).toFixed(2)}`;
3823
3946
  }
3824
3947
  function createUsageCommand() {
3825
- const usage = new import_commander14.Command("usage").description("Show API usage, billing, and rate limits");
3948
+ const usage = new import_commander15.Command("usage").description("Show API usage, billing, and rate limits");
3826
3949
  usage.command("summary").description("Usage for the current billing period").option("--json", "Output as JSON").action(async (options) => {
3827
3950
  const client = getClient();
3828
3951
  const spinner = (0, import_ora15.default)("Fetching usage summary...").start();
@@ -3902,10 +4025,10 @@ function createUsageCommand() {
3902
4025
  }
3903
4026
 
3904
4027
  // src/commands/keys.ts
3905
- var import_commander15 = require("commander");
4028
+ var import_commander16 = require("commander");
3906
4029
  var import_ora16 = __toESM(require("ora"));
3907
4030
  var import_crypto3 = require("crypto");
3908
- var import_sdk6 = require("@delegance/sdk");
4031
+ var import_sdk7 = require("@delegance/sdk");
3909
4032
  var KEYS_PORTAL_URL = `${PORTAL_URL}/portal/settings/api-keys`;
3910
4033
  function parseExpiresInDays(raw) {
3911
4034
  if (raw === void 0 || raw === "") return void 0;
@@ -3914,9 +4037,9 @@ function parseExpiresInDays(raw) {
3914
4037
  }
3915
4038
  function parseScopes(raw) {
3916
4039
  const parts = (Array.isArray(raw) ? raw : [raw ?? "read,write"]).flatMap((p) => p.split(/[\s,]+/)).map((p) => p.trim()).filter(Boolean);
3917
- const unknown = parts.filter((p) => !import_sdk6.API_KEY_SCOPES.includes(p));
4040
+ const unknown = parts.filter((p) => !import_sdk7.API_KEY_SCOPES.includes(p));
3918
4041
  if (unknown.length > 0) {
3919
- throw new Error(`Unknown scope(s): ${unknown.join(", ")}. Allowed: ${import_sdk6.API_KEY_SCOPES.join(", ")}`);
4042
+ throw new Error(`Unknown scope(s): ${unknown.join(", ")}. Allowed: ${import_sdk7.API_KEY_SCOPES.join(", ")}`);
3920
4043
  }
3921
4044
  return Array.from(new Set(parts));
3922
4045
  }
@@ -3945,7 +4068,7 @@ function printCreatedKey(created) {
3945
4068
  console.log(` ${created.key}`);
3946
4069
  }
3947
4070
  function createKeysCommand() {
3948
- const keys = new import_commander15.Command("keys").alias("api-keys").description("Manage API keys");
4071
+ const keys = new import_commander16.Command("keys").alias("api-keys").description("Manage API keys");
3949
4072
  keys.command("list").alias("ls").description("List API keys for your company").option("-l, --limit <n>", "Maximum results", "50").option("--cursor <cursor>", "Page cursor from a previous list").option("--json", "Output as JSON").action(async (options) => {
3950
4073
  const client = getClient();
3951
4074
  const spinner = (0, import_ora16.default)("Fetching API keys...").start();
@@ -3981,7 +4104,7 @@ function createKeysCommand() {
3981
4104
  failWith("API error", err);
3982
4105
  }
3983
4106
  });
3984
- keys.command("create <name>").description("Create an API key (needs a key with the admin scope)").option("-s, --scopes <scopes>", `Comma-separated scopes (${import_sdk6.API_KEY_SCOPES.join(", ")})`, "read,write").option("-e, --expires-in-days <days>", 'Expire the key after N days (1-365; default 90), or "never" for a read-only key').option("--json", "Output as JSON").action(async (name, options) => {
4107
+ keys.command("create <name>").description("Create an API key (needs a key with the admin scope)").option("-s, --scopes <scopes>", `Comma-separated scopes (${import_sdk7.API_KEY_SCOPES.join(", ")})`, "read,write").option("-e, --expires-in-days <days>", 'Expire the key after N days (1-365; default 90), or "never" for a read-only key').option("--json", "Output as JSON").action(async (name, options) => {
3985
4108
  let scopes;
3986
4109
  try {
3987
4110
  scopes = parseScopes(options.scopes);
@@ -4060,7 +4183,7 @@ function createKeysCommand() {
4060
4183
  spinner.succeed("API key revoked");
4061
4184
  } catch (err) {
4062
4185
  spinner.fail("Failed to revoke API key");
4063
- if (err instanceof import_sdk6.AuthenticationError) {
4186
+ if (err instanceof import_sdk7.AuthenticationError) {
4064
4187
  error("Revoking a key needs a signed-in portal session today");
4065
4188
  info(`Revoke it at ${KEYS_PORTAL_URL}`);
4066
4189
  process.exit(1);
@@ -4072,10 +4195,10 @@ function createKeysCommand() {
4072
4195
  }
4073
4196
 
4074
4197
  // src/commands/config.ts
4075
- var import_commander16 = require("commander");
4076
- var import_inquirer9 = __toESM(require("inquirer"));
4198
+ var import_commander17 = require("commander");
4199
+ var import_inquirer10 = __toESM(require("inquirer"));
4077
4200
  function createConfigCommand() {
4078
- const config2 = new import_commander16.Command("config").description("Manage CLI configuration");
4201
+ const config2 = new import_commander17.Command("config").description("Manage CLI configuration");
4079
4202
  config2.command("show").alias("list").description("Show current configuration").option("--json", "Output as JSON").action((options) => {
4080
4203
  const currentConfig = getConfig();
4081
4204
  const apiKey = getApiKey();
@@ -4119,7 +4242,7 @@ function createConfigCommand() {
4119
4242
  });
4120
4243
  config2.command("reset").description("Reset all configuration to defaults").option("-f, --force", "Skip confirmation").action(async (options) => {
4121
4244
  if (!options.force) {
4122
- const { confirm } = await import_inquirer9.default.prompt([
4245
+ const { confirm } = await import_inquirer10.default.prompt([
4123
4246
  {
4124
4247
  type: "confirm",
4125
4248
  name: "confirm",
@@ -4204,12 +4327,12 @@ function createConfigCommand() {
4204
4327
  }
4205
4328
 
4206
4329
  // src/program.ts
4207
- var import_commander19 = require("commander");
4330
+ var import_commander20 = require("commander");
4208
4331
 
4209
4332
  // src/commands/feedback.ts
4210
- var import_commander17 = require("commander");
4211
- var import_inquirer10 = __toESM(require("inquirer"));
4212
- var import_sdk7 = require("@delegance/sdk");
4333
+ var import_commander18 = require("commander");
4334
+ var import_inquirer11 = __toESM(require("inquirer"));
4335
+ var import_sdk8 = require("@delegance/sdk");
4213
4336
  var TYPES = ["bug", "idea", "question"];
4214
4337
  var MESSAGE_MAX = 500;
4215
4338
  var USAGE = `${cliInvocation()} feedback "what happened" [--type bug|idea|question] [--include-last]`;
@@ -4226,7 +4349,7 @@ function buildFeedbackContext(last) {
4226
4349
  ctx.at = last.at;
4227
4350
  }
4228
4351
  ctx.cliVersion = CLI_VERSION;
4229
- ctx.sdkVersion = import_sdk7.SDK_VERSION;
4352
+ ctx.sdkVersion = import_sdk8.SDK_VERSION;
4230
4353
  return ctx;
4231
4354
  }
4232
4355
  function usageError(message) {
@@ -4235,14 +4358,14 @@ function usageError(message) {
4235
4358
  process.exit(2);
4236
4359
  }
4237
4360
  function createFeedbackCommand() {
4238
- return new import_commander17.Command("feedback").alias("bug").description("Report a bug, an idea, or a question to Delegance").argument("[message...]", "What happened (asked for when left out on a terminal)").option("-t, --type <type>", "bug, idea, or question", "bug").option("--include-last", "Attach the last command name, exit code, trace id, and CLI/SDK versions (never its arguments)").option("--json", "Output as JSON").action(async (words, options) => {
4361
+ return new import_commander18.Command("feedback").alias("bug").description("Report a bug, an idea, or a question to Delegance").argument("[message...]", "What happened (asked for when left out on a terminal)").option("-t, --type <type>", "bug, idea, or question", "bug").option("--include-last", "Attach the last command name, exit code, trace id, and CLI/SDK versions (never its arguments)").option("--json", "Output as JSON").action(async (words, options) => {
4239
4362
  const type = String(options.type ?? "bug").toLowerCase();
4240
4363
  if (!TYPES.includes(type)) usageError(`--type must be bug, idea, or question, got "${options.type}"`);
4241
4364
  let message = (words ?? []).join(" ").trim();
4242
4365
  const mode = feedbackInputMode({ message, isTTY: Boolean(process.stdin.isTTY && process.stdout.isTTY) });
4243
4366
  if (mode === "usage_error") usageError(`Say what happened: ${USAGE}`);
4244
4367
  if (mode === "prompt") {
4245
- const answer = await import_inquirer10.default.prompt([
4368
+ const answer = await import_inquirer11.default.prompt([
4246
4369
  { type: "input", name: "message", message: type === "bug" ? "What went wrong?" : "What would you like to tell us?" }
4247
4370
  ]);
4248
4371
  message = String(answer.message ?? "").trim();
@@ -4264,7 +4387,7 @@ function createFeedbackCommand() {
4264
4387
  }
4265
4388
 
4266
4389
  // src/utils/checkbox-prompt.ts
4267
- var import_inquirer11 = __toESM(require("inquirer"));
4390
+ var import_inquirer12 = __toESM(require("inquirer"));
4268
4391
  var import_chalk3 = __toESM(require("chalk"));
4269
4392
  var CHECKBOX_HINT = "(space to select, Enter to continue)";
4270
4393
  var registered = false;
@@ -4286,19 +4409,19 @@ function minimalCheckboxPrompt(Base) {
4286
4409
  }
4287
4410
  function registerMinimalCheckbox() {
4288
4411
  if (registered) return;
4289
- const prompts = import_inquirer11.default.prompt.prompts;
4412
+ const prompts = import_inquirer12.default.prompt.prompts;
4290
4413
  const Base = prompts?.checkbox;
4291
4414
  if (!Base) return;
4292
- import_inquirer11.default.registerPrompt("checkbox", minimalCheckboxPrompt(Base));
4415
+ import_inquirer12.default.registerPrompt("checkbox", minimalCheckboxPrompt(Base));
4293
4416
  registered = true;
4294
4417
  }
4295
4418
 
4296
4419
  // src/commands/commerce.ts
4297
- var import_commander18 = require("commander");
4420
+ var import_commander19 = require("commander");
4298
4421
  var fs7 = __toESM(require("fs"));
4299
- var import_inquirer12 = __toESM(require("inquirer"));
4422
+ var import_inquirer13 = __toESM(require("inquirer"));
4300
4423
  var import_ora17 = __toESM(require("ora"));
4301
- var import_sdk8 = require("@delegance/sdk");
4424
+ var import_sdk9 = require("@delegance/sdk");
4302
4425
  function formatCents(cents2, currency = "usd") {
4303
4426
  return currency.toLowerCase() === "usd" ? formatCurrency(cents2 / 100) : `${(cents2 / 100).toFixed(2)} ${currency.toUpperCase()}`;
4304
4427
  }
@@ -4324,6 +4447,35 @@ function describeBindResult(r) {
4324
4447
  lines.push(r.next);
4325
4448
  return lines;
4326
4449
  }
4450
+ var BROKER_REVIEW_EMAIL = "support@delegancebrokerage.com";
4451
+ function selfDirectedAckLines(submissionId, offerId) {
4452
+ return [
4453
+ "This is a self-directed placement: Delegance binds the coverage you chose and does not advise on whether it fits your needs (Terms Section 9A).",
4454
+ `Want a licensed broker to review it first? Run: ${cliInvocation()} bind ${submissionId} ${offerId} --broker-review`
4455
+ ];
4456
+ }
4457
+ function brokerReviewMailto(submissionId, offerId) {
4458
+ const subject = encodeURIComponent(`Broker review before bind: submission ${submissionId}, offer ${offerId}`);
4459
+ return `mailto:${BROKER_REVIEW_EMAIL}?subject=${subject}`;
4460
+ }
4461
+ function brokerReviewLines(submissionId, offerId) {
4462
+ return [
4463
+ "Nothing was bound, and no review has been requested yet.",
4464
+ `To request a review by a licensed Delegance broker, send an email to ${BROKER_REVIEW_EMAIL}`,
4465
+ `naming submission ${submissionId} and offer ${offerId}: ${brokerReviewMailto(submissionId, offerId)}`,
4466
+ "Wait for the broker to reply before you bind. A reviewed placement is not self-directed."
4467
+ ];
4468
+ }
4469
+ function brokerReviewResult(submissionId, offerId) {
4470
+ return {
4471
+ bound: false,
4472
+ reviewRequested: false,
4473
+ submissionId,
4474
+ offerId,
4475
+ brokerReview: { email: BROKER_REVIEW_EMAIL, mailto: brokerReviewMailto(submissionId, offerId) },
4476
+ message: brokerReviewLines(submissionId, offerId)
4477
+ };
4478
+ }
4327
4479
  function exactDollars(cents2) {
4328
4480
  return `$${(cents2 / 100).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
4329
4481
  }
@@ -4346,7 +4498,7 @@ function describeFinancing(f) {
4346
4498
  }
4347
4499
  async function askCode() {
4348
4500
  if (!process.stdin.isTTY) return null;
4349
- const answer = await import_inquirer12.default.prompt([{
4501
+ const answer = await import_inquirer13.default.prompt([{
4350
4502
  type: "input",
4351
4503
  name: "code",
4352
4504
  message: "Code from your email:",
@@ -4355,11 +4507,19 @@ async function askCode() {
4355
4507
  return String(answer.code).trim();
4356
4508
  }
4357
4509
  function createBindCommand() {
4358
- return new import_commander18.Command("bind").description('Bind one offer from "quote status": the carrier checkout when the carrier offers it, otherwise a broker review').argument("<submissionId>", "The quote submission id").argument("<offerId>", "The offer id from the quote table").option("--attest", "Confirm the application answers are accurate (asked interactively when omitted)").option("--step-up <id>", "Finish an earlier attempt: the stepUpId the code email belongs to").option("--code <code>", "The 6-digit code from the email").option("--json", "Output as JSON").action(async (submissionId, offerId, options) => {
4510
+ return new import_commander19.Command("bind").description('Bind one offer from "quote status": the carrier checkout when the carrier offers it, otherwise a broker review').argument("<submissionId>", "The quote submission id").argument("<offerId>", "The offer id from the quote table").option("--attest", "Confirm the application answers are accurate (asked interactively when omitted)").option("--broker-review", "Do not bind; ask a licensed broker to review this coverage first").option("--step-up <id>", "Finish an earlier attempt: the stepUpId the code email belongs to").option("--code <code>", "The 6-digit code from the email").option("--json", "Output as JSON").action(async (submissionId, offerId, options) => {
4511
+ if (options.brokerReview) {
4512
+ if (options.json) json(brokerReviewResult(submissionId, offerId));
4513
+ else brokerReviewLines(submissionId, offerId).forEach((l) => info(l));
4514
+ return;
4515
+ }
4359
4516
  const client = getClient();
4517
+ const ack = selfDirectedAckLines(submissionId, offerId);
4518
+ if (options.json) ack.forEach((l) => console.error(l));
4519
+ else ack.forEach((l) => info(l));
4360
4520
  let attest = options.attest === true;
4361
4521
  if (!attest && process.stdin.isTTY && !options.json) {
4362
- const a = await import_inquirer12.default.prompt([{
4522
+ const a = await import_inquirer13.default.prompt([{
4363
4523
  type: "confirm",
4364
4524
  name: "ok",
4365
4525
  message: "Are the answers on this application accurate? Binding relies on them.",
@@ -4393,7 +4553,7 @@ function createBindCommand() {
4393
4553
  }
4394
4554
  }
4395
4555
  if (options.json) {
4396
- json(r);
4556
+ json({ ...r, selfDirected: true, disclosure: ack[0] });
4397
4557
  return;
4398
4558
  }
4399
4559
  if (r.existing) warn(`A bind for this coverage is already open (${r.carrierName}). Showing it.`);
@@ -4403,7 +4563,7 @@ function createBindCommand() {
4403
4563
  describeFinancing(r.financing).forEach((l) => info(l));
4404
4564
  } catch (err) {
4405
4565
  spinner?.stop();
4406
- if (err instanceof import_sdk8.DeleganceError && [400, 403, 409].includes(err.statusCode ?? 0)) {
4566
+ if (err instanceof import_sdk9.DeleganceError && [400, 403, 409].includes(err.statusCode ?? 0)) {
4407
4567
  error(err.message);
4408
4568
  process.exit(1);
4409
4569
  }
@@ -4424,7 +4584,7 @@ function summarizeBilling(payments) {
4424
4584
  return { openCents, paidCents, openCount };
4425
4585
  }
4426
4586
  function createBillingCommand() {
4427
- return new import_commander18.Command("billing").description("What you owe and what you paid: every premium payment request on the account").option("--json", "Output as JSON").action(async (options) => {
4587
+ return new import_commander19.Command("billing").description("What you owe and what you paid: every premium payment request on the account").option("--json", "Output as JSON").action(async (options) => {
4428
4588
  try {
4429
4589
  const payments = await getClient().payments.list();
4430
4590
  const sum = summarizeBilling(payments);
@@ -4448,7 +4608,7 @@ function createBillingCommand() {
4448
4608
  });
4449
4609
  }
4450
4610
  function createPayCommand() {
4451
- return new import_commander18.Command("pay").description("Pay a premium: list payment requests, or get a checkout link for one").argument("[paymentId]", "Payment request to pay (omit to list them)").option("--json", "Output as JSON").action(async (paymentId, options) => {
4611
+ return new import_commander19.Command("pay").description("Pay a premium: list payment requests, or get a checkout link for one").argument("[paymentId]", "Payment request to pay (omit to list them)").option("--json", "Output as JSON").action(async (paymentId, options) => {
4452
4612
  const client = getClient();
4453
4613
  try {
4454
4614
  if (!paymentId) {
@@ -4533,7 +4693,7 @@ function bondStartLines(r, ctx = {}) {
4533
4693
  return out;
4534
4694
  }
4535
4695
  function createBondCommand() {
4536
- const bond = new import_commander18.Command("bond").alias("bonds").description("Surety bond quotes");
4696
+ const bond = new import_commander19.Command("bond").alias("bonds").description("Surety bond quotes");
4537
4697
  bond.command("quote").description("Start a bond quote and list its questions").requiredOption("-s, --state <state>", "Two-letter state, e.g. TX").option("-b, --bond <name>", 'Bond name or keyword, e.g. "notary", "contractor license"').option("--entity-id <id>", "Exact bond id, when you have it").option("--contract-amount <amount>", "Contract value, for contract bonds").option("--bond-amount <amount>", "Bond penal sum").option("--json", "Output as JSON").action(async (options) => {
4538
4698
  try {
4539
4699
  const r = await getClient().bonds.start({
@@ -4579,7 +4739,7 @@ function createBondCommand() {
4579
4739
  return bond;
4580
4740
  }
4581
4741
  function createClaimCommand() {
4582
- const claim = new import_commander18.Command("claim").alias("claims").description("File and track claims");
4742
+ const claim = new import_commander19.Command("claim").alias("claims").description("File and track claims");
4583
4743
  claim.command("file").description("File a claim. The first time, accept the claims disclaimer in the portal").option("-d, --description <text>", "What happened (visible in shell history; prefer --description-file)").option("--description-file <file>", "Read what happened from a file, or - for stdin").option("--date <yyyy-mm-dd>", "When it happened").option("--policy <id>", "Policy id, if you know it").option("--json", "Output as JSON").action(async (options) => {
4584
4744
  let description = options.description;
4585
4745
  if (options.descriptionFile) {
@@ -4603,7 +4763,7 @@ function createClaimCommand() {
4603
4763
  success(r.message);
4604
4764
  keyValue({ Claim: r.claimId, Status: r.status, Portal: r.portalUrl });
4605
4765
  } catch (err) {
4606
- if (err instanceof import_sdk8.DeleganceError && err.reason === "gate_not_acknowledged") {
4766
+ if (err instanceof import_sdk9.DeleganceError && err.reason === "gate_not_acknowledged") {
4607
4767
  error("Accept the claims disclaimer once in the portal, then file again. It cannot be accepted for you.");
4608
4768
  info(String(err.body?.portalUrl ?? ""));
4609
4769
  process.exit(1);
@@ -4636,7 +4796,7 @@ function createClaimCommand() {
4636
4796
  // src/program.ts
4637
4797
  function createProgram() {
4638
4798
  registerMinimalCheckbox();
4639
- const program = new import_commander19.Command();
4799
+ const program = new import_commander20.Command();
4640
4800
  program.name("delegance").description("CLI for the Delegance Brokerage platform").version(CLI_VERSION).enablePositionalOptions().option("-v, --verbose", "Enable verbose output").option("--json", "Output in JSON format").hook("preAction", () => {
4641
4801
  migrateLegacyConfigKey();
4642
4802
  });
@@ -4662,6 +4822,7 @@ function createProgram() {
4662
4822
  program.addCommand(createBondCommand());
4663
4823
  program.addCommand(createClaimCommand());
4664
4824
  program.addCommand(createFeedbackCommand());
4825
+ program.addCommand(createTermsCommand());
4665
4826
  program.addCommand(createConfigCommand());
4666
4827
  return program;
4667
4828
  }