@tinycloud/node-sdk 3.2.0-beta.7 → 3.2.0-beta.9

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
@@ -18429,6 +18429,10 @@ var MemorySessionStorage = class {
18429
18429
  };
18430
18430
 
18431
18431
  // src/authorization/NodeUserAuthorization.ts
18432
+ function pkhSpaceIdentity(spaceId) {
18433
+ const match = /^(tinycloud:pkh:eip155:\d+:)(0x[0-9a-fA-F]{40})(:.+)$/.exec(spaceId);
18434
+ return match === null ? spaceId : `${match[1]}${match[2].toLowerCase()}${match[3]}`;
18435
+ }
18432
18436
  var DECRYPT_ACTION = import_sdk_core4.ENCRYPTION.DECRYPT;
18433
18437
  var NETWORK_CREATE_ACTION = import_sdk_core4.ENCRYPTION.NETWORK_CREATE;
18434
18438
  function describeHostFailure(result) {
@@ -19227,11 +19231,26 @@ var NodeUserAuthorization = class {
19227
19231
  const jwk = JSON.parse(jwkString);
19228
19232
  const now = /* @__PURE__ */ new Date();
19229
19233
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
19230
- const abilities = (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)(
19231
- options.capabilityRequest.resources
19232
- );
19234
+ const primaryIdentity = pkhSpaceIdentity(options.spaceId);
19235
+ const resourcesBySpace = /* @__PURE__ */ new Map();
19236
+ for (const resource of options.capabilityRequest.resources) {
19237
+ const resolved = this.resolveSpaceName(resource.space, address, chainId);
19238
+ const identity = pkhSpaceIdentity(resolved);
19239
+ const group = resourcesBySpace.get(identity) ?? {
19240
+ spaceId: identity === primaryIdentity ? options.spaceId : resolved,
19241
+ resources: []
19242
+ };
19243
+ group.resources.push(resource);
19244
+ resourcesBySpace.set(identity, group);
19245
+ }
19246
+ const spaceAbilities = {};
19247
+ for (const { spaceId, resources } of resourcesBySpace.values()) {
19248
+ spaceAbilities[spaceId] = (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)(resources);
19249
+ }
19250
+ const abilities = spaceAbilities[options.spaceId] ?? (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)([]);
19233
19251
  const prepared = this.wasm.prepareSession({
19234
19252
  abilities,
19253
+ spaceAbilities,
19235
19254
  ...options.rawAbilities !== void 0 ? { rawAbilities: options.rawAbilities } : {},
19236
19255
  address,
19237
19256
  chainId,
@@ -20859,6 +20878,32 @@ function authorizationHeader(headers) {
20859
20878
  }
20860
20879
  return value;
20861
20880
  }
20881
+ function accountIndexWarningDiagnostic(error) {
20882
+ const diagnostic = {};
20883
+ let current = error;
20884
+ for (let depth = 0; depth < 8 && current !== null && typeof current === "object"; depth += 1) {
20885
+ const record = current;
20886
+ if (diagnostic.status === void 0) {
20887
+ if (typeof record.status === "number" && Number.isFinite(record.status)) {
20888
+ diagnostic.status = record.status;
20889
+ } else if (typeof record.statusCode === "number" && Number.isFinite(record.statusCode)) {
20890
+ diagnostic.status = record.statusCode;
20891
+ } else {
20892
+ const meta = record.meta;
20893
+ if (meta !== null && typeof meta === "object") {
20894
+ const status = meta.status;
20895
+ if (typeof status === "number" && Number.isFinite(status)) diagnostic.status = status;
20896
+ }
20897
+ }
20898
+ }
20899
+ if (diagnostic.code === void 0 && typeof record.code === "string" && /^[A-Z][A-Z0-9_]*$/.test(record.code)) {
20900
+ diagnostic.code = record.code;
20901
+ }
20902
+ if (diagnostic.status !== void 0 && diagnostic.code !== void 0) break;
20903
+ current = record.cause;
20904
+ }
20905
+ return diagnostic;
20906
+ }
20862
20907
  var _TinyCloudNode = class _TinyCloudNode {
20863
20908
  /**
20864
20909
  * Create a new TinyCloudNode instance.
@@ -20940,7 +20985,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20940
20985
  const grantedOperation = grant?.operations.find(
20941
20986
  (candidate) => this.operationCovers(candidate, operation)
20942
20987
  );
20943
- const invocationSession = !grant || grant.provenance === "primary" ? session : grant.session;
20988
+ const invocationSession = !grant || grant.provenance === "primary" ? session : this.grantSessionForSpace(grant, session.spaceId);
20944
20989
  if ((grantedOperation?.caveats?.length ?? 0) > 0) {
20945
20990
  if (!this.wasmBindings.invokeAny) {
20946
20991
  throw new Error("WASM binding does not support caveat-preserving invocation");
@@ -22102,13 +22147,27 @@ var _TinyCloudNode = class _TinyCloudNode {
22102
22147
  jwk: current.jwk
22103
22148
  });
22104
22149
  const registry = this.createAccountRegistryServices(context, controller.signal);
22150
+ let indexWarningLogged = false;
22105
22151
  try {
22106
22152
  await this.withAccountRegistryRetry(async () => {
22107
22153
  if (controller.signal.aborted) throw controller.signal.reason;
22108
22154
  if (this.currentTinyCloudSession() !== session || this.ownStorageFull) return;
22109
- await registry.account.index.ensure();
22155
+ let indexFailure;
22156
+ try {
22157
+ const index = await registry.account.index.ensure();
22158
+ if (!index.ok) indexFailure = index.error;
22159
+ } catch (error) {
22160
+ indexFailure = error;
22161
+ }
22110
22162
  if (controller.signal.aborted) throw controller.signal.reason;
22111
22163
  if (this.currentTinyCloudSession() !== session || this.ownStorageFull) return;
22164
+ if (indexFailure !== void 0 && !indexWarningLogged) {
22165
+ indexWarningLogged = true;
22166
+ console.warn(
22167
+ "TinyCloud account index initialization failed; continuing registry sync",
22168
+ accountIndexWarningDiagnostic(indexFailure)
22169
+ );
22170
+ }
22112
22171
  await this.writeManifestRegistryRecords(registry.account, controller.signal);
22113
22172
  if (controller.signal.aborted) throw controller.signal.reason;
22114
22173
  if (this.currentTinyCloudSession() !== session || this.ownStorageFull) return;
@@ -22194,7 +22253,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22194
22253
  }
22195
22254
  const verdict = (0, import_sdk_core9.authorizationVerdictOf)(error);
22196
22255
  const message = error instanceof Error ? error.message : String(error);
22197
- const isAuthorizationVerdict = verdict === void 0 ? /Unauthorized Action|\b(?:401|403)\b/.test(message) : verdict !== "other";
22256
+ const isAuthorizationVerdict = verdict === void 0 ? /^(?:Unauthorized Action\b|(?:(?:request failed|HTTP request failed|status(?: code)?|response status)\s*:\s*)?(?:HTTP\s*)?(?:401|403)\b)/i.test(message) : verdict !== "other";
22198
22257
  if (isAuthorizationVerdict) {
22199
22258
  console.warn(
22200
22259
  "TinyCloud account registry sync stopped: authorization verdict is not retryable",
@@ -25842,7 +25901,18 @@ var _TinyCloudNode = class _TinyCloudNode {
25842
25901
  if (!grant) {
25843
25902
  return fallback;
25844
25903
  }
25845
- return grant.provenance === "primary" ? fallback : grant.session;
25904
+ return grant.provenance === "primary" ? fallback : this.grantSessionForSpace(grant, fallback.spaceId);
25905
+ }
25906
+ /**
25907
+ * A non-primary grant's session, aimed at `spaceId`. The grant's delegation
25908
+ * may span spaces (the widened default bootstrap session also carries
25909
+ * account-space entries, TC-957); its session's own `spaceId` is the space
25910
+ * it was minted for, so an op on another covered space must keep the grant's
25911
+ * key and proof but target that space. A grant on the target space itself is
25912
+ * returned unchanged, keeping its own spelling of the space id.
25913
+ */
25914
+ grantSessionForSpace(grant, spaceId) {
25915
+ return this.spaceIdsEqual(grant.session.spaceId, spaceId) ? grant.session : { ...grant.session, spaceId };
25846
25916
  }
25847
25917
  findGrantForOperations(operations, options) {
25848
25918
  if (operations.length === 0) {