@tinycloud/node-sdk 2.4.0 → 2.4.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.
package/dist/index.cjs CHANGED
@@ -18540,12 +18540,12 @@ function displayActionUrn(action) {
18540
18540
  function secretActionName(action) {
18541
18541
  return action;
18542
18542
  }
18543
- function secretPermissionEntries(name, options, action, encryptionNetworkId) {
18543
+ function secretPermissionEntries(name, options, action, space, encryptionNetworkId) {
18544
18544
  const entries = [];
18545
18545
  const path = action === "list" ? (0, import_sdk_core6.resolveSecretListPrefix)(options) : (0, import_sdk_core6.resolveSecretPath)(name, options).permissionPaths.vault;
18546
18546
  entries.push({
18547
18547
  service: "tinycloud.kv",
18548
- space: SECRETS_SPACE,
18548
+ space,
18549
18549
  path,
18550
18550
  actions: [secretActionName(action)],
18551
18551
  skipPrefix: true
@@ -18560,11 +18560,23 @@ function secretPermissionEntries(name, options, action, encryptionNetworkId) {
18560
18560
  }
18561
18561
  return entries;
18562
18562
  }
18563
+ function normalizeSpace(space, resolveSpace) {
18564
+ if (!space) return void 0;
18565
+ if (space.startsWith("tinycloud:")) return space;
18566
+ return resolveSpace?.(space) ?? space;
18567
+ }
18568
+ function spaceMatches(granted, requested, resolveSpace) {
18569
+ if (!granted || !requested) return false;
18570
+ return normalizeSpace(granted, resolveSpace) === normalizeSpace(requested, resolveSpace);
18571
+ }
18563
18572
  var NodeSecretsService = class {
18564
18573
  constructor(config) {
18565
18574
  this.config = config;
18566
18575
  this.shouldRestoreUnlock = false;
18567
18576
  }
18577
+ get space() {
18578
+ return this.config.space ?? SECRETS_SPACE;
18579
+ }
18568
18580
  get vault() {
18569
18581
  return this.service.vault;
18570
18582
  }
@@ -18617,6 +18629,7 @@ var NodeSecretsService = class {
18617
18629
  name,
18618
18630
  options,
18619
18631
  action,
18632
+ this.space,
18620
18633
  action === "get" ? this.config.getEncryptionNetworkId?.() : void 0
18621
18634
  );
18622
18635
  } catch (error) {
@@ -18666,7 +18679,7 @@ var NodeSecretsService = class {
18666
18679
  (entry) => manifests.some((candidate) => {
18667
18680
  const resolved = (0, import_sdk_core6.resolveManifest)(candidate);
18668
18681
  return resolved.resources.some(
18669
- (resource) => resource.service === entry.service && resource.space === entry.space && resource.path === entry.path && entry.actions.every((action) => resource.actions.includes(action))
18682
+ (resource) => resource.service === entry.service && spaceMatches(resource.space, entry.space, this.config.resolveSpace) && resource.path === entry.path && entry.actions.every((action) => resource.actions.includes(action))
18670
18683
  );
18671
18684
  })
18672
18685
  );
@@ -18690,6 +18703,20 @@ function didPrincipalMatches2(actual, expected) {
18690
18703
  return actual === expected;
18691
18704
  }
18692
18705
  }
18706
+ function sharingActionsToAbilities(path, actions) {
18707
+ var _a;
18708
+ const abilities = {};
18709
+ for (const action of actions) {
18710
+ const slash = action.indexOf("/");
18711
+ if (slash === -1) return void 0;
18712
+ const shortService = import_sdk_core7.SERVICE_LONG_TO_SHORT[action.slice(0, slash)];
18713
+ if (shortService === void 0) return void 0;
18714
+ abilities[shortService] ?? (abilities[shortService] = {});
18715
+ (_a = abilities[shortService])[path] ?? (_a[path] = []);
18716
+ abilities[shortService][path].push(action);
18717
+ }
18718
+ return Object.keys(abilities).length > 0 ? abilities : void 0;
18719
+ }
18693
18720
  function base64UrlEncode(bytes) {
18694
18721
  const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
18695
18722
  let output = "";
@@ -18802,6 +18829,8 @@ var _TinyCloudNode = class _TinyCloudNode {
18802
18829
  this.auth = null;
18803
18830
  this.tc = null;
18804
18831
  this._chainId = 1;
18832
+ this._baseSecrets = /* @__PURE__ */ new Map();
18833
+ this._secrets = /* @__PURE__ */ new Map();
18805
18834
  this.runtimePermissionGrants = [];
18806
18835
  this.invokeWithRuntimePermissions = (session, service, path, action, facts) => {
18807
18836
  return this.wasmBindings.invoke(
@@ -19064,6 +19093,13 @@ var _TinyCloudNode = class _TinyCloudNode {
19064
19093
  get session() {
19065
19094
  return this.auth?.tinyCloudSession;
19066
19095
  }
19096
+ /**
19097
+ * Get the currently active session in the shape callers can persist and later
19098
+ * pass back to {@link restoreSession}.
19099
+ */
19100
+ get restorableSession() {
19101
+ return this.currentTinyCloudSession();
19102
+ }
19067
19103
  /**
19068
19104
  * Sign in and create a new session.
19069
19105
  * This creates the user's space if it doesn't exist.
@@ -19086,8 +19122,8 @@ var _TinyCloudNode = class _TinyCloudNode {
19086
19122
  this._hooks = void 0;
19087
19123
  this._vault = void 0;
19088
19124
  this._encryption = void 0;
19089
- this._baseSecrets = void 0;
19090
- this._secrets = void 0;
19125
+ this._baseSecrets.clear();
19126
+ this._secrets.clear();
19091
19127
  this._spaceService = void 0;
19092
19128
  this._serviceContext = void 0;
19093
19129
  this.runtimePermissionGrants = [];
@@ -19573,8 +19609,8 @@ var _TinyCloudNode = class _TinyCloudNode {
19573
19609
  this._hooks = void 0;
19574
19610
  this._vault = void 0;
19575
19611
  this._encryption = void 0;
19576
- this._baseSecrets = void 0;
19577
- this._secrets = void 0;
19612
+ this._baseSecrets.clear();
19613
+ this._secrets.clear();
19578
19614
  this._spaceService = void 0;
19579
19615
  this._serviceContext = void 0;
19580
19616
  this.runtimePermissionGrants = [];
@@ -19864,6 +19900,20 @@ var _TinyCloudNode = class _TinyCloudNode {
19864
19900
  getDefaultEncryptionNetworkId(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
19865
19901
  return `urn:tinycloud:encryption:${this.did}:${name}`;
19866
19902
  }
19903
+ getEncryptionNetworkIdForSpace(spaceId, name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
19904
+ const ownerDid = this.ownerDidFromSpaceId(spaceId) ?? this.did;
19905
+ return `urn:tinycloud:encryption:${ownerDid}:${name}`;
19906
+ }
19907
+ ownerDidFromSpaceId(spaceId) {
19908
+ if (!spaceId.startsWith("tinycloud:")) return void 0;
19909
+ const body = spaceId.slice("tinycloud:".length);
19910
+ const lastSeparator = body.lastIndexOf(":");
19911
+ if (lastSeparator <= 0) return void 0;
19912
+ const owner = body.slice(0, lastSeparator);
19913
+ if (owner.startsWith("did:")) return owner;
19914
+ if (!owner.includes(":")) return void 0;
19915
+ return `did:${owner}`;
19916
+ }
19867
19917
  requireServiceSession() {
19868
19918
  const session = this._serviceContext?.session;
19869
19919
  if (!session) {
@@ -20051,7 +20101,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20051
20101
  spaceId,
20052
20102
  crypto: vaultCrypto,
20053
20103
  encryption: {
20054
- networkId: this.getDefaultEncryptionNetworkId(),
20104
+ networkId: this.getEncryptionNetworkIdForSpace(spaceId),
20055
20105
  service: this.getEncryptionService(),
20056
20106
  decryptCapabilityProof: () => ({
20057
20107
  proofs: [this.requireServiceSession().delegationCid]
@@ -20182,6 +20232,9 @@ var _TinyCloudNode = class _TinyCloudNode {
20182
20232
  }
20183
20233
  return vaultService;
20184
20234
  },
20235
+ createSecretsService: (spaceId) => {
20236
+ return this.secretsForSpace(spaceId);
20237
+ },
20185
20238
  // Enable space.delegations.create() via SIWE-based delegation
20186
20239
  createDelegation: async (params) => {
20187
20240
  try {
@@ -20304,11 +20357,10 @@ var _TinyCloudNode = class _TinyCloudNode {
20304
20357
  try {
20305
20358
  const host = this.config.host;
20306
20359
  const now = /* @__PURE__ */ new Date();
20307
- const abilities = {
20308
- kv: {
20309
- [params.path]: params.actions
20310
- }
20311
- };
20360
+ const abilities = sharingActionsToAbilities(params.path, params.actions);
20361
+ if (!abilities) {
20362
+ return void 0;
20363
+ }
20312
20364
  const prepared = this.wasmBindings.prepareSession({
20313
20365
  abilities,
20314
20366
  address: this.wasmBindings.ensureEip55(session.address),
@@ -20564,27 +20616,49 @@ var _TinyCloudNode = class _TinyCloudNode {
20564
20616
  if (!this._spaceService) {
20565
20617
  throw new Error("Not signed in. Call signIn() first.");
20566
20618
  }
20567
- if (!this._secrets) {
20568
- this._secrets = new NodeSecretsService({
20569
- getService: () => this.getBaseSecrets(),
20619
+ return this.secretsForSpace("secrets");
20620
+ }
20621
+ /**
20622
+ * App-facing secrets API backed by the requested space's vault.
20623
+ */
20624
+ secretsForSpace(spaceId) {
20625
+ if (!this._spaceService) {
20626
+ throw new Error("Not signed in. Call signIn() first.");
20627
+ }
20628
+ const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
20629
+ let secrets = this._secrets.get(resolvedSpace);
20630
+ if (!secrets) {
20631
+ secrets = new NodeSecretsService({
20632
+ getService: () => this.getBaseSecrets(resolvedSpace),
20633
+ space: resolvedSpace,
20570
20634
  getManifest: () => this.manifest,
20571
20635
  hasPermissions: (permissions) => this.hasRuntimePermissions(permissions),
20572
20636
  grantPermissions: (additional) => this.grantRuntimePermissions(additional),
20573
20637
  canEscalate: () => this.signer !== void 0 && this.tc !== void 0,
20574
- getEncryptionNetworkId: () => this.getDefaultEncryptionNetworkId(),
20638
+ getEncryptionNetworkId: () => this.getEncryptionNetworkIdForSpace(resolvedSpace),
20639
+ resolveSpace: (space) => space.startsWith("tinycloud:") ? space : this.ownedSpaceId(space),
20575
20640
  getUnlockSigner: () => this.signer ?? void 0
20576
20641
  });
20642
+ this._secrets.set(resolvedSpace, secrets);
20577
20643
  }
20578
- return this._secrets;
20644
+ return secrets;
20579
20645
  }
20580
- getBaseSecrets() {
20646
+ getBaseSecrets(spaceId) {
20581
20647
  if (!this._spaceService) {
20582
20648
  throw new Error("Not signed in. Call signIn() first.");
20583
20649
  }
20584
- if (!this._baseSecrets) {
20585
- this._baseSecrets = new import_sdk_core7.SecretsService(() => this.space("secrets").vault);
20650
+ const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
20651
+ let secrets = this._baseSecrets.get(resolvedSpace);
20652
+ if (!secrets) {
20653
+ const kvService = this.createSpaceScopedKVService(resolvedSpace);
20654
+ const vaultService = this.createVaultService(resolvedSpace, kvService);
20655
+ if (this._serviceContext) {
20656
+ vaultService.initialize(this._serviceContext);
20657
+ }
20658
+ secrets = new import_sdk_core7.SecretsService(() => vaultService);
20659
+ this._baseSecrets.set(resolvedSpace, secrets);
20586
20660
  }
20587
- return this._baseSecrets;
20661
+ return secrets;
20588
20662
  }
20589
20663
  /**
20590
20664
  * Hooks write stream subscription API.