@tinycloud/cli 0.5.0 → 0.6.0-beta.1

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
@@ -548,7 +548,7 @@ var ProfileManager = class _ProfileManager {
548
548
  };
549
549
 
550
550
  // src/auth/local-key.ts
551
- import { TCWSessionManager, initPanicHook } from "@tinycloud/node-sdk-wasm";
551
+ import { TCWSessionManager, importKey, initPanicHook } from "@tinycloud/node-sdk-wasm";
552
552
  import { PrivateKeySigner } from "@tinycloud/node-sdk";
553
553
  import { randomBytes } from "crypto";
554
554
  var wasmInitialized = false;
@@ -568,6 +568,12 @@ function generateKey() {
568
568
  const did = mgr.getDID(keyId);
569
569
  return { jwk, did };
570
570
  }
571
+ function keyToDID(jwk) {
572
+ ensureWasm();
573
+ const mgr = new TCWSessionManager();
574
+ const keyId = importKey(mgr, JSON.stringify(jwk), "imported");
575
+ return mgr.getDID(keyId);
576
+ }
571
577
  function generateEthereumPrivateKey() {
572
578
  const keyBytes = randomBytes(32);
573
579
  return "0x" + keyBytes.toString("hex");
@@ -594,10 +600,20 @@ async function localKeySignIn(options) {
594
600
  });
595
601
  await node.signIn();
596
602
  const address = await new PrivateKeySigner(options.privateKey).getAddress();
603
+ const session = node.session;
604
+ if (!session) {
605
+ throw new Error("Local key sign-in did not produce a TinyCloud session");
606
+ }
597
607
  return {
598
- spaceId: node.spaceId ?? "",
608
+ spaceId: session.spaceId,
599
609
  address,
600
- chainId: 1
610
+ chainId: 1,
611
+ delegationHeader: session.delegationHeader,
612
+ delegationCid: session.delegationCid,
613
+ jwk: session.jwk,
614
+ verificationMethod: session.verificationMethod,
615
+ siwe: session.siwe,
616
+ signature: session.signature
601
617
  };
602
618
  }
603
619
 
@@ -843,12 +859,41 @@ function registerInitCommand(program2) {
843
859
  }
844
860
 
845
861
  // src/commands/auth.ts
862
+ import { get as httpGet } from "http";
863
+ import { get as httpsGet } from "https";
864
+ import { spawn } from "child_process";
865
+ import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
866
+ import { dirname as dirname2 } from "path";
846
867
  import { createInterface as createInterface2 } from "readline";
847
868
 
869
+ // src/config/types.ts
870
+ var CLI_PROFILE_POSTURES = [
871
+ "owner-openkey",
872
+ "delegate-session",
873
+ "local-owner-key"
874
+ ];
875
+ var CLI_OPERATOR_TYPES = ["human", "agent"];
876
+ function isCLIProfilePosture(value) {
877
+ return typeof value === "string" && CLI_PROFILE_POSTURES.includes(value);
878
+ }
879
+ function isCLIOperatorType(value) {
880
+ return typeof value === "string" && CLI_OPERATOR_TYPES.includes(value);
881
+ }
882
+ function resolveProfilePosture(profile) {
883
+ if (isCLIProfilePosture(profile.posture)) return profile.posture;
884
+ if (profile.authMethod === "local") return "local-owner-key";
885
+ return "owner-openkey";
886
+ }
887
+ function resolveProfileOperatorType(profile) {
888
+ if (isCLIOperatorType(profile.operatorType)) return profile.operatorType;
889
+ return "human";
890
+ }
891
+
848
892
  // src/lib/sdk.ts
849
893
  import { TinyCloudNode } from "@tinycloud/node-sdk";
850
894
 
851
895
  // src/lib/permissions.ts
896
+ import { randomBytes as randomBytes2 } from "crypto";
852
897
  import { appendFile, readFile as readFile2 } from "fs/promises";
853
898
  import { join as join4 } from "path";
854
899
  import {
@@ -898,9 +943,37 @@ async function resolveSpaceUri(input, profileName) {
898
943
  function additionalDelegationsPath(profile) {
899
944
  return join4(PROFILES_DIR, profile, "additional-delegations.json");
900
945
  }
946
+ function permissionRequestsPath(profile) {
947
+ return join4(PROFILES_DIR, profile, "auth-requests.json");
948
+ }
901
949
  function grantHistoryPath(profile) {
902
950
  return join4(PROFILES_DIR, profile, "auth-grants.jsonl");
903
951
  }
952
+ function createPermissionRequestArtifact(params) {
953
+ return {
954
+ kind: "tinycloud.auth.request",
955
+ version: 1,
956
+ requestId: `req_${Date.now().toString(36)}_${randomBytes2(4).toString("hex")}`,
957
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
958
+ profile: params.profileName,
959
+ posture: resolveProfilePosture(params.profile),
960
+ operatorType: resolveProfileOperatorType(params.profile),
961
+ host: params.host,
962
+ did: didWithoutFragment(params.profile.sessionDid ?? params.profile.did),
963
+ primaryDid: params.profile.primaryDid,
964
+ spaceId: params.profile.spaceId,
965
+ requestedExpiry: params.requestedExpiry,
966
+ requested: params.requested,
967
+ command: {
968
+ argv: params.argv ?? process.argv.slice(2),
969
+ cwd: params.cwd ?? process.cwd()
970
+ }
971
+ };
972
+ }
973
+ function didWithoutFragment(did) {
974
+ const fragment = did.indexOf("#");
975
+ return fragment === -1 ? did : did.slice(0, fragment);
976
+ }
904
977
  async function loadAdditionalDelegations(profile) {
905
978
  const raw = await readJson(
906
979
  additionalDelegationsPath(profile)
@@ -918,6 +991,41 @@ async function appendAdditionalDelegation(profile, entry) {
918
991
  next.push(entry);
919
992
  await saveAdditionalDelegations(profile, next);
920
993
  }
994
+ async function loadPermissionRequestArtifacts(profile) {
995
+ const raw = await readJson(
996
+ permissionRequestsPath(profile)
997
+ );
998
+ return Array.isArray(raw) ? raw.filter(isPermissionRequestArtifact) : [];
999
+ }
1000
+ async function savePermissionRequestArtifacts(profile, entries) {
1001
+ const profileDir = join4(PROFILES_DIR, profile);
1002
+ await ensureDir(profileDir);
1003
+ await writeJson(permissionRequestsPath(profile), entries);
1004
+ }
1005
+ async function appendPermissionRequestArtifact(profile, artifact) {
1006
+ const existing = await loadPermissionRequestArtifacts(profile);
1007
+ const next = existing.filter((item) => item.requestId !== artifact.requestId);
1008
+ next.push(artifact);
1009
+ await savePermissionRequestArtifacts(profile, next);
1010
+ }
1011
+ async function getPermissionRequestArtifact(profile, requestId) {
1012
+ const existing = await loadPermissionRequestArtifacts(profile);
1013
+ return existing.find((item) => item.requestId === requestId) ?? null;
1014
+ }
1015
+ async function getLastPermissionRequestArtifact(profile) {
1016
+ const existing = await loadPermissionRequestArtifacts(profile);
1017
+ return existing.at(-1) ?? null;
1018
+ }
1019
+ function isPermissionRequestArtifact(value) {
1020
+ if (value === null || typeof value !== "object") return false;
1021
+ const candidate = value;
1022
+ return candidate.kind === "tinycloud.auth.request" && candidate.version === 1 && typeof candidate.requestId === "string" && Array.isArray(candidate.requested);
1023
+ }
1024
+ function isDelegationImportArtifact(value) {
1025
+ if (value === null || typeof value !== "object") return false;
1026
+ const candidate = value;
1027
+ return candidate.kind === "tinycloud.auth.delegation" && candidate.version === 1 && candidate.delegation !== void 0 && typeof candidate.delegation === "object";
1028
+ }
921
1029
  async function replayAdditionalDelegations(node, profile) {
922
1030
  const entries = await loadAdditionalDelegations(profile);
923
1031
  for (const entry of entries) {
@@ -1130,7 +1238,21 @@ async function createSDKInstance(ctx, options) {
1130
1238
  host: ctx.host,
1131
1239
  privateKey: effectivePrivateKey
1132
1240
  });
1133
- await node2.signIn();
1241
+ if (session && session.delegationHeader && session.delegationCid && session.spaceId) {
1242
+ await node2.restoreSession({
1243
+ delegationHeader: session.delegationHeader,
1244
+ delegationCid: session.delegationCid,
1245
+ spaceId: session.spaceId,
1246
+ jwk: session.jwk ?? key,
1247
+ verificationMethod: session.verificationMethod ?? profile.sessionDid ?? profile.did,
1248
+ address: session.address,
1249
+ chainId: session.chainId,
1250
+ siwe: session.siwe,
1251
+ signature: session.signature
1252
+ });
1253
+ } else {
1254
+ await node2.signIn();
1255
+ }
1134
1256
  await replayAdditionalDelegations(node2, ctx.profile);
1135
1257
  return node2;
1136
1258
  }
@@ -1252,17 +1374,22 @@ function registerAuthCommand(program2) {
1252
1374
  } catch {
1253
1375
  profile = null;
1254
1376
  }
1377
+ const posture = profile ? resolveProfilePosture(profile) : null;
1378
+ const operatorType = profile ? resolveProfileOperatorType(profile) : null;
1255
1379
  const authenticated = session !== null;
1256
1380
  if (shouldOutputJson()) {
1257
1381
  outputJson({
1258
1382
  authenticated,
1259
1383
  did: profile?.did ?? null,
1384
+ sessionDid: profile?.sessionDid ?? null,
1260
1385
  primaryDid: profile?.primaryDid ?? null,
1261
1386
  spaceId: profile?.spaceId ?? null,
1262
1387
  host: ctx.host,
1263
1388
  profile: ctx.profile,
1264
1389
  hasKey: hasKey !== null,
1265
1390
  authMethod: profile?.authMethod ?? null,
1391
+ posture,
1392
+ operatorType,
1266
1393
  address: profile?.address ?? null
1267
1394
  });
1268
1395
  } else {
@@ -1270,8 +1397,11 @@ function registerAuthCommand(program2) {
1270
1397
  process.stdout.write(formatField("Profile", ctx.profile) + "\n");
1271
1398
  process.stdout.write(formatField("Authenticated", authenticated) + "\n");
1272
1399
  process.stdout.write(formatField("Auth Method", profile?.authMethod ?? null) + "\n");
1400
+ process.stdout.write(formatField("Posture", posture) + "\n");
1401
+ process.stdout.write(formatField("Operator", operatorType) + "\n");
1273
1402
  process.stdout.write(formatField("Host", ctx.host) + "\n");
1274
1403
  process.stdout.write(formatField("DID", profile?.did ?? null) + "\n");
1404
+ process.stdout.write(formatField("Session DID", profile?.sessionDid ?? null) + "\n");
1275
1405
  process.stdout.write(formatField("Primary DID", profile?.primaryDid ?? null) + "\n");
1276
1406
  process.stdout.write(formatField("Address", profile?.address ?? null) + "\n");
1277
1407
  process.stdout.write(formatField("Space ID", profile?.spaceId ?? null) + "\n");
@@ -1281,7 +1411,7 @@ function registerAuthCommand(program2) {
1281
1411
  handleError(error);
1282
1412
  }
1283
1413
  });
1284
- auth.command("request").description("Request additional TinyCloud permissions for the active session").option(
1414
+ auth.command("request").description("Create a TinyCloud permission request artifact").option(
1285
1415
  "--cap <spec>",
1286
1416
  "Capability spec: tinycloud.<service>:<space>:<path>:<actions-csv> (repeatable)",
1287
1417
  (value, previous) => [...previous, value],
@@ -1289,13 +1419,13 @@ function registerAuthCommand(program2) {
1289
1419
  ).option("--permission <file>", 'JSON permission request: { "permissions": PermissionEntry[] }').option("--manifest <fileOrBase64>", "Manifest file, base64:<json>, or raw base64 JSON").option(
1290
1420
  "--expiry <duration>",
1291
1421
  `Lifetime of the granted delegation. ms-format string (e.g. "7d", "30m") or raw milliseconds. Defaults to 7d, capped by the active session's expiry.`
1292
- ).option("--yes", "Skip local-key TTY confirmation", false).action(async (options, cmd) => {
1422
+ ).option("--emit [file]", "Emit the request artifact to stdout, or write it to file when provided").option("--grant", "Grant the requested permissions immediately with this owner profile").option("--yes", "Skip local-key TTY confirmation", false).action(async (options, cmd) => {
1293
1423
  try {
1294
1424
  const globalOpts = cmd.optsWithGlobals();
1295
1425
  const ctx = await ProfileManager.resolveContext(globalOpts);
1296
1426
  const profile = await ProfileManager.getProfile(ctx.profile);
1297
- const session = await ProfileManager.getSession(ctx.profile);
1298
1427
  const requested = await collectRequestedPermissions(options, ctx.profile);
1428
+ const expiryOption = parseExpiryOption(options.expiry);
1299
1429
  if (requested.length === 0) {
1300
1430
  throw new CLIError(
1301
1431
  "NO_CAPS_REQUESTED",
@@ -1303,6 +1433,18 @@ function registerAuthCommand(program2) {
1303
1433
  ExitCode.USAGE_ERROR
1304
1434
  );
1305
1435
  }
1436
+ if (!options.grant) {
1437
+ const artifact = createPermissionRequestArtifact({
1438
+ profileName: ctx.profile,
1439
+ profile,
1440
+ host: ctx.host,
1441
+ requested,
1442
+ requestedExpiry: expiryOption
1443
+ });
1444
+ await appendPermissionRequestArtifact(ctx.profile, artifact);
1445
+ await emitPermissionRequestArtifact(artifact, options.emit);
1446
+ return;
1447
+ }
1306
1448
  const node = await ensureAuthenticated(ctx);
1307
1449
  if (node.hasRuntimePermissions(requested)) {
1308
1450
  outputJson({ changed: false, missing: [], added: [] });
@@ -1316,14 +1458,13 @@ function registerAuthCommand(program2) {
1316
1458
  const delegationCids2 = [];
1317
1459
  let expiry2;
1318
1460
  const openkeyHost = resolveOpenKeyHost(profile);
1319
- const expiryOption2 = parseExpiryOption(options.expiry);
1320
1461
  for (const group of groupPermissionsBySpace(requested)) {
1321
1462
  const delegationData = await startAuthFlow(profile.did, {
1322
1463
  jwk: key,
1323
1464
  host: ctx.host,
1324
1465
  permissions: group,
1325
1466
  openkeyHost,
1326
- expiry: expiryOption2
1467
+ expiry: expiryOption
1327
1468
  });
1328
1469
  const delegation = portableFromOpenKeyDelegation(delegationData, group, ctx.host);
1329
1470
  const stored = storedAdditionalDelegation(delegation, group);
@@ -1358,8 +1499,6 @@ function registerAuthCommand(program2) {
1358
1499
  ExitCode.USAGE_ERROR
1359
1500
  );
1360
1501
  }
1361
- void session;
1362
- const expiryOption = parseExpiryOption(options.expiry);
1363
1502
  const delegations = await node.grantRuntimePermissions(
1364
1503
  requested,
1365
1504
  expiryOption !== void 0 ? { expiry: expiryOption } : void 0
@@ -1394,6 +1533,136 @@ function registerAuthCommand(program2) {
1394
1533
  handleError(error);
1395
1534
  }
1396
1535
  });
1536
+ auth.command("import [source]").description("Import a TinyCloud delegation or permission request artifact").option("--stdin", "Read the JSON artifact from stdin").option("--paste", "Read the JSON artifact from stdin").action(async (source, options, cmd) => {
1537
+ try {
1538
+ const globalOpts = cmd.optsWithGlobals();
1539
+ const ctx = await ProfileManager.resolveContext(globalOpts);
1540
+ const raw = await readAuthArtifactSource(source, {
1541
+ stdin: options.stdin === true || options.paste === true
1542
+ });
1543
+ const parsed = JSON.parse(raw);
1544
+ if (isPermissionRequestArtifact(parsed)) {
1545
+ await appendPermissionRequestArtifact(ctx.profile, parsed);
1546
+ outputJson({
1547
+ imported: true,
1548
+ kind: parsed.kind,
1549
+ requestId: parsed.requestId,
1550
+ requested: parsed.requested,
1551
+ next: `tc auth retry ${parsed.requestId}`
1552
+ });
1553
+ return;
1554
+ }
1555
+ const imported = normalizeDelegationImport(parsed);
1556
+ const node = await ensureAuthenticated(ctx);
1557
+ await appendAdditionalDelegation(ctx.profile, storedAdditionalDelegation(
1558
+ imported.delegation,
1559
+ imported.permissions
1560
+ ));
1561
+ await node.useRuntimeDelegation(imported.delegation);
1562
+ await appendGrantHistory(ctx.profile, {
1563
+ addedCaps: imported.permissions,
1564
+ source: "cli",
1565
+ delegationCid: imported.delegation.cid,
1566
+ expiry: imported.delegation.expiry.toISOString()
1567
+ });
1568
+ outputJson({
1569
+ imported: true,
1570
+ kind: "tinycloud.auth.delegation",
1571
+ requestId: imported.requestId ?? null,
1572
+ delegationCid: imported.delegation.cid,
1573
+ permissions: imported.permissions,
1574
+ expiry: imported.delegation.expiry.toISOString()
1575
+ });
1576
+ } catch (error) {
1577
+ handleError(error);
1578
+ }
1579
+ });
1580
+ auth.command("grant [request]").description("Grant a TinyCloud permission request artifact to its requester").option("--stdin", "Read the JSON request artifact from stdin").option("--paste", "Read the JSON request artifact from stdin").option("--yes", "Skip local-key TTY confirmation", false).action(async (source, options, cmd) => {
1581
+ try {
1582
+ const globalOpts = cmd.optsWithGlobals();
1583
+ const ctx = await ProfileManager.resolveContext(globalOpts);
1584
+ const profile = await ProfileManager.getProfile(ctx.profile);
1585
+ const raw = await readAuthArtifactSource(source, {
1586
+ stdin: options.stdin === true || options.paste === true
1587
+ });
1588
+ const parsed = JSON.parse(raw);
1589
+ if (!isPermissionRequestArtifact(parsed)) {
1590
+ throw new CLIError(
1591
+ "INVALID_AUTH_REQUEST",
1592
+ "Auth grant requires a tinycloud.auth.request artifact.",
1593
+ ExitCode.USAGE_ERROR
1594
+ );
1595
+ }
1596
+ const node = await ensureAuthenticated(ctx);
1597
+ await ensureDelegationAuthority({
1598
+ ctx,
1599
+ profile,
1600
+ node,
1601
+ requested: parsed.requested,
1602
+ expiryOption: parsed.requestedExpiry,
1603
+ yes: options.yes === true
1604
+ });
1605
+ const result = await node.delegateTo(
1606
+ parsed.did,
1607
+ parsed.requested,
1608
+ parsed.requestedExpiry !== void 0 ? { expiry: parsed.requestedExpiry } : void 0
1609
+ );
1610
+ outputJson({
1611
+ kind: "tinycloud.auth.delegation",
1612
+ version: 1,
1613
+ requestId: parsed.requestId,
1614
+ delegationCid: result.delegation.cid,
1615
+ delegation: result.delegation,
1616
+ permissions: parsed.requested,
1617
+ expiry: result.delegation.expiry.toISOString(),
1618
+ prompted: result.prompted
1619
+ });
1620
+ } catch (error) {
1621
+ handleError(error);
1622
+ }
1623
+ });
1624
+ auth.command("retry [requestId]").description("Check whether a stored permission request is now satisfied").option("--last", "Use the latest stored permission request for this profile").option("--exec", "Run the captured command when the request is covered").action(async (requestId, options, cmd) => {
1625
+ try {
1626
+ const globalOpts = cmd.optsWithGlobals();
1627
+ const ctx = await ProfileManager.resolveContext(globalOpts);
1628
+ const artifact = options.last ? await getLastPermissionRequestArtifact(ctx.profile) : requestId ? await getPermissionRequestArtifact(ctx.profile, requestId) : null;
1629
+ if (!artifact) {
1630
+ throw new CLIError(
1631
+ "REQUEST_NOT_FOUND",
1632
+ options.last ? `No stored permission requests exist for profile "${ctx.profile}".` : "Provide a requestId or use --last.",
1633
+ ExitCode.NOT_FOUND
1634
+ );
1635
+ }
1636
+ const node = await ensureAuthenticated(ctx);
1637
+ const covered = node.hasRuntimePermissions(artifact.requested);
1638
+ if (options.exec) {
1639
+ if (!covered) {
1640
+ throw new CLIError(
1641
+ "PERMISSIONS_MISSING",
1642
+ `Request ${artifact.requestId} is not covered yet. Import a delegation, then retry with --exec.`,
1643
+ ExitCode.PERMISSION_DENIED
1644
+ );
1645
+ }
1646
+ if (!artifact.command?.argv?.length) {
1647
+ throw new CLIError(
1648
+ "COMMAND_NOT_CAPTURED",
1649
+ `Request ${artifact.requestId} does not include a captured command.`,
1650
+ ExitCode.USAGE_ERROR
1651
+ );
1652
+ }
1653
+ await execCapturedCommand(artifact.command);
1654
+ return;
1655
+ }
1656
+ outputJson({
1657
+ requestId: artifact.requestId,
1658
+ covered,
1659
+ missing: covered ? [] : artifact.requested,
1660
+ command: artifact.command ?? null
1661
+ });
1662
+ } catch (error) {
1663
+ handleError(error);
1664
+ }
1665
+ });
1397
1666
  auth.command("caps").description("Show granted capabilities for the active session").option("--diff <spec>", "Show missing capabilities for a spec").option("--history", "Show recent permission grants").action(async (options, cmd) => {
1398
1667
  try {
1399
1668
  const globalOpts = cmd.optsWithGlobals();
@@ -1459,23 +1728,31 @@ function registerAuthCommand(program2) {
1459
1728
  const profile = await ProfileManager.getProfile(ctx.profile);
1460
1729
  const session = await ProfileManager.getSession(ctx.profile);
1461
1730
  const authenticated = session !== null;
1731
+ const posture = resolveProfilePosture(profile);
1732
+ const operatorType = resolveProfileOperatorType(profile);
1462
1733
  if (shouldOutputJson()) {
1463
1734
  outputJson({
1464
1735
  profile: ctx.profile,
1465
1736
  did: profile.did,
1737
+ sessionDid: profile.sessionDid ?? null,
1466
1738
  primaryDid: profile.primaryDid ?? null,
1467
1739
  spaceId: profile.spaceId ?? null,
1468
1740
  host: profile.host,
1469
1741
  authenticated,
1470
1742
  authMethod: profile.authMethod ?? null,
1743
+ posture,
1744
+ operatorType,
1471
1745
  address: profile.address ?? null
1472
1746
  });
1473
1747
  } else {
1474
1748
  process.stdout.write(theme.heading("Identity") + "\n");
1475
1749
  process.stdout.write(formatField("Profile", ctx.profile) + "\n");
1476
1750
  process.stdout.write(formatField("DID", profile.did) + "\n");
1751
+ process.stdout.write(formatField("Session DID", profile.sessionDid ?? null) + "\n");
1477
1752
  process.stdout.write(formatField("Primary DID", profile.primaryDid ?? null) + "\n");
1478
1753
  process.stdout.write(formatField("Auth Method", profile.authMethod ?? null) + "\n");
1754
+ process.stdout.write(formatField("Posture", posture) + "\n");
1755
+ process.stdout.write(formatField("Operator", operatorType) + "\n");
1479
1756
  process.stdout.write(formatField("Address", profile.address ?? null) + "\n");
1480
1757
  process.stdout.write(formatField("Space ID", profile.spaceId ?? null) + "\n");
1481
1758
  process.stdout.write(formatField("Host", profile.host) + "\n");
@@ -1486,6 +1763,210 @@ function registerAuthCommand(program2) {
1486
1763
  }
1487
1764
  });
1488
1765
  }
1766
+ async function emitPermissionRequestArtifact(artifact, emitOption) {
1767
+ if (typeof emitOption === "string" && emitOption.length > 0) {
1768
+ await mkdir2(dirname2(emitOption), { recursive: true });
1769
+ await writeFile2(emitOption, JSON.stringify(artifact, null, 2) + "\n", "utf8");
1770
+ outputJson({
1771
+ emitted: true,
1772
+ path: emitOption,
1773
+ requestId: artifact.requestId,
1774
+ requested: artifact.requested
1775
+ });
1776
+ return;
1777
+ }
1778
+ outputJson(artifact);
1779
+ }
1780
+ async function readAuthArtifactSource(source, options) {
1781
+ if (options.stdin || source === "-" || !source && !isInteractive()) {
1782
+ return readStdin();
1783
+ }
1784
+ if (!source) {
1785
+ throw new CLIError(
1786
+ "IMPORT_SOURCE_REQUIRED",
1787
+ "Provide an artifact file, URL, or use --stdin.",
1788
+ ExitCode.USAGE_ERROR
1789
+ );
1790
+ }
1791
+ if (source.startsWith("http://") || source.startsWith("https://")) {
1792
+ return readUrl(source);
1793
+ }
1794
+ return readFile3(source, "utf8");
1795
+ }
1796
+ async function readStdin() {
1797
+ const chunks = [];
1798
+ for await (const chunk of process.stdin) {
1799
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
1800
+ }
1801
+ return Buffer.concat(chunks).toString("utf8");
1802
+ }
1803
+ function readUrl(source) {
1804
+ return new Promise((resolve3, reject) => {
1805
+ const getter = source.startsWith("https://") ? httpsGet : httpGet;
1806
+ const request = getter(source, (response) => {
1807
+ const status = response.statusCode ?? 0;
1808
+ if (status >= 300 && status < 400 && response.headers.location) {
1809
+ response.resume();
1810
+ readUrl(new URL(response.headers.location, source).toString()).then(resolve3, reject);
1811
+ return;
1812
+ }
1813
+ if (status < 200 || status >= 300) {
1814
+ response.resume();
1815
+ reject(new CLIError(
1816
+ "IMPORT_FETCH_FAILED",
1817
+ `Failed to fetch ${source}: HTTP ${status}.`,
1818
+ ExitCode.ERROR
1819
+ ));
1820
+ return;
1821
+ }
1822
+ const chunks = [];
1823
+ response.on("data", (chunk) => {
1824
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
1825
+ });
1826
+ response.on("end", () => resolve3(Buffer.concat(chunks).toString("utf8")));
1827
+ });
1828
+ request.on("error", reject);
1829
+ });
1830
+ }
1831
+ function normalizeDelegationImport(value) {
1832
+ if (isDelegationImportArtifact(value)) {
1833
+ const delegation = normalizePortableDelegation(value.delegation);
1834
+ return {
1835
+ requestId: value.requestId,
1836
+ delegation,
1837
+ permissions: Array.isArray(value.permissions) && value.permissions.length > 0 ? value.permissions : permissionsFromDelegation(delegation)
1838
+ };
1839
+ }
1840
+ if (isStoredDelegationLike(value)) {
1841
+ const delegation = normalizePortableDelegation(value.delegation);
1842
+ return {
1843
+ delegation,
1844
+ permissions: Array.isArray(value.permissions) && value.permissions.length > 0 ? value.permissions : permissionsFromDelegation(delegation)
1845
+ };
1846
+ }
1847
+ if (isPortableDelegationLike(value)) {
1848
+ const delegation = normalizePortableDelegation(value);
1849
+ return {
1850
+ delegation,
1851
+ permissions: permissionsFromDelegation(delegation)
1852
+ };
1853
+ }
1854
+ throw new CLIError(
1855
+ "INVALID_AUTH_IMPORT",
1856
+ "Auth import must be a tinycloud.auth.delegation artifact, a portable delegation, or a tinycloud.auth.request artifact.",
1857
+ ExitCode.USAGE_ERROR
1858
+ );
1859
+ }
1860
+ function isStoredDelegationLike(value) {
1861
+ if (value === null || typeof value !== "object") return false;
1862
+ const candidate = value;
1863
+ return isPortableDelegationLike(candidate.delegation);
1864
+ }
1865
+ function isPortableDelegationLike(value) {
1866
+ if (value === null || typeof value !== "object") return false;
1867
+ const candidate = value;
1868
+ return typeof candidate.cid === "string" && typeof candidate.spaceId === "string" && typeof candidate.path === "string" && Array.isArray(candidate.actions) && candidate.delegationHeader !== void 0 && typeof candidate.delegationHeader === "object";
1869
+ }
1870
+ function normalizePortableDelegation(delegation) {
1871
+ const rawExpiry = delegation.expiry;
1872
+ const expiry = rawExpiry instanceof Date ? rawExpiry : new Date(String(rawExpiry));
1873
+ if (Number.isNaN(expiry.getTime())) {
1874
+ throw new CLIError(
1875
+ "INVALID_AUTH_IMPORT",
1876
+ "Imported delegation must include a valid expiry.",
1877
+ ExitCode.USAGE_ERROR
1878
+ );
1879
+ }
1880
+ return { ...delegation, expiry };
1881
+ }
1882
+ async function ensureDelegationAuthority(params) {
1883
+ if (params.node.hasRuntimePermissions(params.requested)) return;
1884
+ if (params.profile.authMethod === "openkey") {
1885
+ const key = await ProfileManager.getKey(params.ctx.profile);
1886
+ if (!key) {
1887
+ throw new CLIError(
1888
+ "NO_KEY",
1889
+ `No key found for profile "${params.ctx.profile}". Run \`tc init\` first.`,
1890
+ ExitCode.AUTH_REQUIRED
1891
+ );
1892
+ }
1893
+ const openkeyHost = resolveOpenKeyHost(params.profile);
1894
+ for (const group of groupPermissionsBySpace(params.requested)) {
1895
+ const delegationData = await startAuthFlow(params.profile.did, {
1896
+ jwk: key,
1897
+ host: params.ctx.host,
1898
+ permissions: group,
1899
+ openkeyHost,
1900
+ expiry: params.expiryOption
1901
+ });
1902
+ const delegation = portableFromOpenKeyDelegation(delegationData, group, params.ctx.host);
1903
+ await appendAdditionalDelegation(
1904
+ params.ctx.profile,
1905
+ storedAdditionalDelegation(delegation, group)
1906
+ );
1907
+ await params.node.useRuntimeDelegation(delegation);
1908
+ await appendGrantHistory(params.ctx.profile, {
1909
+ addedCaps: group,
1910
+ source: "cli",
1911
+ delegationCid: delegation.cid,
1912
+ expiry: delegation.expiry.toISOString()
1913
+ });
1914
+ }
1915
+ return;
1916
+ }
1917
+ if (isInteractive()) {
1918
+ if (!params.yes) {
1919
+ await confirmPermissionRequest(params.requested);
1920
+ }
1921
+ } else if (!params.yes) {
1922
+ throw new CLIError(
1923
+ "CONFIRMATION_REQUIRED",
1924
+ "Local-key auth grants in non-interactive mode require --yes.",
1925
+ ExitCode.USAGE_ERROR
1926
+ );
1927
+ }
1928
+ const delegations = await params.node.grantRuntimePermissions(
1929
+ params.requested,
1930
+ params.expiryOption !== void 0 ? { expiry: params.expiryOption } : void 0
1931
+ );
1932
+ for (const delegation of delegations) {
1933
+ const covering = permissionsFromDelegation(delegation);
1934
+ await appendAdditionalDelegation(
1935
+ params.ctx.profile,
1936
+ storedAdditionalDelegation(delegation, covering)
1937
+ );
1938
+ await appendGrantHistory(params.ctx.profile, {
1939
+ addedCaps: covering,
1940
+ source: "cli",
1941
+ delegationCid: delegation.cid,
1942
+ expiry: delegation.expiry.toISOString()
1943
+ });
1944
+ }
1945
+ }
1946
+ function execCapturedCommand(command) {
1947
+ return new Promise((resolve3, reject) => {
1948
+ const child = spawn(process.execPath, [process.argv[1], ...command.argv], {
1949
+ cwd: command.cwd,
1950
+ env: process.env,
1951
+ stdio: "inherit"
1952
+ });
1953
+ child.on("error", reject);
1954
+ child.on("exit", (code, signal) => {
1955
+ if (signal) {
1956
+ reject(new CLIError(
1957
+ "COMMAND_SIGNAL",
1958
+ `Captured command exited from signal ${signal}.`,
1959
+ ExitCode.ERROR
1960
+ ));
1961
+ return;
1962
+ }
1963
+ if (code && code !== 0) {
1964
+ process.exitCode = code;
1965
+ }
1966
+ resolve3();
1967
+ });
1968
+ });
1969
+ }
1489
1970
  async function collectRequestedPermissions(options, profile) {
1490
1971
  const permissions = [];
1491
1972
  for (const spec of options.cap ?? []) {
@@ -1596,6 +2077,7 @@ async function handleLocalAuth(profileName, host) {
1596
2077
  let privateKey;
1597
2078
  let address;
1598
2079
  let did;
2080
+ let sessionDid = profile?.sessionDid;
1599
2081
  if (profile?.authMethod === "local" && profile.privateKey && profile.address) {
1600
2082
  privateKey = profile.privateKey;
1601
2083
  address = profile.address;
@@ -1619,10 +2101,13 @@ async function handleLocalAuth(profileName, host) {
1619
2101
  }
1620
2102
  const hasKey = await ProfileManager.getKey(profileName);
1621
2103
  if (!hasKey) {
1622
- const { jwk } = await withSpinner("Generating session key...", async () => {
2104
+ const { jwk, did: generatedSessionDid } = await withSpinner("Generating session key...", async () => {
1623
2105
  return generateKey();
1624
2106
  });
1625
2107
  await ProfileManager.setKey(profileName, jwk);
2108
+ sessionDid = generatedSessionDid;
2109
+ } else if (!sessionDid) {
2110
+ sessionDid = keyToDID(hasKey);
1626
2111
  }
1627
2112
  const sessionResult = await withSpinner("Signing in...", async () => {
1628
2113
  return localKeySignIn({ privateKey, host });
@@ -1631,17 +2116,28 @@ async function handleLocalAuth(profileName, host) {
1631
2116
  authMethod: "local",
1632
2117
  address,
1633
2118
  chainId: DEFAULT_CHAIN_ID,
1634
- spaceId: sessionResult.spaceId
2119
+ spaceId: sessionResult.spaceId,
2120
+ delegationHeader: sessionResult.delegationHeader,
2121
+ delegationCid: sessionResult.delegationCid,
2122
+ jwk: sessionResult.jwk,
2123
+ verificationMethod: sessionResult.verificationMethod,
2124
+ siwe: sessionResult.siwe,
2125
+ signature: sessionResult.signature
1635
2126
  });
2127
+ sessionDid = sessionResult.verificationMethod;
1636
2128
  await ProfileManager.setProfile(profileName, {
2129
+ ...profile,
1637
2130
  name: profileName,
1638
2131
  host,
1639
2132
  chainId: DEFAULT_CHAIN_ID,
1640
2133
  spaceName: "default",
1641
2134
  did,
2135
+ sessionDid,
1642
2136
  primaryDid: did,
1643
2137
  spaceId: sessionResult.spaceId,
1644
2138
  createdAt: profile?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
2139
+ posture: profile?.posture ?? "local-owner-key",
2140
+ operatorType: profile?.operatorType ?? "human",
1645
2141
  authMethod: "local",
1646
2142
  privateKey,
1647
2143
  address
@@ -1650,6 +2146,7 @@ async function handleLocalAuth(profileName, host) {
1650
2146
  authenticated: true,
1651
2147
  profile: profileName,
1652
2148
  did,
2149
+ sessionDid,
1653
2150
  address,
1654
2151
  spaceId: sessionResult.spaceId,
1655
2152
  authMethod: "local"
@@ -1674,6 +2171,9 @@ async function handleOpenKeyAuth(profileName, host, paste) {
1674
2171
  await ProfileManager.setSession(profileName, delegationData);
1675
2172
  const updatedProfile = {
1676
2173
  ...profile,
2174
+ sessionDid: profile.sessionDid ?? profile.did,
2175
+ posture: profile.posture ?? "owner-openkey",
2176
+ operatorType: profile.operatorType ?? "human",
1677
2177
  authMethod: "openkey"
1678
2178
  };
1679
2179
  if (delegationData.spaceId) {
@@ -1691,9 +2191,9 @@ async function handleOpenKeyAuth(profileName, host, paste) {
1691
2191
  }
1692
2192
 
1693
2193
  // src/commands/kv.ts
1694
- import { readFile as readFile3 } from "fs/promises";
1695
- import { writeFile as writeFile2 } from "fs/promises";
1696
- async function readStdin() {
2194
+ import { readFile as readFile4 } from "fs/promises";
2195
+ import { writeFile as writeFile3 } from "fs/promises";
2196
+ async function readStdin2() {
1697
2197
  const chunks = [];
1698
2198
  for await (const chunk of process.stdin) {
1699
2199
  chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
@@ -1718,7 +2218,7 @@ function registerKvCommand(program2) {
1718
2218
  const metadata = result.data.headers ?? {};
1719
2219
  if (options.output) {
1720
2220
  const content = typeof data === "string" ? data : JSON.stringify(data);
1721
- await writeFile2(options.output, content);
2221
+ await writeFile3(options.output, content);
1722
2222
  outputJson({ key, written: options.output });
1723
2223
  return;
1724
2224
  }
@@ -1755,9 +2255,9 @@ function registerKvCommand(program2) {
1755
2255
  throw new CLIError("USAGE_ERROR", "Provide only one of: value argument, --file, or --stdin", ExitCode.USAGE_ERROR);
1756
2256
  }
1757
2257
  if (options.file) {
1758
- putValue = await readFile3(options.file);
2258
+ putValue = await readFile4(options.file);
1759
2259
  } else if (options.stdin) {
1760
- putValue = await readStdin();
2260
+ putValue = await readStdin2();
1761
2261
  } else {
1762
2262
  try {
1763
2263
  putValue = JSON.parse(value);
@@ -2225,10 +2725,19 @@ function registerProfileCommand(program2) {
2225
2725
  name: p.name,
2226
2726
  host: p.host,
2227
2727
  did: p.did,
2728
+ posture: resolveProfilePosture(p),
2729
+ operatorType: resolveProfileOperatorType(p),
2228
2730
  active: name === config.defaultProfile
2229
2731
  };
2230
2732
  } catch {
2231
- return { name, host: null, did: null, active: name === config.defaultProfile };
2733
+ return {
2734
+ name,
2735
+ host: null,
2736
+ did: null,
2737
+ posture: null,
2738
+ operatorType: null,
2739
+ active: name === config.defaultProfile
2740
+ };
2232
2741
  }
2233
2742
  })
2234
2743
  );
@@ -2242,7 +2751,8 @@ function registerProfileCommand(program2) {
2242
2751
  const marker = p.active ? theme.success("\u25CF ") : " ";
2243
2752
  const name = p.active ? theme.brand(p.name) : p.name;
2244
2753
  const host = theme.muted(p.host || "no host");
2245
- process.stdout.write(`${marker}${name} ${host}
2754
+ const posture = p.posture ? theme.muted(String(p.posture)) : theme.muted("no posture");
2755
+ process.stdout.write(`${marker}${name} ${host} ${posture}
2246
2756
  `);
2247
2757
  }
2248
2758
  }
@@ -2250,10 +2760,18 @@ function registerProfileCommand(program2) {
2250
2760
  handleError(error);
2251
2761
  }
2252
2762
  });
2253
- profile.command("create <name>").description("Create a new profile").option("--host <url>", "TinyCloud node URL").action(async (name, options, cmd) => {
2763
+ profile.command("create <name>").description("Create a new profile").option("--host <url>", "TinyCloud node URL").option(
2764
+ "--posture <posture>",
2765
+ `Profile posture: ${CLI_PROFILE_POSTURES.join(", ")}. Defaults to owner-openkey.`
2766
+ ).option(
2767
+ "--operator <type>",
2768
+ `Operator type: ${CLI_OPERATOR_TYPES.join(", ")}. Defaults to human.`
2769
+ ).action(async (name, options, cmd) => {
2254
2770
  try {
2255
2771
  const globalOpts = cmd.optsWithGlobals();
2256
2772
  const host = options.host ?? globalOpts.host ?? "https://node.tinycloud.xyz";
2773
+ const posture = parseProfilePosture(options.posture);
2774
+ const operatorType = parseOperatorType(options.operator);
2257
2775
  if (await ProfileManager.profileExists(name)) {
2258
2776
  throw new CLIError("PROFILE_EXISTS", `Profile "${name}" already exists`, ExitCode.ERROR);
2259
2777
  }
@@ -2266,9 +2784,12 @@ function registerProfileCommand(program2) {
2266
2784
  chainId: 1,
2267
2785
  spaceName: "default",
2268
2786
  did,
2269
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
2787
+ sessionDid: did,
2788
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
2789
+ posture,
2790
+ operatorType
2270
2791
  });
2271
- outputJson({ profile: name, did, host, created: true });
2792
+ outputJson({ profile: name, did, host, posture, operatorType, created: true });
2272
2793
  } catch (error) {
2273
2794
  handleError(error);
2274
2795
  }
@@ -2283,9 +2804,13 @@ function registerProfileCommand(program2) {
2283
2804
  const hasSession = await ProfileManager.getSession(profileName) !== null;
2284
2805
  const config = await ProfileManager.getConfig();
2285
2806
  const isDefault = profileName === config.defaultProfile;
2807
+ const posture = resolveProfilePosture(p);
2808
+ const operatorType = resolveProfileOperatorType(p);
2286
2809
  if (shouldOutputJson()) {
2287
2810
  outputJson({
2288
2811
  ...p,
2812
+ posture,
2813
+ operatorType,
2289
2814
  hasKey,
2290
2815
  hasSession,
2291
2816
  isDefault
@@ -2295,6 +2820,9 @@ function registerProfileCommand(program2) {
2295
2820
  `);
2296
2821
  process.stdout.write(formatField("Host", p.host) + "\n");
2297
2822
  process.stdout.write(formatField("DID", p.did) + "\n");
2823
+ process.stdout.write(formatField("Session DID", p.sessionDid ?? null) + "\n");
2824
+ process.stdout.write(formatField("Posture", posture) + "\n");
2825
+ process.stdout.write(formatField("Operator", operatorType) + "\n");
2298
2826
  process.stdout.write(formatField("Space", p.spaceId || null) + "\n");
2299
2827
  process.stdout.write(formatField("Key", hasKey) + "\n");
2300
2828
  process.stdout.write(formatField("Session", hasSession) + "\n");
@@ -2336,6 +2864,24 @@ function registerProfileCommand(program2) {
2336
2864
  }
2337
2865
  });
2338
2866
  }
2867
+ function parseProfilePosture(raw) {
2868
+ if (raw === void 0 || raw === null || raw === "") return "owner-openkey";
2869
+ if (isCLIProfilePosture(raw)) return raw;
2870
+ throw new CLIError(
2871
+ "INVALID_POSTURE",
2872
+ `Invalid posture "${String(raw)}". Use one of: ${CLI_PROFILE_POSTURES.join(", ")}.`,
2873
+ ExitCode.USAGE_ERROR
2874
+ );
2875
+ }
2876
+ function parseOperatorType(raw) {
2877
+ if (raw === void 0 || raw === null || raw === "") return "human";
2878
+ if (isCLIOperatorType(raw)) return raw;
2879
+ throw new CLIError(
2880
+ "INVALID_OPERATOR",
2881
+ `Invalid operator "${String(raw)}". Use one of: ${CLI_OPERATOR_TYPES.join(", ")}.`,
2882
+ ExitCode.USAGE_ERROR
2883
+ );
2884
+ }
2339
2885
 
2340
2886
  // src/commands/completion.ts
2341
2887
  function registerCompletionCommand(program2) {
@@ -2468,10 +3014,10 @@ complete -c tc -l quiet -s q -d "Suppress non-essential output"
2468
3014
  }
2469
3015
 
2470
3016
  // src/commands/vault.ts
2471
- import { readFile as readFile4 } from "fs/promises";
2472
- import { writeFile as writeFile3 } from "fs/promises";
3017
+ import { readFile as readFile5 } from "fs/promises";
3018
+ import { writeFile as writeFile4 } from "fs/promises";
2473
3019
  import { PrivateKeySigner as PrivateKeySigner2 } from "@tinycloud/node-sdk";
2474
- async function readStdin2() {
3020
+ async function readStdin3() {
2475
3021
  const chunks = [];
2476
3022
  for await (const chunk of process.stdin) {
2477
3023
  chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
@@ -2526,9 +3072,9 @@ function registerVaultCommand(program2) {
2526
3072
  throw new CLIError("USAGE_ERROR", "Provide only one of: value argument, --file, or --stdin", ExitCode.USAGE_ERROR);
2527
3073
  }
2528
3074
  if (options.file) {
2529
- putValue = new Uint8Array(await readFile4(options.file));
3075
+ putValue = new Uint8Array(await readFile5(options.file));
2530
3076
  } else if (options.stdin) {
2531
- putValue = new Uint8Array(await readStdin2());
3077
+ putValue = new Uint8Array(await readStdin3());
2532
3078
  } else {
2533
3079
  putValue = value;
2534
3080
  }
@@ -2558,7 +3104,7 @@ function registerVaultCommand(program2) {
2558
3104
  const data = result.data.data ?? result.data;
2559
3105
  if (options.output) {
2560
3106
  const content = data instanceof Uint8Array ? Buffer.from(data) : typeof data === "string" ? data : JSON.stringify(data);
2561
- await writeFile3(options.output, content);
3107
+ await writeFile4(options.output, content);
2562
3108
  outputJson({ key, written: options.output });
2563
3109
  return;
2564
3110
  }
@@ -2641,9 +3187,9 @@ function registerVaultCommand(program2) {
2641
3187
  }
2642
3188
 
2643
3189
  // src/commands/secrets.ts
2644
- import { readFile as readFile5 } from "fs/promises";
2645
- import { writeFile as writeFile4 } from "fs/promises";
2646
- async function readStdin3() {
3190
+ import { readFile as readFile6 } from "fs/promises";
3191
+ import { writeFile as writeFile5 } from "fs/promises";
3192
+ async function readStdin4() {
2647
3193
  const chunks = [];
2648
3194
  for await (const chunk of process.stdin) {
2649
3195
  chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
@@ -2741,7 +3287,7 @@ function registerSecretsCommand(program2) {
2741
3287
  }
2742
3288
  const value = String(result.data);
2743
3289
  if (options.output) {
2744
- await writeFile4(options.output, value);
3290
+ await writeFile5(options.output, value);
2745
3291
  outputJson({ name, written: options.output });
2746
3292
  return;
2747
3293
  }
@@ -2768,9 +3314,9 @@ function registerSecretsCommand(program2) {
2768
3314
  throw new CLIError("USAGE_ERROR", "Provide only one of: value argument, --file, or --stdin", ExitCode.USAGE_ERROR);
2769
3315
  }
2770
3316
  if (options.file) {
2771
- secretValue = await readFile5(options.file, "utf-8");
3317
+ secretValue = await readFile6(options.file, "utf-8");
2772
3318
  } else if (options.stdin) {
2773
- secretValue = (await readStdin3()).toString("utf-8");
3319
+ secretValue = (await readStdin4()).toString("utf-8");
2774
3320
  } else {
2775
3321
  secretValue = value;
2776
3322
  }
@@ -2848,10 +3394,10 @@ function registerSecretsCommand(program2) {
2848
3394
  }
2849
3395
 
2850
3396
  // src/commands/vars.ts
2851
- import { readFile as readFile6 } from "fs/promises";
2852
- import { writeFile as writeFile5 } from "fs/promises";
3397
+ import { readFile as readFile7 } from "fs/promises";
3398
+ import { writeFile as writeFile6 } from "fs/promises";
2853
3399
  var VARIABLES_PREFIX = "variables/";
2854
- async function readStdin4() {
3400
+ async function readStdin5() {
2855
3401
  const chunks = [];
2856
3402
  for await (const chunk of process.stdin) {
2857
3403
  chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
@@ -2921,7 +3467,7 @@ function registerVarsCommand(program2) {
2921
3467
  value = typeof data === "string" ? data : JSON.stringify(data);
2922
3468
  }
2923
3469
  if (options.output) {
2924
- await writeFile5(options.output, value);
3470
+ await writeFile6(options.output, value);
2925
3471
  outputJson({ name, written: options.output });
2926
3472
  return;
2927
3473
  }
@@ -2949,9 +3495,9 @@ function registerVarsCommand(program2) {
2949
3495
  throw new CLIError("USAGE_ERROR", "Provide only one of: value argument, --file, or --stdin", ExitCode.USAGE_ERROR);
2950
3496
  }
2951
3497
  if (options.file) {
2952
- varValue = await readFile6(options.file, "utf-8");
3498
+ varValue = await readFile7(options.file, "utf-8");
2953
3499
  } else if (options.stdin) {
2954
- varValue = (await readStdin4()).toString("utf-8");
3500
+ varValue = (await readStdin5()).toString("utf-8");
2955
3501
  } else {
2956
3502
  varValue = value;
2957
3503
  }
@@ -3095,7 +3641,7 @@ function registerDoctorCommand(program2) {
3095
3641
  }
3096
3642
 
3097
3643
  // src/commands/sql.ts
3098
- import { writeFile as writeFile6 } from "fs/promises";
3644
+ import { writeFile as writeFile7 } from "fs/promises";
3099
3645
  import { resolve } from "path";
3100
3646
  async function dbHandle(node, dbName, spaceInput, profileName) {
3101
3647
  const spaceUri = await resolveSpaceUri(spaceInput, profileName);
@@ -3231,7 +3777,7 @@ Output:
3231
3777
  const blob = result.data;
3232
3778
  const buffer = Buffer.from(await blob.arrayBuffer());
3233
3779
  const outputPath = resolve(options.output);
3234
- await writeFile6(outputPath, buffer);
3780
+ await writeFile7(outputPath, buffer);
3235
3781
  outputJson({
3236
3782
  file: outputPath,
3237
3783
  size: blob.size,
@@ -3360,7 +3906,7 @@ function quoteIdent(name) {
3360
3906
  }
3361
3907
 
3362
3908
  // src/commands/duckdb.ts
3363
- import { readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
3909
+ import { readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
3364
3910
  import { resolve as resolve2 } from "path";
3365
3911
  function registerDuckdbCommand(program2) {
3366
3912
  const duckdb = program2.command("duckdb").description("DuckDB database operations");
@@ -3474,7 +4020,7 @@ ${rowCount} row${rowCount === 1 ? "" : "s"} returned`) + "\n");
3474
4020
  const blob = result.data;
3475
4021
  const buffer = Buffer.from(await blob.arrayBuffer());
3476
4022
  const outputPath = resolve2(options.output);
3477
- await writeFile7(outputPath, buffer);
4023
+ await writeFile8(outputPath, buffer);
3478
4024
  outputJson({
3479
4025
  file: outputPath,
3480
4026
  size: blob.size,
@@ -3490,7 +4036,7 @@ ${rowCount} row${rowCount === 1 ? "" : "s"} returned`) + "\n");
3490
4036
  const ctx = await ProfileManager.resolveContext(globalOpts);
3491
4037
  const node = await ensureAuthenticated(ctx);
3492
4038
  const filePath = resolve2(file);
3493
- const bytes = new Uint8Array(await readFile7(filePath));
4039
+ const bytes = new Uint8Array(await readFile8(filePath));
3494
4040
  const result = await withSpinner(
3495
4041
  "Importing database...",
3496
4042
  () => node.duckdb.db(options.db).import(bytes)
@@ -3511,7 +4057,7 @@ ${rowCount} row${rowCount === 1 ? "" : "s"} returned`) + "\n");
3511
4057
  }
3512
4058
 
3513
4059
  // src/commands/manifest.ts
3514
- import { readFile as readFile8 } from "fs/promises";
4060
+ import { readFile as readFile9 } from "fs/promises";
3515
4061
  var DEFAULT_APP_SPACE = "applications";
3516
4062
  function registerManifestCommand(program2) {
3517
4063
  const manifest = program2.command("manifest").description("Inspect TinyCloud app manifests");
@@ -3619,7 +4165,7 @@ async function loadManifestSource(source) {
3619
4165
  }
3620
4166
  return response.text();
3621
4167
  }
3622
- return readFile8(source, "utf8");
4168
+ return readFile9(source, "utf8");
3623
4169
  }
3624
4170
  function prefixWithAppId(path, appId) {
3625
4171
  const slash = path.indexOf("/");
@@ -3764,6 +4310,7 @@ ${theme.heading("Examples:")}
3764
4310
  ${theme.command("tc auth login")} ${theme.muted("Authenticate via browser")}
3765
4311
  ${theme.command('tc kv put greeting "Hello"')} ${theme.muted("Store a value")}
3766
4312
  ${theme.command("tc kv list")} ${theme.muted("List all keys")}
4313
+ ${theme.command("tc secrets network init")} ${theme.muted("Create the default secrets network")}
3767
4314
  ${theme.command("tc delegation create --to did:pkh:...")} ${theme.muted("Grant access to another user")}
3768
4315
  ${theme.command("tc space list")} ${theme.muted("Show your spaces")}
3769
4316