@tinycloud/node-sdk 3.3.0-beta.7 → 3.3.0-beta.8

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.
@@ -1283,6 +1283,13 @@ interface DelegateToOptions {
1283
1283
  * aborts activation and propagates from `delegateTo`.
1284
1284
  */
1285
1285
  onPrepared?: (prepared: PortableDelegation) => Promise<void>;
1286
+ /**
1287
+ * Mark the delegation terminal: the node refuses any delegation that cites
1288
+ * it as a parent (`terminal-parent-cannot-redelegate`). The delegate can
1289
+ * still use it directly. Only session-key UCAN delegations can carry the
1290
+ * marker, so this throws with `forceWalletSign`. Default false.
1291
+ */
1292
+ disableSubDelegation?: boolean;
1286
1293
  }
1287
1294
  /**
1288
1295
  * Result of {@link TinyCloudNode.delegateTo}.
@@ -2138,7 +2145,8 @@ declare class TinyCloudNode {
2138
2145
  * Both SharingService (single-entry) and
2139
2146
  * {@link TinyCloudNode.delegateTo} (multi-entry) drive this through
2140
2147
  * the same code path so there's exactly one place that touches the
2141
- * WASM boundary.
2148
+ * WASM boundary. `terminal` adds the node's terminal marker, which the
2149
+ * WASM builder cannot emit.
2142
2150
  *
2143
2151
  * @internal
2144
2152
  */
@@ -2734,7 +2742,12 @@ declare class TinyCloudNode {
2734
2742
  actions: string[];
2735
2743
  /** DID of the recipient (from their TinyCloudNode.did) */
2736
2744
  delegateDID: string;
2737
- /** Whether to prevent the recipient from creating sub-delegations (default: false) */
2745
+ /**
2746
+ * Prevent the recipient from creating sub-delegations (default: false).
2747
+ * The delegation carries the node's terminal marker, so the node refuses
2748
+ * its children. Needs capabilities the current session holds; throws
2749
+ * rather than fall back to a wallet-signed delegation.
2750
+ */
2738
2751
  disableSubDelegation?: boolean;
2739
2752
  /** Expiration time in milliseconds from now (default: 1 hour) */
2740
2753
  expiryMs?: number;
@@ -2782,7 +2795,10 @@ declare class TinyCloudNode {
2782
2795
  actions: string[];
2783
2796
  /** DID of the recipient */
2784
2797
  delegateDID: string;
2785
- /** Whether to prevent the recipient from creating further sub-delegations */
2798
+ /**
2799
+ * Not supported: this method issues a wallet-signed delegation, which
2800
+ * cannot carry the node's terminal marker, so `true` throws.
2801
+ */
2786
2802
  disableSubDelegation?: boolean;
2787
2803
  /** Expiration in milliseconds from now; defaults to the parent's own expiry, the longest allowed. */
2788
2804
  expiryMs?: number;
@@ -1283,6 +1283,13 @@ interface DelegateToOptions {
1283
1283
  * aborts activation and propagates from `delegateTo`.
1284
1284
  */
1285
1285
  onPrepared?: (prepared: PortableDelegation) => Promise<void>;
1286
+ /**
1287
+ * Mark the delegation terminal: the node refuses any delegation that cites
1288
+ * it as a parent (`terminal-parent-cannot-redelegate`). The delegate can
1289
+ * still use it directly. Only session-key UCAN delegations can carry the
1290
+ * marker, so this throws with `forceWalletSign`. Default false.
1291
+ */
1292
+ disableSubDelegation?: boolean;
1286
1293
  }
1287
1294
  /**
1288
1295
  * Result of {@link TinyCloudNode.delegateTo}.
@@ -2138,7 +2145,8 @@ declare class TinyCloudNode {
2138
2145
  * Both SharingService (single-entry) and
2139
2146
  * {@link TinyCloudNode.delegateTo} (multi-entry) drive this through
2140
2147
  * the same code path so there's exactly one place that touches the
2141
- * WASM boundary.
2148
+ * WASM boundary. `terminal` adds the node's terminal marker, which the
2149
+ * WASM builder cannot emit.
2142
2150
  *
2143
2151
  * @internal
2144
2152
  */
@@ -2734,7 +2742,12 @@ declare class TinyCloudNode {
2734
2742
  actions: string[];
2735
2743
  /** DID of the recipient (from their TinyCloudNode.did) */
2736
2744
  delegateDID: string;
2737
- /** Whether to prevent the recipient from creating sub-delegations (default: false) */
2745
+ /**
2746
+ * Prevent the recipient from creating sub-delegations (default: false).
2747
+ * The delegation carries the node's terminal marker, so the node refuses
2748
+ * its children. Needs capabilities the current session holds; throws
2749
+ * rather than fall back to a wallet-signed delegation.
2750
+ */
2738
2751
  disableSubDelegation?: boolean;
2739
2752
  /** Expiration time in milliseconds from now (default: 1 hour) */
2740
2753
  expiryMs?: number;
@@ -2782,7 +2795,10 @@ declare class TinyCloudNode {
2782
2795
  actions: string[];
2783
2796
  /** DID of the recipient */
2784
2797
  delegateDID: string;
2785
- /** Whether to prevent the recipient from creating further sub-delegations */
2798
+ /**
2799
+ * Not supported: this method issues a wallet-signed delegation, which
2800
+ * cannot carry the node's terminal marker, so `true` throws.
2801
+ */
2786
2802
  disableSubDelegation?: boolean;
2787
2803
  /** Expiration in milliseconds from now; defaults to the parent's own expiry, the longest allowed. */
2788
2804
  expiryMs?: number;
@@ -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 { ReplicaSessionStamp, ReplicaDenyInput } from '@tinycloud/sdk-services/kv/replication';
4
- import { T as TinyCloudNode } from './TinyCloudNode-BchWB_zv.cjs';
4
+ import { T as TinyCloudNode } from './TinyCloudNode-CcNh20QX.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 & {
@@ -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 { ReplicaSessionStamp, ReplicaDenyInput } from '@tinycloud/sdk-services/kv/replication';
4
- import { T as TinyCloudNode } from './TinyCloudNode-BchWB_zv.js';
4
+ import { T as TinyCloudNode } from './TinyCloudNode-CcNh20QX.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 & {
package/dist/core.cjs CHANGED
@@ -3347,6 +3347,7 @@ function ownerPermissionsToAbilities(permissions) {
3347
3347
  }
3348
3348
  return { abilities, rawAbilities };
3349
3349
  }
3350
+ var TERMINAL_DELEGATION_REQUIRES_SESSION_KEY = "disableSubDelegation requires a session-key delegation";
3350
3351
  function base64UrlEncode(bytes) {
3351
3352
  const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
3352
3353
  let output = "";
@@ -6932,11 +6933,12 @@ var _TinyCloudNode = class _TinyCloudNode {
6932
6933
  * Both SharingService (single-entry) and
6933
6934
  * {@link TinyCloudNode.delegateTo} (multi-entry) drive this through
6934
6935
  * the same code path so there's exactly one place that touches the
6935
- * WASM boundary.
6936
+ * WASM boundary. `terminal` adds the node's terminal marker, which the
6937
+ * WASM builder cannot emit.
6936
6938
  *
6937
6939
  * @internal
6938
6940
  */
6939
- createDelegationWrapper(params) {
6941
+ createDelegationWrapper(params, terminal = false) {
6940
6942
  const wasmSession = {
6941
6943
  delegationHeader: params.session.delegationHeader,
6942
6944
  delegationCid: params.session.delegationCid,
@@ -6956,8 +6958,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6956
6958
  params.notBeforeSecs
6957
6959
  );
6958
6960
  return {
6959
- delegation: result.delegation,
6960
- cid: result.cid,
6961
+ ...terminal ? (0, import_sdk_core10.markDelegationTerminal)(result.delegation, params.session.jwk) : { delegation: result.delegation, cid: result.cid },
6961
6962
  // Rust serde `rename_all = "camelCase"` emits `delegateDid`
6962
6963
  // (lowercase d); the TypeScript interface uses `delegateDID`
6963
6964
  // (historical, matches Delegation.delegateDID). Normalize here.
@@ -8206,6 +8207,9 @@ var _TinyCloudNode = class _TinyCloudNode {
8206
8207
  effectiveExpiration = sessionExpiry;
8207
8208
  }
8208
8209
  if (options?.forceWalletSign) {
8210
+ if (options.disableSubDelegation) {
8211
+ throw new Error(TERMINAL_DELEGATION_REQUIRES_SESSION_KEY);
8212
+ }
8209
8213
  if (expandedEntries.length > 1) {
8210
8214
  throw new Error(
8211
8215
  "delegateTo with forceWalletSign=true supports at most one PermissionEntry. Multi-entry requests must go through the session-key UCAN path (drop forceWalletSign) or the legacy createDelegation method."
@@ -8241,7 +8245,8 @@ var _TinyCloudNode = class _TinyCloudNode {
8241
8245
  plan.effectiveExpiration,
8242
8246
  plan.grant,
8243
8247
  plan.operations,
8244
- onPrepared
8248
+ onPrepared,
8249
+ options?.disableSubDelegation === true
8245
8250
  );
8246
8251
  return { delegation: delegation2, prompted: false };
8247
8252
  }
@@ -8250,7 +8255,8 @@ var _TinyCloudNode = class _TinyCloudNode {
8250
8255
  expandedEntries,
8251
8256
  effectiveExpiration,
8252
8257
  session,
8253
- onPrepared
8258
+ onPrepared,
8259
+ options?.disableSubDelegation === true
8254
8260
  );
8255
8261
  return { delegation, prompted: false };
8256
8262
  }
@@ -8481,7 +8487,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8481
8487
  *
8482
8488
  * @internal
8483
8489
  */
8484
- async createDelegationViaWasmPath(did, entries, expirationTime, session, onPrepared) {
8490
+ async createDelegationViaWasmPath(did, entries, expirationTime, session, onPrepared, disableSubDelegation = false) {
8485
8491
  if (entries.length === 0) {
8486
8492
  throw new Error(
8487
8493
  "createDelegationViaWasmPath requires a non-empty entries array"
@@ -8541,7 +8547,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8541
8547
  spaceId,
8542
8548
  abilities,
8543
8549
  expirationSecs
8544
- });
8550
+ }, disableSubDelegation);
8545
8551
  const primary = result.resources[0];
8546
8552
  const delegationHeader = { Authorization: result.delegation };
8547
8553
  const delegation = {
@@ -8551,7 +8557,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8551
8557
  path: primary.path,
8552
8558
  actions: primary.actions,
8553
8559
  resources: result.resources,
8554
- disableSubDelegation: false,
8560
+ disableSubDelegation,
8555
8561
  expiry: result.expiry,
8556
8562
  delegateDID: did,
8557
8563
  ownerAddress: session.address,
@@ -8573,7 +8579,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8573
8579
  }
8574
8580
  return delegation;
8575
8581
  }
8576
- async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant, requestedOperations, onPrepared) {
8582
+ async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant, requestedOperations, onPrepared, disableSubDelegation = false) {
8577
8583
  this.assertRuntimeGrantCaveatsPreservable(entries, requestedOperations, grant);
8578
8584
  this.assertDelegationCaveatsPreservable(entries);
8579
8585
  const result = this.createDelegationWrapper({
@@ -8582,7 +8588,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8582
8588
  spaceId: grant.session.spaceId,
8583
8589
  abilities: this.permissionsToAbilities(entries),
8584
8590
  expirationSecs: Math.floor(expirationTime.getTime() / 1e3)
8585
- });
8591
+ }, disableSubDelegation);
8586
8592
  const primary = result.resources[0];
8587
8593
  const delegationHeader = { Authorization: result.delegation };
8588
8594
  const targetHost = grant.delegation.host ?? this.config.host;
@@ -8593,7 +8599,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8593
8599
  path: primary.path,
8594
8600
  actions: primary.actions,
8595
8601
  resources: result.resources,
8596
- disableSubDelegation: false,
8602
+ disableSubDelegation,
8597
8603
  expiry: result.expiry,
8598
8604
  delegateDID: did,
8599
8605
  ownerAddress: grant.delegation.ownerAddress,
@@ -9177,11 +9183,10 @@ var _TinyCloudNode = class _TinyCloudNode {
9177
9183
  params.spaceIdOverride
9178
9184
  );
9179
9185
  try {
9180
- const result = await this.delegateTo(
9181
- resolvedDelegateDID,
9182
- entries,
9183
- params.expiryMs !== void 0 ? { expiry: params.expiryMs } : void 0
9184
- );
9186
+ const result = await this.delegateTo(resolvedDelegateDID, entries, {
9187
+ ...params.expiryMs !== void 0 ? { expiry: params.expiryMs } : {},
9188
+ disableSubDelegation: params.disableSubDelegation
9189
+ });
9185
9190
  return result.delegation;
9186
9191
  } catch (err2) {
9187
9192
  if (err2 instanceof import_sdk_core10.PermissionNotInManifestError) {
@@ -9202,6 +9207,9 @@ var _TinyCloudNode = class _TinyCloudNode {
9202
9207
  * @internal
9203
9208
  */
9204
9209
  async createDelegationWalletPath(params) {
9210
+ if (params.disableSubDelegation) {
9211
+ throw new Error(TERMINAL_DELEGATION_REQUIRES_SESSION_KEY);
9212
+ }
9205
9213
  if (!this.signer) {
9206
9214
  throw new Error("Cannot createDelegation() in session-only mode. Requires wallet mode.");
9207
9215
  }
@@ -9257,7 +9265,7 @@ var _TinyCloudNode = class _TinyCloudNode {
9257
9265
  spaceId: params.spaceIdOverride ?? session.spaceId,
9258
9266
  path: params.path,
9259
9267
  actions: params.actions,
9260
- disableSubDelegation: params.disableSubDelegation ?? false,
9268
+ disableSubDelegation: false,
9261
9269
  expiry: expirationTime,
9262
9270
  delegateDID: params.delegateDID,
9263
9271
  ownerAddress: session.address,
@@ -9300,7 +9308,7 @@ var _TinyCloudNode = class _TinyCloudNode {
9300
9308
  spaceId: publicSpaceId,
9301
9309
  path: "",
9302
9310
  actions: [import_sdk_core10.KV.GET, import_sdk_core10.KV.PUT, import_sdk_core10.KV.METADATA],
9303
- disableSubDelegation: params.disableSubDelegation ?? false,
9311
+ disableSubDelegation: false,
9304
9312
  expiry: expirationTime,
9305
9313
  delegateDID: params.delegateDID,
9306
9314
  ownerAddress: session.address,
@@ -9467,6 +9475,9 @@ var _TinyCloudNode = class _TinyCloudNode {
9467
9475
  if (parentDelegation.disableSubDelegation) {
9468
9476
  throw new Error("Parent delegation does not allow sub-delegation");
9469
9477
  }
9478
+ if (params.disableSubDelegation) {
9479
+ throw new Error(TERMINAL_DELEGATION_REQUIRES_SESSION_KEY);
9480
+ }
9470
9481
  const parentResources = parentDelegation.resources ?? [{
9471
9482
  service: parentDelegation.actions[0]?.split("/", 1)[0]?.replace(/^tinycloud\./, "") ?? "kv",
9472
9483
  space: parentDelegation.spaceId,
@@ -9539,7 +9550,7 @@ var _TinyCloudNode = class _TinyCloudNode {
9539
9550
  spaceId: parentDelegation.spaceId,
9540
9551
  path: requestedResources[0].path,
9541
9552
  actions: requestedResources[0].actions,
9542
- disableSubDelegation: params.disableSubDelegation ?? false,
9553
+ disableSubDelegation: false,
9543
9554
  expiry: actualExpiry,
9544
9555
  delegateDID: params.delegateDID,
9545
9556
  ownerAddress: parentDelegation.ownerAddress,