@tinycloud/node-sdk 3.1.0-beta.11 → 3.1.0-beta.13

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.
@@ -2303,6 +2303,7 @@ declare class TinyCloudNode {
2303
2303
  private shortServiceName;
2304
2304
  private permissionsToAbilities;
2305
2305
  private isEncryptionPermissionEntry;
2306
+ private isRawRevocationPermissionEntry;
2306
2307
  private permissionsToRawAbilities;
2307
2308
  private permissionOperations;
2308
2309
  /** Raw network authority cannot be covered by a nested encryption space. */
@@ -2303,6 +2303,7 @@ declare class TinyCloudNode {
2303
2303
  private shortServiceName;
2304
2304
  private permissionsToAbilities;
2305
2305
  private isEncryptionPermissionEntry;
2306
+ private isRawRevocationPermissionEntry;
2306
2307
  private permissionsToRawAbilities;
2307
2308
  private permissionOperations;
2308
2309
  /** Raw network authority cannot be covered by a nested encryption space. */
package/dist/core.cjs CHANGED
@@ -2699,15 +2699,21 @@ var _TinyCloudNode = class _TinyCloudNode {
2699
2699
  if (!this.wasmBindings.invokeAny) {
2700
2700
  throw new Error("WASM binding does not support invokeAny");
2701
2701
  }
2702
- const operations = entries.flatMap((entry) => {
2702
+ const routedEntries = entries;
2703
+ const operations = routedEntries.flatMap((entry) => {
2703
2704
  const operation = this.operationFromInvokeAnyEntry(entry);
2704
2705
  return operation ? [operation] : [];
2705
2706
  });
2706
- const grant = this.findGrantForOperations(operations);
2707
- const invocationSession = !grant || grant.provenance === "primary" ? session : grant.session;
2708
- const caveatPreservingEntries = grant ? entries.map((entry) => {
2707
+ const authorityCid = routedEntries.length === 1 ? routedEntries[0]?.revokeAuthorityCid : void 0;
2708
+ const explicitGrant = authorityCid === void 0 ? void 0 : this.runtimePermissionGrants.find((grant2) => grant2.delegation.cid === authorityCid);
2709
+ if (authorityCid !== void 0 && !explicitGrant) {
2710
+ throw new Error(`Explicit revocation authority ${authorityCid} is not installed.`);
2711
+ }
2712
+ const grant = explicitGrant ?? this.findGrantForOperations(operations);
2713
+ const invocationSession = explicitGrant ? explicitGrant.session : !grant || grant.provenance === "primary" ? session : grant.session;
2714
+ const caveatPreservingEntries = routedEntries.map(({ revokeAuthorityCid: _cid, ...entry }) => {
2709
2715
  const requested = this.operationFromInvokeAnyEntry(entry);
2710
- const granted = requested && grant.operations.find(
2716
+ const granted = grant && requested && grant.operations.find(
2711
2717
  (candidate) => this.operationCovers(candidate, requested)
2712
2718
  );
2713
2719
  if (!granted?.caveats?.length) {
@@ -2717,7 +2723,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2717
2723
  throw new Error("Invocation caveats do not match signed ReCap authority.");
2718
2724
  }
2719
2725
  return { ...entry, caveats: cloneRecapCaveats(granted.caveats) };
2720
- }) : entries;
2726
+ });
2721
2727
  return this.wasmBindings.invokeAny(invocationSession, caveatPreservingEntries, facts);
2722
2728
  };
2723
2729
  this.explicitHost = config.host;
@@ -4063,6 +4069,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4063
4069
  stagedSessionExpiry,
4064
4070
  stagedRecap
4065
4071
  );
4072
+ const stagedAccountSpaceId = stagedAddress ? this.wasmBindings.makeSpaceId(stagedAddress, stagedChainId, import_sdk_core8.ACCOUNT_REGISTRY_SPACE) : void 0;
4066
4073
  const stagedGraph = this.stageRestoredServiceGraph({
4067
4074
  host: stagedHost,
4068
4075
  manager: stagedManager,
@@ -4071,6 +4078,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4071
4078
  nodeDid: stagedNodeDid,
4072
4079
  address: stagedAddress,
4073
4080
  chainId: stagedChainId,
4081
+ accountSpaceId: stagedAccountSpaceId,
4074
4082
  tinyCloudSession: stagedTcSession,
4075
4083
  sessionExpiry: stagedSessionExpiry,
4076
4084
  recap: stagedRecap
@@ -4236,6 +4244,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4236
4244
  }
4237
4245
  const delegationManager = new import_sdk_core8.DelegationManager({
4238
4246
  hosts: [input.host],
4247
+ accountSpaceId: input.accountSpaceId,
4239
4248
  session: input.serviceSession,
4240
4249
  invoke: graph.invoke,
4241
4250
  invokeAny: graph.invokeAny,
@@ -5940,6 +5949,14 @@ var _TinyCloudNode = class _TinyCloudNode {
5940
5949
  delegation.delegationHeader
5941
5950
  );
5942
5951
  if (!activateResult.success) {
5952
+ if (this.operationsFromDelegation(delegation).some(
5953
+ (operation) => operation.resource?.startsWith("urn:cid:") === true && operation.service === "delegation" && operation.action === "tinycloud.delegation/revoke"
5954
+ ) && activateResult.status === 401 && /Cannot find parent delegation/i.test(activateResult.error ?? "")) {
5955
+ throw Object.assign(
5956
+ new Error("The host cannot activate a root raw-CID revoke authority without a parent delegation."),
5957
+ { code: "RAW_RECAP_RESOURCE_UNSUPPORTED", cause: activateResult }
5958
+ );
5959
+ }
5943
5960
  throw Object.assign(
5944
5961
  new Error(`Failed to activate runtime permission delegation: ${describeHostFailure2(activateResult)}`),
5945
5962
  { cause: activateResult }
@@ -5987,10 +6004,10 @@ var _TinyCloudNode = class _TinyCloudNode {
5987
6004
  }
5988
6005
  this.assertDelegationCaveatsPreservable(expanded);
5989
6006
  const rawEntries = expanded.filter(
5990
- (entry) => this.isEncryptionPermissionEntry(entry)
6007
+ (entry) => this.isEncryptionPermissionEntry(entry) || this.isRawRevocationPermissionEntry(entry)
5991
6008
  );
5992
6009
  const spaceEntries = expanded.filter(
5993
- (entry) => !this.isEncryptionPermissionEntry(entry)
6010
+ (entry) => !this.isEncryptionPermissionEntry(entry) && !this.isRawRevocationPermissionEntry(entry)
5994
6011
  );
5995
6012
  const bySpace = /* @__PURE__ */ new Map();
5996
6013
  for (const entry of spaceEntries) {
@@ -6017,17 +6034,29 @@ var _TinyCloudNode = class _TinyCloudNode {
6017
6034
  }
6018
6035
  const delegatedEntries = [...entries, ...rawForDelegation];
6019
6036
  const abilities = this.permissionsToAbilities(entries);
6020
- const prepared = this.wasmBindings.prepareSession({
6021
- abilities,
6022
- ...rawForDelegation.length > 0 ? { rawAbilities: this.permissionsToRawAbilities(rawForDelegation) } : {},
6023
- address: this.wasmBindings.ensureEip55(session.address),
6024
- chainId: session.chainId,
6025
- domain: this.siweDomain,
6026
- issuedAt: now.toISOString(),
6027
- expirationTime: expiresAt.toISOString(),
6028
- spaceId,
6029
- jwk: session.jwk
6030
- });
6037
+ const prepared = (() => {
6038
+ try {
6039
+ return this.wasmBindings.prepareSession({
6040
+ abilities,
6041
+ ...rawForDelegation.length > 0 ? { rawAbilities: this.permissionsToRawAbilities(rawForDelegation) } : {},
6042
+ address: this.wasmBindings.ensureEip55(session.address),
6043
+ chainId: session.chainId,
6044
+ domain: this.siweDomain,
6045
+ issuedAt: now.toISOString(),
6046
+ expirationTime: expiresAt.toISOString(),
6047
+ spaceId,
6048
+ jwk: session.jwk
6049
+ });
6050
+ } catch (error) {
6051
+ if (rawForDelegation.some((entry) => this.isRawRevocationPermissionEntry(entry)) && /invalid ReCap resource URI/i.test(error instanceof Error ? error.message : String(error))) {
6052
+ throw Object.assign(
6053
+ new Error("This WASM build cannot encode raw urn:cid ReCap resources."),
6054
+ { code: "RAW_RECAP_RESOURCE_UNSUPPORTED", cause: error }
6055
+ );
6056
+ }
6057
+ throw error;
6058
+ }
6059
+ })();
6031
6060
  const signature = await this.signer.signMessage(prepared.siwe);
6032
6061
  const delegatedSession = this.wasmBindings.completeSessionSetup({
6033
6062
  ...prepared,
@@ -6038,6 +6067,12 @@ var _TinyCloudNode = class _TinyCloudNode {
6038
6067
  delegatedSession.delegationHeader
6039
6068
  );
6040
6069
  if (!activateResult.success) {
6070
+ if (rawForDelegation.some((entry) => this.isRawRevocationPermissionEntry(entry)) && activateResult.status === 401 && /Cannot find parent delegation/i.test(activateResult.error ?? "")) {
6071
+ throw Object.assign(
6072
+ new Error("The host cannot activate a root raw-CID revoke authority without a parent delegation."),
6073
+ { code: "RAW_RECAP_RESOURCE_UNSUPPORTED", cause: activateResult }
6074
+ );
6075
+ }
6041
6076
  throw Object.assign(
6042
6077
  new Error(`Failed to activate runtime permission delegation: ${describeHostFailure2(activateResult)}`),
6043
6078
  { cause: activateResult }
@@ -6739,6 +6774,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6739
6774
  permissionsToAbilities(entries) {
6740
6775
  const abilities = {};
6741
6776
  for (const entry of entries) {
6777
+ if (this.isRawRevocationPermissionEntry(entry)) continue;
6742
6778
  const service = this.shortServiceName(entry.service);
6743
6779
  abilities[service] ?? (abilities[service] = {});
6744
6780
  const existing = abilities[service][entry.path] ?? [];
@@ -6756,9 +6792,16 @@ var _TinyCloudNode = class _TinyCloudNode {
6756
6792
  isEncryptionPermissionEntry(entry) {
6757
6793
  return entry.service === import_sdk_core8.ENCRYPTION_PERMISSION_SERVICE && this.isEncryptionNetworkOperation("encryption", entry.path, entry.space);
6758
6794
  }
6795
+ isRawRevocationPermissionEntry(entry) {
6796
+ return entry.service === "tinycloud.delegation" && entry.path === "" && entry.space?.startsWith("urn:cid:") === true && entry.actions.includes("tinycloud.delegation/revoke");
6797
+ }
6759
6798
  permissionsToRawAbilities(entries) {
6760
6799
  const rawAbilities = {};
6761
6800
  for (const entry of entries) {
6801
+ if (this.isRawRevocationPermissionEntry(entry)) {
6802
+ rawAbilities[entry.space] = [...new Set(entry.actions)];
6803
+ continue;
6804
+ }
6762
6805
  if (!this.isEncryptionPermissionEntry(entry)) {
6763
6806
  continue;
6764
6807
  }
@@ -6778,7 +6821,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6778
6821
  return entries.flatMap((entry) => {
6779
6822
  const service = this.shortServiceName(entry.service);
6780
6823
  return entry.actions.map((action) => ({
6781
- ...this.isEncryptionNetworkOperation(service, entry.path, entry.space) ? { resource: entry.path } : { spaceId },
6824
+ ...this.isRawRevocationPermissionEntry(entry) ? { resource: entry.space } : this.isEncryptionNetworkOperation(service, entry.path, entry.space) ? { resource: entry.path } : { spaceId },
6782
6825
  service,
6783
6826
  path: entry.path,
6784
6827
  action,
@@ -6788,11 +6831,13 @@ var _TinyCloudNode = class _TinyCloudNode {
6788
6831
  }
6789
6832
  /** Raw network authority cannot be covered by a nested encryption space. */
6790
6833
  signedCapabilitySubset(requested, granted) {
6791
- const rawGranted = granted.filter((entry) => this.isEncryptionPermissionEntry(entry)).map((entry) => ({ ...entry, space: "encryption" }));
6792
- const spaceGranted = granted.filter((entry) => !this.isEncryptionPermissionEntry(entry));
6834
+ const rawGranted = granted.filter((entry) => this.isEncryptionPermissionEntry(entry) || this.isRawRevocationPermissionEntry(entry)).map((entry) => this.isEncryptionPermissionEntry(entry) ? { ...entry, space: "encryption" } : entry);
6835
+ const spaceGranted = granted.filter(
6836
+ (entry) => !this.isEncryptionPermissionEntry(entry) && !this.isRawRevocationPermissionEntry(entry)
6837
+ );
6793
6838
  const missing = requested.filter((entry) => {
6794
- const raw = this.isEncryptionPermissionEntry(entry);
6795
- const comparable = raw ? { ...entry, space: "encryption" } : entry;
6839
+ const raw = this.isEncryptionPermissionEntry(entry) || this.isRawRevocationPermissionEntry(entry);
6840
+ const comparable = raw && this.isEncryptionPermissionEntry(entry) ? { ...entry, space: "encryption" } : entry;
6796
6841
  return !(0, import_sdk_core8.isCapabilitySubset)([comparable], raw ? rawGranted : spaceGranted).subset;
6797
6842
  });
6798
6843
  return { subset: missing.length === 0, missing };
@@ -6807,10 +6852,11 @@ var _TinyCloudNode = class _TinyCloudNode {
6807
6852
  }
6808
6853
  permissionEntriesToOperations(entries, session) {
6809
6854
  return entries.flatMap((entry) => {
6810
- const spaceId = this.resolvePermissionSpace(entry.space, session);
6855
+ const rawRevocation = this.isRawRevocationPermissionEntry(entry);
6856
+ const spaceId = rawRevocation ? void 0 : this.resolvePermissionSpace(entry.space, session);
6811
6857
  const service = this.shortServiceName(entry.service);
6812
6858
  return entry.actions.map((action) => ({
6813
- ...this.isEncryptionNetworkOperation(service, entry.path, entry.space) ? { resource: entry.path } : { spaceId },
6859
+ ...rawRevocation ? { resource: entry.space } : this.isEncryptionNetworkOperation(service, entry.path, entry.space) ? { resource: entry.path } : { spaceId },
6814
6860
  service,
6815
6861
  path: entry.path,
6816
6862
  action,
@@ -6889,7 +6935,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6889
6935
  delegatedResourcesForEntries(entries, spaceId) {
6890
6936
  return entries.map((entry) => ({
6891
6937
  service: this.shortServiceName(entry.service),
6892
- space: this.isEncryptionPermissionEntry(entry) ? "encryption" : spaceId,
6938
+ space: this.isRawRevocationPermissionEntry(entry) ? entry.space : this.isEncryptionPermissionEntry(entry) ? "encryption" : spaceId,
6893
6939
  path: entry.path,
6894
6940
  actions: [...entry.actions],
6895
6941
  ...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
@@ -6899,8 +6945,9 @@ var _TinyCloudNode = class _TinyCloudNode {
6899
6945
  const resources = delegation.resources !== void 0 && delegation.resources.length > 0 ? delegation.resources : this.flatDelegationResources(delegation);
6900
6946
  return resources.flatMap((resource) => {
6901
6947
  const service = this.invocationServiceName(resource.service);
6948
+ const rawRevocation = service === "delegation" && resource.space.startsWith("urn:cid:") && resource.path === "";
6902
6949
  return resource.actions.map((action) => ({
6903
- ...this.isEncryptionNetworkOperation(service, resource.path, resource.space) ? { resource: resource.path } : { spaceId: resource.space },
6950
+ ...rawRevocation ? { resource: resource.space } : this.isEncryptionNetworkOperation(service, resource.path, resource.space) ? { resource: resource.path } : { spaceId: resource.space },
6904
6951
  service,
6905
6952
  path: resource.path,
6906
6953
  action,
@@ -6946,7 +6993,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6946
6993
  * @internal
6947
6994
  */
6948
6995
  buildActivationAbilities(delegation) {
6949
- var _a, _b, _c;
6996
+ var _a, _b, _c, _d;
6950
6997
  const resources = delegation.resources !== void 0 && delegation.resources.length > 0 ? delegation.resources : this.flatDelegationResources(delegation);
6951
6998
  const abilities = {};
6952
6999
  const rawAbilities = {};
@@ -6966,13 +7013,18 @@ var _TinyCloudNode = class _TinyCloudNode {
6966
7013
  addActions(rawAbilities[resource.path], resource.actions);
6967
7014
  continue;
6968
7015
  }
7016
+ if (service === "delegation" && resource.space.startsWith("urn:cid:") && resource.path === "") {
7017
+ rawAbilities[_b = resource.space] ?? (rawAbilities[_b] = []);
7018
+ addActions(rawAbilities[resource.space], resource.actions);
7019
+ continue;
7020
+ }
6969
7021
  if (resource.space !== delegation.spaceId) {
6970
7022
  throw new Error(
6971
7023
  `useDelegation: resource targets space '${resource.space}' but the delegation activates space '${delegation.spaceId}'. Multi-space delegations cannot be activated in a single useDelegation call.`
6972
7024
  );
6973
7025
  }
6974
7026
  abilities[service] ?? (abilities[service] = {});
6975
- (_b = abilities[service])[_c = resource.path] ?? (_b[_c] = []);
7027
+ (_c = abilities[service])[_d = resource.path] ?? (_c[_d] = []);
6976
7028
  addActions(abilities[service][resource.path], resource.actions);
6977
7029
  }
6978
7030
  return { abilities, rawAbilities };