@tinycloud/node-sdk 2.3.0 → 2.3.1-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.
@@ -1427,6 +1427,28 @@ declare class TinyCloudNode {
1427
1427
  private delegatedResourcesForEntries;
1428
1428
  private operationsFromDelegation;
1429
1429
  private flatDelegationResources;
1430
+ /**
1431
+ * Build the abilities/rawAbilities maps for a wallet-mode activation
1432
+ * sub-delegation from the FULL resource set of a received delegation.
1433
+ *
1434
+ * Each entry in `delegation.resources[]` is one `(service, space, path,
1435
+ * actions)` grant; the flat top-level `path`/`actions` mirror only the
1436
+ * first resource. We must reconstruct every grant so the activated
1437
+ * session carries all of them (e.g. both `tinycloud.kv/get` and
1438
+ * `tinycloud.encryption/decrypt`) — not just the primary one.
1439
+ *
1440
+ * Encryption resources are raw network URNs (space-independent) and go
1441
+ * into `rawAbilities`. All other resources are space-scoped and go into
1442
+ * `abilities` keyed by short service name. The activation `prepareSession`
1443
+ * call uses a single `spaceId` (`delegation.spaceId`), so every
1444
+ * non-encryption resource must target that same space — which is exactly
1445
+ * what the multi-resource issuance path enforces. A resource targeting a
1446
+ * different space cannot be activated in one call, so we fail loudly
1447
+ * rather than silently dropping it.
1448
+ *
1449
+ * @internal
1450
+ */
1451
+ private buildActivationAbilities;
1430
1452
  private selectInvocationSession;
1431
1453
  private findGrantForOperations;
1432
1454
  private findGrantForOperation;
@@ -1427,6 +1427,28 @@ declare class TinyCloudNode {
1427
1427
  private delegatedResourcesForEntries;
1428
1428
  private operationsFromDelegation;
1429
1429
  private flatDelegationResources;
1430
+ /**
1431
+ * Build the abilities/rawAbilities maps for a wallet-mode activation
1432
+ * sub-delegation from the FULL resource set of a received delegation.
1433
+ *
1434
+ * Each entry in `delegation.resources[]` is one `(service, space, path,
1435
+ * actions)` grant; the flat top-level `path`/`actions` mirror only the
1436
+ * first resource. We must reconstruct every grant so the activated
1437
+ * session carries all of them (e.g. both `tinycloud.kv/get` and
1438
+ * `tinycloud.encryption/decrypt`) — not just the primary one.
1439
+ *
1440
+ * Encryption resources are raw network URNs (space-independent) and go
1441
+ * into `rawAbilities`. All other resources are space-scoped and go into
1442
+ * `abilities` keyed by short service name. The activation `prepareSession`
1443
+ * call uses a single `spaceId` (`delegation.spaceId`), so every
1444
+ * non-encryption resource must target that same space — which is exactly
1445
+ * what the multi-resource issuance path enforces. A resource targeting a
1446
+ * different space cannot be activated in one call, so we fail loudly
1447
+ * rather than silently dropping it.
1448
+ *
1449
+ * @internal
1450
+ */
1451
+ private buildActivationAbilities;
1430
1452
  private selectInvocationSession;
1431
1453
  private findGrantForOperations;
1432
1454
  private findGrantForOperation;
package/dist/core.cjs CHANGED
@@ -3951,6 +3951,59 @@ var _TinyCloudNode = class _TinyCloudNode {
3951
3951
  actions
3952
3952
  }));
3953
3953
  }
3954
+ /**
3955
+ * Build the abilities/rawAbilities maps for a wallet-mode activation
3956
+ * sub-delegation from the FULL resource set of a received delegation.
3957
+ *
3958
+ * Each entry in `delegation.resources[]` is one `(service, space, path,
3959
+ * actions)` grant; the flat top-level `path`/`actions` mirror only the
3960
+ * first resource. We must reconstruct every grant so the activated
3961
+ * session carries all of them (e.g. both `tinycloud.kv/get` and
3962
+ * `tinycloud.encryption/decrypt`) — not just the primary one.
3963
+ *
3964
+ * Encryption resources are raw network URNs (space-independent) and go
3965
+ * into `rawAbilities`. All other resources are space-scoped and go into
3966
+ * `abilities` keyed by short service name. The activation `prepareSession`
3967
+ * call uses a single `spaceId` (`delegation.spaceId`), so every
3968
+ * non-encryption resource must target that same space — which is exactly
3969
+ * what the multi-resource issuance path enforces. A resource targeting a
3970
+ * different space cannot be activated in one call, so we fail loudly
3971
+ * rather than silently dropping it.
3972
+ *
3973
+ * @internal
3974
+ */
3975
+ buildActivationAbilities(delegation) {
3976
+ var _a, _b, _c;
3977
+ const resources = delegation.resources !== void 0 && delegation.resources.length > 0 ? delegation.resources : this.flatDelegationResources(delegation);
3978
+ const abilities = {};
3979
+ const rawAbilities = {};
3980
+ const addActions = (target, actions) => {
3981
+ const seen = new Set(target);
3982
+ for (const action of actions) {
3983
+ if (!seen.has(action)) {
3984
+ target.push(action);
3985
+ seen.add(action);
3986
+ }
3987
+ }
3988
+ };
3989
+ for (const resource of resources) {
3990
+ const service = this.invocationServiceName(resource.service);
3991
+ if (this.isEncryptionNetworkOperation(service, resource.path)) {
3992
+ rawAbilities[_a = resource.path] ?? (rawAbilities[_a] = []);
3993
+ addActions(rawAbilities[resource.path], resource.actions);
3994
+ continue;
3995
+ }
3996
+ if (resource.space !== delegation.spaceId) {
3997
+ throw new Error(
3998
+ `useDelegation: resource targets space '${resource.space}' but the delegation activates space '${delegation.spaceId}'. Multi-space delegations cannot be activated in a single useDelegation call.`
3999
+ );
4000
+ }
4001
+ abilities[service] ?? (abilities[service] = {});
4002
+ (_b = abilities[service])[_c = resource.path] ?? (_b[_c] = []);
4003
+ addActions(abilities[service][resource.path], resource.actions);
4004
+ }
4005
+ return { abilities, rawAbilities };
4006
+ }
3954
4007
  selectInvocationSession(fallback, service, path, action) {
3955
4008
  const grant = this.findGrantForOperation({
3956
4009
  spaceId: fallback.spaceId,
@@ -4297,26 +4350,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4297
4350
  throw new Error("Not signed in. Call signIn() first.");
4298
4351
  }
4299
4352
  const jwk = mySession.jwk;
4300
- const abilities = {};
4301
- const kvActions = delegation.actions.filter((a) => a.startsWith("tinycloud.kv/"));
4302
- const sqlActions = delegation.actions.filter((a) => a.startsWith("tinycloud.sql/"));
4303
- const duckdbActions = delegation.actions.filter((a) => a.startsWith("tinycloud.duckdb/"));
4304
- const encryptionActions = delegation.actions.filter(
4305
- (a) => a.startsWith("tinycloud.encryption/")
4306
- );
4307
- const rawAbilities = {};
4308
- if (kvActions.length > 0) {
4309
- abilities.kv = { [delegation.path]: kvActions };
4310
- }
4311
- if (sqlActions.length > 0) {
4312
- abilities.sql = { [delegation.path]: sqlActions };
4313
- }
4314
- if (duckdbActions.length > 0) {
4315
- abilities.duckdb = { [delegation.path]: duckdbActions };
4316
- }
4317
- if (encryptionActions.length > 0 && delegation.path.startsWith("urn:tinycloud:encryption:")) {
4318
- rawAbilities[delegation.path] = encryptionActions;
4319
- }
4353
+ const { abilities, rawAbilities } = this.buildActivationAbilities(delegation);
4320
4354
  const now = /* @__PURE__ */ new Date();
4321
4355
  const maxExpiry = new Date(now.getTime() + 60 * 60 * 1e3);
4322
4356
  const expirationTime = delegation.expiry < maxExpiry ? delegation.expiry : maxExpiry;