@tinycloud/cli 1.2.2-beta.2 → 1.2.2-beta.3

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.
@@ -16288,7 +16288,7 @@ function eddsa(Point, cHash, eddsaOpts = {}) {
16288
16288
  });
16289
16289
  const { prehash } = eddsaOpts;
16290
16290
  const { BASE, Fp: Fp2, Fn: Fn2 } = Point;
16291
- const randomBytes8 = eddsaOpts.randomBytes || randomBytes;
16291
+ const randomBytes9 = eddsaOpts.randomBytes || randomBytes;
16292
16292
  const adjustScalarBytes2 = eddsaOpts.adjustScalarBytes || ((bytes) => bytes);
16293
16293
  const domain = eddsaOpts.domain || ((data, ctx, phflag) => {
16294
16294
  _abool2(phflag, "phflag");
@@ -16370,7 +16370,7 @@ function eddsa(Point, cHash, eddsaOpts = {}) {
16370
16370
  signature: 2 * _size,
16371
16371
  seed: _size
16372
16372
  };
16373
- function randomSecretKey(seed = randomBytes8(lengths.seed)) {
16373
+ function randomSecretKey(seed = randomBytes9(lengths.seed)) {
16374
16374
  return _abytes2(seed, lengths.seed, "seed");
16375
16375
  }
16376
16376
  function keygen(seed) {
@@ -20282,6 +20282,7 @@ init_types();
20282
20282
  init_constants();
20283
20283
  init_errors();
20284
20284
  import { createServer } from "http";
20285
+ import { randomBytes as randomBytes3 } from "crypto";
20285
20286
  import { createInterface } from "readline";
20286
20287
  var PRIVATE_JWK_FIELDS = /* @__PURE__ */ new Set([
20287
20288
  "d",
@@ -20293,6 +20294,7 @@ var PRIVATE_JWK_FIELDS = /* @__PURE__ */ new Set([
20293
20294
  "oth",
20294
20295
  "k"
20295
20296
  ]);
20297
+ var MAX_CALLBACK_BODY_BYTES = 1024 * 1024;
20296
20298
  function publicJwkForDelegation(jwk) {
20297
20299
  const publicJwk = {};
20298
20300
  for (const [key, value] of Object.entries(jwk)) {
@@ -20443,6 +20445,7 @@ async function callbackFlow(did, options = {}) {
20443
20445
  settled = true;
20444
20446
  clearTimeout(timeout);
20445
20447
  server.close();
20448
+ server.closeAllConnections();
20446
20449
  if (rl) {
20447
20450
  rl.close();
20448
20451
  }
@@ -20452,37 +20455,50 @@ async function callbackFlow(did, options = {}) {
20452
20455
  reject(result.error);
20453
20456
  }
20454
20457
  }
20455
- const server = createServer((req, res) => {
20456
- if (req.method === "POST" && req.url === "/callback") {
20457
- let body = "";
20458
+ const callbackPath = `/callback/${randomBytes3(16).toString("base64url")}`;
20459
+ const openKeyOrigin = new URL(options.openkeyHost ?? DEFAULT_OPENKEY_HOST).origin;
20460
+ const cors = { "Access-Control-Allow-Origin": openKeyOrigin, "Vary": "Origin" };
20461
+ const server = createServer({ connectionsCheckingInterval: 1e3 }, (req, res) => {
20462
+ if (req.headers.origin !== openKeyOrigin) {
20463
+ res.writeHead(403);
20464
+ res.end();
20465
+ return;
20466
+ }
20467
+ if (req.method === "POST" && req.url === callbackPath) {
20468
+ const chunks = [];
20469
+ let size = 0;
20458
20470
  req.on("data", (chunk) => {
20459
- body += chunk.toString();
20471
+ size += chunk.length;
20472
+ if (size > MAX_CALLBACK_BODY_BYTES) {
20473
+ res.writeHead(413, cors);
20474
+ res.end();
20475
+ req.destroy();
20476
+ return;
20477
+ }
20478
+ chunks.push(chunk);
20460
20479
  });
20461
20480
  req.on("end", () => {
20481
+ let data;
20462
20482
  try {
20463
- const data = JSON.parse(body);
20464
- const invalid2 = validateDelegationCallbackPayload(data);
20465
- if (invalid2) {
20466
- res.writeHead(400, { "Content-Type": "application/json" });
20467
- res.end(JSON.stringify({ error: invalid2 }));
20468
- settle({ error: new Error(`Invalid delegation payload: ${invalid2}`) });
20469
- return;
20470
- }
20471
- res.writeHead(200, {
20472
- "Content-Type": "application/json",
20473
- "Access-Control-Allow-Origin": "*"
20474
- });
20475
- res.end(JSON.stringify({ success: true }));
20476
- settle({ data });
20477
- } catch (err2) {
20478
- res.writeHead(400, { "Content-Type": "application/json" });
20483
+ data = JSON.parse(Buffer.concat(chunks).toString("utf8"));
20484
+ } catch {
20485
+ res.writeHead(400, { ...cors, "Content-Type": "application/json" });
20479
20486
  res.end(JSON.stringify({ error: "Invalid JSON" }));
20480
- settle({ error: new Error("Invalid delegation data received") });
20487
+ return;
20488
+ }
20489
+ const invalid2 = validateDelegationCallbackPayload(data);
20490
+ if (invalid2) {
20491
+ res.writeHead(400, { ...cors, "Content-Type": "application/json" });
20492
+ res.end(JSON.stringify({ error: invalid2 }));
20493
+ return;
20481
20494
  }
20495
+ res.writeHead(200, { ...cors, "Content-Type": "application/json" });
20496
+ res.end(JSON.stringify({ success: true }));
20497
+ settle({ data });
20482
20498
  });
20483
- } else if (req.method === "OPTIONS") {
20499
+ } else if (req.method === "OPTIONS" && req.url === callbackPath) {
20484
20500
  res.writeHead(204, {
20485
- "Access-Control-Allow-Origin": "*",
20501
+ ...cors,
20486
20502
  "Access-Control-Allow-Methods": "POST, OPTIONS",
20487
20503
  "Access-Control-Allow-Headers": "Content-Type"
20488
20504
  });
@@ -20492,6 +20508,8 @@ async function callbackFlow(did, options = {}) {
20492
20508
  res.end();
20493
20509
  }
20494
20510
  });
20511
+ server.headersTimeout = 1e4;
20512
+ server.requestTimeout = 1e4;
20495
20513
  server.listen(0, "127.0.0.1", async () => {
20496
20514
  const addr = server.address();
20497
20515
  if (!addr || typeof addr === "string") {
@@ -20499,7 +20517,7 @@ async function callbackFlow(did, options = {}) {
20499
20517
  return;
20500
20518
  }
20501
20519
  const port = addr.port;
20502
- const callbackUrl = `http://127.0.0.1:${port}/callback`;
20520
+ const callbackUrl = `http://127.0.0.1:${port}${callbackPath}`;
20503
20521
  const authUrl = buildAuthUrl(did, { ...options, callback: callbackUrl });
20504
20522
  const openBrowser = shouldOpenBrowser(options);
20505
20523
  const hasTerminal = Boolean(process.stdin.isTTY || process.stderr.isTTY);
@@ -20589,14 +20607,14 @@ import {
20589
20607
  createECDH,
20590
20608
  createHash,
20591
20609
  createHmac,
20592
- randomBytes as randomBytes4
20610
+ randomBytes as randomBytes5
20593
20611
  } from "crypto";
20594
20612
 
20595
20613
  // src/auth/local-key.ts
20596
20614
  init_replication_config();
20597
20615
  import { TCWSessionManager, importKey, initPanicHook } from "@tinycloud/node-sdk-wasm";
20598
20616
  import { PrivateKeySigner } from "@tinycloud/node-sdk";
20599
- import { randomBytes as randomBytes3 } from "crypto";
20617
+ import { randomBytes as randomBytes4 } from "crypto";
20600
20618
  var wasmInitialized = false;
20601
20619
  function ensureWasm() {
20602
20620
  if (!wasmInitialized) {
@@ -20621,7 +20639,7 @@ function keyToDID(jwk) {
20621
20639
  return mgr.getDID(keyId);
20622
20640
  }
20623
20641
  function generateEthereumPrivateKey() {
20624
- const keyBytes = randomBytes3(32);
20642
+ const keyBytes = randomBytes4(32);
20625
20643
  return "0x" + keyBytes.toString("hex");
20626
20644
  }
20627
20645
  async function deriveAddress(privateKey) {
@@ -21140,6 +21158,11 @@ function warnIfNotPrimaryKey(ownerDid, primary) {
21140
21158
  if (primary !== false || ownerDid === void 0) return;
21141
21159
  process.stderr.write(nonPrimaryKeyWarning(ownerDid));
21142
21160
  }
21161
+ function announceFirstOwner(profileName2, expectedOwner, ownerDid) {
21162
+ if (expectedOwner !== void 0 || ownerDid === void 0) return;
21163
+ process.stderr.write(`Profile "${profileName2}" now belongs to ${ownerDid}. If that isn't your OpenKey account, stop using this profile and create a new one with tc init.
21164
+ `);
21165
+ }
21143
21166
  function ownerLoginPermissions(owner) {
21144
21167
  const space = ownerSpaceId("default", owner);
21145
21168
  return [
@@ -21385,8 +21408,8 @@ async function acquireDeviceDelegation(input) {
21385
21408
  const nodeOrigin = canonicalOrigin(input.nodeOrigin, "TinyCloud node origin");
21386
21409
  const shareOrigin = canonicalOrigin(input.shareOrigin, "Share origin");
21387
21410
  const fetchFn = input.fetchFn ?? globalThis.fetch;
21388
- const deviceSecret = randomBytes4(32).toString("base64url");
21389
- const codeVerifier = randomBytes4(32).toString("base64url");
21411
+ const deviceSecret = randomBytes5(32).toString("base64url");
21412
+ const codeVerifier = randomBytes5(32).toString("base64url");
21390
21413
  const relayKey = createECDH("prime256v1");
21391
21414
  relayKey.generateKeys();
21392
21415
  const relayPublicJwk = relayPublicJwkOf(relayKey);
@@ -21545,6 +21568,7 @@ async function loginWithDeviceAuthorization(input) {
21545
21568
  approved: { scope: result.session.permissions, ownerDid: result.ownerDid, replaceSession: input.replaceSession === true }
21546
21569
  });
21547
21570
  warnIfNotPrimaryKey(result.ownerDid, result.primary);
21571
+ announceFirstOwner(input.profileName, expectedOwner, result.ownerDid);
21548
21572
  return { profile, result };
21549
21573
  }
21550
21574
 
@@ -23436,10 +23460,10 @@ async function handleOpenKeyAuth(profileName2, host, options = {}) {
23436
23460
  profile: profileName2,
23437
23461
  did: profile.did,
23438
23462
  spaceId: delegationData.spaceId,
23463
+ ownerDid: profile.ownerDid ?? null,
23439
23464
  authMethod: "openkey",
23440
23465
  ...options.permissions ? {
23441
23466
  scoped: true,
23442
- ownerDid: profile.ownerDid,
23443
23467
  host,
23444
23468
  permissions: delegationData.permissions,
23445
23469
  declined,
@@ -23559,6 +23583,7 @@ async function refreshOpenKeySession(profileName2, host, options = {}) {
23559
23583
  ...permissions && verifiedOwner ? { approved: { scope: sanitizedSession.permissions, ownerDid: verifiedOwner, replaceSession: options.replaceSession === true } } : {}
23560
23584
  });
23561
23585
  warnIfNotPrimaryKey(verifiedOwner, ownerKeyPrimary);
23586
+ announceFirstOwner(profileName2, expectedOwner, verifiedOwner);
23562
23587
  return { profile: updatedProfile, delegationData: sanitizedSession, declined, legacyNested };
23563
23588
  }
23564
23589
 
@@ -23858,6 +23883,8 @@ init_constants();
23858
23883
  init_formatter();
23859
23884
  init_theme();
23860
23885
  init_errors();
23886
+ init_session_expired();
23887
+ init_types();
23861
23888
  function registerDoctorCommand(program) {
23862
23889
  program.command("doctor").description("Run diagnostic checks").action(async (_options, cmd) => {
23863
23890
  try {
@@ -23903,8 +23930,14 @@ function registerDoctorCommand(program) {
23903
23930
  if (profileOk && profileName2) {
23904
23931
  try {
23905
23932
  const session = await ProfileManager.getSession(profileName2);
23906
- sessionOk = session !== null;
23907
- sessionDetail = sessionOk ? "active" : "no session \u2014 run tc auth login";
23933
+ const { state: state2, expiresAt } = storedSessionState(session);
23934
+ sessionOk = sessionStateIsUsable(state2);
23935
+ if (state2 === "expired") {
23936
+ const posture = resolveProfilePosture(await ProfileManager.getProfile(profileName2));
23937
+ sessionDetail = `expired ${expiresAt} \u2014 ${signInAgainHint(profileName2, posture)}`;
23938
+ } else {
23939
+ sessionDetail = sessionOk ? "active" : "no session \u2014 run tc auth login";
23940
+ }
23908
23941
  } catch {
23909
23942
  sessionDetail = "error reading session";
23910
23943
  }
@@ -23917,7 +23950,7 @@ function registerDoctorCommand(program) {
23917
23950
  try {
23918
23951
  const host = profileOk && profileName2 ? (await ProfileManager.getProfile(profileName2)).host : globalOpts.host || DEFAULT_HOST;
23919
23952
  const start = Date.now();
23920
- const response = await fetch(`${host}/health`);
23953
+ const response = await fetch(`${host}/healthz`);
23921
23954
  const latency = Date.now() - start;
23922
23955
  nodeReachable = response.ok;
23923
23956
  nodeDetail = nodeReachable ? `${host} (${latency}ms)` : `${host} returned ${response.status}`;
@@ -23936,7 +23969,7 @@ function registerDoctorCommand(program) {
23936
23969
  spaceDetail = "error checking space";
23937
23970
  }
23938
23971
  } else {
23939
- spaceDetail = "skipped (no session)";
23972
+ spaceDetail = "skipped (no active session)";
23940
23973
  }
23941
23974
  checks.push({ name: "Space", ok: spaceOk, detail: spaceDetail });
23942
23975
  const result = {
@@ -24922,7 +24955,7 @@ function parseOperatorType(raw) {
24922
24955
  // src/commands/replica.ts
24923
24956
  init_sdk();
24924
24957
  init_replication_registry();
24925
- import { randomBytes as randomBytes5 } from "crypto";
24958
+ import { randomBytes as randomBytes6 } from "crypto";
24926
24959
  import { constants as fsConstants2 } from "fs";
24927
24960
  import { open as open4, readdir as readdir5, rename as rename3, stat as stat3, unlink as unlink2, readFile as readFile9, lstat as lstat4 } from "fs/promises";
24928
24961
  import { basename as basename3, dirname as dirname5, join as join10, resolve as resolve2 } from "path";
@@ -25269,7 +25302,7 @@ function describeStatus(status) {
25269
25302
  }
25270
25303
  async function writeFileAtomic(path, bytes) {
25271
25304
  const target = resolve2(path);
25272
- const temp = join10(dirname5(target), `.${basename3(target)}.${randomBytes5(6).toString("hex")}.tmp`);
25305
+ const temp = join10(dirname5(target), `.${basename3(target)}.${randomBytes6(6).toString("hex")}.tmp`);
25273
25306
  const handle = await open4(temp, fsConstants2.O_CREAT | fsConstants2.O_EXCL | fsConstants2.O_WRONLY, 384);
25274
25307
  try {
25275
25308
  await handle.writeFile(bytes);
@@ -25456,7 +25489,7 @@ or coverage incomplete; 5 grant expired, revoked or not yet valid; 6 network;
25456
25489
  chooseGrant(grants, deviceDid, space, prefix);
25457
25490
  store = await createReplica(profile, {
25458
25491
  name,
25459
- replicaId: randomBytes5(16).toString("hex"),
25492
+ replicaId: randomBytes6(16).toString("hex"),
25460
25493
  host,
25461
25494
  space,
25462
25495
  prefix,
@@ -35546,7 +35579,7 @@ function receiveJson(result, path) {
35546
35579
  // src/share/io.ts
35547
35580
  import { constants } from "fs";
35548
35581
  import { lstat as lstat5, mkdir as mkdir4, mkdtemp, open as open7, readFile as readFile11, realpath as realpath2, stat as stat4, link as link2, rename as rename4, rm as rm6, unlink as unlink3 } from "fs/promises";
35549
- import { randomBytes as randomBytes6 } from "crypto";
35582
+ import { randomBytes as randomBytes7 } from "crypto";
35550
35583
  import { basename as basename4, join as join12, resolve as resolve3, sep as sep2 } from "path";
35551
35584
  init_errors();
35552
35585
  var MAX_SHARE_STDIN_BYTES = 100 * 1024 * 1024;
@@ -35633,7 +35666,7 @@ async function writeShareOutput(directory, filename, bytes, force) {
35633
35666
  const stagingDirectory = await mkdtemp(join12(stableDirectory, ".tinycloud-share-stage-"));
35634
35667
  const stagingInfo = await lstat5(stagingDirectory);
35635
35668
  if (!stagingInfo.isDirectory() || (stagingInfo.mode & 511) !== 448) throw new Error("OUTPUT_EXISTS");
35636
- const stagingPath = join12(stagingDirectory, `.tinycloud-share-${randomBytes6(16).toString("hex")}.tmp`);
35669
+ const stagingPath = join12(stagingDirectory, `.tinycloud-share-${randomBytes7(16).toString("hex")}.tmp`);
35637
35670
  let temporaryPath;
35638
35671
  let handle;
35639
35672
  try {
@@ -36091,7 +36124,7 @@ init_constants();
36091
36124
  init_sdk();
36092
36125
  init_host();
36093
36126
  init_theme();
36094
- import { randomBytes as randomBytes7 } from "crypto";
36127
+ import { randomBytes as randomBytes8 } from "crypto";
36095
36128
  import { mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
36096
36129
  import { dirname as dirname6 } from "path";
36097
36130
  function didWithoutFragment2(did) {
@@ -36172,7 +36205,7 @@ it directly with \`tc space host <name>\` (no request needed).
36172
36205
  const artifact = {
36173
36206
  kind: "tinycloud.host.request",
36174
36207
  version: 1,
36175
- requestId: `hostreq_${Date.now().toString(36)}_${randomBytes7(4).toString("hex")}`,
36208
+ requestId: `hostreq_${Date.now().toString(36)}_${randomBytes8(4).toString("hex")}`,
36176
36209
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
36177
36210
  spaceName,
36178
36211
  spaceId,