@tinycloud/node-sdk 3.8.0-beta.20 → 3.8.0-beta.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1191,6 +1191,8 @@ interface DelegateToResult {
1191
1191
  interface RuntimePermissionGrantOptions {
1192
1192
  /** Override expiry. ms-format string ("7d", "1h") or raw milliseconds. */
1193
1193
  expiry?: string | number;
1194
+ /** In-memory key snapshot captured when exact Share-key consent opened. */
1195
+ expectedSessionKey?: Readonly<TinyCloudSession["jwk"]>;
1194
1196
  }
1195
1197
  interface EnsureEncryptionNetworkOptions {
1196
1198
  /**
@@ -1191,6 +1191,8 @@ interface DelegateToResult {
1191
1191
  interface RuntimePermissionGrantOptions {
1192
1192
  /** Override expiry. ms-format string ("7d", "1h") or raw milliseconds. */
1193
1193
  expiry?: string | number;
1194
+ /** In-memory key snapshot captured when exact Share-key consent opened. */
1195
+ expectedSessionKey?: Readonly<TinyCloudSession["jwk"]>;
1194
1196
  }
1195
1197
  interface EnsureEncryptionNetworkOptions {
1196
1198
  /**
@@ -1,7 +1,7 @@
1
1
  import { ReplicationOptions, PermissionEntry, TinyCloudSession, KVReplicaStorage, ServiceContext, IWasmBindings, WasmRecapEntry } from '@tinycloud/sdk-core';
2
2
  import { ReplicaConsentAnchor, AuthorityRefusal, ReplicationAuthority } from '@tinycloud/sdk-services';
3
3
  import { ReplicaLocalEraseOutcome, ReplicaPurgeLocalCopyResult, ReplicaPurgeTrigger, ReplicaPurgeFailedEvent, ReplicaSessionStamp, ReplicaDenyInput } from '@tinycloud/sdk-services/kv/replication';
4
- import { T as TinyCloudNode } from './TinyCloudNode-BRyeZas2.js';
4
+ import { T as TinyCloudNode } from './TinyCloudNode-k3TbBwwj.js';
5
5
 
6
6
  /** Constructor-time validation; the space-dependent secrets check runs at sign-in and open. */
7
7
  declare function assertValidReplicationConfig(replication: (ReplicationOptions & {
@@ -1,7 +1,7 @@
1
1
  import { ReplicationOptions, PermissionEntry, TinyCloudSession, KVReplicaStorage, ServiceContext, IWasmBindings, WasmRecapEntry } from '@tinycloud/sdk-core';
2
2
  import { ReplicaConsentAnchor, AuthorityRefusal, ReplicationAuthority } from '@tinycloud/sdk-services';
3
3
  import { ReplicaLocalEraseOutcome, ReplicaPurgeLocalCopyResult, ReplicaPurgeTrigger, ReplicaPurgeFailedEvent, ReplicaSessionStamp, ReplicaDenyInput } from '@tinycloud/sdk-services/kv/replication';
4
- import { T as TinyCloudNode } from './TinyCloudNode-NrmztjDd.cjs';
4
+ import { T as TinyCloudNode } from './TinyCloudNode-DaD5vJhL.cjs';
5
5
 
6
6
  /** Constructor-time validation; the space-dependent secrets check runs at sign-in and open. */
7
7
  declare function assertValidReplicationConfig(replication: (ReplicationOptions & {
package/dist/core.cjs CHANGED
@@ -1525,8 +1525,8 @@ var NodeUserAuthorization = class {
1525
1525
  this.assertSignInCurrent(generation);
1526
1526
  await this.refreshNamedKeyFeatureForSignIn(address, chainId);
1527
1527
  this.assertSignInCurrent(generation);
1528
- const keyId = `session-${Date.now()}`;
1529
- this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
1528
+ const keyId = `session-${Date.now()}-${Math.random().toString(36).slice(2)}`;
1529
+ this.sessionManager.createSessionKey(keyId);
1530
1530
  this.activeSessionKeyId = keyId;
1531
1531
  const jwkString = this.sessionManager.jwk(keyId);
1532
1532
  if (!jwkString) {
@@ -2960,6 +2960,7 @@ function deserializeDelegation(data) {
2960
2960
 
2961
2961
  // src/TinyCloudNode.ts
2962
2962
  var import_siwe2 = require("siwe");
2963
+ var import_share_envelope = require("@tinycloud/share-envelope");
2963
2964
  var import_sdk_core11 = require("@tinycloud/sdk-core");
2964
2965
  var import_sdk_services4 = require("@tinycloud/sdk-services");
2965
2966
  var import_requestLog2 = require("@tinycloud/sdk-services/telemetry/requestLog");
@@ -8283,7 +8284,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8283
8284
  if (!session || !Array.isArray(permissions) || permissions.length === 0) {
8284
8285
  return false;
8285
8286
  }
8286
- const expanded = this.expandPermissionEntries(permissions);
8287
+ const expanded = (0, import_sdk_core11.expandRuntimePermissionEntries)(permissions, (0, import_sdk_core11.pkhDid)(session.address, session.chainId));
8287
8288
  if (this.sessionCoversPermissionEntries(session, expanded)) {
8288
8289
  return true;
8289
8290
  }
@@ -8303,7 +8304,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8303
8304
  if (!session || !Array.isArray(permissions) || permissions.length === 0) {
8304
8305
  return [];
8305
8306
  }
8306
- const expanded = this.expandPermissionEntries(permissions);
8307
+ const expanded = (0, import_sdk_core11.expandRuntimePermissionEntries)(permissions, (0, import_sdk_core11.pkhDid)(session.address, session.chainId));
8307
8308
  return this.findRuntimeGrantsForPermissionEntries(expanded, session).map(
8308
8309
  (grant) => grant.delegation
8309
8310
  );
@@ -8478,7 +8479,28 @@ var _TinyCloudNode = class _TinyCloudNode {
8478
8479
  throw new import_sdk_core11.SessionExpiredError(sessionExpiry);
8479
8480
  }
8480
8481
  }
8481
- const expanded = this.expandPermissionEntries(permissions);
8482
+ const expanded = (0, import_sdk_core11.expandRuntimePermissionEntries)(permissions, (0, import_sdk_core11.pkhDid)(session.address, session.chainId));
8483
+ const bindsShareKey = expanded.some((entry) => entry.service === import_sdk_core11.ENCRYPTION_PERMISSION_SERVICE && entry.actions.includes("tinycloud.encryption/key.create"));
8484
+ const captured = bindsShareKey ? { ...session, jwk: { ...options?.expectedSessionKey ?? session.jwk } } : session;
8485
+ const assertCapturedKey = bindsShareKey ? () => {
8486
+ const live = session.jwk;
8487
+ const key = captured.jwk;
8488
+ if (this.currentTinyCloudSession() !== session || session.verificationMethod !== captured.verificationMethod || session.delegationCid !== captured.delegationCid || session.spaceId !== captured.spaceId || session.address !== captured.address || session.chainId !== captured.chainId || live?.kty !== key.kty || live?.crv !== key.crv || live?.x !== key.x || live?.y !== key.y || live?.d !== key.d) {
8489
+ throw new Error("Runtime permission request cancelled because the session key changed.");
8490
+ }
8491
+ } : void 0;
8492
+ const sessionKeyDid = bindsShareKey ? this.sessionDid : void 0;
8493
+ if (bindsShareKey) {
8494
+ const key = captured.jwk;
8495
+ if (key.kty !== "OKP" || key.crv !== "Ed25519" || typeof key.x !== "string") {
8496
+ throw new Error("Runtime permission session key does not match its signed identity.");
8497
+ }
8498
+ const keyDid = (0, import_share_envelope.didKeyFromEd25519PublicKey)(base64UrlDecode(key.x));
8499
+ if (!didPrincipalMatches2(keyDid, sessionKeyDid) || !didPrincipalMatches2(keyDid, captured.verificationMethod) || !didPrincipalMatches2(keyDid, new import_siwe2.SiweMessage(session.siwe).uri)) {
8500
+ throw new Error("Runtime permission session key does not match its signed identity.");
8501
+ }
8502
+ assertCapturedKey();
8503
+ }
8482
8504
  if (this.sessionCoversPermissionEntries(session, expanded)) {
8483
8505
  return [];
8484
8506
  }
@@ -8528,13 +8550,13 @@ var _TinyCloudNode = class _TinyCloudNode {
8528
8550
  return this.wasmBindings.prepareSession({
8529
8551
  abilities,
8530
8552
  ...rawForDelegation.length > 0 ? { rawAbilities: this.permissionsToRawAbilities(rawForDelegation) } : {},
8531
- address: this.wasmBindings.ensureEip55(session.address),
8532
- chainId: session.chainId,
8553
+ address: this.wasmBindings.ensureEip55(captured.address),
8554
+ chainId: captured.chainId,
8533
8555
  domain: this.siweDomain,
8534
8556
  issuedAt: now.toISOString(),
8535
8557
  expirationTime: expiresAt.toISOString(),
8536
8558
  spaceId,
8537
- jwk: session.jwk
8559
+ jwk: captured.jwk
8538
8560
  });
8539
8561
  } catch (error) {
8540
8562
  if (rawForDelegation.some((entry) => this.isRawRevocationPermissionEntry(entry)) && /invalid ReCap resource URI/i.test(error instanceof Error ? error.message : String(error))) {
@@ -8546,8 +8568,13 @@ var _TinyCloudNode = class _TinyCloudNode {
8546
8568
  throw error;
8547
8569
  }
8548
8570
  })();
8571
+ if (bindsShareKey && !didPrincipalMatches2(new import_siwe2.SiweMessage(prepared.siwe).uri, sessionKeyDid)) {
8572
+ throw new Error("Prepared runtime permission targets a different session key.");
8573
+ }
8574
+ assertCapturedKey?.();
8549
8575
  const signature = await this.signer.signMessage(prepared.siwe);
8550
8576
  graph.assertActive();
8577
+ assertCapturedKey?.();
8551
8578
  const delegatedSession = this.wasmBindings.completeSessionSetup({
8552
8579
  ...prepared,
8553
8580
  signature
@@ -8576,18 +8603,19 @@ var _TinyCloudNode = class _TinyCloudNode {
8576
8603
  delegatedSession,
8577
8604
  delegatedEntries,
8578
8605
  spaceId,
8579
- session,
8606
+ captured,
8580
8607
  expiresAt,
8581
8608
  { siwe: prepared.siwe, signature }
8582
8609
  );
8583
8610
  graph.assertActive();
8611
+ assertCapturedKey?.();
8584
8612
  this.runtimePermissionGrants.push({
8585
8613
  session: {
8586
8614
  delegationHeader: delegatedSession.delegationHeader,
8587
8615
  delegationCid: delegatedSession.delegationCid,
8588
8616
  spaceId,
8589
- verificationMethod: session.verificationMethod,
8590
- jwk: session.jwk
8617
+ verificationMethod: captured.verificationMethod,
8618
+ jwk: captured.jwk
8591
8619
  },
8592
8620
  delegation,
8593
8621
  operations: this.permissionOperations(delegatedEntries, spaceId),