@thecorporation/cli 26.3.20 → 26.3.22

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
@@ -90,9 +90,13 @@ function allowUnsafeApiUrl() {
90
90
  return process.env.CORP_UNSAFE_API_URL === "1";
91
91
  }
92
92
  function validateApiUrl(value) {
93
+ const trimmed = value.trim();
94
+ if (trimmed.startsWith("process://")) {
95
+ return trimmed;
96
+ }
93
97
  let parsed;
94
98
  try {
95
- parsed = new URL(value.trim());
99
+ parsed = new URL(trimmed);
96
100
  } catch {
97
101
  throw new Error("api_url must be a valid absolute URL");
98
102
  }
@@ -217,6 +221,7 @@ function normalizeConfig(raw) {
217
221
  cfg.workspace_id = normalizeString(raw.workspace_id) ?? cfg.workspace_id;
218
222
  cfg.hosting_mode = normalizeString(raw.hosting_mode) ?? cfg.hosting_mode;
219
223
  cfg.active_entity_id = normalizeString(raw.active_entity_id) ?? cfg.active_entity_id;
224
+ cfg.data_dir = normalizeString(raw.data_dir) ?? cfg.data_dir;
220
225
  if (isObject(raw.llm)) {
221
226
  cfg.llm.provider = normalizeString(raw.llm.provider) ?? cfg.llm.provider;
222
227
  cfg.llm.api_key = normalizeString(raw.llm.api_key) ?? cfg.llm.api_key;
@@ -263,7 +268,8 @@ function serializeConfig(cfg) {
263
268
  name: normalized.user.name,
264
269
  email: normalized.user.email
265
270
  },
266
- active_entity_id: normalized.active_entity_id
271
+ active_entity_id: normalized.active_entity_id,
272
+ ...normalized.data_dir ? { data_dir: normalized.data_dir } : {}
267
273
  };
268
274
  if (normalized.active_entity_ids && Object.keys(normalized.active_entity_ids).length > 0) {
269
275
  serialized.active_entity_ids = normalized.active_entity_ids;
@@ -283,6 +289,20 @@ function serializeAuth(cfg) {
283
289
  if (normalized.llm.api_key) {
284
290
  serialized.llm = { api_key: normalized.llm.api_key };
285
291
  }
292
+ const existingAuth = readJsonFile(AUTH_FILE);
293
+ if (isObject(existingAuth) && isObject(existingAuth.server_secrets)) {
294
+ const ss = existingAuth.server_secrets;
295
+ if (typeof ss.jwt_secret === "string" && typeof ss.secrets_master_key === "string" && typeof ss.internal_worker_token === "string") {
296
+ serialized.server_secrets = {
297
+ jwt_secret: ss.jwt_secret,
298
+ secrets_master_key: ss.secrets_master_key,
299
+ internal_worker_token: ss.internal_worker_token
300
+ };
301
+ }
302
+ }
303
+ if (cfg._server_secrets) {
304
+ serialized.server_secrets = cfg._server_secrets;
305
+ }
286
306
  return JSON.stringify(serialized, null, 2) + "\n";
287
307
  }
288
308
  function requireSupportedConfigKey(dotPath) {
@@ -292,7 +312,9 @@ function requireSupportedConfigKey(dotPath) {
292
312
  }
293
313
  function validateSensitiveConfigUpdate(dotPath, forceSensitive = false) {
294
314
  if (SENSITIVE_CONFIG_KEYS.has(dotPath) && !forceSensitive) {
295
- throw new Error(`refusing to update security-sensitive key '${dotPath}' without --force`);
315
+ throw new Error(
316
+ `refusing to update security-sensitive key '${dotPath}' without --force; this key controls authentication or API routing, so explicit confirmation is required`
317
+ );
296
318
  }
297
319
  }
298
320
  function setKnownConfigValue(cfg, dotPath, value) {
@@ -309,6 +331,9 @@ function setKnownConfigValue(cfg, dotPath, value) {
309
331
  case "hosting_mode":
310
332
  cfg.hosting_mode = value.trim();
311
333
  return;
334
+ case "data_dir":
335
+ cfg.data_dir = value.trim();
336
+ return;
312
337
  case "llm.provider":
313
338
  cfg.llm.provider = value.trim();
314
339
  return;
@@ -490,7 +515,8 @@ var init_config = __esm({
490
515
  "llm.base_url",
491
516
  "user.name",
492
517
  "user.email",
493
- "active_entity_id"
518
+ "active_entity_id",
519
+ "data_dir"
494
520
  ]);
495
521
  SENSITIVE_CONFIG_KEYS = /* @__PURE__ */ new Set(["api_url", "api_key", "workspace_id"]);
496
522
  DEFAULTS = {
@@ -505,7 +531,8 @@ var init_config = __esm({
505
531
  base_url: process.env.CORP_LLM_BASE_URL || void 0
506
532
  },
507
533
  user: { name: "", email: "" },
508
- active_entity_id: ""
534
+ active_entity_id: "",
535
+ data_dir: ""
509
536
  };
510
537
  }
511
538
  });
@@ -656,7 +683,11 @@ function describeReferenceRecord(kind, record) {
656
683
  idFields: ["share_class_id", "id"],
657
684
  labelFields: ["class_code", "name", "share_class"]
658
685
  },
659
- round: { idFields: ["round_id", "equity_round_id", "id"], labelFields: ["name"] }
686
+ round: { idFields: ["round_id", "equity_round_id", "id"], labelFields: ["name"] },
687
+ service_request: {
688
+ idFields: ["request_id", "service_request_id", "id"],
689
+ labelFields: ["service_slug", "status"]
690
+ }
660
691
  };
661
692
  const spec = specs[kind];
662
693
  const id = extractId(record, spec.idFields);
@@ -724,7 +755,8 @@ var init_references = __esm({
724
755
  "safe_note",
725
756
  "instrument",
726
757
  "share_class",
727
- "round"
758
+ "round",
759
+ "service_request"
728
760
  ];
729
761
  VALID_RESOURCE_KINDS = new Set(RESOURCE_KINDS);
730
762
  MAX_REFERENCE_INPUT_LEN = 256;
@@ -753,6 +785,7 @@ var init_references = __esm({
753
785
  valuationsCache = /* @__PURE__ */ new Map();
754
786
  safeNotesCache = /* @__PURE__ */ new Map();
755
787
  roundsCache = /* @__PURE__ */ new Map();
788
+ serviceRequestsCache = /* @__PURE__ */ new Map();
756
789
  capTableCache = /* @__PURE__ */ new Map();
757
790
  agentsCache;
758
791
  constructor(client, cfg) {
@@ -775,6 +808,29 @@ var init_references = __esm({
775
808
  async resolveContact(entityId, ref) {
776
809
  return this.resolve("contact", ref, { entityId });
777
810
  }
811
+ async resolveWorkItemActor(entityId, ref) {
812
+ const trimmed = validateReferenceInput(ref, "actor reference");
813
+ const [contactResult, agentResult] = await Promise.allSettled([
814
+ this.resolveContact(entityId, trimmed),
815
+ this.resolveAgent(trimmed)
816
+ ]);
817
+ const contactId = contactResult.status === "fulfilled" ? contactResult.value : void 0;
818
+ const agentId = agentResult.status === "fulfilled" ? agentResult.value : void 0;
819
+ if (contactId && agentId && contactId !== agentId) {
820
+ throw new Error(
821
+ `Actor reference '${trimmed}' is ambiguous between a contact and an agent. Use a unique ref or explicit @last:contact / @last:agent.`
822
+ );
823
+ }
824
+ if (contactId) {
825
+ return { actor_type: "contact", actor_id: contactId };
826
+ }
827
+ if (agentId) {
828
+ return { actor_type: "agent", actor_id: agentId };
829
+ }
830
+ throw new Error(
831
+ `No matching contact or agent found for '${trimmed}'. Try 'corp find contact <query>' or 'corp find agent <query>'.`
832
+ );
833
+ }
778
834
  async resolveShareTransfer(entityId, ref) {
779
835
  return this.resolve("share_transfer", ref, { entityId });
780
836
  }
@@ -844,6 +900,9 @@ var init_references = __esm({
844
900
  async resolveRound(entityId, ref) {
845
901
  return this.resolve("round", ref, { entityId });
846
902
  }
903
+ async resolveServiceRequest(entityId, ref) {
904
+ return this.resolve("service_request", ref, { entityId });
905
+ }
847
906
  async find(kind, query, scope = {}) {
848
907
  const trimmedQuery = validateReferenceInput(query, "query", { allowEmpty: true });
849
908
  const records = await this.listRecords(kind, scope);
@@ -1031,6 +1090,8 @@ var init_references = __esm({
1031
1090
  return this.listShareClasses(scope.entityId);
1032
1091
  case "round":
1033
1092
  return this.listRounds(scope.entityId);
1093
+ case "service_request":
1094
+ return this.listServiceRequestRecords(scope.entityId);
1034
1095
  }
1035
1096
  })();
1036
1097
  return this.attachStableHandles(kind, records, scope.entityId);
@@ -1295,51 +1356,19 @@ var init_references = __esm({
1295
1356
  const capTable = await this.getCapTable(entityId);
1296
1357
  return Array.isArray(capTable.share_classes) ? capTable.share_classes : [];
1297
1358
  }
1359
+ async listServiceRequestRecords(entityId) {
1360
+ if (!entityId) throw new Error("An entity context is required to resolve service requests.");
1361
+ const cached = this.serviceRequestsCache.get(entityId);
1362
+ if (cached) return cached;
1363
+ const requests = await this.client.listServiceRequests(entityId);
1364
+ this.serviceRequestsCache.set(entityId, requests);
1365
+ return requests;
1366
+ }
1298
1367
  };
1299
1368
  }
1300
1369
  });
1301
1370
 
1302
1371
  // src/output.ts
1303
- var output_exports = {};
1304
- __export(output_exports, {
1305
- printAgendaItemsTable: () => printAgendaItemsTable,
1306
- printAgentsTable: () => printAgentsTable,
1307
- printApprovalsTable: () => printApprovalsTable,
1308
- printBankAccountsTable: () => printBankAccountsTable,
1309
- printBillingPanel: () => printBillingPanel,
1310
- printCapTable: () => printCapTable,
1311
- printClassificationsTable: () => printClassificationsTable,
1312
- printContactsTable: () => printContactsTable,
1313
- printDeadlinesTable: () => printDeadlinesTable,
1314
- printDistributionsTable: () => printDistributionsTable,
1315
- printDocumentsTable: () => printDocumentsTable,
1316
- printDryRun: () => printDryRun,
1317
- printEntitiesTable: () => printEntitiesTable,
1318
- printError: () => printError,
1319
- printGovernanceTable: () => printGovernanceTable,
1320
- printInstrumentsTable: () => printInstrumentsTable,
1321
- printInvoicesTable: () => printInvoicesTable,
1322
- printJson: () => printJson,
1323
- printMeetingsTable: () => printMeetingsTable,
1324
- printObligationsTable: () => printObligationsTable,
1325
- printPaymentsTable: () => printPaymentsTable,
1326
- printPayrollRunsTable: () => printPayrollRunsTable,
1327
- printReconciliationsTable: () => printReconciliationsTable,
1328
- printReferenceSummary: () => printReferenceSummary,
1329
- printResolutionsTable: () => printResolutionsTable,
1330
- printRoundsTable: () => printRoundsTable,
1331
- printSafesTable: () => printSafesTable,
1332
- printSeatsTable: () => printSeatsTable,
1333
- printShareClassesTable: () => printShareClassesTable,
1334
- printStatusPanel: () => printStatusPanel,
1335
- printSuccess: () => printSuccess,
1336
- printTaxFilingsTable: () => printTaxFilingsTable,
1337
- printTransfersTable: () => printTransfersTable,
1338
- printValuationsTable: () => printValuationsTable,
1339
- printWarning: () => printWarning,
1340
- printWorkItemsTable: () => printWorkItemsTable,
1341
- printWriteResult: () => printWriteResult
1342
- });
1343
1372
  import chalk from "chalk";
1344
1373
  import Table from "cli-table3";
1345
1374
  function printError(msg) {
@@ -1420,6 +1449,30 @@ function printStatusPanel(data) {
1420
1449
  }
1421
1450
  console.log(chalk.blue("\u2500".repeat(50)));
1422
1451
  }
1452
+ function printFinanceSummaryPanel(data) {
1453
+ const invoices = data.invoices ?? {};
1454
+ const bankAccounts = data.bank_accounts ?? {};
1455
+ const payments = data.payments ?? {};
1456
+ const payrollRuns = data.payroll_runs ?? {};
1457
+ const distributions = data.distributions ?? {};
1458
+ const reconciliations = data.reconciliations ?? {};
1459
+ const classifications = data.contractor_classifications ?? {};
1460
+ console.log(chalk.green("\u2500".repeat(54)));
1461
+ console.log(chalk.green.bold(" Finance Summary"));
1462
+ console.log(chalk.green("\u2500".repeat(54)));
1463
+ console.log(` ${chalk.bold("Entity:")} ${s(data.entity_id) || "N/A"}`);
1464
+ console.log(` ${chalk.bold("Invoices:")} ${s(invoices.count)} total, ${s(invoices.open_count)} open, ${money(invoices.total_amount_cents)}`);
1465
+ if (invoices.latest_due_date) {
1466
+ console.log(` ${chalk.bold("Invoice Horizon:")} next due ${date(invoices.latest_due_date)}`);
1467
+ }
1468
+ console.log(` ${chalk.bold("Bank Accounts:")} ${s(bankAccounts.active_count)}/${s(bankAccounts.count)} active`);
1469
+ console.log(` ${chalk.bold("Payments:")} ${s(payments.count)} total, ${s(payments.pending_count)} pending, ${money(payments.total_amount_cents)}`);
1470
+ console.log(` ${chalk.bold("Payroll Runs:")} ${s(payrollRuns.count)} total${payrollRuns.latest_period_end ? `, latest ${date(payrollRuns.latest_period_end)}` : ""}`);
1471
+ console.log(` ${chalk.bold("Distributions:")} ${s(distributions.count)} total, ${money(distributions.total_amount_cents)}`);
1472
+ console.log(` ${chalk.bold("Reconciliations:")} ${s(reconciliations.balanced_count)}/${s(reconciliations.count)} balanced`);
1473
+ console.log(` ${chalk.bold("Contractors:")} ${s(classifications.count)} classifications, ${s(classifications.high_risk_count)} high risk`);
1474
+ console.log(chalk.green("\u2500".repeat(54)));
1475
+ }
1423
1476
  function makeTable(title, columns) {
1424
1477
  console.log(`
1425
1478
  ${chalk.bold(title)}`);
@@ -1443,6 +1496,17 @@ function date(val) {
1443
1496
  const parsed = new Date(str);
1444
1497
  return Number.isNaN(parsed.getTime()) ? str : parsed.toISOString().slice(0, 10);
1445
1498
  }
1499
+ function actorLabel(record, field) {
1500
+ const actor = record[`${field}_actor`];
1501
+ if (actor && typeof actor === "object" && !Array.isArray(actor)) {
1502
+ const label = s(actor.label);
1503
+ const actorType = s(actor.actor_type);
1504
+ if (label) {
1505
+ return actorType ? `${label} (${actorType})` : label;
1506
+ }
1507
+ }
1508
+ return s(record[field]);
1509
+ }
1446
1510
  function printEntitiesTable(entities) {
1447
1511
  const table = makeTable("Entities", ["Ref", "Name", "Type", "Jurisdiction", "Status"]);
1448
1512
  for (const e of entities) {
@@ -1848,7 +1912,7 @@ function printWorkItemsTable(items) {
1848
1912
  s(w.category),
1849
1913
  colored,
1850
1914
  w.asap ? chalk.red.bold("ASAP") : s(w.deadline ?? ""),
1851
- s(w.claimed_by ?? "")
1915
+ actorLabel(w, "claimed_by")
1852
1916
  ]);
1853
1917
  }
1854
1918
  console.log(table.toString());
@@ -1862,17 +1926,29 @@ function printAgentsTable(agents) {
1862
1926
  }
1863
1927
  console.log(table.toString());
1864
1928
  }
1865
- function printApprovalsTable(approvals) {
1866
- const table = makeTable("Pending Approvals", ["ID", "Type", "Requested By", "Description", "Created"]);
1867
- for (const a of approvals) {
1868
- let desc = s(a.description ?? a.summary);
1869
- if (desc.length > 60) desc = desc.slice(0, 57) + "...";
1929
+ function printServiceCatalogTable(items) {
1930
+ const table = makeTable("Service Catalog", ["Slug", "Name", "Price", "Type"]);
1931
+ for (const item of items) {
1870
1932
  table.push([
1871
- s(a.approval_id ?? a.id, 12),
1872
- s(a.approval_type ?? a.type),
1873
- s(a.requested_by ?? a.requester),
1874
- desc,
1875
- s(a.created_at)
1933
+ s(item.slug),
1934
+ s(item.name),
1935
+ money(item.amount_cents),
1936
+ s(item.price_type)
1937
+ ]);
1938
+ }
1939
+ console.log(table.toString());
1940
+ }
1941
+ function printServiceRequestsTable(requests) {
1942
+ const table = makeTable("Service Requests", ["Ref", "Service", "Amount", "Status", "Created"]);
1943
+ for (const r of requests) {
1944
+ const status = s(r.status);
1945
+ const colored = status === "fulfilled" ? chalk.green(status) : status === "paid" ? chalk.cyan(status) : status === "checkout" ? chalk.yellow(status) : status === "failed" ? chalk.dim(status) : status;
1946
+ table.push([
1947
+ formatReferenceCell("service_request", r),
1948
+ s(r.service_slug),
1949
+ money(r.amount_cents),
1950
+ colored,
1951
+ date(r.created_at)
1876
1952
  ]);
1877
1953
  }
1878
1954
  console.log(table.toString());
@@ -1930,7 +2006,15 @@ var setup_exports = {};
1930
2006
  __export(setup_exports, {
1931
2007
  setupCommand: () => setupCommand
1932
2008
  });
1933
- import { input, confirm } from "@inquirer/prompts";
2009
+ import { input, select } from "@inquirer/prompts";
2010
+ import { homedir as homedir2 } from "os";
2011
+ import { join as join2 } from "path";
2012
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync } from "fs";
2013
+ import {
2014
+ generateSecret,
2015
+ generateFernetKey,
2016
+ processRequest
2017
+ } from "@thecorporation/corp-tools";
1934
2018
  async function requestMagicLink(apiUrl, email, tosAccepted) {
1935
2019
  const resp = await fetch(`${apiUrl}/v1/auth/magic-link`, {
1936
2020
  method: "POST",
@@ -1966,9 +2050,6 @@ async function verifyMagicLinkCode(apiUrl, code) {
1966
2050
  workspace_id: data.workspace_id
1967
2051
  };
1968
2052
  }
1969
- function isCloudApi(url) {
1970
- return url.replace(/\/+$/, "").includes("thecorporation.ai");
1971
- }
1972
2053
  async function magicLinkAuth(apiUrl, email) {
1973
2054
  console.log("\nSending magic link to " + email + "...");
1974
2055
  await requestMagicLink(apiUrl, email, true);
@@ -1984,22 +2065,46 @@ async function magicLinkAuth(apiUrl, email) {
1984
2065
  console.log("Verifying...");
1985
2066
  return verifyMagicLinkCode(apiUrl, trimmed);
1986
2067
  }
2068
+ function setupDataDir(dirPath) {
2069
+ if (!existsSync2(dirPath)) {
2070
+ mkdirSync2(dirPath, { recursive: true });
2071
+ return { isNew: true };
2072
+ }
2073
+ try {
2074
+ const entries = readdirSync(dirPath);
2075
+ if (entries.length > 0) {
2076
+ console.log("Found existing data, reusing.");
2077
+ return { isNew: false };
2078
+ }
2079
+ } catch {
2080
+ }
2081
+ return { isNew: true };
2082
+ }
2083
+ async function localProvision(dataDir, name) {
2084
+ const resp = processRequest(
2085
+ "process://",
2086
+ "POST",
2087
+ "/v1/workspaces/provision",
2088
+ { "Content-Type": "application/json" },
2089
+ JSON.stringify({ name }),
2090
+ { dataDir }
2091
+ );
2092
+ if (!resp.ok) {
2093
+ const detail = await resp.text();
2094
+ throw new Error(`Provision failed: HTTP ${resp.status} \u2014 ${detail}`);
2095
+ }
2096
+ const body = await resp.json();
2097
+ if (!body.api_key || !body.workspace_id) {
2098
+ throw new Error("Provision response missing api_key or workspace_id");
2099
+ }
2100
+ return {
2101
+ api_key: body.api_key,
2102
+ workspace_id: body.workspace_id
2103
+ };
2104
+ }
1987
2105
  async function setupCommand() {
1988
2106
  const cfg = loadConfig();
1989
2107
  console.log("Welcome to corp \u2014 corporate governance from the terminal.\n");
1990
- const customUrl = process.env.CORP_API_URL;
1991
- if (customUrl) {
1992
- try {
1993
- cfg.api_url = validateApiUrl(customUrl);
1994
- } catch (err) {
1995
- printError(`Invalid CORP_API_URL: ${err}`);
1996
- process.exit(1);
1997
- }
1998
- console.log(`Using API: ${cfg.api_url}
1999
- `);
2000
- } else {
2001
- cfg.api_url = CLOUD_API_URL;
2002
- }
2003
2108
  console.log("--- User Info ---");
2004
2109
  const user = cfg.user ?? { name: "", email: "" };
2005
2110
  user.name = await input({
@@ -2011,10 +2116,53 @@ async function setupCommand() {
2011
2116
  default: user.email || void 0
2012
2117
  });
2013
2118
  cfg.user = user;
2014
- const needsAuth = !cfg.api_key || !cfg.workspace_id;
2015
- const cloud = isCloudApi(cfg.api_url);
2016
- if (needsAuth) {
2017
- if (cloud) {
2119
+ console.log("\n--- Hosting Mode ---");
2120
+ const hostingMode = await select({
2121
+ message: "How would you like to run corp?",
2122
+ choices: [
2123
+ { value: "local", name: "Local (your machine)" },
2124
+ { value: "cloud", name: "TheCorporation cloud" },
2125
+ { value: "self-hosted", name: "Self-hosted server (custom URL)" }
2126
+ ],
2127
+ default: cfg.hosting_mode || "local"
2128
+ });
2129
+ cfg.hosting_mode = hostingMode;
2130
+ if (hostingMode === "local") {
2131
+ const dataDir = await input({
2132
+ message: "Data directory",
2133
+ default: cfg.data_dir || DEFAULT_DATA_DIR
2134
+ });
2135
+ cfg.data_dir = dataDir;
2136
+ cfg.api_url = "process://";
2137
+ const { isNew } = setupDataDir(dataDir);
2138
+ const serverSecrets = {
2139
+ jwt_secret: generateSecret(),
2140
+ secrets_master_key: generateFernetKey(),
2141
+ internal_worker_token: generateSecret()
2142
+ };
2143
+ process.env.JWT_SECRET = serverSecrets.jwt_secret;
2144
+ process.env.SECRETS_MASTER_KEY = serverSecrets.secrets_master_key;
2145
+ process.env.INTERNAL_WORKER_TOKEN = serverSecrets.internal_worker_token;
2146
+ cfg._server_secrets = serverSecrets;
2147
+ if (isNew || !cfg.workspace_id) {
2148
+ console.log("\nProvisioning workspace...");
2149
+ try {
2150
+ const result = await localProvision(dataDir, `${user.name}'s workspace`);
2151
+ cfg.api_key = result.api_key;
2152
+ cfg.workspace_id = result.workspace_id;
2153
+ printSuccess(`Local workspace ready: ${result.workspace_id}`);
2154
+ } catch (err) {
2155
+ printError(`Workspace provisioning failed: ${err}`);
2156
+ console.log("You can retry with 'corp setup'.");
2157
+ }
2158
+ } else {
2159
+ console.log("\nExisting workspace found.");
2160
+ }
2161
+ } else if (hostingMode === "cloud") {
2162
+ cfg.api_url = CLOUD_API_URL;
2163
+ cfg.data_dir = "";
2164
+ const needsAuth = !cfg.api_key || !cfg.workspace_id;
2165
+ if (needsAuth) {
2018
2166
  try {
2019
2167
  const result = await magicLinkAuth(cfg.api_url, user.email);
2020
2168
  cfg.api_key = result.api_key;
@@ -2027,6 +2175,22 @@ async function setupCommand() {
2027
2175
  );
2028
2176
  }
2029
2177
  } else {
2178
+ console.log("\nExisting credentials found. Run 'corp status' to verify.");
2179
+ }
2180
+ } else {
2181
+ const url = await input({
2182
+ message: "Server URL",
2183
+ default: cfg.api_url !== CLOUD_API_URL && !cfg.api_url.startsWith("process://") ? cfg.api_url : void 0
2184
+ });
2185
+ try {
2186
+ cfg.api_url = validateApiUrl(url);
2187
+ } catch (err) {
2188
+ printError(`Invalid URL: ${err}`);
2189
+ process.exit(1);
2190
+ }
2191
+ cfg.data_dir = "";
2192
+ const needsAuth = !cfg.api_key || !cfg.workspace_id;
2193
+ if (needsAuth) {
2030
2194
  console.log("\nProvisioning workspace...");
2031
2195
  try {
2032
2196
  const result = await provisionWorkspace(
@@ -2043,57 +2207,13 @@ async function setupCommand() {
2043
2207
  );
2044
2208
  }
2045
2209
  }
2046
- } else {
2047
- console.log("\nVerifying existing credentials...");
2048
- let keyValid = false;
2049
- try {
2050
- const resp = await fetch(
2051
- `${cfg.api_url.replace(/\/+$/, "")}/v1/workspaces/${cfg.workspace_id}/status`,
2052
- { headers: { Authorization: `Bearer ${cfg.api_key}` } }
2053
- );
2054
- keyValid = resp.status !== 401;
2055
- } catch {
2056
- }
2057
- if (keyValid) {
2058
- console.log("Credentials OK.");
2059
- } else {
2060
- console.log("API key is no longer valid.");
2061
- const reauth = await confirm({
2062
- message: cloud ? "Re-authenticate via magic link?" : "Provision a new workspace? (This will replace your current credentials)",
2063
- default: true
2064
- });
2065
- if (reauth) {
2066
- try {
2067
- if (cloud) {
2068
- const result = await magicLinkAuth(cfg.api_url, user.email);
2069
- cfg.api_key = result.api_key;
2070
- cfg.workspace_id = result.workspace_id;
2071
- printSuccess(`Authenticated. Workspace: ${result.workspace_id}`);
2072
- } else {
2073
- const result = await provisionWorkspace(
2074
- cfg.api_url,
2075
- `${user.name}'s workspace`
2076
- );
2077
- cfg.api_key = result.api_key;
2078
- cfg.workspace_id = result.workspace_id;
2079
- console.log(`Workspace provisioned: ${result.workspace_id}`);
2080
- }
2081
- } catch (err) {
2082
- printError(`Authentication failed: ${err}`);
2083
- }
2084
- } else {
2085
- console.log(
2086
- "Keeping existing credentials. You can manually update with: corp config set api_key <key>"
2087
- );
2088
- }
2089
- }
2090
2210
  }
2091
2211
  saveConfig(cfg);
2092
2212
  console.log("\nSettings saved to ~/.corp/config.json");
2093
2213
  console.log("Credentials saved to ~/.corp/auth.json");
2094
2214
  console.log("Run 'corp status' to verify your connection.");
2095
2215
  }
2096
- var CLOUD_API_URL;
2216
+ var CLOUD_API_URL, DEFAULT_DATA_DIR;
2097
2217
  var init_setup = __esm({
2098
2218
  "src/commands/setup.ts"() {
2099
2219
  "use strict";
@@ -2101,6 +2221,7 @@ var init_setup = __esm({
2101
2221
  init_api_client();
2102
2222
  init_output();
2103
2223
  CLOUD_API_URL = "https://api.thecorporation.ai";
2224
+ DEFAULT_DATA_DIR = join2(homedir2(), ".corp", "data");
2104
2225
  }
2105
2226
  });
2106
2227
 
@@ -3109,11 +3230,11 @@ import {
3109
3230
  isWriteTool as _isWriteTool,
3110
3231
  executeTool as _executeTool
3111
3232
  } from "@thecorporation/corp-tools";
3112
- import { join as join2 } from "path";
3113
- import { homedir as homedir2 } from "os";
3233
+ import { join as join3 } from "path";
3234
+ import { homedir as homedir3 } from "os";
3114
3235
  async function executeTool(name, args, client) {
3115
3236
  return _executeTool(name, args, client, {
3116
- dataDir: join2(homedir2(), ".corp"),
3237
+ dataDir: join3(homedir3(), ".corp"),
3117
3238
  onEntityFormed: (entityId) => {
3118
3239
  try {
3119
3240
  updateConfig((cfg) => {
@@ -3828,7 +3949,26 @@ async function fourOhNineACommand(opts) {
3828
3949
  } catch (err) {
3829
3950
  const msg = String(err);
3830
3951
  if (msg.includes("404")) {
3831
- console.log("No 409A valuation found for this entity. Create one with:\n corp cap-table create-valuation --type four_oh_nine_a --date YYYY-MM-DD --methodology <method>");
3952
+ try {
3953
+ const eid = await resolver.resolveEntity(opts.entityId);
3954
+ const valuations = await client.getValuations(eid);
3955
+ const pending409a = valuations.filter((valuation) => valuation.valuation_type === "four_oh_nine_a").find((valuation) => valuation.status === "pending_approval");
3956
+ if (pending409a) {
3957
+ const effectiveDate = pending409a.effective_date ?? "unknown date";
3958
+ console.log(
3959
+ `No current approved 409A valuation found. A 409A valuation is pending approval (${effectiveDate}).
3960
+ Complete board approval, then re-run: corp cap-table 409a`
3961
+ );
3962
+ } else {
3963
+ console.log(
3964
+ "No 409A valuation found for this entity. Create one with:\n corp cap-table create-valuation --type four_oh_nine_a --date YYYY-MM-DD --methodology <method>"
3965
+ );
3966
+ }
3967
+ } catch {
3968
+ console.log(
3969
+ "No 409A valuation found for this entity. Create one with:\n corp cap-table create-valuation --type four_oh_nine_a --date YYYY-MM-DD --methodology <method>"
3970
+ );
3971
+ }
3832
3972
  } else {
3833
3973
  printError(`Failed to fetch 409A valuation: ${err}`);
3834
3974
  }
@@ -4361,8 +4501,112 @@ __export(finance_exports, {
4361
4501
  financePayrollCommand: () => financePayrollCommand,
4362
4502
  financePayrollRunsCommand: () => financePayrollRunsCommand,
4363
4503
  financeReconcileCommand: () => financeReconcileCommand,
4364
- financeReconciliationsCommand: () => financeReconciliationsCommand
4365
- });
4504
+ financeReconciliationsCommand: () => financeReconciliationsCommand,
4505
+ financeSummaryCommand: () => financeSummaryCommand
4506
+ });
4507
+ function sumAmounts(records, candidates) {
4508
+ return records.reduce((sum, record) => {
4509
+ for (const key of candidates) {
4510
+ if (typeof record[key] === "number" && Number.isFinite(record[key])) {
4511
+ return sum + Number(record[key]);
4512
+ }
4513
+ }
4514
+ return sum;
4515
+ }, 0);
4516
+ }
4517
+ function latestDate(records, candidates) {
4518
+ const values = records.flatMap((record) => candidates.map((key) => record[key])).filter((value) => typeof value === "string" && value.trim().length > 0).map((value) => ({ raw: value, time: new Date(value).getTime() })).filter((value) => Number.isFinite(value.time)).sort((a, b) => b.time - a.time);
4519
+ return values[0]?.raw;
4520
+ }
4521
+ function countByStatus(records, statuses) {
4522
+ const expected = new Set(statuses.map((status) => status.toLowerCase()));
4523
+ return records.filter((record) => expected.has(String(record.status ?? "").toLowerCase())).length;
4524
+ }
4525
+ function countByField(records, field, values) {
4526
+ const expected = new Set(values.map((value) => value.toLowerCase()));
4527
+ return records.filter((record) => expected.has(String(record[field] ?? "").toLowerCase())).length;
4528
+ }
4529
+ async function financeSummaryCommand(opts) {
4530
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
4531
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
4532
+ const resolver = new ReferenceResolver(client, cfg);
4533
+ try {
4534
+ const eid = await resolver.resolveEntity(opts.entityId);
4535
+ const [
4536
+ invoices,
4537
+ accounts,
4538
+ payments,
4539
+ payrollRuns,
4540
+ distributions,
4541
+ reconciliations,
4542
+ classifications
4543
+ ] = await Promise.all([
4544
+ client.listInvoices(eid),
4545
+ client.listBankAccounts(eid),
4546
+ client.listPayments(eid),
4547
+ client.listPayrollRuns(eid),
4548
+ client.listDistributions(eid),
4549
+ client.listReconciliations(eid),
4550
+ client.listContractorClassifications(eid)
4551
+ ]);
4552
+ await Promise.all([
4553
+ resolver.stabilizeRecords("invoice", invoices, eid),
4554
+ resolver.stabilizeRecords("bank_account", accounts, eid),
4555
+ resolver.stabilizeRecords("payment", payments, eid),
4556
+ resolver.stabilizeRecords("payroll_run", payrollRuns, eid),
4557
+ resolver.stabilizeRecords("distribution", distributions, eid),
4558
+ resolver.stabilizeRecords("reconciliation", reconciliations, eid),
4559
+ resolver.stabilizeRecords("classification", classifications, eid)
4560
+ ]);
4561
+ const summary = {
4562
+ entity_id: eid,
4563
+ invoices: {
4564
+ count: invoices.length,
4565
+ open_count: invoices.length - countByStatus(invoices, ["paid", "cancelled", "void"]),
4566
+ overdue_count: countByStatus(invoices, ["overdue"]),
4567
+ total_amount_cents: sumAmounts(invoices, ["amount_cents", "total_amount_cents"]),
4568
+ latest_due_date: latestDate(invoices, ["due_date", "created_at"])
4569
+ },
4570
+ bank_accounts: {
4571
+ count: accounts.length,
4572
+ active_count: countByStatus(accounts, ["active", "approved", "open"])
4573
+ },
4574
+ payments: {
4575
+ count: payments.length,
4576
+ pending_count: countByStatus(payments, ["pending", "submitted", "queued"]),
4577
+ total_amount_cents: sumAmounts(payments, ["amount_cents"]),
4578
+ latest_submitted_at: latestDate(payments, ["submitted_at", "created_at"])
4579
+ },
4580
+ payroll_runs: {
4581
+ count: payrollRuns.length,
4582
+ latest_period_end: latestDate(payrollRuns, ["pay_period_end", "created_at"])
4583
+ },
4584
+ distributions: {
4585
+ count: distributions.length,
4586
+ total_amount_cents: sumAmounts(distributions, ["amount_cents", "distribution_amount_cents"]),
4587
+ latest_declared_at: latestDate(distributions, ["declared_at", "created_at"])
4588
+ },
4589
+ reconciliations: {
4590
+ count: reconciliations.length,
4591
+ balanced_count: reconciliations.filter((record) => record.is_balanced === true).length,
4592
+ latest_as_of_date: latestDate(reconciliations, ["as_of_date", "created_at"])
4593
+ },
4594
+ contractor_classifications: {
4595
+ count: classifications.length,
4596
+ high_risk_count: countByField(classifications, "risk_level", ["high"]),
4597
+ medium_risk_count: countByField(classifications, "risk_level", ["medium"])
4598
+ }
4599
+ };
4600
+ if (opts.json) {
4601
+ printJson(summary);
4602
+ return;
4603
+ }
4604
+ printFinanceSummaryPanel(summary);
4605
+ } catch (err) {
4606
+ printError(`Failed to fetch finance summary: ${err}`);
4607
+ process.exit(1);
4608
+ }
4609
+ }
4366
4610
  async function financeInvoicesCommand(opts) {
4367
4611
  const cfg = requireConfig("api_url", "api_key", "workspace_id");
4368
4612
  const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
@@ -5102,12 +5346,206 @@ var init_governance = __esm({
5102
5346
  }
5103
5347
  });
5104
5348
 
5349
+ // src/formation-automation.ts
5350
+ function normalizeRole(value) {
5351
+ return String(value ?? "").trim().toLowerCase();
5352
+ }
5353
+ function fallbackSignerEmail(requirement) {
5354
+ const slug = String(requirement.signer_name ?? "signer").toLowerCase().replace(/[^a-z0-9]+/g, ".").replace(/^\.+|\.+$/g, "");
5355
+ return `${slug || "signer"}@example.com`;
5356
+ }
5357
+ function getSignatureRequirements(document) {
5358
+ const content = document.content;
5359
+ if (!content || typeof content !== "object" || Array.isArray(content)) {
5360
+ return [];
5361
+ }
5362
+ const requirements = content.signature_requirements;
5363
+ if (!Array.isArray(requirements)) {
5364
+ return [];
5365
+ }
5366
+ return requirements.filter((item) => typeof item === "object" && item !== null && !Array.isArray(item)).map((item) => ({
5367
+ role: String(item.role ?? "").trim(),
5368
+ signer_name: String(item.signer_name ?? "").trim(),
5369
+ signer_email: typeof item.signer_email === "string" && item.signer_email.trim() ? item.signer_email.trim() : void 0
5370
+ })).filter((item) => item.role.length > 0 && item.signer_name.length > 0);
5371
+ }
5372
+ function getSignedRoles(document) {
5373
+ const signatures = Array.isArray(document.signatures) ? document.signatures : [];
5374
+ return new Set(
5375
+ signatures.filter((item) => typeof item === "object" && item !== null && !Array.isArray(item)).map((item) => normalizeRole(item.signer_role)).filter(Boolean)
5376
+ );
5377
+ }
5378
+ function deterministicEin(entityId) {
5379
+ const digits = entityId.replace(/\D/g, "");
5380
+ const nineDigits = `${digits}123456789`.slice(0, 9).padEnd(9, "0");
5381
+ return `${nineDigits.slice(0, 2)}-${nineDigits.slice(2)}`;
5382
+ }
5383
+ function filingIdentifier(prefix, entityId) {
5384
+ const token = entityId.replace(/[^a-zA-Z0-9]/g, "").slice(0, 12).toLowerCase() || "formation";
5385
+ return `${prefix}-${token}`;
5386
+ }
5387
+ async function autoSignFormationDocument(client, entityId, documentId) {
5388
+ const document = await client.getDocument(documentId, entityId);
5389
+ const requiredSignatures = getSignatureRequirements(document);
5390
+ if (requiredSignatures.length === 0) {
5391
+ return { document, signatures_added: 0 };
5392
+ }
5393
+ const signedRoles = getSignedRoles(document);
5394
+ let signaturesAdded = 0;
5395
+ for (const requirement of requiredSignatures) {
5396
+ if (signedRoles.has(normalizeRole(requirement.role))) {
5397
+ continue;
5398
+ }
5399
+ await client.signDocument(documentId, entityId, {
5400
+ signer_name: requirement.signer_name,
5401
+ signer_role: requirement.role,
5402
+ signer_email: requirement.signer_email ?? fallbackSignerEmail(requirement),
5403
+ signature_text: requirement.signer_name,
5404
+ consent_text: DEFAULT_SIGNATURE_CONSENT
5405
+ });
5406
+ signedRoles.add(normalizeRole(requirement.role));
5407
+ signaturesAdded += 1;
5408
+ }
5409
+ const refreshed = await client.getDocument(documentId, entityId);
5410
+ return { document: refreshed, signatures_added: signaturesAdded };
5411
+ }
5412
+ async function autoSignFormationDocuments(client, resolver, entityId) {
5413
+ const summaries = await client.getEntityDocuments(entityId);
5414
+ await resolver.stabilizeRecords("document", summaries, entityId);
5415
+ let signaturesAdded = 0;
5416
+ let documentsSigned = 0;
5417
+ const documents = [];
5418
+ for (const summary of summaries) {
5419
+ const documentId = String(summary.document_id ?? "");
5420
+ if (!documentId) {
5421
+ continue;
5422
+ }
5423
+ const { document, signatures_added } = await autoSignFormationDocument(
5424
+ client,
5425
+ entityId,
5426
+ documentId
5427
+ );
5428
+ signaturesAdded += signatures_added;
5429
+ if (signatures_added > 0) {
5430
+ documentsSigned += 1;
5431
+ }
5432
+ documents.push(document);
5433
+ }
5434
+ return {
5435
+ documents_seen: summaries.length,
5436
+ documents_signed: documentsSigned,
5437
+ signatures_added: signaturesAdded,
5438
+ documents
5439
+ };
5440
+ }
5441
+ async function activateFormationEntity(client, resolver, entityId, options = {}) {
5442
+ let formation = await client.getFormation(entityId);
5443
+ const initialStatus = String(formation.formation_status ?? "");
5444
+ const steps = [];
5445
+ let signaturesAdded = 0;
5446
+ let documentsSigned = 0;
5447
+ for (let i = 0; i < 10; i += 1) {
5448
+ const status = String(formation.formation_status ?? "");
5449
+ if (status === "active") {
5450
+ return {
5451
+ entity_id: entityId,
5452
+ initial_status: initialStatus,
5453
+ final_status: status,
5454
+ signatures_added: signaturesAdded,
5455
+ documents_signed: documentsSigned,
5456
+ steps,
5457
+ formation
5458
+ };
5459
+ }
5460
+ if (status === "pending") {
5461
+ throw new Error("Formation is still pending. Finalize it before activation.");
5462
+ }
5463
+ if (status === "documents_generated") {
5464
+ const signed = await autoSignFormationDocuments(client, resolver, entityId);
5465
+ signaturesAdded += signed.signatures_added;
5466
+ documentsSigned += signed.documents_signed;
5467
+ await client.markFormationDocumentsSigned(entityId);
5468
+ steps.push(`signed ${signed.signatures_added} signatures across ${signed.documents_signed} documents`);
5469
+ formation = await client.getFormation(entityId);
5470
+ continue;
5471
+ }
5472
+ if (status === "documents_signed") {
5473
+ const gates = await client.getFormationGates(entityId);
5474
+ if (gates.requires_natural_person_attestation && !gates.attestation_recorded) {
5475
+ await client.recordFilingAttestation(entityId, {
5476
+ signer_name: gates.designated_attestor_name,
5477
+ signer_role: gates.designated_attestor_role,
5478
+ signer_email: gates.designated_attestor_email ?? fallbackSignerEmail({
5479
+ role: String(gates.designated_attestor_role ?? "attestor"),
5480
+ signer_name: String(gates.designated_attestor_name ?? "attestor")
5481
+ }),
5482
+ consent_text: DEFAULT_ATTESTATION_CONSENT,
5483
+ notes: "Recorded automatically by corp form activate"
5484
+ });
5485
+ steps.push("recorded filing attestation");
5486
+ }
5487
+ const gatesAfterAttestation = await client.getFormationGates(entityId);
5488
+ if (gatesAfterAttestation.requires_registered_agent_consent_evidence && Number(gatesAfterAttestation.registered_agent_consent_evidence_count ?? 0) === 0) {
5489
+ await client.addRegisteredAgentConsentEvidence(entityId, {
5490
+ evidence_uri: options.evidenceUri ?? `generated://registered-agent-consent/${entityId}`,
5491
+ evidence_type: options.evidenceType ?? "generated",
5492
+ notes: "Recorded automatically by corp form activate"
5493
+ });
5494
+ steps.push("recorded registered-agent consent evidence");
5495
+ }
5496
+ const finalGates = await client.getFormationGates(entityId);
5497
+ if (Array.isArray(finalGates.filing_submission_blockers) && finalGates.filing_submission_blockers.length > 0) {
5498
+ throw new Error(
5499
+ `Formation filing is still blocked: ${finalGates.filing_submission_blockers.join("; ")}`
5500
+ );
5501
+ }
5502
+ await client.submitFiling(entityId);
5503
+ steps.push("submitted filing");
5504
+ formation = await client.getFormation(entityId);
5505
+ continue;
5506
+ }
5507
+ if (status === "filing_submitted") {
5508
+ await client.confirmFiling(entityId, {
5509
+ external_filing_id: options.filingId ?? filingIdentifier("sim", entityId),
5510
+ receipt_reference: options.receiptReference ?? filingIdentifier("receipt", entityId)
5511
+ });
5512
+ steps.push("confirmed filing");
5513
+ formation = await client.getFormation(entityId);
5514
+ continue;
5515
+ }
5516
+ if (status === "filed") {
5517
+ await client.applyEin(entityId);
5518
+ steps.push("submitted EIN application");
5519
+ formation = await client.getFormation(entityId);
5520
+ continue;
5521
+ }
5522
+ if (status === "ein_applied") {
5523
+ await client.confirmEin(entityId, { ein: options.ein ?? deterministicEin(entityId) });
5524
+ steps.push("confirmed EIN");
5525
+ formation = await client.getFormation(entityId);
5526
+ continue;
5527
+ }
5528
+ throw new Error(`Unsupported formation status for activation: ${status || "unknown"}`);
5529
+ }
5530
+ throw new Error("Formation activation did not converge within 10 steps.");
5531
+ }
5532
+ var DEFAULT_SIGNATURE_CONSENT, DEFAULT_ATTESTATION_CONSENT;
5533
+ var init_formation_automation = __esm({
5534
+ "src/formation-automation.ts"() {
5535
+ "use strict";
5536
+ DEFAULT_SIGNATURE_CONSENT = "I agree to sign this document electronically.";
5537
+ DEFAULT_ATTESTATION_CONSENT = "I attest the filing information is accurate and authorized.";
5538
+ }
5539
+ });
5540
+
5105
5541
  // src/commands/documents.ts
5106
5542
  var documents_exports = {};
5107
5543
  __export(documents_exports, {
5108
5544
  documentsGenerateCommand: () => documentsGenerateCommand,
5109
5545
  documentsListCommand: () => documentsListCommand,
5110
5546
  documentsPreviewPdfCommand: () => documentsPreviewPdfCommand,
5547
+ documentsSignAllCommand: () => documentsSignAllCommand,
5548
+ documentsSignCommand: () => documentsSignCommand,
5111
5549
  documentsSigningLinkCommand: () => documentsSigningLinkCommand
5112
5550
  });
5113
5551
  function formatSigningLink(docId, result) {
@@ -5213,7 +5651,78 @@ function coerceParamValue(raw) {
5213
5651
  }
5214
5652
  return raw;
5215
5653
  }
5654
+ async function documentsSignCommand(docId, opts) {
5655
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
5656
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
5657
+ const resolver = new ReferenceResolver(client, cfg);
5658
+ try {
5659
+ const eid = await resolver.resolveEntity(opts.entityId);
5660
+ const resolvedDocumentId = await resolver.resolveDocument(eid, docId);
5661
+ if (opts.signerName || opts.signerRole || opts.signerEmail || opts.signatureText) {
5662
+ if (!opts.signerName || !opts.signerRole || !opts.signerEmail) {
5663
+ throw new Error("Manual signing requires --signer-name, --signer-role, and --signer-email.");
5664
+ }
5665
+ const result2 = await client.signDocument(resolvedDocumentId, eid, {
5666
+ signer_name: opts.signerName,
5667
+ signer_role: opts.signerRole,
5668
+ signer_email: opts.signerEmail,
5669
+ signature_text: opts.signatureText ?? opts.signerName
5670
+ });
5671
+ await resolver.stabilizeRecord("document", { document_id: resolvedDocumentId, title: docId }, eid);
5672
+ printWriteResult(result2, `Document ${resolvedDocumentId} signed.`, opts.json);
5673
+ return;
5674
+ }
5675
+ const result = await autoSignFormationDocument(client, eid, resolvedDocumentId);
5676
+ await resolver.stabilizeRecord("document", result.document, eid);
5677
+ resolver.rememberFromRecord("document", result.document, eid);
5678
+ if (opts.json) {
5679
+ printJson({
5680
+ document_id: resolvedDocumentId,
5681
+ signatures_added: result.signatures_added,
5682
+ document: result.document
5683
+ });
5684
+ return;
5685
+ }
5686
+ printSuccess(
5687
+ result.signatures_added > 0 ? `Applied ${result.signatures_added} signature(s) to ${resolvedDocumentId}.` : `No signatures were needed for ${resolvedDocumentId}.`
5688
+ );
5689
+ printReferenceSummary("document", result.document, { showReuseHint: true });
5690
+ printJson(result.document);
5691
+ } catch (err) {
5692
+ printError(`Failed to sign document: ${err}`);
5693
+ process.exit(1);
5694
+ }
5695
+ }
5696
+ async function documentsSignAllCommand(opts) {
5697
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
5698
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
5699
+ const resolver = new ReferenceResolver(client, cfg);
5700
+ try {
5701
+ const eid = await resolver.resolveEntity(opts.entityId);
5702
+ const result = await autoSignFormationDocuments(client, resolver, eid);
5703
+ if (opts.json) {
5704
+ printJson(result);
5705
+ return;
5706
+ }
5707
+ printSuccess(
5708
+ `Processed ${result.documents_seen} formation document(s); added ${result.signatures_added} signature(s) across ${result.documents_signed} document(s).`
5709
+ );
5710
+ printJson(result.documents.map((document) => ({
5711
+ document_id: document.document_id,
5712
+ title: document.title,
5713
+ status: document.status,
5714
+ signatures: Array.isArray(document.signatures) ? document.signatures.length : document.signatures
5715
+ })));
5716
+ } catch (err) {
5717
+ printError(`Failed to sign formation documents: ${err}`);
5718
+ process.exit(1);
5719
+ }
5720
+ }
5216
5721
  async function documentsPreviewPdfCommand(opts) {
5722
+ if (!opts.documentId || opts.documentId.trim().length === 0) {
5723
+ printError("preview-pdf requires --definition-id (or deprecated alias --document-id)");
5724
+ process.exit(1);
5725
+ }
5217
5726
  const cfg = requireConfig("api_url", "api_key", "workspace_id");
5218
5727
  const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
5219
5728
  const resolver = new ReferenceResolver(client, cfg);
@@ -5236,6 +5745,7 @@ var init_documents = __esm({
5236
5745
  init_api_client();
5237
5746
  init_output();
5238
5747
  init_references();
5748
+ init_formation_automation();
5239
5749
  HUMANS_APP_ORIGIN = "https://humans.thecorporation.ai";
5240
5750
  }
5241
5751
  });
@@ -5560,6 +6070,18 @@ __export(work_items_exports, {
5560
6070
  workItemsShowCommand: () => workItemsShowCommand
5561
6071
  });
5562
6072
  import chalk10 from "chalk";
6073
+ function actorLabel2(record, key) {
6074
+ const actor = record[`${key}_actor`];
6075
+ if (actor && typeof actor === "object" && !Array.isArray(actor)) {
6076
+ const label = actor.label;
6077
+ const actorType = actor.actor_type;
6078
+ if (typeof label === "string" && label.trim()) {
6079
+ return typeof actorType === "string" && actorType.trim() ? `${label} (${actorType})` : label;
6080
+ }
6081
+ }
6082
+ const legacy = record[key];
6083
+ return typeof legacy === "string" && legacy.trim() ? legacy : void 0;
6084
+ }
5563
6085
  async function workItemsListCommand(opts) {
5564
6086
  const cfg = requireConfig("api_url", "api_key", "workspace_id");
5565
6087
  const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
@@ -5602,13 +6124,16 @@ async function workItemsShowCommand(workItemId, opts) {
5602
6124
  if (w.description) console.log(` ${chalk10.bold("Description:")} ${w.description}`);
5603
6125
  if (w.deadline) console.log(` ${chalk10.bold("Deadline:")} ${w.deadline}`);
5604
6126
  if (w.asap) console.log(` ${chalk10.bold("Priority:")} ${chalk10.red.bold("ASAP")}`);
5605
- if (w.claimed_by) console.log(` ${chalk10.bold("Claimed by:")} ${w.claimed_by}`);
6127
+ const claimedBy = actorLabel2(w, "claimed_by");
6128
+ const completedBy = actorLabel2(w, "completed_by");
6129
+ const createdBy = actorLabel2(w, "created_by");
6130
+ if (claimedBy) console.log(` ${chalk10.bold("Claimed by:")} ${claimedBy}`);
5606
6131
  if (w.claimed_at) console.log(` ${chalk10.bold("Claimed at:")} ${w.claimed_at}`);
5607
6132
  if (w.claim_ttl_seconds) console.log(` ${chalk10.bold("Claim TTL:")} ${w.claim_ttl_seconds}s`);
5608
- if (w.completed_by) console.log(` ${chalk10.bold("Completed by:")} ${w.completed_by}`);
6133
+ if (completedBy) console.log(` ${chalk10.bold("Completed by:")} ${completedBy}`);
5609
6134
  if (w.completed_at) console.log(` ${chalk10.bold("Completed at:")} ${w.completed_at}`);
5610
6135
  if (w.result) console.log(` ${chalk10.bold("Result:")} ${w.result}`);
5611
- if (w.created_by) console.log(` ${chalk10.bold("Created by:")} ${w.created_by}`);
6136
+ if (createdBy) console.log(` ${chalk10.bold("Created by:")} ${createdBy}`);
5612
6137
  console.log(` ${chalk10.bold("Created at:")} ${w.created_at ?? "N/A"}`);
5613
6138
  console.log(chalk10.cyan("\u2500".repeat(40)));
5614
6139
  } catch (err) {
@@ -5630,7 +6155,7 @@ async function workItemsCreateCommand(opts) {
5630
6155
  if (opts.description) data.description = opts.description;
5631
6156
  if (opts.deadline) data.deadline = opts.deadline;
5632
6157
  if (opts.asap) data.asap = true;
5633
- if (opts.createdBy) data.created_by = await resolver.resolveContact(eid, opts.createdBy);
6158
+ if (opts.createdBy) data.created_by_actor = await resolver.resolveWorkItemActor(eid, opts.createdBy);
5634
6159
  const result = await client.createWorkItem(eid, data);
5635
6160
  await resolver.stabilizeRecord("work_item", result, eid);
5636
6161
  resolver.rememberFromRecord("work_item", result, eid);
@@ -5652,7 +6177,7 @@ async function workItemsClaimCommand(workItemId, opts) {
5652
6177
  const eid = await resolver.resolveEntity(opts.entityId);
5653
6178
  const resolvedWorkItemId = await resolver.resolveWorkItem(eid, workItemId);
5654
6179
  const data = {
5655
- claimed_by: await resolver.resolveContact(eid, opts.claimedBy)
6180
+ claimed_by_actor: await resolver.resolveWorkItemActor(eid, opts.claimedBy)
5656
6181
  };
5657
6182
  if (opts.ttl != null) data.ttl_seconds = opts.ttl;
5658
6183
  const result = await client.claimWorkItem(eid, resolvedWorkItemId, data);
@@ -5670,7 +6195,7 @@ async function workItemsCompleteCommand(workItemId, opts) {
5670
6195
  const eid = await resolver.resolveEntity(opts.entityId);
5671
6196
  const resolvedWorkItemId = await resolver.resolveWorkItem(eid, workItemId);
5672
6197
  const data = {
5673
- completed_by: await resolver.resolveContact(eid, opts.completedBy)
6198
+ completed_by_actor: await resolver.resolveWorkItemActor(eid, opts.completedBy)
5674
6199
  };
5675
6200
  if (opts.result) data.result = opts.result;
5676
6201
  const result = await client.completeWorkItem(eid, resolvedWorkItemId, data);
@@ -5718,6 +6243,171 @@ var init_work_items = __esm({
5718
6243
  }
5719
6244
  });
5720
6245
 
6246
+ // src/commands/services.ts
6247
+ var services_exports = {};
6248
+ __export(services_exports, {
6249
+ servicesBuyCommand: () => servicesBuyCommand,
6250
+ servicesCancelCommand: () => servicesCancelCommand,
6251
+ servicesCatalogCommand: () => servicesCatalogCommand,
6252
+ servicesFulfillCommand: () => servicesFulfillCommand,
6253
+ servicesListCommand: () => servicesListCommand,
6254
+ servicesShowCommand: () => servicesShowCommand
6255
+ });
6256
+ import chalk11 from "chalk";
6257
+ async function servicesCatalogCommand(opts) {
6258
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
6259
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
6260
+ try {
6261
+ const items = await client.listServiceCatalog();
6262
+ if (opts.json) {
6263
+ printJson(items);
6264
+ return;
6265
+ }
6266
+ printServiceCatalogTable(items);
6267
+ } catch (err) {
6268
+ printError(`Failed to list service catalog: ${err}`);
6269
+ process.exit(1);
6270
+ }
6271
+ }
6272
+ async function servicesBuyCommand(slug, opts) {
6273
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
6274
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
6275
+ const resolver = new ReferenceResolver(client, cfg);
6276
+ try {
6277
+ const eid = await resolver.resolveEntity(opts.entityId);
6278
+ const payload = { entity_id: eid, service_slug: slug };
6279
+ if (opts.dryRun) {
6280
+ printDryRun("services.create_request", payload);
6281
+ return;
6282
+ }
6283
+ const result = await client.createServiceRequest(payload);
6284
+ await resolver.stabilizeRecord("service_request", result, eid);
6285
+ resolver.rememberFromRecord("service_request", result, eid);
6286
+ const requestId = String(result.request_id ?? result.id ?? "");
6287
+ if (requestId) {
6288
+ const checkout = await client.beginServiceCheckout(requestId, { entity_id: eid });
6289
+ if (opts.json) {
6290
+ printJson(checkout);
6291
+ return;
6292
+ }
6293
+ printSuccess(`Service request created: ${requestId}`);
6294
+ printReferenceSummary("service_request", result, { showReuseHint: true });
6295
+ if (checkout.checkout_url) {
6296
+ console.log(`
6297
+ ${chalk11.bold("Checkout URL:")} ${checkout.checkout_url}`);
6298
+ }
6299
+ console.log(chalk11.dim("\n Next steps:"));
6300
+ console.log(chalk11.dim(" Complete payment at the checkout URL above"));
6301
+ console.log(chalk11.dim(" corp services list --entity-id <id>"));
6302
+ } else {
6303
+ printWriteResult(result, "Service request created", {
6304
+ referenceKind: "service_request",
6305
+ showReuseHint: true
6306
+ });
6307
+ }
6308
+ } catch (err) {
6309
+ printError(`Failed to create service request: ${err}`);
6310
+ process.exit(1);
6311
+ }
6312
+ }
6313
+ async function servicesListCommand(opts) {
6314
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
6315
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
6316
+ const resolver = new ReferenceResolver(client, cfg);
6317
+ try {
6318
+ const eid = await resolver.resolveEntity(opts.entityId);
6319
+ const requests = await client.listServiceRequests(eid);
6320
+ const stable = await resolver.stabilizeRecords("service_request", requests, eid);
6321
+ if (opts.json) {
6322
+ printJson(stable);
6323
+ return;
6324
+ }
6325
+ printServiceRequestsTable(stable);
6326
+ } catch (err) {
6327
+ printError(`Failed to list service requests: ${err}`);
6328
+ process.exit(1);
6329
+ }
6330
+ }
6331
+ async function servicesShowCommand(ref_, opts) {
6332
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
6333
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
6334
+ const resolver = new ReferenceResolver(client, cfg);
6335
+ try {
6336
+ const eid = await resolver.resolveEntity(opts.entityId);
6337
+ const requestId = await resolver.resolveServiceRequest(eid, ref_);
6338
+ const result = await client.getServiceRequest(requestId, eid);
6339
+ await resolver.stabilizeRecord("service_request", result, eid);
6340
+ resolver.rememberFromRecord("service_request", result, eid);
6341
+ if (opts.json) {
6342
+ printJson(result);
6343
+ return;
6344
+ }
6345
+ printReferenceSummary("service_request", result);
6346
+ printJson(result);
6347
+ } catch (err) {
6348
+ printError(`Failed to show service request: ${err}`);
6349
+ process.exit(1);
6350
+ }
6351
+ }
6352
+ async function servicesFulfillCommand(ref_, opts) {
6353
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
6354
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
6355
+ const resolver = new ReferenceResolver(client, cfg);
6356
+ try {
6357
+ const eid = await resolver.resolveEntity(opts.entityId);
6358
+ const requestId = await resolver.resolveServiceRequest(eid, ref_);
6359
+ const result = await client.fulfillServiceRequest(requestId, {
6360
+ entity_id: eid,
6361
+ note: opts.note
6362
+ });
6363
+ await resolver.stabilizeRecord("service_request", result, eid);
6364
+ resolver.rememberFromRecord("service_request", result, eid);
6365
+ if (opts.json) {
6366
+ printJson(result);
6367
+ return;
6368
+ }
6369
+ printSuccess(`Service request fulfilled: ${requestId}`);
6370
+ printReferenceSummary("service_request", result, { showReuseHint: true });
6371
+ printJson(result);
6372
+ } catch (err) {
6373
+ printError(`Failed to fulfill service request: ${err}`);
6374
+ process.exit(1);
6375
+ }
6376
+ }
6377
+ async function servicesCancelCommand(ref_, opts) {
6378
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
6379
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
6380
+ const resolver = new ReferenceResolver(client, cfg);
6381
+ try {
6382
+ const eid = await resolver.resolveEntity(opts.entityId);
6383
+ const requestId = await resolver.resolveServiceRequest(eid, ref_);
6384
+ const result = await client.cancelServiceRequest(requestId, {
6385
+ entity_id: eid
6386
+ });
6387
+ await resolver.stabilizeRecord("service_request", result, eid);
6388
+ resolver.rememberFromRecord("service_request", result, eid);
6389
+ if (opts.json) {
6390
+ printJson(result);
6391
+ return;
6392
+ }
6393
+ printSuccess(`Service request cancelled: ${requestId}`);
6394
+ printReferenceSummary("service_request", result, { showReuseHint: true });
6395
+ printJson(result);
6396
+ } catch (err) {
6397
+ printError(`Failed to cancel service request: ${err}`);
6398
+ process.exit(1);
6399
+ }
6400
+ }
6401
+ var init_services = __esm({
6402
+ "src/commands/services.ts"() {
6403
+ "use strict";
6404
+ init_config();
6405
+ init_api_client();
6406
+ init_output();
6407
+ init_references();
6408
+ }
6409
+ });
6410
+
5721
6411
  // src/commands/billing.ts
5722
6412
  var billing_exports = {};
5723
6413
  __export(billing_exports, {
@@ -5794,16 +6484,42 @@ var init_billing = __esm({
5794
6484
  }
5795
6485
  });
5796
6486
 
6487
+ // src/commands/approvals.ts
6488
+ var approvals_exports = {};
6489
+ __export(approvals_exports, {
6490
+ approvalsListCommand: () => approvalsListCommand,
6491
+ approvalsRespondCommand: () => approvalsRespondCommand
6492
+ });
6493
+ async function approvalsListCommand(_opts) {
6494
+ printError(
6495
+ "Approvals are managed through governance meetings.\n Use: corp governance convene ... to schedule a board meeting\n Use: corp governance vote <meeting-ref> <item-ref> ... to cast votes"
6496
+ );
6497
+ process.exit(1);
6498
+ }
6499
+ async function approvalsRespondCommand(_approvalId, _decision, _opts) {
6500
+ printError(
6501
+ "Approvals are managed through governance meetings.\n Use: corp governance vote <meeting-ref> <item-ref> --voter <contact-ref> --vote for"
6502
+ );
6503
+ process.exit(1);
6504
+ }
6505
+ var init_approvals = __esm({
6506
+ "src/commands/approvals.ts"() {
6507
+ "use strict";
6508
+ init_output();
6509
+ }
6510
+ });
6511
+
5797
6512
  // src/commands/form.ts
5798
6513
  var form_exports = {};
5799
6514
  __export(form_exports, {
6515
+ formActivateCommand: () => formActivateCommand,
5800
6516
  formAddFounderCommand: () => formAddFounderCommand,
5801
6517
  formCommand: () => formCommand,
5802
6518
  formCreateCommand: () => formCreateCommand,
5803
6519
  formFinalizeCommand: () => formFinalizeCommand
5804
6520
  });
5805
- import { input as input2, select, confirm as confirm2, number } from "@inquirer/prompts";
5806
- import chalk11 from "chalk";
6521
+ import { input as input2, select as select2, confirm as confirm2, number } from "@inquirer/prompts";
6522
+ import chalk12 from "chalk";
5807
6523
  import Table3 from "cli-table3";
5808
6524
  import { readFileSync as readFileSync3, realpathSync as realpathSync2 } from "fs";
5809
6525
  import { relative as relative2, resolve as resolve2 } from "path";
@@ -5813,9 +6529,9 @@ function isCorp(entityType) {
5813
6529
  }
5814
6530
  function sectionHeader(title) {
5815
6531
  console.log();
5816
- console.log(chalk11.blue("\u2500".repeat(50)));
5817
- console.log(chalk11.blue.bold(` ${title}`));
5818
- console.log(chalk11.blue("\u2500".repeat(50)));
6532
+ console.log(chalk12.blue("\u2500".repeat(50)));
6533
+ console.log(chalk12.blue.bold(` ${title}`));
6534
+ console.log(chalk12.blue("\u2500".repeat(50)));
5819
6535
  }
5820
6536
  function officerTitleLabel(title) {
5821
6537
  switch (title) {
@@ -5975,7 +6691,7 @@ async function phaseEntityDetails(opts, serverCfg, scripted) {
5975
6691
  if (scripted) {
5976
6692
  entityType = "llc";
5977
6693
  } else {
5978
- entityType = await select({
6694
+ entityType = await select2({
5979
6695
  message: "Entity type",
5980
6696
  choices: [
5981
6697
  { value: "llc", name: "LLC" },
@@ -6034,13 +6750,13 @@ async function phasePeople(opts, entityType, scripted) {
6034
6750
  }
6035
6751
  const founderCount = await number({ message: "Number of founders (1-6)", default: 1 }) ?? 1;
6036
6752
  for (let i = 0; i < founderCount; i++) {
6037
- console.log(chalk11.dim(`
6753
+ console.log(chalk12.dim(`
6038
6754
  Founder ${i + 1} of ${founderCount}:`));
6039
6755
  const name = await input2({ message: ` Name` });
6040
6756
  const email = await input2({ message: ` Email` });
6041
6757
  let role = "member";
6042
6758
  if (isCorp(entityType)) {
6043
- role = await select({
6759
+ role = await select2({
6044
6760
  message: " Role",
6045
6761
  choices: [
6046
6762
  { value: "director", name: "Director" },
@@ -6055,7 +6771,7 @@ async function phasePeople(opts, entityType, scripted) {
6055
6771
  if (isCorp(entityType)) {
6056
6772
  const wantOfficer = role === "officer" || await confirm2({ message: " Assign officer title?", default: i === 0 });
6057
6773
  if (wantOfficer) {
6058
- officerTitle = await select({
6774
+ officerTitle = await select2({
6059
6775
  message: " Officer title",
6060
6776
  choices: OfficerTitle.map((t) => ({
6061
6777
  value: t,
@@ -6080,7 +6796,7 @@ async function phaseStock(opts, entityType, founders, scripted) {
6080
6796
  const rofr = opts.rofr ?? (!scripted && isCorp(entityType) ? await confirm2({ message: "Right of first refusal?", default: true }) : isCorp(entityType));
6081
6797
  if (!scripted) {
6082
6798
  for (const f of founders) {
6083
- console.log(chalk11.dim(`
6799
+ console.log(chalk12.dim(`
6084
6800
  Equity for ${f.name}:`));
6085
6801
  if (isCorp(entityType)) {
6086
6802
  const shares = await number({ message: ` Shares to purchase`, default: 0 });
@@ -6101,7 +6817,7 @@ async function phaseStock(opts, entityType, founders, scripted) {
6101
6817
  if (wantVesting) {
6102
6818
  const totalMonths = await number({ message: " Total vesting months", default: 48 }) ?? 48;
6103
6819
  const cliffMonths = await number({ message: " Cliff months", default: 12 }) ?? 12;
6104
- const acceleration = await select({
6820
+ const acceleration = await select2({
6105
6821
  message: " Acceleration",
6106
6822
  choices: [
6107
6823
  { value: "none", name: "None" },
@@ -6126,17 +6842,17 @@ async function phaseStock(opts, entityType, founders, scripted) {
6126
6842
  }
6127
6843
  function printSummary(entityType, name, jurisdiction, fiscalYearEnd, sCorpElection, founders, transferRestrictions, rofr) {
6128
6844
  sectionHeader("Formation Summary");
6129
- console.log(` ${chalk11.bold("Entity:")} ${name}`);
6130
- console.log(` ${chalk11.bold("Type:")} ${entityType}`);
6131
- console.log(` ${chalk11.bold("Jurisdiction:")} ${jurisdiction}`);
6132
- console.log(` ${chalk11.bold("Fiscal Year End:")} ${fiscalYearEnd}`);
6845
+ console.log(` ${chalk12.bold("Entity:")} ${name}`);
6846
+ console.log(` ${chalk12.bold("Type:")} ${entityType}`);
6847
+ console.log(` ${chalk12.bold("Jurisdiction:")} ${jurisdiction}`);
6848
+ console.log(` ${chalk12.bold("Fiscal Year End:")} ${fiscalYearEnd}`);
6133
6849
  if (isCorp(entityType)) {
6134
- console.log(` ${chalk11.bold("S-Corp Election:")} ${sCorpElection ? "Yes" : "No"}`);
6135
- console.log(` ${chalk11.bold("Transfer Restrictions:")} ${transferRestrictions ? "Yes" : "No"}`);
6136
- console.log(` ${chalk11.bold("Right of First Refusal:")} ${rofr ? "Yes" : "No"}`);
6850
+ console.log(` ${chalk12.bold("S-Corp Election:")} ${sCorpElection ? "Yes" : "No"}`);
6851
+ console.log(` ${chalk12.bold("Transfer Restrictions:")} ${transferRestrictions ? "Yes" : "No"}`);
6852
+ console.log(` ${chalk12.bold("Right of First Refusal:")} ${rofr ? "Yes" : "No"}`);
6137
6853
  }
6138
6854
  const table = new Table3({
6139
- head: [chalk11.dim("Name"), chalk11.dim("Email"), chalk11.dim("Role"), chalk11.dim("Equity"), chalk11.dim("Officer")]
6855
+ head: [chalk12.dim("Name"), chalk12.dim("Email"), chalk12.dim("Role"), chalk12.dim("Equity"), chalk12.dim("Officer")]
6140
6856
  });
6141
6857
  for (const f of founders) {
6142
6858
  const equity = f.shares_purchased ? `${f.shares_purchased.toLocaleString()} shares` : f.ownership_pct ? `${f.ownership_pct}%` : "\u2014";
@@ -6163,7 +6879,7 @@ async function formCommand(opts) {
6163
6879
  printSummary(entityType, name, jurisdiction, fiscalYearEnd, sCorpElection, founders, transferRestrictions, rofr);
6164
6880
  const shouldProceed = scripted ? true : await confirm2({ message: "Proceed with formation?", default: true });
6165
6881
  if (!shouldProceed) {
6166
- console.log(chalk11.yellow("Formation cancelled."));
6882
+ console.log(chalk12.yellow("Formation cancelled."));
6167
6883
  return;
6168
6884
  }
6169
6885
  const members = founders.map((f) => {
@@ -6219,17 +6935,17 @@ async function formCommand(opts) {
6219
6935
  if (holders.length > 0) {
6220
6936
  console.log();
6221
6937
  const table = new Table3({
6222
- head: [chalk11.dim("Holder"), chalk11.dim("Shares"), chalk11.dim("Ownership %")]
6938
+ head: [chalk12.dim("Holder"), chalk12.dim("Shares"), chalk12.dim("Ownership %")]
6223
6939
  });
6224
6940
  for (const h of holders) {
6225
6941
  const pct = typeof h.ownership_pct === "number" ? `${h.ownership_pct.toFixed(1)}%` : "\u2014";
6226
6942
  table.push([String(h.name ?? "?"), String(h.shares ?? 0), pct]);
6227
6943
  }
6228
- console.log(chalk11.bold(" Cap Table:"));
6944
+ console.log(chalk12.bold(" Cap Table:"));
6229
6945
  console.log(table.toString());
6230
6946
  }
6231
6947
  if (result.next_action) {
6232
- console.log(chalk11.yellow(`
6948
+ console.log(chalk12.yellow(`
6233
6949
  Next: ${result.next_action}`));
6234
6950
  }
6235
6951
  } catch (err) {
@@ -6300,7 +7016,7 @@ async function formCreateCommand(opts) {
6300
7016
  console.log(` Type: ${result.entity_type}`);
6301
7017
  console.log(` Jurisdiction: ${result.jurisdiction}`);
6302
7018
  console.log(` Status: ${result.formation_status}`);
6303
- console.log(chalk11.yellow(`
7019
+ console.log(chalk12.yellow(`
6304
7020
  Next: corp form add-founder @last:entity --name "..." --email "..." --role member --pct 50`));
6305
7021
  } catch (err) {
6306
7022
  printError(`Failed to create pending entity: ${err}`);
@@ -6338,7 +7054,7 @@ async function formAddFounderCommand(entityId, opts) {
6338
7054
  const pct = typeof m.ownership_pct === "number" ? ` (${m.ownership_pct}%)` : "";
6339
7055
  console.log(` - ${m.name} <${m.email ?? "no email"}> [${m.role ?? "member"}]${pct}`);
6340
7056
  }
6341
- console.log(chalk11.yellow(`
7057
+ console.log(chalk12.yellow(`
6342
7058
  Next: add more founders or run: corp form finalize @last:entity`));
6343
7059
  } catch (err) {
6344
7060
  printError(`Failed to add founder: ${err}`);
@@ -6402,17 +7118,17 @@ async function formFinalizeCommand(entityId, opts) {
6402
7118
  if (holders.length > 0) {
6403
7119
  console.log();
6404
7120
  const table = new Table3({
6405
- head: [chalk11.dim("Holder"), chalk11.dim("Shares"), chalk11.dim("Ownership %")]
7121
+ head: [chalk12.dim("Holder"), chalk12.dim("Shares"), chalk12.dim("Ownership %")]
6406
7122
  });
6407
7123
  for (const h of holders) {
6408
7124
  const pct = typeof h.ownership_pct === "number" ? `${h.ownership_pct.toFixed(1)}%` : "\u2014";
6409
7125
  table.push([String(h.name ?? "?"), String(h.shares ?? 0), pct]);
6410
7126
  }
6411
- console.log(chalk11.bold(" Cap Table:"));
7127
+ console.log(chalk12.bold(" Cap Table:"));
6412
7128
  console.log(table.toString());
6413
7129
  }
6414
7130
  if (result.next_action) {
6415
- console.log(chalk11.yellow(`
7131
+ console.log(chalk12.yellow(`
6416
7132
  Next: ${result.next_action}`));
6417
7133
  }
6418
7134
  } catch (err) {
@@ -6420,6 +7136,55 @@ async function formFinalizeCommand(entityId, opts) {
6420
7136
  process.exit(1);
6421
7137
  }
6422
7138
  }
7139
+ async function formActivateCommand(entityId, opts) {
7140
+ const cfg = requireConfig("api_url", "api_key", "workspace_id");
7141
+ const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
7142
+ const resolver = new ReferenceResolver(client, cfg);
7143
+ try {
7144
+ const resolvedEntityId = await resolveEntityRefForFormCommand(resolver, entityId, opts.dryRun);
7145
+ const payload = { entity_id: resolvedEntityId };
7146
+ if (opts.evidenceUri) payload.evidence_uri = opts.evidenceUri;
7147
+ if (opts.evidenceType) payload.evidence_type = opts.evidenceType;
7148
+ if (opts.filingId) payload.filing_id = opts.filingId;
7149
+ if (opts.receiptReference) payload.receipt_reference = opts.receiptReference;
7150
+ if (opts.ein) payload.ein = opts.ein;
7151
+ if (opts.dryRun) {
7152
+ printDryRun("formation.activate", payload);
7153
+ return;
7154
+ }
7155
+ const result = await activateFormationEntity(client, resolver, resolvedEntityId, {
7156
+ evidenceUri: opts.evidenceUri,
7157
+ evidenceType: opts.evidenceType,
7158
+ filingId: opts.filingId,
7159
+ receiptReference: opts.receiptReference,
7160
+ ein: opts.ein
7161
+ });
7162
+ const formation = await client.getFormation(resolvedEntityId);
7163
+ await resolver.stabilizeRecord("entity", formation);
7164
+ resolver.rememberFromRecord("entity", formation);
7165
+ if (opts.json) {
7166
+ printJson({
7167
+ ...result,
7168
+ formation
7169
+ });
7170
+ return;
7171
+ }
7172
+ printSuccess(`Formation advanced to ${result.final_status}.`);
7173
+ printReferenceSummary("entity", formation, { showReuseHint: true });
7174
+ if (result.steps.length > 0) {
7175
+ console.log(" Steps:");
7176
+ for (const step of result.steps) {
7177
+ console.log(` - ${step}`);
7178
+ }
7179
+ }
7180
+ console.log(` Signatures added: ${result.signatures_added}`);
7181
+ console.log(` Documents updated: ${result.documents_signed}`);
7182
+ printJson(formation);
7183
+ } catch (err) {
7184
+ printError(`Failed to activate formation: ${err}`);
7185
+ process.exit(1);
7186
+ }
7187
+ }
6423
7188
  var init_form = __esm({
6424
7189
  "src/commands/form.ts"() {
6425
7190
  "use strict";
@@ -6427,6 +7192,7 @@ var init_form = __esm({
6427
7192
  init_api_client();
6428
7193
  init_output();
6429
7194
  init_references();
7195
+ init_formation_automation();
6430
7196
  }
6431
7197
  });
6432
7198
 
@@ -6435,7 +7201,7 @@ var api_keys_exports = {};
6435
7201
  __export(api_keys_exports, {
6436
7202
  apiKeysCommand: () => apiKeysCommand
6437
7203
  });
6438
- import chalk12 from "chalk";
7204
+ import chalk13 from "chalk";
6439
7205
  import Table4 from "cli-table3";
6440
7206
  async function apiKeysCommand(opts) {
6441
7207
  const cfg = requireConfig("api_url", "api_key", "workspace_id");
@@ -6455,9 +7221,9 @@ async function apiKeysCommand(opts) {
6455
7221
  return;
6456
7222
  }
6457
7223
  console.log(`
6458
- ${chalk12.bold("API Keys")}`);
7224
+ ${chalk13.bold("API Keys")}`);
6459
7225
  const table = new Table4({
6460
- head: [chalk12.dim("ID"), chalk12.dim("Name"), chalk12.dim("Key"), chalk12.dim("Created")]
7226
+ head: [chalk13.dim("ID"), chalk13.dim("Name"), chalk13.dim("Key"), chalk13.dim("Created")]
6461
7227
  });
6462
7228
  for (const k of keys) {
6463
7229
  table.push([
@@ -6487,12 +7253,235 @@ var demo_exports = {};
6487
7253
  __export(demo_exports, {
6488
7254
  demoCommand: () => demoCommand
6489
7255
  });
7256
+ function scenarioConfig(name, scenario) {
7257
+ switch (scenario) {
7258
+ case "llc":
7259
+ return {
7260
+ entity_type: "llc",
7261
+ legal_name: name,
7262
+ jurisdiction: "US-WY",
7263
+ members: [
7264
+ {
7265
+ name: "Alice Chen",
7266
+ email: "alice@example.com",
7267
+ role: "member",
7268
+ investor_type: "natural_person",
7269
+ ownership_pct: 60
7270
+ },
7271
+ {
7272
+ name: "Bob Martinez",
7273
+ email: "bob@example.com",
7274
+ role: "member",
7275
+ investor_type: "natural_person",
7276
+ ownership_pct: 40
7277
+ }
7278
+ ],
7279
+ fiscal_year_end: "12-31",
7280
+ company_address: {
7281
+ street: "251 Little Falls Dr",
7282
+ city: "Wilmington",
7283
+ state: "DE",
7284
+ zip: "19808"
7285
+ }
7286
+ };
7287
+ case "restaurant":
7288
+ return {
7289
+ entity_type: "llc",
7290
+ legal_name: name,
7291
+ jurisdiction: "US-DE",
7292
+ members: [
7293
+ {
7294
+ name: "Rosa Alvarez",
7295
+ email: "rosa@example.com",
7296
+ role: "manager",
7297
+ investor_type: "natural_person",
7298
+ ownership_pct: 55
7299
+ },
7300
+ {
7301
+ name: "Noah Patel",
7302
+ email: "noah@example.com",
7303
+ role: "member",
7304
+ investor_type: "natural_person",
7305
+ ownership_pct: 45
7306
+ }
7307
+ ],
7308
+ fiscal_year_end: "12-31",
7309
+ company_address: {
7310
+ street: "18 Market St",
7311
+ city: "Wilmington",
7312
+ state: "DE",
7313
+ zip: "19801"
7314
+ }
7315
+ };
7316
+ case "startup":
7317
+ default:
7318
+ return {
7319
+ entity_type: "c_corp",
7320
+ legal_name: name,
7321
+ jurisdiction: "US-DE",
7322
+ authorized_shares: 1e7,
7323
+ par_value: "0.0001",
7324
+ transfer_restrictions: true,
7325
+ right_of_first_refusal: true,
7326
+ members: [
7327
+ {
7328
+ name: "Alice Chen",
7329
+ email: "alice@example.com",
7330
+ role: "chair",
7331
+ investor_type: "natural_person",
7332
+ shares_purchased: 6e6,
7333
+ officer_title: "ceo",
7334
+ is_incorporator: true
7335
+ },
7336
+ {
7337
+ name: "Bob Martinez",
7338
+ email: "bob@example.com",
7339
+ role: "director",
7340
+ investor_type: "natural_person",
7341
+ shares_purchased: 4e6,
7342
+ officer_title: "cto"
7343
+ }
7344
+ ],
7345
+ fiscal_year_end: "12-31",
7346
+ company_address: {
7347
+ street: "251 Little Falls Dr",
7348
+ city: "Wilmington",
7349
+ state: "DE",
7350
+ zip: "19808"
7351
+ }
7352
+ };
7353
+ }
7354
+ }
7355
+ function meetingTypeForBody(body) {
7356
+ return String(body.body_type) === "llc_member_vote" ? "member_meeting" : "board_meeting";
7357
+ }
6490
7358
  async function demoCommand(opts) {
6491
7359
  const cfg = requireConfig("api_url", "api_key", "workspace_id");
6492
7360
  const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
7361
+ const resolver = new ReferenceResolver(client, cfg);
7362
+ const scenario = opts.scenario ?? "startup";
6493
7363
  try {
6494
- const result = await withSpinner("Loading", () => client.seedDemo(opts.name));
6495
- printSuccess(`Demo seeded: ${result.entity_id ?? "OK"}`);
7364
+ if (opts.minimal) {
7365
+ const result2 = await withSpinner("Loading", () => client.seedDemo({
7366
+ name: opts.name,
7367
+ scenario
7368
+ }));
7369
+ if (opts.json) {
7370
+ printJson(result2);
7371
+ return;
7372
+ }
7373
+ printSuccess("Minimal demo seeded.");
7374
+ printJson(result2);
7375
+ return;
7376
+ }
7377
+ const formationPayload = scenarioConfig(opts.name, scenario);
7378
+ const created = await withSpinner(
7379
+ "Creating demo entity",
7380
+ () => client.createFormationWithCapTable(formationPayload)
7381
+ );
7382
+ const entityId = String(created.entity_id ?? created.formation_id ?? "");
7383
+ if (!entityId) {
7384
+ throw new Error("demo formation did not return an entity_id");
7385
+ }
7386
+ await resolver.stabilizeRecord("entity", created);
7387
+ resolver.rememberFromRecord("entity", created);
7388
+ const activation = await withSpinner(
7389
+ "Activating formation",
7390
+ () => activateFormationEntity(client, resolver, entityId)
7391
+ );
7392
+ const agent = await withSpinner(
7393
+ "Creating demo agent",
7394
+ () => client.createAgent({
7395
+ name: `${opts.name} Operator`,
7396
+ entity_id: entityId,
7397
+ system_prompt: `Operate ${opts.name} and keep the workspace data clean.`,
7398
+ scopes: []
7399
+ })
7400
+ );
7401
+ await resolver.stabilizeRecord("agent", agent);
7402
+ resolver.rememberFromRecord("agent", agent);
7403
+ const bodies = await client.listGovernanceBodies(entityId);
7404
+ await resolver.stabilizeRecords("body", bodies, entityId);
7405
+ let meeting;
7406
+ if (bodies.length > 0) {
7407
+ meeting = await client.scheduleMeeting({
7408
+ entity_id: entityId,
7409
+ body_id: bodies[0].body_id,
7410
+ meeting_type: meetingTypeForBody(bodies[0]),
7411
+ title: "Demo kickoff meeting",
7412
+ agenda_item_titles: [
7413
+ "Approve demo operating budget",
7414
+ "Review founder vesting and cap table"
7415
+ ]
7416
+ });
7417
+ await resolver.stabilizeRecord("meeting", meeting, entityId);
7418
+ resolver.rememberFromRecord("meeting", meeting, entityId);
7419
+ }
7420
+ const workItem = await client.createWorkItem(entityId, {
7421
+ title: "Review demo workspace",
7422
+ description: "Check documents, governance, cap table, and treasury setup.",
7423
+ category: "ops",
7424
+ created_by_actor: {
7425
+ actor_type: "agent",
7426
+ actor_id: String(agent.agent_id)
7427
+ }
7428
+ });
7429
+ await resolver.stabilizeRecord("work_item", workItem, entityId);
7430
+ resolver.rememberFromRecord("work_item", workItem, entityId);
7431
+ const claimedWorkItem = await client.claimWorkItem(entityId, String(workItem.work_item_id), {
7432
+ claimed_by_actor: {
7433
+ actor_type: "agent",
7434
+ actor_id: String(agent.agent_id)
7435
+ }
7436
+ });
7437
+ const bankAccount = await client.openBankAccount({
7438
+ entity_id: entityId,
7439
+ bank_name: "Mercury"
7440
+ });
7441
+ await resolver.stabilizeRecord("bank_account", bankAccount, entityId);
7442
+ resolver.rememberFromRecord("bank_account", bankAccount, entityId);
7443
+ const invoice = await client.createInvoice({
7444
+ entity_id: entityId,
7445
+ customer_name: "Acme Customer",
7446
+ amount_cents: 25e4,
7447
+ due_date: "2026-04-01",
7448
+ description: "Demo advisory services"
7449
+ });
7450
+ await resolver.stabilizeRecord("invoice", invoice, entityId);
7451
+ resolver.rememberFromRecord("invoice", invoice, entityId);
7452
+ const contract = await client.generateContract({
7453
+ entity_id: entityId,
7454
+ template_type: "nda",
7455
+ counterparty_name: "Example Counterparty",
7456
+ effective_date: "2026-03-12",
7457
+ parameters: {}
7458
+ });
7459
+ await resolver.stabilizeRecord("document", contract, entityId);
7460
+ resolver.rememberFromRecord("document", contract, entityId);
7461
+ const result = {
7462
+ scenario,
7463
+ entity: created,
7464
+ activation,
7465
+ agent,
7466
+ meeting,
7467
+ work_item: claimedWorkItem,
7468
+ bank_account: bankAccount,
7469
+ invoice,
7470
+ contract
7471
+ };
7472
+ if (opts.json) {
7473
+ printJson(result);
7474
+ return;
7475
+ }
7476
+ printSuccess(`Demo environment created for ${opts.name}.`);
7477
+ printReferenceSummary("entity", created, { showReuseHint: true });
7478
+ printReferenceSummary("agent", agent, { showReuseHint: true });
7479
+ if (meeting) {
7480
+ printReferenceSummary("meeting", meeting, { showReuseHint: true });
7481
+ }
7482
+ printReferenceSummary("work_item", claimedWorkItem, { showReuseHint: true });
7483
+ printReferenceSummary("invoice", invoice, { showReuseHint: true });
7484
+ printReferenceSummary("bank_account", bankAccount, { showReuseHint: true });
6496
7485
  printJson(result);
6497
7486
  } catch (err) {
6498
7487
  printError(`Failed to seed demo: ${err}`);
@@ -6506,6 +7495,8 @@ var init_demo = __esm({
6506
7495
  init_api_client();
6507
7496
  init_output();
6508
7497
  init_spinner();
7498
+ init_references();
7499
+ init_formation_automation();
6509
7500
  }
6510
7501
  });
6511
7502
 
@@ -6514,7 +7505,7 @@ var feedback_exports = {};
6514
7505
  __export(feedback_exports, {
6515
7506
  feedbackCommand: () => feedbackCommand
6516
7507
  });
6517
- import chalk13 from "chalk";
7508
+ import chalk14 from "chalk";
6518
7509
  async function feedbackCommand(message, opts) {
6519
7510
  if (!message || message.trim().length === 0) {
6520
7511
  printError("Feedback message cannot be empty");
@@ -6533,9 +7524,17 @@ async function feedbackCommand(message, opts) {
6533
7524
  return;
6534
7525
  }
6535
7526
  console.log(`
6536
- ${chalk13.green("\u2713")} Feedback submitted (${chalk13.dim(result.feedback_id)})`);
7527
+ ${chalk14.green("\u2713")} Feedback submitted (${chalk14.dim(result.feedback_id)})`);
6537
7528
  } catch (err) {
6538
- printError("Failed to submit feedback", err);
7529
+ const detail = String(err);
7530
+ if (detail.includes("404")) {
7531
+ printError(
7532
+ `Failed to submit feedback: ${detail}
7533
+ This server does not expose /v1/feedback. Local api-rs dev servers currently do not support feedback submission.`
7534
+ );
7535
+ } else {
7536
+ printError(`Failed to submit feedback: ${detail}`);
7537
+ }
6539
7538
  process.exit(1);
6540
7539
  }
6541
7540
  }
@@ -6555,38 +7554,8 @@ var serve_exports = {};
6555
7554
  __export(serve_exports, {
6556
7555
  serveCommand: () => serveCommand
6557
7556
  });
6558
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
6559
7557
  import { resolve as resolve3 } from "path";
6560
- import { randomBytes } from "crypto";
6561
- function generateFernetKey() {
6562
- return randomBytes(32).toString("base64url") + "=";
6563
- }
6564
- function generateSecret(length = 32) {
6565
- return randomBytes(length).toString("hex");
6566
- }
6567
- function loadEnvFile(path) {
6568
- if (!existsSync2(path)) return;
6569
- const content = readFileSync4(path, "utf-8");
6570
- for (const line of content.split("\n")) {
6571
- const trimmed = line.trim();
6572
- if (!trimmed || trimmed.startsWith("#")) continue;
6573
- const eqIdx = trimmed.indexOf("=");
6574
- if (eqIdx === -1) continue;
6575
- const key = trimmed.slice(0, eqIdx).trim();
6576
- const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
6577
- if (!process.env[key]) {
6578
- process.env[key] = value;
6579
- }
6580
- }
6581
- }
6582
- function ensureEnvFile(envPath) {
6583
- if (existsSync2(envPath)) return;
6584
- console.log("No .env file found. Generating one with dev defaults...\n");
6585
- const content = ENV_TEMPLATE.replace("{{JWT_SECRET}}", generateSecret()).replace("{{SECRETS_MASTER_KEY}}", generateFernetKey()).replace("{{INTERNAL_WORKER_TOKEN}}", generateSecret());
6586
- writeFileSync2(envPath, content, "utf-8");
6587
- console.log(` Created ${envPath}
6588
- `);
6589
- }
7558
+ import { ensureEnvFile, loadEnvFile } from "@thecorporation/corp-tools";
6590
7559
  async function serveCommand(opts) {
6591
7560
  let server;
6592
7561
  try {
@@ -6631,40 +7600,9 @@ async function serveCommand(opts) {
6631
7600
  process.exit(code ?? 0);
6632
7601
  });
6633
7602
  }
6634
- var ENV_TEMPLATE;
6635
7603
  var init_serve = __esm({
6636
7604
  "src/commands/serve.ts"() {
6637
7605
  "use strict";
6638
- ENV_TEMPLATE = `# Corporation API server configuration
6639
- # Generated by: corp serve
6640
-
6641
- # Required \u2014 secret for signing JWTs
6642
- JWT_SECRET={{JWT_SECRET}}
6643
-
6644
- # Required \u2014 Fernet key for encrypting secrets at rest (base64url, 32 bytes)
6645
- SECRETS_MASTER_KEY={{SECRETS_MASTER_KEY}}
6646
-
6647
- # Required \u2014 bearer token for internal worker-to-server auth
6648
- INTERNAL_WORKER_TOKEN={{INTERNAL_WORKER_TOKEN}}
6649
-
6650
- # Server port (default: 8000)
6651
- # PORT=8000
6652
-
6653
- # Data directory for git repos (default: ./data/repos)
6654
- # DATA_DIR=./data/repos
6655
-
6656
- # Redis URL for agent job queue (optional)
6657
- # REDIS_URL=redis://localhost:6379/0
6658
-
6659
- # LLM proxy upstream (default: https://openrouter.ai/api/v1)
6660
- # LLM_UPSTREAM_URL=https://openrouter.ai/api/v1
6661
-
6662
- # PEM-encoded Ed25519 key for signing git commits (optional)
6663
- # COMMIT_SIGNING_KEY=
6664
-
6665
- # Max agent queue depth (default: 1000)
6666
- # MAX_QUEUE_DEPTH=1000
6667
- `;
6668
7606
  }
6669
7607
  });
6670
7608
 
@@ -6699,6 +7637,12 @@ var TAX_DOCUMENT_TYPE_CHOICES = [
6699
7637
  "w2",
6700
7638
  "form_w2"
6701
7639
  ];
7640
+ var FINALIZE_ITEM_STATUS_CHOICES = [
7641
+ "discussed",
7642
+ "voted",
7643
+ "tabled",
7644
+ "withdrawn"
7645
+ ];
6702
7646
  var program = new Command();
6703
7647
  program.name("corp").description("corp \u2014 Corporate governance from the terminal").version(pkg.version);
6704
7648
  program.command("setup").description("Interactive setup wizard").action(async () => {
@@ -6949,7 +7893,10 @@ capTableCmd.command("approve-valuation <valuation-ref>").option("--resolution-id
6949
7893
  json: inheritOption(opts.json, parent.json)
6950
7894
  });
6951
7895
  });
6952
- var financeCmd = program.command("finance").description("Invoicing, payroll, payments, banking").option("--entity-id <ref>", "Entity reference (ID, short ID, @last, or unique name)").option("--json", "Output as JSON");
7896
+ var financeCmd = program.command("finance").description("Invoicing, payroll, payments, banking").option("--entity-id <ref>", "Entity reference (ID, short ID, @last, or unique name)").option("--json", "Output as JSON").action(async (opts) => {
7897
+ const { financeSummaryCommand: financeSummaryCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
7898
+ await financeSummaryCommand2(opts);
7899
+ });
6953
7900
  financeCmd.command("invoices").option("--json", "Output as JSON").description("List invoices").action(async (opts, cmd) => {
6954
7901
  const parent = cmd.parent.opts();
6955
7902
  const { financeInvoicesCommand: financeInvoicesCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
@@ -7173,7 +8120,12 @@ governanceCmd.command("agenda-items <meeting-ref>").description("List agenda ite
7173
8120
  const { listAgendaItemsCommand: listAgendaItemsCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
7174
8121
  await listAgendaItemsCommand2(meetingId, { entityId: parent.entityId, json: parent.json });
7175
8122
  });
7176
- governanceCmd.command("finalize-item <meeting-ref> <item-ref>").requiredOption("--status <status>", "Status: voted, discussed, tabled, withdrawn").option("--json", "Output as JSON").option("--dry-run", "Show the request without finalizing the item").description("Finalize an agenda item").action(async (meetingId, itemId, opts, cmd) => {
8123
+ governanceCmd.command("finalize-item <meeting-ref> <item-ref>").addOption(
8124
+ new Option(
8125
+ "--status <status>",
8126
+ `Status (${FINALIZE_ITEM_STATUS_CHOICES.join(", ")})`
8127
+ ).choices([...FINALIZE_ITEM_STATUS_CHOICES]).makeOptionMandatory()
8128
+ ).option("--json", "Output as JSON").option("--dry-run", "Show the request without finalizing the item").description("Finalize an agenda item").action(async (meetingId, itemId, opts, cmd) => {
7177
8129
  const parent = cmd.parent.opts();
7178
8130
  const { finalizeAgendaItemCommand: finalizeAgendaItemCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
7179
8131
  await finalizeAgendaItemCommand2(meetingId, itemId, {
@@ -7209,6 +8161,24 @@ documentsCmd.command("signing-link <doc-ref>").option("--entity-id <ref>", "Enti
7209
8161
  const { documentsSigningLinkCommand: documentsSigningLinkCommand2 } = await Promise.resolve().then(() => (init_documents(), documents_exports));
7210
8162
  await documentsSigningLinkCommand2(docId, { entityId: opts.entityId ?? parent.entityId });
7211
8163
  });
8164
+ documentsCmd.command("sign <doc-ref>").option("--entity-id <ref>", "Entity reference (overrides active entity and parent command)").option("--signer-name <name>", "Manual signer name").option("--signer-role <role>", "Manual signer role").option("--signer-email <email>", "Manual signer email").option("--signature-text <text>", "Manual signature text (defaults to signer name)").option("--json", "Output as JSON").description("Sign a formation document, or auto-sign all missing required signatures").action(async (docId, opts, cmd) => {
8165
+ const parent = cmd.parent.opts();
8166
+ const { documentsSignCommand: documentsSignCommand2 } = await Promise.resolve().then(() => (init_documents(), documents_exports));
8167
+ await documentsSignCommand2(docId, {
8168
+ ...opts,
8169
+ entityId: opts.entityId ?? parent.entityId,
8170
+ json: inheritOption(opts.json, parent.json)
8171
+ });
8172
+ });
8173
+ documentsCmd.command("sign-all").option("--entity-id <ref>", "Entity reference (overrides active entity and parent command)").option("--json", "Output as JSON").description("Auto-sign all outstanding formation documents for an entity").action(async (opts, cmd) => {
8174
+ const parent = cmd.parent.opts();
8175
+ const { documentsSignAllCommand: documentsSignAllCommand2 } = await Promise.resolve().then(() => (init_documents(), documents_exports));
8176
+ await documentsSignAllCommand2({
8177
+ ...opts,
8178
+ entityId: opts.entityId ?? parent.entityId,
8179
+ json: inheritOption(opts.json, parent.json)
8180
+ });
8181
+ });
7212
8182
  documentsCmd.command("generate").requiredOption("--template <type>", "Template type (consulting_agreement, employment_offer, contractor_agreement, nda, custom)").requiredOption("--counterparty <name>", "Counterparty name").option("--effective-date <date>", "Effective date (ISO 8601, defaults to today)").option("--base-salary <amount>", "Employment offer base salary (for employment_offer)").option("--param <key=value>", "Additional template parameter (repeatable)", (value, values) => [...values, value], []).option("--json", "Output as JSON").description("Generate a contract from a template").action(async (opts, cmd) => {
7213
8183
  const parent = cmd.parent.opts();
7214
8184
  const { documentsGenerateCommand: documentsGenerateCommand2 } = await Promise.resolve().then(() => (init_documents(), documents_exports));
@@ -7218,7 +8188,7 @@ documentsCmd.command("generate").requiredOption("--template <type>", "Template t
7218
8188
  json: inheritOption(opts.json, parent.json)
7219
8189
  });
7220
8190
  });
7221
- documentsCmd.command("preview-pdf").requiredOption("--definition-id <id>", "AST document definition ID (e.g. 'bylaws')").option("--document-id <id>", "Deprecated alias for --definition-id").description("Validate and print the authenticated PDF preview URL for a governance document").action(async (opts, cmd) => {
8191
+ documentsCmd.command("preview-pdf").option("--definition-id <id>", "AST document definition ID (e.g. 'bylaws')").option("--document-id <id>", "Deprecated alias for --definition-id").description("Validate and print the authenticated PDF preview URL for a governance document").action(async (opts, cmd) => {
7222
8192
  const parent = cmd.parent.opts();
7223
8193
  const { documentsPreviewPdfCommand: documentsPreviewPdfCommand2 } = await Promise.resolve().then(() => (init_documents(), documents_exports));
7224
8194
  await documentsPreviewPdfCommand2({
@@ -7390,6 +8360,59 @@ workItemsCmd.command("cancel <item-ref>").option("--json", "Output as JSON").des
7390
8360
  json: inheritOption(opts.json, parent.json)
7391
8361
  });
7392
8362
  });
8363
+ var servicesCmd = program.command("services").description("Service catalog and fulfillment").option("--entity-id <ref>", "Entity reference (ID, short ID, @last, or unique name)").option("--json", "Output as JSON");
8364
+ servicesCmd.command("catalog").option("--json", "Output as JSON").description("List the service catalog").action(async (opts, cmd) => {
8365
+ const parent = cmd.parent.opts();
8366
+ const { servicesCatalogCommand: servicesCatalogCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
8367
+ await servicesCatalogCommand2({
8368
+ json: inheritOption(opts.json, parent.json)
8369
+ });
8370
+ });
8371
+ servicesCmd.command("buy <slug>").option("--json", "Output as JSON").option("--dry-run", "Show the request without executing").description("Purchase a service from the catalog").action(async (slug, opts, cmd) => {
8372
+ const parent = cmd.parent.opts();
8373
+ const { servicesBuyCommand: servicesBuyCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
8374
+ await servicesBuyCommand2(slug, {
8375
+ ...opts,
8376
+ entityId: parent.entityId,
8377
+ json: inheritOption(opts.json, parent.json)
8378
+ });
8379
+ });
8380
+ servicesCmd.command("list").option("--json", "Output as JSON").description("List service requests for an entity").action(async (opts, cmd) => {
8381
+ const parent = cmd.parent.opts();
8382
+ const { servicesListCommand: servicesListCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
8383
+ await servicesListCommand2({
8384
+ ...opts,
8385
+ entityId: parent.entityId,
8386
+ json: inheritOption(opts.json, parent.json)
8387
+ });
8388
+ });
8389
+ servicesCmd.command("show <ref>").option("--json", "Output as JSON").description("Show service request detail").action(async (ref_, opts, cmd) => {
8390
+ const parent = cmd.parent.opts();
8391
+ const { servicesShowCommand: servicesShowCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
8392
+ await servicesShowCommand2(ref_, {
8393
+ ...opts,
8394
+ entityId: parent.entityId,
8395
+ json: inheritOption(opts.json, parent.json)
8396
+ });
8397
+ });
8398
+ servicesCmd.command("fulfill <ref>").option("--note <note>", "Fulfillment note").option("--json", "Output as JSON").description("Mark a service request as fulfilled (operator)").action(async (ref_, opts, cmd) => {
8399
+ const parent = cmd.parent.opts();
8400
+ const { servicesFulfillCommand: servicesFulfillCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
8401
+ await servicesFulfillCommand2(ref_, {
8402
+ ...opts,
8403
+ entityId: parent.entityId,
8404
+ json: inheritOption(opts.json, parent.json)
8405
+ });
8406
+ });
8407
+ servicesCmd.command("cancel <ref>").option("--json", "Output as JSON").description("Cancel a service request").action(async (ref_, opts, cmd) => {
8408
+ const parent = cmd.parent.opts();
8409
+ const { servicesCancelCommand: servicesCancelCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
8410
+ await servicesCancelCommand2(ref_, {
8411
+ ...opts,
8412
+ entityId: parent.entityId,
8413
+ json: inheritOption(opts.json, parent.json)
8414
+ });
8415
+ });
7393
8416
  var billingCmd = program.command("billing").description("Billing status, plans, and subscription management").option("--json", "Output as JSON").action(async (opts) => {
7394
8417
  const { billingCommand: billingCommand2 } = await Promise.resolve().then(() => (init_billing(), billing_exports));
7395
8418
  await billingCommand2(opts);
@@ -7403,10 +8426,8 @@ billingCmd.command("upgrade").option("--plan <plan>", "Plan ID to upgrade to (fr
7403
8426
  await billingUpgradeCommand2(opts);
7404
8427
  });
7405
8428
  program.command("approvals").description("Approvals are managed through governance meetings and execution intents").action(async () => {
7406
- const { printError: printError2 } = await Promise.resolve().then(() => (init_output(), output_exports));
7407
- printError2(
7408
- "Approvals are managed through governance meetings.\n Use: corp governance convene ... to schedule a board meeting\n Use: corp governance vote <meeting-ref> <item-ref> ... to cast votes"
7409
- );
8429
+ const { approvalsListCommand: approvalsListCommand2 } = await Promise.resolve().then(() => (init_approvals(), approvals_exports));
8430
+ await approvalsListCommand2({});
7410
8431
  });
7411
8432
  var formCmd = program.command("form").description("Form a new entity with founders and cap table").option("--entity-type <type>", "Entity type (llc, c_corp)").option("--legal-name <name>", "Legal name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. US-DE, US-WY)").option("--member <member>", "Founder as 'name,email,role[,pct[,address[,officer_title[,is_incorporator]]]]' with address as street|city|state|zip, or key=value pairs like 'name=...,email=...,role=...,officer_title=cto,is_incorporator=true,address=street|city|state|zip' (repeatable)", (v, a) => [...a, v], []).option("--member-json <json>", "Founder JSON object (repeatable)", (v, a) => [...a, v], []).option("--members-file <path>", 'Path to a JSON array of founders or {"members": [...]}').option("--address <address>", "Company address as 'street,city,state,zip'").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)", "12-31").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the entity").action(async (opts) => {
7412
8433
  if (opts.entityType && !opts.type) opts.type = opts.entityType;
@@ -7415,11 +8436,13 @@ var formCmd = program.command("form").description("Form a new entity with founde
7415
8436
  await formCommand2(opts);
7416
8437
  });
7417
8438
  formCmd.command("create").description("Create a pending entity (staged flow step 1)").requiredOption("--type <type>", "Entity type (llc, c_corp)").requiredOption("--name <name>", "Legal name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. US-DE, US-WY)").option("--registered-agent-name <name>", "Registered agent legal name").option("--registered-agent-address <address>", "Registered agent address line").option("--formation-date <date>", "Formation date (RFC3339 or YYYY-MM-DD)").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--company-address <address>", "Company address as 'street,city,state,zip'").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the pending entity").action(async (opts, cmd) => {
8439
+ const parent = cmd.parent.opts();
7418
8440
  const { formCreateCommand: formCreateCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
7419
8441
  await formCreateCommand2({
7420
8442
  ...opts,
7421
- json: inheritOption(opts.json, cmd.parent.opts().json),
7422
- dryRun: inheritOption(opts.dryRun, cmd.parent.opts().dryRun)
8443
+ jurisdiction: inheritOption(opts.jurisdiction, parent.jurisdiction),
8444
+ json: inheritOption(opts.json, parent.json),
8445
+ dryRun: inheritOption(opts.dryRun, parent.dryRun)
7423
8446
  });
7424
8447
  });
7425
8448
  formCmd.command("add-founder <entity-ref>").description("Add a founder to a pending entity (staged flow step 2)").requiredOption("--name <name>", "Founder name").requiredOption("--email <email>", "Founder email").requiredOption("--role <role>", "Role: director|officer|manager|member|chair").requiredOption("--pct <pct>", "Ownership percentage").addOption(new Option("--officer-title <title>", "Officer title (corporations only)").choices(["ceo", "cfo", "cto", "coo", "secretary", "treasurer", "president", "vp", "other"])).option("--incorporator", "Mark as sole incorporator (corporations only)").option("--address <address>", "Founder address as 'street,city,state,zip'").option("--json", "Output as JSON").option("--dry-run", "Show the request without adding the founder").action(async (entityId, opts, cmd) => {
@@ -7438,11 +8461,19 @@ formCmd.command("finalize <entity-ref>").description("Finalize formation and gen
7438
8461
  dryRun: inheritOption(opts.dryRun, cmd.parent.opts().dryRun)
7439
8462
  });
7440
8463
  });
8464
+ formCmd.command("activate <entity-ref>").description("Programmatically sign formation documents and advance an entity to active").option("--evidence-uri <uri>", "Registered-agent consent evidence URI placeholder").option("--evidence-type <type>", "Registered-agent consent evidence type", "generated").option("--filing-id <id>", "External filing identifier to record").option("--receipt-reference <ref>", "External receipt reference to record").option("--ein <ein>", "EIN to confirm (defaults to a deterministic simulated EIN)").option("--json", "Output as JSON").option("--dry-run", "Show the activation plan without mutating").action(async (entityId, opts, cmd) => {
8465
+ const { formActivateCommand: formActivateCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
8466
+ await formActivateCommand2(entityId, {
8467
+ ...opts,
8468
+ json: inheritOption(opts.json, cmd.parent.opts().json),
8469
+ dryRun: inheritOption(opts.dryRun, cmd.parent.opts().dryRun)
8470
+ });
8471
+ });
7441
8472
  program.command("api-keys").description("List API keys").option("--json", "Output as JSON").action(async (opts) => {
7442
8473
  const { apiKeysCommand: apiKeysCommand2 } = await Promise.resolve().then(() => (init_api_keys(), api_keys_exports));
7443
8474
  await apiKeysCommand2(opts);
7444
8475
  });
7445
- program.command("demo").description("Seed a fully-populated demo corporation").requiredOption("--name <name>", "Corporation name").action(async (opts) => {
8476
+ program.command("demo").description("Create a usable demo workspace environment").requiredOption("--name <name>", "Corporation name").option("--scenario <scenario>", "Scenario to create (startup, llc, restaurant)", "startup").option("--minimal", "Use the minimal server-side demo seed instead of the full CLI workflow").option("--json", "Output as JSON").action(async (opts) => {
7446
8477
  const { demoCommand: demoCommand2 } = await Promise.resolve().then(() => (init_demo(), demo_exports));
7447
8478
  await demoCommand2(opts);
7448
8479
  });