@tinycloud/cli 1.2.2-beta.1 → 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) {
@@ -17797,6 +17797,7 @@ __export(sdk_exports, {
17797
17797
  storedSessionVerifiesLocally: () => storedSessionVerifiesLocally
17798
17798
  });
17799
17799
  import { TinyCloudNode, signedCompactUcanExpiry } from "@tinycloud/node-sdk";
17800
+ import { ownerSessionLacksProof } from "@tinycloud/operations/profile";
17800
17801
  function jwkHasPrivateParameter(jwk) {
17801
17802
  if (!jwk || typeof jwk !== "object") return false;
17802
17803
  const d = jwk.d;
@@ -17828,11 +17829,15 @@ function signedLifetimePassed(delegation) {
17828
17829
  return expiry !== void 0 && expiry.getTime() <= Date.now();
17829
17830
  }
17830
17831
  async function restoreProfileSession(node, profileName2, profile, sessionData) {
17832
+ const posture = profile === null ? void 0 : resolveProfilePosture(profile);
17833
+ if (ownerSessionLacksProof(sessionData, profile)) {
17834
+ throw sessionExpiredError(profileName2, posture);
17835
+ }
17831
17836
  try {
17832
17837
  await node.restoreSession(sessionData);
17833
17838
  } catch (error) {
17834
17839
  if (typeof error === "object" && error !== null && "code" in error && error.code === "AUTH_EXPIRED") {
17835
- throw sessionExpiredError(profileName2, profile === null ? void 0 : resolveProfilePosture(profile));
17840
+ throw sessionExpiredError(profileName2, posture);
17836
17841
  }
17837
17842
  throw error;
17838
17843
  }
@@ -20277,6 +20282,7 @@ init_types();
20277
20282
  init_constants();
20278
20283
  init_errors();
20279
20284
  import { createServer } from "http";
20285
+ import { randomBytes as randomBytes3 } from "crypto";
20280
20286
  import { createInterface } from "readline";
20281
20287
  var PRIVATE_JWK_FIELDS = /* @__PURE__ */ new Set([
20282
20288
  "d",
@@ -20288,6 +20294,7 @@ var PRIVATE_JWK_FIELDS = /* @__PURE__ */ new Set([
20288
20294
  "oth",
20289
20295
  "k"
20290
20296
  ]);
20297
+ var MAX_CALLBACK_BODY_BYTES = 1024 * 1024;
20291
20298
  function publicJwkForDelegation(jwk) {
20292
20299
  const publicJwk = {};
20293
20300
  for (const [key, value] of Object.entries(jwk)) {
@@ -20438,6 +20445,7 @@ async function callbackFlow(did, options = {}) {
20438
20445
  settled = true;
20439
20446
  clearTimeout(timeout);
20440
20447
  server.close();
20448
+ server.closeAllConnections();
20441
20449
  if (rl) {
20442
20450
  rl.close();
20443
20451
  }
@@ -20447,37 +20455,50 @@ async function callbackFlow(did, options = {}) {
20447
20455
  reject(result.error);
20448
20456
  }
20449
20457
  }
20450
- const server = createServer((req, res) => {
20451
- if (req.method === "POST" && req.url === "/callback") {
20452
- 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;
20453
20470
  req.on("data", (chunk) => {
20454
- 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);
20455
20479
  });
20456
20480
  req.on("end", () => {
20481
+ let data;
20457
20482
  try {
20458
- const data = JSON.parse(body);
20459
- const invalid2 = validateDelegationCallbackPayload(data);
20460
- if (invalid2) {
20461
- res.writeHead(400, { "Content-Type": "application/json" });
20462
- res.end(JSON.stringify({ error: invalid2 }));
20463
- settle({ error: new Error(`Invalid delegation payload: ${invalid2}`) });
20464
- return;
20465
- }
20466
- res.writeHead(200, {
20467
- "Content-Type": "application/json",
20468
- "Access-Control-Allow-Origin": "*"
20469
- });
20470
- res.end(JSON.stringify({ success: true }));
20471
- settle({ data });
20472
- } catch (err2) {
20473
- 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" });
20474
20486
  res.end(JSON.stringify({ error: "Invalid JSON" }));
20475
- settle({ error: new Error("Invalid delegation data received") });
20487
+ return;
20476
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;
20494
+ }
20495
+ res.writeHead(200, { ...cors, "Content-Type": "application/json" });
20496
+ res.end(JSON.stringify({ success: true }));
20497
+ settle({ data });
20477
20498
  });
20478
- } else if (req.method === "OPTIONS") {
20499
+ } else if (req.method === "OPTIONS" && req.url === callbackPath) {
20479
20500
  res.writeHead(204, {
20480
- "Access-Control-Allow-Origin": "*",
20501
+ ...cors,
20481
20502
  "Access-Control-Allow-Methods": "POST, OPTIONS",
20482
20503
  "Access-Control-Allow-Headers": "Content-Type"
20483
20504
  });
@@ -20487,6 +20508,8 @@ async function callbackFlow(did, options = {}) {
20487
20508
  res.end();
20488
20509
  }
20489
20510
  });
20511
+ server.headersTimeout = 1e4;
20512
+ server.requestTimeout = 1e4;
20490
20513
  server.listen(0, "127.0.0.1", async () => {
20491
20514
  const addr = server.address();
20492
20515
  if (!addr || typeof addr === "string") {
@@ -20494,7 +20517,7 @@ async function callbackFlow(did, options = {}) {
20494
20517
  return;
20495
20518
  }
20496
20519
  const port = addr.port;
20497
- const callbackUrl = `http://127.0.0.1:${port}/callback`;
20520
+ const callbackUrl = `http://127.0.0.1:${port}${callbackPath}`;
20498
20521
  const authUrl = buildAuthUrl(did, { ...options, callback: callbackUrl });
20499
20522
  const openBrowser = shouldOpenBrowser(options);
20500
20523
  const hasTerminal = Boolean(process.stdin.isTTY || process.stderr.isTTY);
@@ -20584,14 +20607,14 @@ import {
20584
20607
  createECDH,
20585
20608
  createHash,
20586
20609
  createHmac,
20587
- randomBytes as randomBytes4
20610
+ randomBytes as randomBytes5
20588
20611
  } from "crypto";
20589
20612
 
20590
20613
  // src/auth/local-key.ts
20591
20614
  init_replication_config();
20592
20615
  import { TCWSessionManager, importKey, initPanicHook } from "@tinycloud/node-sdk-wasm";
20593
20616
  import { PrivateKeySigner } from "@tinycloud/node-sdk";
20594
- import { randomBytes as randomBytes3 } from "crypto";
20617
+ import { randomBytes as randomBytes4 } from "crypto";
20595
20618
  var wasmInitialized = false;
20596
20619
  function ensureWasm() {
20597
20620
  if (!wasmInitialized) {
@@ -20616,7 +20639,7 @@ function keyToDID(jwk) {
20616
20639
  return mgr.getDID(keyId);
20617
20640
  }
20618
20641
  function generateEthereumPrivateKey() {
20619
- const keyBytes = randomBytes3(32);
20642
+ const keyBytes = randomBytes4(32);
20620
20643
  return "0x" + keyBytes.toString("hex");
20621
20644
  }
20622
20645
  async function deriveAddress(privateKey) {
@@ -20670,7 +20693,7 @@ async function localKeySignIn(options) {
20670
20693
  init_errors();
20671
20694
  init_constants();
20672
20695
  import { NodeWasmBindings, signedCompactUcanExpiry as signedCompactUcanExpiry2 } from "@tinycloud/node-sdk";
20673
- import { isLocalOwnerProfile as isLocalOwnerProfile2 } from "@tinycloud/operations/profile";
20696
+ import { isLocalOwnerProfile as isLocalOwnerProfile2, ownerSessionLacksProof as ownerSessionLacksProof2 } from "@tinycloud/operations/profile";
20674
20697
 
20675
20698
  // src/lib/duration.ts
20676
20699
  function parseDuration(input) {
@@ -20772,8 +20795,9 @@ function sessionExpiresAt(session) {
20772
20795
  if (typeof value === "string") return new Date(value).toISOString();
20773
20796
  return null;
20774
20797
  }
20775
- function storedSessionState(session) {
20798
+ function storedSessionState(session, profile) {
20776
20799
  if (session === null) return { state: "missing", expiresAt: null };
20800
+ if (ownerSessionLacksProof2(session, profile)) return { state: "unverified", expiresAt: null };
20777
20801
  const siweExpiry = typeof session.siwe === "string" ? session.siwe.match(/^Expiration Time:\s*(.+)$/m)?.[1] : void 0;
20778
20802
  const expiresAt = siweExpiry !== void 0 && Number.isFinite(Date.parse(siweExpiry)) ? new Date(siweExpiry).toISOString() : sessionExpiresAt(session);
20779
20803
  if (expiresAt === null) return { state: "unknown-expiry", expiresAt };
@@ -21134,6 +21158,11 @@ function warnIfNotPrimaryKey(ownerDid, primary) {
21134
21158
  if (primary !== false || ownerDid === void 0) return;
21135
21159
  process.stderr.write(nonPrimaryKeyWarning(ownerDid));
21136
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
+ }
21137
21166
  function ownerLoginPermissions(owner) {
21138
21167
  const space = ownerSpaceId("default", owner);
21139
21168
  return [
@@ -21379,8 +21408,8 @@ async function acquireDeviceDelegation(input) {
21379
21408
  const nodeOrigin = canonicalOrigin(input.nodeOrigin, "TinyCloud node origin");
21380
21409
  const shareOrigin = canonicalOrigin(input.shareOrigin, "Share origin");
21381
21410
  const fetchFn = input.fetchFn ?? globalThis.fetch;
21382
- const deviceSecret = randomBytes4(32).toString("base64url");
21383
- const codeVerifier = randomBytes4(32).toString("base64url");
21411
+ const deviceSecret = randomBytes5(32).toString("base64url");
21412
+ const codeVerifier = randomBytes5(32).toString("base64url");
21384
21413
  const relayKey = createECDH("prime256v1");
21385
21414
  relayKey.generateKeys();
21386
21415
  const relayPublicJwk = relayPublicJwkOf(relayKey);
@@ -21495,15 +21524,6 @@ async function acquireDeviceDelegation(input) {
21495
21524
  }
21496
21525
  throw new CLIError("DEVICE_AUTH_EXPIRED", "OpenKey device authorization expired before approval. Run the command again.", ExitCode.AUTH_REQUIRED);
21497
21526
  }
21498
- function mergePrivateJwkIntoSession(session, key) {
21499
- const sessionJwk = session.jwk;
21500
- if (!sessionJwk || typeof sessionJwk !== "object") return session;
21501
- const sessionJwkRecord = sessionJwk;
21502
- if (typeof sessionJwkRecord.d === "string" && sessionJwkRecord.d.length > 0) return session;
21503
- const privateParameter = key.d;
21504
- if (typeof privateParameter !== "string" || privateParameter.length === 0) return session;
21505
- return { ...session, jwk: { ...sessionJwkRecord, d: privateParameter } };
21506
- }
21507
21527
  async function loginWithDeviceAuthorization(input) {
21508
21528
  const snapshot = await readProfileSnapshot(input.profileName);
21509
21529
  const existing = snapshot.profile;
@@ -21548,6 +21568,7 @@ async function loginWithDeviceAuthorization(input) {
21548
21568
  approved: { scope: result.session.permissions, ownerDid: result.ownerDid, replaceSession: input.replaceSession === true }
21549
21569
  });
21550
21570
  warnIfNotPrimaryKey(result.ownerDid, result.primary);
21571
+ announceFirstOwner(input.profileName, expectedOwner, result.ownerDid);
21551
21572
  return { profile, result };
21552
21573
  }
21553
21574
 
@@ -22254,7 +22275,7 @@ function registerAuthCommand(program, options) {
22254
22275
  }
22255
22276
  const posture = profile ? resolveProfilePosture(profile) : null;
22256
22277
  const operatorType = profile ? resolveProfileOperatorType(profile) : null;
22257
- const { state: sessionState, expiresAt } = storedSessionState(session);
22278
+ const { state: sessionState, expiresAt } = storedSessionState(session, profile);
22258
22279
  const authenticated = sessionStateIsUsable(sessionState);
22259
22280
  if (shouldOutputJson()) {
22260
22281
  outputJson({
@@ -22289,7 +22310,7 @@ function registerAuthCommand(program, options) {
22289
22310
  process.stdout.write(formatField("Address", profile?.address ?? null) + "\n");
22290
22311
  process.stdout.write(formatField("Space ID", profile?.spaceId ?? null) + "\n");
22291
22312
  process.stdout.write(formatField("Has Key", hasKey !== null) + "\n");
22292
- if (sessionState === "expired") {
22313
+ if (sessionState === "expired" || sessionState === "unverified") {
22293
22314
  process.stdout.write(`
22294
22315
  ${signInAgainHint(ctx.profile, posture ?? void 0)}
22295
22316
  `);
@@ -22741,9 +22762,9 @@ ${signInAgainHint(ctx.profile, posture ?? void 0)}
22741
22762
  const ctx = await ProfileManager.resolveContext(globalOpts, { storedSession: "unused" });
22742
22763
  const profile = await ProfileManager.getProfile(ctx.profile);
22743
22764
  const session = await ProfileManager.getSession(ctx.profile);
22744
- const { state: sessionState, expiresAt } = storedSessionState(session);
22745
- const authenticated = sessionStateIsUsable(sessionState);
22746
22765
  const posture = resolveProfilePosture(profile);
22766
+ const { state: sessionState, expiresAt } = storedSessionState(session, profile);
22767
+ const authenticated = sessionStateIsUsable(sessionState);
22747
22768
  const operatorType = resolveProfileOperatorType(profile);
22748
22769
  if (shouldOutputJson()) {
22749
22770
  outputJson({
@@ -22790,6 +22811,8 @@ function describeSession(state2, expiresAt) {
22790
22811
  return `active until ${expiresAt}`;
22791
22812
  case "unknown-expiry":
22792
22813
  return "active (no recorded expiry)";
22814
+ case "unverified":
22815
+ return "not usable (no signed OpenKey proof)";
22793
22816
  }
22794
22817
  }
22795
22818
  async function emitPermissionRequestArtifact(artifact, emitOption) {
@@ -23437,10 +23460,10 @@ async function handleOpenKeyAuth(profileName2, host, options = {}) {
23437
23460
  profile: profileName2,
23438
23461
  did: profile.did,
23439
23462
  spaceId: delegationData.spaceId,
23463
+ ownerDid: profile.ownerDid ?? null,
23440
23464
  authMethod: "openkey",
23441
23465
  ...options.permissions ? {
23442
23466
  scoped: true,
23443
- ownerDid: profile.ownerDid,
23444
23467
  host,
23445
23468
  permissions: delegationData.permissions,
23446
23469
  declined,
@@ -23534,15 +23557,13 @@ async function refreshOpenKeySession(profileName2, host, options = {}) {
23534
23557
  verifiedOwner = sanitizedSession.ownerDid;
23535
23558
  declined = declinedPermissions(permissions, sanitizedSession.permissions, verifiedOwner);
23536
23559
  } else {
23537
- const carriesProof = typeof delegationData.siwe === "string" && typeof delegationData.signature === "string";
23538
- const merged = mergePrivateJwkIntoSession(delegationData, key);
23539
- if (carriesProof || expiry !== void 0 || expectedOwner !== void 0) {
23540
- const signed = verifySignedSession(delegationData, key, sessionDid, { expectedOwner, expiry });
23541
- verifiedOwner = signed.ownerDid;
23542
- sanitizedSession = withVerifiedAuthority(merged, signed);
23543
- } else {
23544
- sanitizedSession = Object.fromEntries(Object.entries(withoutTrustFields(merged)).filter(([name]) => name !== "siwe" && name !== "signature"));
23560
+ const signed = verifySignedSession(delegationData, key, sessionDid, { expectedOwner, expiry });
23561
+ const spaceId = String(delegationData.spaceId);
23562
+ if (normalizePkhIdentifier(ownerSpaceId(spaceId.split(":").at(-1) ?? "", signed.ownerDid)) !== normalizePkhIdentifier(spaceId)) {
23563
+ throw new CLIError("OPENKEY_SCOPE_MISMATCH", "The approved session is for a space the signing account doesn't own. No session was saved.", ExitCode.PERMISSION_DENIED);
23545
23564
  }
23565
+ verifiedOwner = signed.ownerDid;
23566
+ sanitizedSession = withVerifiedAuthority({ ...delegationData, jwk: key }, signed);
23546
23567
  }
23547
23568
  const ownerKeyPrimary = verifiedOwner === void 0 ? void 0 : openKeyPrimaryFlag(delegationData);
23548
23569
  const updatedProfile = withOwnerKeyPrimary({
@@ -23562,6 +23583,7 @@ async function refreshOpenKeySession(profileName2, host, options = {}) {
23562
23583
  ...permissions && verifiedOwner ? { approved: { scope: sanitizedSession.permissions, ownerDid: verifiedOwner, replaceSession: options.replaceSession === true } } : {}
23563
23584
  });
23564
23585
  warnIfNotPrimaryKey(verifiedOwner, ownerKeyPrimary);
23586
+ announceFirstOwner(profileName2, expectedOwner, verifiedOwner);
23565
23587
  return { profile: updatedProfile, delegationData: sanitizedSession, declined, legacyNested };
23566
23588
  }
23567
23589
 
@@ -23731,7 +23753,7 @@ function registerContextCommand(program) {
23731
23753
  host: ctx.host,
23732
23754
  spaceId,
23733
23755
  session: {
23734
- ...storedSessionState(session),
23756
+ ...storedSessionState(session, profile),
23735
23757
  evidence: "local-metadata"
23736
23758
  },
23737
23759
  access: "not-tested"
@@ -23861,6 +23883,8 @@ init_constants();
23861
23883
  init_formatter();
23862
23884
  init_theme();
23863
23885
  init_errors();
23886
+ init_session_expired();
23887
+ init_types();
23864
23888
  function registerDoctorCommand(program) {
23865
23889
  program.command("doctor").description("Run diagnostic checks").action(async (_options, cmd) => {
23866
23890
  try {
@@ -23906,8 +23930,14 @@ function registerDoctorCommand(program) {
23906
23930
  if (profileOk && profileName2) {
23907
23931
  try {
23908
23932
  const session = await ProfileManager.getSession(profileName2);
23909
- sessionOk = session !== null;
23910
- 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
+ }
23911
23941
  } catch {
23912
23942
  sessionDetail = "error reading session";
23913
23943
  }
@@ -23920,7 +23950,7 @@ function registerDoctorCommand(program) {
23920
23950
  try {
23921
23951
  const host = profileOk && profileName2 ? (await ProfileManager.getProfile(profileName2)).host : globalOpts.host || DEFAULT_HOST;
23922
23952
  const start = Date.now();
23923
- const response = await fetch(`${host}/health`);
23953
+ const response = await fetch(`${host}/healthz`);
23924
23954
  const latency = Date.now() - start;
23925
23955
  nodeReachable = response.ok;
23926
23956
  nodeDetail = nodeReachable ? `${host} (${latency}ms)` : `${host} returned ${response.status}`;
@@ -23939,7 +23969,7 @@ function registerDoctorCommand(program) {
23939
23969
  spaceDetail = "error checking space";
23940
23970
  }
23941
23971
  } else {
23942
- spaceDetail = "skipped (no session)";
23972
+ spaceDetail = "skipped (no active session)";
23943
23973
  }
23944
23974
  checks.push({ name: "Space", ok: spaceOk, detail: spaceDetail });
23945
23975
  const result = {
@@ -24925,7 +24955,7 @@ function parseOperatorType(raw) {
24925
24955
  // src/commands/replica.ts
24926
24956
  init_sdk();
24927
24957
  init_replication_registry();
24928
- import { randomBytes as randomBytes5 } from "crypto";
24958
+ import { randomBytes as randomBytes6 } from "crypto";
24929
24959
  import { constants as fsConstants2 } from "fs";
24930
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";
24931
24961
  import { basename as basename3, dirname as dirname5, join as join10, resolve as resolve2 } from "path";
@@ -25272,7 +25302,7 @@ function describeStatus(status) {
25272
25302
  }
25273
25303
  async function writeFileAtomic(path, bytes) {
25274
25304
  const target = resolve2(path);
25275
- 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`);
25276
25306
  const handle = await open4(temp, fsConstants2.O_CREAT | fsConstants2.O_EXCL | fsConstants2.O_WRONLY, 384);
25277
25307
  try {
25278
25308
  await handle.writeFile(bytes);
@@ -25459,7 +25489,7 @@ or coverage incomplete; 5 grant expired, revoked or not yet valid; 6 network;
25459
25489
  chooseGrant(grants, deviceDid, space, prefix);
25460
25490
  store = await createReplica(profile, {
25461
25491
  name,
25462
- replicaId: randomBytes5(16).toString("hex"),
25492
+ replicaId: randomBytes6(16).toString("hex"),
25463
25493
  host,
25464
25494
  space,
25465
25495
  prefix,
@@ -35549,7 +35579,7 @@ function receiveJson(result, path) {
35549
35579
  // src/share/io.ts
35550
35580
  import { constants } from "fs";
35551
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";
35552
- import { randomBytes as randomBytes6 } from "crypto";
35582
+ import { randomBytes as randomBytes7 } from "crypto";
35553
35583
  import { basename as basename4, join as join12, resolve as resolve3, sep as sep2 } from "path";
35554
35584
  init_errors();
35555
35585
  var MAX_SHARE_STDIN_BYTES = 100 * 1024 * 1024;
@@ -35636,7 +35666,7 @@ async function writeShareOutput(directory, filename, bytes, force) {
35636
35666
  const stagingDirectory = await mkdtemp(join12(stableDirectory, ".tinycloud-share-stage-"));
35637
35667
  const stagingInfo = await lstat5(stagingDirectory);
35638
35668
  if (!stagingInfo.isDirectory() || (stagingInfo.mode & 511) !== 448) throw new Error("OUTPUT_EXISTS");
35639
- const stagingPath = join12(stagingDirectory, `.tinycloud-share-${randomBytes6(16).toString("hex")}.tmp`);
35669
+ const stagingPath = join12(stagingDirectory, `.tinycloud-share-${randomBytes7(16).toString("hex")}.tmp`);
35640
35670
  let temporaryPath;
35641
35671
  let handle;
35642
35672
  try {
@@ -36094,7 +36124,7 @@ init_constants();
36094
36124
  init_sdk();
36095
36125
  init_host();
36096
36126
  init_theme();
36097
- import { randomBytes as randomBytes7 } from "crypto";
36127
+ import { randomBytes as randomBytes8 } from "crypto";
36098
36128
  import { mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
36099
36129
  import { dirname as dirname6 } from "path";
36100
36130
  function didWithoutFragment2(did) {
@@ -36175,7 +36205,7 @@ it directly with \`tc space host <name>\` (no request needed).
36175
36205
  const artifact = {
36176
36206
  kind: "tinycloud.host.request",
36177
36207
  version: 1,
36178
- requestId: `hostreq_${Date.now().toString(36)}_${randomBytes7(4).toString("hex")}`,
36208
+ requestId: `hostreq_${Date.now().toString(36)}_${randomBytes8(4).toString("hex")}`,
36179
36209
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
36180
36210
  spaceName,
36181
36211
  spaceId,
@@ -36517,6 +36547,7 @@ init_permissions();
36517
36547
  import {
36518
36548
  NodeWasmBindings as NodeWasmBindings2
36519
36549
  } from "@tinycloud/node-sdk";
36550
+ import { ownerSessionLacksProof as ownerSessionLacksProof3 } from "@tinycloud/operations/profile";
36520
36551
  var wasmBindings = null;
36521
36552
  function registerStatusCommand(program) {
36522
36553
  program.command("status").description("Show local TinyCloud profile, session, delegation, and permission state").action(async (_options, cmd) => {
@@ -36583,7 +36614,7 @@ async function inspectProfile(params) {
36583
36614
  ]);
36584
36615
  const hasPrivateKey = typeof profile?.privateKey === "string" && profile.privateKey.length > 0;
36585
36616
  const localKeyAuthenticated = profile?.authMethod === "local" && hasPrivateKey;
36586
- const sessionAuthenticated = session !== null && sessionExpired !== true;
36617
+ const sessionAuthenticated = session !== null && sessionExpired !== true && !ownerSessionLacksProof3(session, profile);
36587
36618
  const authenticated = localKeyAuthenticated || sessionAuthenticated;
36588
36619
  const status = resolveStatus({
36589
36620
  exists: profile !== null,