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

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.
@@ -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
  }
@@ -20670,7 +20675,7 @@ async function localKeySignIn(options) {
20670
20675
  init_errors();
20671
20676
  init_constants();
20672
20677
  import { NodeWasmBindings, signedCompactUcanExpiry as signedCompactUcanExpiry2 } from "@tinycloud/node-sdk";
20673
- import { isLocalOwnerProfile as isLocalOwnerProfile2 } from "@tinycloud/operations/profile";
20678
+ import { isLocalOwnerProfile as isLocalOwnerProfile2, ownerSessionLacksProof as ownerSessionLacksProof2 } from "@tinycloud/operations/profile";
20674
20679
 
20675
20680
  // src/lib/duration.ts
20676
20681
  function parseDuration(input) {
@@ -20772,8 +20777,9 @@ function sessionExpiresAt(session) {
20772
20777
  if (typeof value === "string") return new Date(value).toISOString();
20773
20778
  return null;
20774
20779
  }
20775
- function storedSessionState(session) {
20780
+ function storedSessionState(session, profile) {
20776
20781
  if (session === null) return { state: "missing", expiresAt: null };
20782
+ if (ownerSessionLacksProof2(session, profile)) return { state: "unverified", expiresAt: null };
20777
20783
  const siweExpiry = typeof session.siwe === "string" ? session.siwe.match(/^Expiration Time:\s*(.+)$/m)?.[1] : void 0;
20778
20784
  const expiresAt = siweExpiry !== void 0 && Number.isFinite(Date.parse(siweExpiry)) ? new Date(siweExpiry).toISOString() : sessionExpiresAt(session);
20779
20785
  if (expiresAt === null) return { state: "unknown-expiry", expiresAt };
@@ -21495,15 +21501,6 @@ async function acquireDeviceDelegation(input) {
21495
21501
  }
21496
21502
  throw new CLIError("DEVICE_AUTH_EXPIRED", "OpenKey device authorization expired before approval. Run the command again.", ExitCode.AUTH_REQUIRED);
21497
21503
  }
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
21504
  async function loginWithDeviceAuthorization(input) {
21508
21505
  const snapshot = await readProfileSnapshot(input.profileName);
21509
21506
  const existing = snapshot.profile;
@@ -22254,7 +22251,7 @@ function registerAuthCommand(program, options) {
22254
22251
  }
22255
22252
  const posture = profile ? resolveProfilePosture(profile) : null;
22256
22253
  const operatorType = profile ? resolveProfileOperatorType(profile) : null;
22257
- const { state: sessionState, expiresAt } = storedSessionState(session);
22254
+ const { state: sessionState, expiresAt } = storedSessionState(session, profile);
22258
22255
  const authenticated = sessionStateIsUsable(sessionState);
22259
22256
  if (shouldOutputJson()) {
22260
22257
  outputJson({
@@ -22289,7 +22286,7 @@ function registerAuthCommand(program, options) {
22289
22286
  process.stdout.write(formatField("Address", profile?.address ?? null) + "\n");
22290
22287
  process.stdout.write(formatField("Space ID", profile?.spaceId ?? null) + "\n");
22291
22288
  process.stdout.write(formatField("Has Key", hasKey !== null) + "\n");
22292
- if (sessionState === "expired") {
22289
+ if (sessionState === "expired" || sessionState === "unverified") {
22293
22290
  process.stdout.write(`
22294
22291
  ${signInAgainHint(ctx.profile, posture ?? void 0)}
22295
22292
  `);
@@ -22741,9 +22738,9 @@ ${signInAgainHint(ctx.profile, posture ?? void 0)}
22741
22738
  const ctx = await ProfileManager.resolveContext(globalOpts, { storedSession: "unused" });
22742
22739
  const profile = await ProfileManager.getProfile(ctx.profile);
22743
22740
  const session = await ProfileManager.getSession(ctx.profile);
22744
- const { state: sessionState, expiresAt } = storedSessionState(session);
22745
- const authenticated = sessionStateIsUsable(sessionState);
22746
22741
  const posture = resolveProfilePosture(profile);
22742
+ const { state: sessionState, expiresAt } = storedSessionState(session, profile);
22743
+ const authenticated = sessionStateIsUsable(sessionState);
22747
22744
  const operatorType = resolveProfileOperatorType(profile);
22748
22745
  if (shouldOutputJson()) {
22749
22746
  outputJson({
@@ -22790,6 +22787,8 @@ function describeSession(state2, expiresAt) {
22790
22787
  return `active until ${expiresAt}`;
22791
22788
  case "unknown-expiry":
22792
22789
  return "active (no recorded expiry)";
22790
+ case "unverified":
22791
+ return "not usable (no signed OpenKey proof)";
22793
22792
  }
22794
22793
  }
22795
22794
  async function emitPermissionRequestArtifact(artifact, emitOption) {
@@ -23534,15 +23533,13 @@ async function refreshOpenKeySession(profileName2, host, options = {}) {
23534
23533
  verifiedOwner = sanitizedSession.ownerDid;
23535
23534
  declined = declinedPermissions(permissions, sanitizedSession.permissions, verifiedOwner);
23536
23535
  } 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"));
23536
+ const signed = verifySignedSession(delegationData, key, sessionDid, { expectedOwner, expiry });
23537
+ const spaceId = String(delegationData.spaceId);
23538
+ if (normalizePkhIdentifier(ownerSpaceId(spaceId.split(":").at(-1) ?? "", signed.ownerDid)) !== normalizePkhIdentifier(spaceId)) {
23539
+ 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
23540
  }
23541
+ verifiedOwner = signed.ownerDid;
23542
+ sanitizedSession = withVerifiedAuthority({ ...delegationData, jwk: key }, signed);
23546
23543
  }
23547
23544
  const ownerKeyPrimary = verifiedOwner === void 0 ? void 0 : openKeyPrimaryFlag(delegationData);
23548
23545
  const updatedProfile = withOwnerKeyPrimary({
@@ -23731,7 +23728,7 @@ function registerContextCommand(program) {
23731
23728
  host: ctx.host,
23732
23729
  spaceId,
23733
23730
  session: {
23734
- ...storedSessionState(session),
23731
+ ...storedSessionState(session, profile),
23735
23732
  evidence: "local-metadata"
23736
23733
  },
23737
23734
  access: "not-tested"
@@ -36517,6 +36514,7 @@ init_permissions();
36517
36514
  import {
36518
36515
  NodeWasmBindings as NodeWasmBindings2
36519
36516
  } from "@tinycloud/node-sdk";
36517
+ import { ownerSessionLacksProof as ownerSessionLacksProof3 } from "@tinycloud/operations/profile";
36520
36518
  var wasmBindings = null;
36521
36519
  function registerStatusCommand(program) {
36522
36520
  program.command("status").description("Show local TinyCloud profile, session, delegation, and permission state").action(async (_options, cmd) => {
@@ -36583,7 +36581,7 @@ async function inspectProfile(params) {
36583
36581
  ]);
36584
36582
  const hasPrivateKey = typeof profile?.privateKey === "string" && profile.privateKey.length > 0;
36585
36583
  const localKeyAuthenticated = profile?.authMethod === "local" && hasPrivateKey;
36586
- const sessionAuthenticated = session !== null && sessionExpired !== true;
36584
+ const sessionAuthenticated = session !== null && sessionExpired !== true && !ownerSessionLacksProof3(session, profile);
36587
36585
  const authenticated = localKeyAuthenticated || sessionAuthenticated;
36588
36586
  const status = resolveStatus({
36589
36587
  exists: profile !== null,