@tinycloud/node-sdk 3.1.0-beta.9 → 3.2.0-beta.0

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.
package/dist/index.cjs CHANGED
@@ -19735,15 +19735,21 @@ var _TinyCloudNode = class _TinyCloudNode {
19735
19735
  if (!this.wasmBindings.invokeAny) {
19736
19736
  throw new Error("WASM binding does not support invokeAny");
19737
19737
  }
19738
- const operations = entries.flatMap((entry) => {
19738
+ const routedEntries = entries;
19739
+ const operations = routedEntries.flatMap((entry) => {
19739
19740
  const operation = this.operationFromInvokeAnyEntry(entry);
19740
19741
  return operation ? [operation] : [];
19741
19742
  });
19742
- const grant = this.findGrantForOperations(operations);
19743
- const invocationSession = !grant || grant.provenance === "primary" ? session : grant.session;
19744
- const caveatPreservingEntries = grant ? entries.map((entry) => {
19743
+ const authorityCid = routedEntries.length === 1 ? routedEntries[0]?.revokeAuthorityCid : void 0;
19744
+ const explicitGrant = authorityCid === void 0 ? void 0 : this.runtimePermissionGrants.find((grant2) => grant2.delegation.cid === authorityCid);
19745
+ if (authorityCid !== void 0 && !explicitGrant) {
19746
+ throw new Error(`Explicit revocation authority ${authorityCid} is not installed.`);
19747
+ }
19748
+ const grant = explicitGrant ?? this.findGrantForOperations(operations);
19749
+ const invocationSession = explicitGrant ? explicitGrant.session : !grant || grant.provenance === "primary" ? session : grant.session;
19750
+ const caveatPreservingEntries = routedEntries.map(({ revokeAuthorityCid: _cid, ...entry }) => {
19745
19751
  const requested = this.operationFromInvokeAnyEntry(entry);
19746
- const granted = requested && grant.operations.find(
19752
+ const granted = grant && requested && grant.operations.find(
19747
19753
  (candidate) => this.operationCovers(candidate, requested)
19748
19754
  );
19749
19755
  if (!granted?.caveats?.length) {
@@ -19753,7 +19759,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19753
19759
  throw new Error("Invocation caveats do not match signed ReCap authority.");
19754
19760
  }
19755
19761
  return { ...entry, caveats: cloneRecapCaveats(granted.caveats) };
19756
- }) : entries;
19762
+ });
19757
19763
  return this.wasmBindings.invokeAny(invocationSession, caveatPreservingEntries, facts);
19758
19764
  };
19759
19765
  this.explicitHost = config.host;
@@ -20218,12 +20224,13 @@ var _TinyCloudNode = class _TinyCloudNode {
20218
20224
  if (!auth) {
20219
20225
  throw new Error("Account bootstrap requires an active wallet session");
20220
20226
  }
20227
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core7.ACCOUNT_REGISTRY_SPACE);
20221
20228
  const skipped = auth.lastActivationSkippedSpaceIds;
20229
+ if (skipped.includes(accountSpaceId)) return { action: "run", mode: "fresh" };
20222
20230
  if (skipped.some((spaceId) => enshrinedSpaceIds.has(spaceId))) {
20223
- return { action: "run", mode: "fresh" };
20231
+ return { action: "run", mode: "repair" };
20224
20232
  }
20225
20233
  try {
20226
- const accountSpaceId = this.ownedSpaceId(import_sdk_core7.ACCOUNT_REGISTRY_SPACE);
20227
20234
  const markerPermission = {
20228
20235
  service: "tinycloud.kv",
20229
20236
  space: accountSpaceId,
@@ -20235,7 +20242,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20235
20242
  }
20236
20243
  const marker = await this.readBootstrapCompletionMarker();
20237
20244
  if (marker.ok) {
20238
- if (this.isAcceptedBootstrapCompletionMarker(marker.data.data)) {
20245
+ if (this.isAcceptedBootstrapCompletionMarker(marker.data.data, steps.map((step) => step.id))) {
20239
20246
  return { action: "skip" };
20240
20247
  }
20241
20248
  return { action: "run", mode: "repair" };
@@ -20285,12 +20292,16 @@ var _TinyCloudNode = class _TinyCloudNode {
20285
20292
  );
20286
20293
  }
20287
20294
  }
20288
- isAcceptedBootstrapCompletionMarker(value) {
20295
+ /**
20296
+ * A marker written before a canonical space was added triggers one bounded repair.
20297
+ */
20298
+ isAcceptedBootstrapCompletionMarker(value, canonicalStepIds) {
20289
20299
  if (typeof value !== "object" || value === null) return false;
20290
20300
  const entries = Object.entries(value);
20291
20301
  const markerValue = (name) => entries.find(([key2]) => key2 === name)?.[1];
20292
20302
  const version23 = markerValue("v");
20293
- return typeof version23 === "number" && Number.isInteger(version23) && ACCEPTED_MARKER_VERSIONS.some((acceptedVersion) => acceptedVersion === version23);
20303
+ const stepIds = markerValue("stepIds");
20304
+ return typeof version23 === "number" && Number.isInteger(version23) && ACCEPTED_MARKER_VERSIONS.some((acceptedVersion) => acceptedVersion === version23) && Array.isArray(stepIds) && canonicalStepIds.every((stepId) => stepIds.includes(stepId));
20294
20305
  }
20295
20306
  markerReadIsUnhostedSpace(meta) {
20296
20307
  return meta?.status === 404;
@@ -20377,30 +20388,39 @@ var _TinyCloudNode = class _TinyCloudNode {
20377
20388
  }
20378
20389
  }
20379
20390
  if (step.kind === "seed-spaces") {
20380
- const registered = await this.account.spaces.registerBatch(
20381
- step.spaces.map((space) => ({
20382
- spaceId: space.spaceId,
20383
- name: space.name,
20384
- ownerDid: this.did,
20385
- type: "owned",
20386
- permissions: ["*"],
20387
- status: "active"
20388
- }))
20389
- );
20390
- if (!registered.ok) {
20391
- throw Object.assign(
20392
- new Error(`Failed to seed account spaces: ${registered.error.message}`),
20393
- { cause: registered.error }
20394
- );
20395
- }
20396
- const batchError = registered.data.recoveredFromBatchError;
20397
- if (batchError) {
20398
- warnings.push({
20399
- stepId: step.id,
20400
- kind: "batch-write-reconciled",
20401
- code: batchError.code,
20402
- message: batchError.message
20403
- });
20391
+ const inputs = step.spaces.map((space) => ({
20392
+ spaceId: space.spaceId,
20393
+ name: space.name,
20394
+ ownerDid: this.did,
20395
+ type: "owned",
20396
+ permissions: ["*"],
20397
+ status: "active"
20398
+ }));
20399
+ if (mode === "fresh") {
20400
+ const registered = await this.account.spaces.registerBatch(inputs);
20401
+ if (!registered.ok) {
20402
+ throw Object.assign(
20403
+ new Error(`Failed to seed account spaces: ${registered.error.message}`),
20404
+ { cause: registered.error }
20405
+ );
20406
+ }
20407
+ const batchError = registered.data.recoveredFromBatchError;
20408
+ if (batchError) {
20409
+ warnings.push({
20410
+ stepId: step.id,
20411
+ kind: "batch-write-reconciled",
20412
+ code: batchError.code,
20413
+ message: batchError.message
20414
+ });
20415
+ }
20416
+ } else {
20417
+ const ensured = await this.account.spaces.registerMissing(inputs);
20418
+ if (!ensured.ok) {
20419
+ throw Object.assign(
20420
+ new Error(`Failed to seed account spaces: ${ensured.error.message}`),
20421
+ { cause: ensured.error }
20422
+ );
20423
+ }
20404
20424
  }
20405
20425
  }
20406
20426
  if (step.kind === "seed-applications") {
@@ -21085,6 +21105,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21085
21105
  stagedSessionExpiry,
21086
21106
  stagedRecap
21087
21107
  );
21108
+ const stagedAccountSpaceId = stagedAddress ? this.wasmBindings.makeSpaceId(stagedAddress, stagedChainId, import_sdk_core7.ACCOUNT_REGISTRY_SPACE) : void 0;
21088
21109
  const stagedGraph = this.stageRestoredServiceGraph({
21089
21110
  host: stagedHost,
21090
21111
  manager: stagedManager,
@@ -21093,6 +21114,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21093
21114
  nodeDid: stagedNodeDid,
21094
21115
  address: stagedAddress,
21095
21116
  chainId: stagedChainId,
21117
+ accountSpaceId: stagedAccountSpaceId,
21096
21118
  tinyCloudSession: stagedTcSession,
21097
21119
  sessionExpiry: stagedSessionExpiry,
21098
21120
  recap: stagedRecap
@@ -21258,6 +21280,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21258
21280
  }
21259
21281
  const delegationManager = new import_sdk_core7.DelegationManager({
21260
21282
  hosts: [input.host],
21283
+ accountSpaceId: input.accountSpaceId,
21261
21284
  session: input.serviceSession,
21262
21285
  invoke: graph.invoke,
21263
21286
  invokeAny: graph.invokeAny,
@@ -22962,6 +22985,14 @@ var _TinyCloudNode = class _TinyCloudNode {
22962
22985
  delegation.delegationHeader
22963
22986
  );
22964
22987
  if (!activateResult.success) {
22988
+ if (this.operationsFromDelegation(delegation).some(
22989
+ (operation) => operation.resource?.startsWith("urn:cid:") === true && operation.service === "delegation" && operation.action === "tinycloud.delegation/revoke"
22990
+ ) && activateResult.status === 401 && /Cannot find parent delegation/i.test(activateResult.error ?? "")) {
22991
+ throw Object.assign(
22992
+ new Error("The host cannot activate a root raw-CID revoke authority without a parent delegation."),
22993
+ { code: "RAW_RECAP_RESOURCE_UNSUPPORTED", cause: activateResult }
22994
+ );
22995
+ }
22965
22996
  throw Object.assign(
22966
22997
  new Error(`Failed to activate runtime permission delegation: ${describeHostFailure2(activateResult)}`),
22967
22998
  { cause: activateResult }
@@ -23009,10 +23040,10 @@ var _TinyCloudNode = class _TinyCloudNode {
23009
23040
  }
23010
23041
  this.assertDelegationCaveatsPreservable(expanded);
23011
23042
  const rawEntries = expanded.filter(
23012
- (entry) => this.isEncryptionPermissionEntry(entry)
23043
+ (entry) => this.isEncryptionPermissionEntry(entry) || this.isRawRevocationPermissionEntry(entry)
23013
23044
  );
23014
23045
  const spaceEntries = expanded.filter(
23015
- (entry) => !this.isEncryptionPermissionEntry(entry)
23046
+ (entry) => !this.isEncryptionPermissionEntry(entry) && !this.isRawRevocationPermissionEntry(entry)
23016
23047
  );
23017
23048
  const bySpace = /* @__PURE__ */ new Map();
23018
23049
  for (const entry of spaceEntries) {
@@ -23039,17 +23070,29 @@ var _TinyCloudNode = class _TinyCloudNode {
23039
23070
  }
23040
23071
  const delegatedEntries = [...entries, ...rawForDelegation];
23041
23072
  const abilities = this.permissionsToAbilities(entries);
23042
- const prepared = this.wasmBindings.prepareSession({
23043
- abilities,
23044
- ...rawForDelegation.length > 0 ? { rawAbilities: this.permissionsToRawAbilities(rawForDelegation) } : {},
23045
- address: this.wasmBindings.ensureEip55(session.address),
23046
- chainId: session.chainId,
23047
- domain: this.siweDomain,
23048
- issuedAt: now.toISOString(),
23049
- expirationTime: expiresAt.toISOString(),
23050
- spaceId,
23051
- jwk: session.jwk
23052
- });
23073
+ const prepared = (() => {
23074
+ try {
23075
+ return this.wasmBindings.prepareSession({
23076
+ abilities,
23077
+ ...rawForDelegation.length > 0 ? { rawAbilities: this.permissionsToRawAbilities(rawForDelegation) } : {},
23078
+ address: this.wasmBindings.ensureEip55(session.address),
23079
+ chainId: session.chainId,
23080
+ domain: this.siweDomain,
23081
+ issuedAt: now.toISOString(),
23082
+ expirationTime: expiresAt.toISOString(),
23083
+ spaceId,
23084
+ jwk: session.jwk
23085
+ });
23086
+ } catch (error) {
23087
+ if (rawForDelegation.some((entry) => this.isRawRevocationPermissionEntry(entry)) && /invalid ReCap resource URI/i.test(error instanceof Error ? error.message : String(error))) {
23088
+ throw Object.assign(
23089
+ new Error("This WASM build cannot encode raw urn:cid ReCap resources."),
23090
+ { code: "RAW_RECAP_RESOURCE_UNSUPPORTED", cause: error }
23091
+ );
23092
+ }
23093
+ throw error;
23094
+ }
23095
+ })();
23053
23096
  const signature2 = await this.signer.signMessage(prepared.siwe);
23054
23097
  const delegatedSession = this.wasmBindings.completeSessionSetup({
23055
23098
  ...prepared,
@@ -23060,6 +23103,12 @@ var _TinyCloudNode = class _TinyCloudNode {
23060
23103
  delegatedSession.delegationHeader
23061
23104
  );
23062
23105
  if (!activateResult.success) {
23106
+ if (rawForDelegation.some((entry) => this.isRawRevocationPermissionEntry(entry)) && activateResult.status === 401 && /Cannot find parent delegation/i.test(activateResult.error ?? "")) {
23107
+ throw Object.assign(
23108
+ new Error("The host cannot activate a root raw-CID revoke authority without a parent delegation."),
23109
+ { code: "RAW_RECAP_RESOURCE_UNSUPPORTED", cause: activateResult }
23110
+ );
23111
+ }
23063
23112
  throw Object.assign(
23064
23113
  new Error(`Failed to activate runtime permission delegation: ${describeHostFailure2(activateResult)}`),
23065
23114
  { cause: activateResult }
@@ -23412,8 +23461,18 @@ var _TinyCloudNode = class _TinyCloudNode {
23412
23461
  * @throws {@link PermissionNotInManifestError} when any requested
23413
23462
  * entry is not a subset of the granted session capabilities and
23414
23463
  * `forceWalletSign` is not set.
23464
+ * @throws when `onPrepared` is combined with `forceWalletSign: true`,
23465
+ * before anything is signed.
23466
+ * @throws the `onPrepared` rejection, unchanged, without activating the
23467
+ * delegation.
23415
23468
  */
23416
23469
  async delegateTo(did, permissions, options) {
23470
+ const onPrepared = options?.onPrepared;
23471
+ if (onPrepared && options?.forceWalletSign) {
23472
+ throw new Error(
23473
+ "delegateTo: onPrepared cannot be combined with forceWalletSign=true; the wallet-signed path activates the delegation before it could be handed to onPrepared."
23474
+ );
23475
+ }
23417
23476
  const session = this.currentTinyCloudSession();
23418
23477
  if (!session) {
23419
23478
  throw new import_sdk_core7.SessionExpiredError(/* @__PURE__ */ new Date(0));
@@ -23472,7 +23531,8 @@ var _TinyCloudNode = class _TinyCloudNode {
23472
23531
  expandedEntries,
23473
23532
  runtimeExpiration,
23474
23533
  runtimeGrant,
23475
- runtimeOperations
23534
+ runtimeOperations,
23535
+ onPrepared
23476
23536
  );
23477
23537
  return { delegation: delegation2, prompted: false };
23478
23538
  }
@@ -23482,7 +23542,8 @@ var _TinyCloudNode = class _TinyCloudNode {
23482
23542
  did,
23483
23543
  expandedEntries,
23484
23544
  effectiveExpiration,
23485
- session
23545
+ session,
23546
+ onPrepared
23486
23547
  );
23487
23548
  return { delegation, prompted: false };
23488
23549
  }
@@ -23536,7 +23597,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23536
23597
  *
23537
23598
  * @internal
23538
23599
  */
23539
- async createDelegationViaWasmPath(did, entries, expirationTime, session) {
23600
+ async createDelegationViaWasmPath(did, entries, expirationTime, session, onPrepared) {
23540
23601
  if (entries.length === 0) {
23541
23602
  throw new Error(
23542
23603
  "createDelegationViaWasmPath requires a non-empty entries array"
@@ -23599,17 +23660,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23599
23660
  });
23600
23661
  const primary = result.resources[0];
23601
23662
  const delegationHeader = { Authorization: result.delegation };
23602
- const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
23603
- this.config.host,
23604
- delegationHeader
23605
- );
23606
- if (!activateResult.success) {
23607
- throw Object.assign(
23608
- new Error(`Failed to activate delegation with host: ${describeHostFailure2(activateResult)}`),
23609
- { cause: activateResult }
23610
- );
23611
- }
23612
- return {
23663
+ const delegation = {
23613
23664
  cid: result.cid,
23614
23665
  delegationHeader,
23615
23666
  spaceId,
@@ -23623,8 +23674,22 @@ var _TinyCloudNode = class _TinyCloudNode {
23623
23674
  chainId: session.chainId,
23624
23675
  host: this.config.host
23625
23676
  };
23677
+ if (onPrepared) {
23678
+ await onPrepared(delegation);
23679
+ }
23680
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
23681
+ this.config.host,
23682
+ delegationHeader
23683
+ );
23684
+ if (!activateResult.success) {
23685
+ throw Object.assign(
23686
+ new Error(`Failed to activate delegation with host: ${describeHostFailure2(activateResult)}`),
23687
+ { cause: activateResult }
23688
+ );
23689
+ }
23690
+ return delegation;
23626
23691
  }
23627
- async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant, requestedOperations) {
23692
+ async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant, requestedOperations, onPrepared) {
23628
23693
  this.assertRuntimeGrantCaveatsPreservable(entries, requestedOperations, grant);
23629
23694
  this.assertDelegationCaveatsPreservable(entries);
23630
23695
  const result = this.createDelegationWrapper({
@@ -23637,17 +23702,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23637
23702
  const primary = result.resources[0];
23638
23703
  const delegationHeader = { Authorization: result.delegation };
23639
23704
  const targetHost = grant.delegation.host ?? this.config.host;
23640
- const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
23641
- targetHost,
23642
- delegationHeader
23643
- );
23644
- if (!activateResult.success) {
23645
- throw Object.assign(
23646
- new Error(`Failed to activate delegation with host: ${describeHostFailure2(activateResult)}`),
23647
- { cause: activateResult }
23648
- );
23649
- }
23650
- return {
23705
+ const delegation = {
23651
23706
  cid: result.cid,
23652
23707
  delegationHeader,
23653
23708
  spaceId: grant.session.spaceId,
@@ -23661,6 +23716,20 @@ var _TinyCloudNode = class _TinyCloudNode {
23661
23716
  chainId: grant.delegation.chainId,
23662
23717
  host: targetHost
23663
23718
  };
23719
+ if (onPrepared) {
23720
+ await onPrepared(delegation);
23721
+ }
23722
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
23723
+ targetHost,
23724
+ delegationHeader
23725
+ );
23726
+ if (!activateResult.success) {
23727
+ throw Object.assign(
23728
+ new Error(`Failed to activate delegation with host: ${describeHostFailure2(activateResult)}`),
23729
+ { cause: activateResult }
23730
+ );
23731
+ }
23732
+ return delegation;
23664
23733
  }
23665
23734
  resolvePermissionSpace(space, session) {
23666
23735
  if (space === void 0) {
@@ -23761,6 +23830,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23761
23830
  permissionsToAbilities(entries) {
23762
23831
  const abilities = {};
23763
23832
  for (const entry of entries) {
23833
+ if (this.isRawRevocationPermissionEntry(entry)) continue;
23764
23834
  const service = this.shortServiceName(entry.service);
23765
23835
  abilities[service] ?? (abilities[service] = {});
23766
23836
  const existing = abilities[service][entry.path] ?? [];
@@ -23778,9 +23848,16 @@ var _TinyCloudNode = class _TinyCloudNode {
23778
23848
  isEncryptionPermissionEntry(entry) {
23779
23849
  return entry.service === import_sdk_core7.ENCRYPTION_PERMISSION_SERVICE && this.isEncryptionNetworkOperation("encryption", entry.path, entry.space);
23780
23850
  }
23851
+ isRawRevocationPermissionEntry(entry) {
23852
+ return entry.service === "tinycloud.delegation" && entry.path === "" && entry.space?.startsWith("urn:cid:") === true && entry.actions.includes("tinycloud.delegation/revoke");
23853
+ }
23781
23854
  permissionsToRawAbilities(entries) {
23782
23855
  const rawAbilities = {};
23783
23856
  for (const entry of entries) {
23857
+ if (this.isRawRevocationPermissionEntry(entry)) {
23858
+ rawAbilities[entry.space] = [...new Set(entry.actions)];
23859
+ continue;
23860
+ }
23784
23861
  if (!this.isEncryptionPermissionEntry(entry)) {
23785
23862
  continue;
23786
23863
  }
@@ -23800,7 +23877,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23800
23877
  return entries.flatMap((entry) => {
23801
23878
  const service = this.shortServiceName(entry.service);
23802
23879
  return entry.actions.map((action) => ({
23803
- ...this.isEncryptionNetworkOperation(service, entry.path, entry.space) ? { resource: entry.path } : { spaceId },
23880
+ ...this.isRawRevocationPermissionEntry(entry) ? { resource: entry.space } : this.isEncryptionNetworkOperation(service, entry.path, entry.space) ? { resource: entry.path } : { spaceId },
23804
23881
  service,
23805
23882
  path: entry.path,
23806
23883
  action,
@@ -23810,11 +23887,13 @@ var _TinyCloudNode = class _TinyCloudNode {
23810
23887
  }
23811
23888
  /** Raw network authority cannot be covered by a nested encryption space. */
23812
23889
  signedCapabilitySubset(requested, granted) {
23813
- const rawGranted = granted.filter((entry) => this.isEncryptionPermissionEntry(entry)).map((entry) => ({ ...entry, space: "encryption" }));
23814
- const spaceGranted = granted.filter((entry) => !this.isEncryptionPermissionEntry(entry));
23890
+ const rawGranted = granted.filter((entry) => this.isEncryptionPermissionEntry(entry) || this.isRawRevocationPermissionEntry(entry)).map((entry) => this.isEncryptionPermissionEntry(entry) ? { ...entry, space: "encryption" } : entry);
23891
+ const spaceGranted = granted.filter(
23892
+ (entry) => !this.isEncryptionPermissionEntry(entry) && !this.isRawRevocationPermissionEntry(entry)
23893
+ );
23815
23894
  const missing = requested.filter((entry) => {
23816
- const raw = this.isEncryptionPermissionEntry(entry);
23817
- const comparable = raw ? { ...entry, space: "encryption" } : entry;
23895
+ const raw = this.isEncryptionPermissionEntry(entry) || this.isRawRevocationPermissionEntry(entry);
23896
+ const comparable = raw && this.isEncryptionPermissionEntry(entry) ? { ...entry, space: "encryption" } : entry;
23818
23897
  return !(0, import_sdk_core7.isCapabilitySubset)([comparable], raw ? rawGranted : spaceGranted).subset;
23819
23898
  });
23820
23899
  return { subset: missing.length === 0, missing };
@@ -23829,10 +23908,11 @@ var _TinyCloudNode = class _TinyCloudNode {
23829
23908
  }
23830
23909
  permissionEntriesToOperations(entries, session) {
23831
23910
  return entries.flatMap((entry) => {
23832
- const spaceId = this.resolvePermissionSpace(entry.space, session);
23911
+ const rawRevocation = this.isRawRevocationPermissionEntry(entry);
23912
+ const spaceId = rawRevocation ? void 0 : this.resolvePermissionSpace(entry.space, session);
23833
23913
  const service = this.shortServiceName(entry.service);
23834
23914
  return entry.actions.map((action) => ({
23835
- ...this.isEncryptionNetworkOperation(service, entry.path, entry.space) ? { resource: entry.path } : { spaceId },
23915
+ ...rawRevocation ? { resource: entry.space } : this.isEncryptionNetworkOperation(service, entry.path, entry.space) ? { resource: entry.path } : { spaceId },
23836
23916
  service,
23837
23917
  path: entry.path,
23838
23918
  action,
@@ -23911,7 +23991,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23911
23991
  delegatedResourcesForEntries(entries, spaceId) {
23912
23992
  return entries.map((entry) => ({
23913
23993
  service: this.shortServiceName(entry.service),
23914
- space: this.isEncryptionPermissionEntry(entry) ? "encryption" : spaceId,
23994
+ space: this.isRawRevocationPermissionEntry(entry) ? entry.space : this.isEncryptionPermissionEntry(entry) ? "encryption" : spaceId,
23915
23995
  path: entry.path,
23916
23996
  actions: [...entry.actions],
23917
23997
  ...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
@@ -23921,8 +24001,9 @@ var _TinyCloudNode = class _TinyCloudNode {
23921
24001
  const resources = delegation.resources !== void 0 && delegation.resources.length > 0 ? delegation.resources : this.flatDelegationResources(delegation);
23922
24002
  return resources.flatMap((resource) => {
23923
24003
  const service = this.invocationServiceName(resource.service);
24004
+ const rawRevocation = service === "delegation" && resource.space.startsWith("urn:cid:") && resource.path === "";
23924
24005
  return resource.actions.map((action) => ({
23925
- ...this.isEncryptionNetworkOperation(service, resource.path, resource.space) ? { resource: resource.path } : { spaceId: resource.space },
24006
+ ...rawRevocation ? { resource: resource.space } : this.isEncryptionNetworkOperation(service, resource.path, resource.space) ? { resource: resource.path } : { spaceId: resource.space },
23926
24007
  service,
23927
24008
  path: resource.path,
23928
24009
  action,
@@ -23968,7 +24049,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23968
24049
  * @internal
23969
24050
  */
23970
24051
  buildActivationAbilities(delegation) {
23971
- var _a, _b, _c;
24052
+ var _a, _b, _c, _d;
23972
24053
  const resources = delegation.resources !== void 0 && delegation.resources.length > 0 ? delegation.resources : this.flatDelegationResources(delegation);
23973
24054
  const abilities = {};
23974
24055
  const rawAbilities = {};
@@ -23988,13 +24069,18 @@ var _TinyCloudNode = class _TinyCloudNode {
23988
24069
  addActions(rawAbilities[resource.path], resource.actions);
23989
24070
  continue;
23990
24071
  }
24072
+ if (service === "delegation" && resource.space.startsWith("urn:cid:") && resource.path === "") {
24073
+ rawAbilities[_b = resource.space] ?? (rawAbilities[_b] = []);
24074
+ addActions(rawAbilities[resource.space], resource.actions);
24075
+ continue;
24076
+ }
23991
24077
  if (resource.space !== delegation.spaceId) {
23992
24078
  throw new Error(
23993
24079
  `useDelegation: resource targets space '${resource.space}' but the delegation activates space '${delegation.spaceId}'. Multi-space delegations cannot be activated in a single useDelegation call.`
23994
24080
  );
23995
24081
  }
23996
24082
  abilities[service] ?? (abilities[service] = {});
23997
- (_b = abilities[service])[_c = resource.path] ?? (_b[_c] = []);
24083
+ (_c = abilities[service])[_d = resource.path] ?? (_c[_d] = []);
23998
24084
  addActions(abilities[service][resource.path], resource.actions);
23999
24085
  }
24000
24086
  return { abilities, rawAbilities };