@tinycloud/node-sdk 3.5.0-beta.0 → 3.5.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/core.js CHANGED
@@ -2750,7 +2750,7 @@ import {
2750
2750
  KV as KV3,
2751
2751
  SQL as SQL2,
2752
2752
  DUCKDB as DUCKDB2,
2753
- ENCRYPTION as ENCRYPTION2,
2753
+ ENCRYPTION as ENCRYPTION3,
2754
2754
  EXPIRY as EXPIRY3,
2755
2755
  canonicalHashHex,
2756
2756
  canonicalizeEncryptionJson,
@@ -2762,7 +2762,7 @@ import {
2762
2762
  createInMemoryRegistrySequenceStore as createInMemoryRegistrySequenceStore2,
2763
2763
  publishLocationRecord,
2764
2764
  principalDidEquals as principalDidEquals3,
2765
- parseNetworkId as parseNetworkId2,
2765
+ parseNetworkId as parseNetworkId3,
2766
2766
  resolveSecretPath as resolveSecretPath2,
2767
2767
  registerPolicyV3,
2768
2768
  CREDENTIAL_INVITATION_REQUEST_DOMAIN,
@@ -2976,7 +2976,11 @@ function createWasmKeyProvider(sessionManager) {
2976
2976
 
2977
2977
  // src/delegateToHelpers.ts
2978
2978
  import {
2979
+ actionContains,
2980
+ ENCRYPTION as ENCRYPTION2,
2979
2981
  parseExpiry,
2982
+ isNetworkId,
2983
+ parseNetworkId as parseNetworkId2,
2980
2984
  SiweMessage as SiweMessage2,
2981
2985
  EXPIRY as EXPIRY2
2982
2986
  } from "@tinycloud/sdk-core";
@@ -3011,6 +3015,16 @@ function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
3011
3015
  return entries;
3012
3016
  }
3013
3017
  var DEFAULT_DELEGATION_EXPIRY_MS = EXPIRY2.SESSION_MS;
3018
+ var SHARE_NETWORK_NAME_RE = /^share-[a-z0-9][a-z0-9-]{15,35}$/;
3019
+ function grantsCappedDecrypt(path, actions) {
3020
+ if (!actions.some((action) => actionContains(action, ENCRYPTION2.DECRYPT))) {
3021
+ return false;
3022
+ }
3023
+ return !(isNetworkId(path) && SHARE_NETWORK_NAME_RE.test(parseNetworkId2(path).name));
3024
+ }
3025
+ function includesDecrypt(entries) {
3026
+ return entries.some((entry) => grantsCappedDecrypt(entry.path, entry.actions));
3027
+ }
3014
3028
  function resolveExpiryMs(expiry) {
3015
3029
  if (expiry === void 0) {
3016
3030
  return DEFAULT_DELEGATION_EXPIRY_MS;
@@ -3184,6 +3198,15 @@ var NodeSecretsService = class {
3184
3198
  if (this.hasPermission(permissionEntries)) {
3185
3199
  return ok();
3186
3200
  }
3201
+ let escalation;
3202
+ try {
3203
+ escalation = this.config.uncoveredEntries?.(permissionEntries) ?? permissionEntries;
3204
+ } catch (error) {
3205
+ return this.escalationError(action, target, error);
3206
+ }
3207
+ if (this.config.uncoveredEntries !== void 0 && escalation.length === 0) {
3208
+ return ok();
3209
+ }
3187
3210
  if (!this.config.canEscalate()) {
3188
3211
  return secretsError(
3189
3212
  ErrorCodes.PERMISSION_DENIED,
@@ -3191,16 +3214,20 @@ var NodeSecretsService = class {
3191
3214
  );
3192
3215
  }
3193
3216
  try {
3194
- await this.config.grantPermissions(permissionEntries);
3217
+ const grant = action === "get" && this.config.grantGetPermissions !== void 0 ? this.config.grantGetPermissions : this.config.grantPermissions;
3218
+ await grant(escalation);
3195
3219
  return this.restoreUnlockAfterEscalation();
3196
3220
  } catch (error) {
3197
- return secretsError(
3198
- ErrorCodes.PERMISSION_DENIED,
3199
- error instanceof Error ? error.message : `Autosign escalation for ${displayActionUrn(action)} on ${target} failed.`,
3200
- error instanceof Error ? error : void 0
3201
- );
3221
+ return this.escalationError(action, target, error);
3202
3222
  }
3203
3223
  }
3224
+ escalationError(action, target, error) {
3225
+ return secretsError(
3226
+ ErrorCodes.PERMISSION_DENIED,
3227
+ error instanceof Error ? error.message : `Autosign escalation for ${displayActionUrn(action)} on ${target} failed.`,
3228
+ error instanceof Error ? error : void 0
3229
+ );
3230
+ }
3204
3231
  async restoreUnlockAfterEscalation() {
3205
3232
  if (!this.shouldRestoreUnlock) {
3206
3233
  return ok();
@@ -3235,8 +3262,8 @@ var NodeSecretsService = class {
3235
3262
  // src/TinyCloudNode.ts
3236
3263
  var DEFAULT_HOST = "https://node.tinycloud.xyz";
3237
3264
  var DEFAULT_ENCRYPTION_NETWORK_NAME = "default";
3238
- var NETWORK_CREATE_ACTION2 = ENCRYPTION2.NETWORK_CREATE;
3239
- var DECRYPT_ACTION2 = ENCRYPTION2.DECRYPT;
3265
+ var NETWORK_CREATE_ACTION2 = ENCRYPTION3.NETWORK_CREATE;
3266
+ var DECRYPT_ACTION2 = ENCRYPTION3.DECRYPT;
3240
3267
  var BOOTSTRAP_COMPLETION_MARKER_KEY = "system/bootstrap/complete";
3241
3268
  var BOOTSTRAP_COMPLETION_MARKER_VERSION = 1;
3242
3269
  var ACCEPTED_MARKER_VERSIONS = [BOOTSTRAP_COMPLETION_MARKER_VERSION];
@@ -3583,7 +3610,7 @@ function ownerDelegationPermissions(params) {
3583
3610
  }
3584
3611
  if (permission.service === ENCRYPTION_PERMISSION_SERVICE2) {
3585
3612
  try {
3586
- parseNetworkId2(permission.path);
3613
+ parseNetworkId3(permission.path);
3587
3614
  } catch {
3588
3615
  throw new Error("Owner delegation encryption permission requires a canonical network URN");
3589
3616
  }
@@ -3606,6 +3633,8 @@ function ownerPermissionsToAbilities(permissions) {
3606
3633
  return { abilities, rawAbilities };
3607
3634
  }
3608
3635
  var TERMINAL_DELEGATION_REQUIRES_SESSION_KEY = "disableSubDelegation requires a session-key delegation to a did:key (not did:pkh); use the session-key DID or drop the flag";
3636
+ var DECRYPT_GRANT_MAX_EXPIRY_MS = 60 * 60 * 1e3;
3637
+ var SECRET_GET_GRANT_EXPIRY_MS = 59 * 60 * 1e3;
3609
3638
  function base64UrlEncode(bytes) {
3610
3639
  const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
3611
3640
  let output = "";
@@ -5514,7 +5543,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5514
5543
  return;
5515
5544
  }
5516
5545
  for (const networkId of this.requestedEncryptionNetworkIds()) {
5517
- const parsed = parseNetworkId2(networkId);
5546
+ const parsed = parseNetworkId3(networkId);
5518
5547
  if (!didPrincipalMatches2(parsed.ownerDid, this.did)) {
5519
5548
  continue;
5520
5549
  }
@@ -7333,7 +7362,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7333
7362
  if (!session) throw new Error("Owner session is required");
7334
7363
  const ownerDid = pkhDid2(session.address, session.chainId);
7335
7364
  for (const permission of permissions) {
7336
- if (permission.service === ENCRYPTION_PERMISSION_SERVICE2 && !principalDidEquals3(parseNetworkId2(permission.path).ownerDid, ownerDid)) {
7365
+ if (permission.service === ENCRYPTION_PERMISSION_SERVICE2 && !principalDidEquals3(parseNetworkId3(permission.path).ownerDid, ownerDid)) {
7337
7366
  throw new Error("Owner delegation cannot grant a foreign encryption network");
7338
7367
  }
7339
7368
  }
@@ -7695,7 +7724,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7695
7724
  return existing;
7696
7725
  }
7697
7726
  }
7698
- const parsed = parseNetworkId2(networkId);
7727
+ const parsed = parseNetworkId3(networkId);
7699
7728
  if (!didPrincipalMatches2(parsed.ownerDid, this.did)) {
7700
7729
  throw new Error(
7701
7730
  `Cannot create encryption network ${networkId}: owner ${parsed.ownerDid} does not match signed-in DID ${this.did}`
@@ -7728,6 +7757,8 @@ var _TinyCloudNode = class _TinyCloudNode {
7728
7757
  getManifest: () => this.manifest,
7729
7758
  hasPermissions: (permissions) => this.hasRuntimePermissions(permissions),
7730
7759
  grantPermissions: (additional) => this.grantRuntimePermissions(additional),
7760
+ grantGetPermissions: (additional) => this.grantRuntimePermissions(additional, { expiry: SECRET_GET_GRANT_EXPIRY_MS }),
7761
+ uncoveredEntries: (permissions) => permissions.filter((entry) => !this.hasRuntimePermissions([entry])),
7731
7762
  canEscalate: () => this.signer !== void 0 && this.tc !== void 0,
7732
7763
  getEncryptionNetworkId: () => this.getEncryptionNetworkIdForSpace(resolvedSpace),
7733
7764
  resolveSpace: (space) => space.startsWith("tinycloud:") ? space : this.ownedSpaceId(space),
@@ -8075,6 +8106,13 @@ var _TinyCloudNode = class _TinyCloudNode {
8075
8106
  }
8076
8107
  }
8077
8108
  const expanded = this.expandPermissionEntries(permissions);
8109
+ const requestsDecrypt = includesDecrypt(expanded);
8110
+ const requestedExpiryMs = requestsDecrypt && options?.expiry === void 0 ? DECRYPT_GRANT_MAX_EXPIRY_MS : resolveExpiryMs(options?.expiry);
8111
+ if (requestsDecrypt && requestedExpiryMs > DECRYPT_GRANT_MAX_EXPIRY_MS) {
8112
+ throw Object.assign(new Error("decrypt grants last at most one hour"), {
8113
+ code: "DECRYPT_EXPIRY_TOO_LONG"
8114
+ });
8115
+ }
8078
8116
  if (this.sessionCoversPermissionEntries(session, expanded)) {
8079
8117
  return [];
8080
8118
  }
@@ -8105,7 +8143,6 @@ var _TinyCloudNode = class _TinyCloudNode {
8105
8143
  bySpace.set(session.spaceId, []);
8106
8144
  }
8107
8145
  const now = /* @__PURE__ */ new Date();
8108
- const requestedExpiryMs = resolveExpiryMs(options?.expiry);
8109
8146
  let expiresAt = new Date(now.getTime() + requestedExpiryMs);
8110
8147
  if (sessionExpiry !== void 0 && sessionExpiry < expiresAt) {
8111
8148
  expiresAt = sessionExpiry;