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

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.js CHANGED
@@ -4409,19 +4409,19 @@ var init_lib4 = __esm({
4409
4409
  resolve(value);
4410
4410
  });
4411
4411
  }
4412
- return new (P || (P = Promise))(function(resolve, reject) {
4412
+ return new (P || (P = Promise))(function(resolve, reject2) {
4413
4413
  function fulfilled(value) {
4414
4414
  try {
4415
4415
  step(generator.next(value));
4416
4416
  } catch (e) {
4417
- reject(e);
4417
+ reject2(e);
4418
4418
  }
4419
4419
  }
4420
4420
  function rejected(value) {
4421
4421
  try {
4422
4422
  step(generator["throw"](value));
4423
4423
  } catch (e) {
4424
- reject(e);
4424
+ reject2(e);
4425
4425
  }
4426
4426
  }
4427
4427
  function step(result) {
@@ -8045,19 +8045,19 @@ var init_typed_data = __esm({
8045
8045
  resolve(value);
8046
8046
  });
8047
8047
  }
8048
- return new (P || (P = Promise))(function(resolve, reject) {
8048
+ return new (P || (P = Promise))(function(resolve, reject2) {
8049
8049
  function fulfilled(value) {
8050
8050
  try {
8051
8051
  step(generator.next(value));
8052
8052
  } catch (e) {
8053
- reject(e);
8053
+ reject2(e);
8054
8054
  }
8055
8055
  }
8056
8056
  function rejected(value) {
8057
8057
  try {
8058
8058
  step(generator["throw"](value));
8059
8059
  } catch (e) {
8060
- reject(e);
8060
+ reject2(e);
8061
8061
  }
8062
8062
  }
8063
8063
  function step(result) {
@@ -14903,14 +14903,14 @@ var require_scrypt = __commonJS({
14903
14903
  }
14904
14904
  const lib = {
14905
14905
  scrypt: function(password, salt, N2, r2, p, dkLen, progressCallback) {
14906
- return new Promise(function(resolve, reject) {
14906
+ return new Promise(function(resolve, reject2) {
14907
14907
  let lastProgress = 0;
14908
14908
  if (progressCallback) {
14909
14909
  progressCallback(0);
14910
14910
  }
14911
14911
  _scrypt(password, salt, N2, r2, p, dkLen, function(error, progress, key2) {
14912
14912
  if (error) {
14913
- reject(error);
14913
+ reject2(error);
14914
14914
  } else if (key2) {
14915
14915
  if (progressCallback && lastProgress !== 1) {
14916
14916
  progressCallback(1);
@@ -15299,19 +15299,19 @@ var init_keystore = __esm({
15299
15299
  resolve(value);
15300
15300
  });
15301
15301
  }
15302
- return new (P || (P = Promise))(function(resolve, reject) {
15302
+ return new (P || (P = Promise))(function(resolve, reject2) {
15303
15303
  function fulfilled(value) {
15304
15304
  try {
15305
15305
  step(generator.next(value));
15306
15306
  } catch (e) {
15307
- reject(e);
15307
+ reject2(e);
15308
15308
  }
15309
15309
  }
15310
15310
  function rejected(value) {
15311
15311
  try {
15312
15312
  step(generator["throw"](value));
15313
15313
  } catch (e) {
15314
- reject(e);
15314
+ reject2(e);
15315
15315
  }
15316
15316
  }
15317
15317
  function step(result) {
@@ -15612,19 +15612,19 @@ var init_lib25 = __esm({
15612
15612
  resolve(value);
15613
15613
  });
15614
15614
  }
15615
- return new (P || (P = Promise))(function(resolve, reject) {
15615
+ return new (P || (P = Promise))(function(resolve, reject2) {
15616
15616
  function fulfilled(value) {
15617
15617
  try {
15618
15618
  step(generator.next(value));
15619
15619
  } catch (e) {
15620
- reject(e);
15620
+ reject2(e);
15621
15621
  }
15622
15622
  }
15623
15623
  function rejected(value) {
15624
15624
  try {
15625
15625
  step(generator["throw"](value));
15626
15626
  } catch (e) {
15627
- reject(e);
15627
+ reject2(e);
15628
15628
  }
15629
15629
  }
15630
15630
  function step(result) {
@@ -15694,19 +15694,19 @@ var init_lib26 = __esm({
15694
15694
  resolve(value);
15695
15695
  });
15696
15696
  }
15697
- return new (P || (P = Promise))(function(resolve, reject) {
15697
+ return new (P || (P = Promise))(function(resolve, reject2) {
15698
15698
  function fulfilled(value) {
15699
15699
  try {
15700
15700
  step(generator.next(value));
15701
15701
  } catch (e) {
15702
- reject(e);
15702
+ reject2(e);
15703
15703
  }
15704
15704
  }
15705
15705
  function rejected(value) {
15706
15706
  try {
15707
15707
  step(generator["throw"](value));
15708
15708
  } catch (e) {
15709
- reject(e);
15709
+ reject2(e);
15710
15710
  }
15711
15711
  }
15712
15712
  function step(result) {
@@ -16016,19 +16016,19 @@ var init_lib27 = __esm({
16016
16016
  resolve(value);
16017
16017
  });
16018
16018
  }
16019
- return new (P || (P = Promise))(function(resolve, reject) {
16019
+ return new (P || (P = Promise))(function(resolve, reject2) {
16020
16020
  function fulfilled(value) {
16021
16021
  try {
16022
16022
  step(generator.next(value));
16023
16023
  } catch (e) {
16024
- reject(e);
16024
+ reject2(e);
16025
16025
  }
16026
16026
  }
16027
16027
  function rejected(value) {
16028
16028
  try {
16029
16029
  step(generator["throw"](value));
16030
16030
  } catch (e) {
16031
- reject(e);
16031
+ reject2(e);
16032
16032
  }
16033
16033
  }
16034
16034
  function step(result) {
@@ -16254,19 +16254,19 @@ var init_geturl = __esm({
16254
16254
  resolve(value);
16255
16255
  });
16256
16256
  }
16257
- return new (P || (P = Promise))(function(resolve, reject) {
16257
+ return new (P || (P = Promise))(function(resolve, reject2) {
16258
16258
  function fulfilled(value) {
16259
16259
  try {
16260
16260
  step(generator.next(value));
16261
16261
  } catch (e) {
16262
- reject(e);
16262
+ reject2(e);
16263
16263
  }
16264
16264
  }
16265
16265
  function rejected(value) {
16266
16266
  try {
16267
16267
  step(generator["throw"](value));
16268
16268
  } catch (e) {
16269
- reject(e);
16269
+ reject2(e);
16270
16270
  }
16271
16271
  }
16272
16272
  function step(result) {
@@ -16407,14 +16407,14 @@ function _fetchData(connection, body, processFunc) {
16407
16407
  options.headers = flatHeaders;
16408
16408
  const runningTimeout = (function() {
16409
16409
  let timer = null;
16410
- const promise = new Promise(function(resolve, reject) {
16410
+ const promise = new Promise(function(resolve, reject2) {
16411
16411
  if (timeout) {
16412
16412
  timer = setTimeout(() => {
16413
16413
  if (timer == null) {
16414
16414
  return;
16415
16415
  }
16416
16416
  timer = null;
16417
- reject(logger28.makeError("timeout", Logger.errors.TIMEOUT, {
16417
+ reject2(logger28.makeError("timeout", Logger.errors.TIMEOUT, {
16418
16418
  requestBody: bodyify(options.body, flatHeaders["content-type"]),
16419
16419
  requestMethod: options.method,
16420
16420
  timeout,
@@ -16577,7 +16577,7 @@ function poll(func, options) {
16577
16577
  if (options.interval == null) {
16578
16578
  options.interval = 250;
16579
16579
  }
16580
- return new Promise(function(resolve, reject) {
16580
+ return new Promise(function(resolve, reject2) {
16581
16581
  let timer = null;
16582
16582
  let done = false;
16583
16583
  const cancel = () => {
@@ -16593,7 +16593,7 @@ function poll(func, options) {
16593
16593
  if (options.timeout) {
16594
16594
  timer = setTimeout(() => {
16595
16595
  if (cancel()) {
16596
- reject(new Error("timeout"));
16596
+ reject2(new Error("timeout"));
16597
16597
  }
16598
16598
  }, options.timeout);
16599
16599
  }
@@ -16613,7 +16613,7 @@ function poll(func, options) {
16613
16613
  attempt++;
16614
16614
  if (attempt > retryLimit) {
16615
16615
  if (cancel()) {
16616
- reject(new Error("retry limit reached"));
16616
+ reject2(new Error("retry limit reached"));
16617
16617
  }
16618
16618
  return;
16619
16619
  }
@@ -16629,7 +16629,7 @@ function poll(func, options) {
16629
16629
  return null;
16630
16630
  }, function(error) {
16631
16631
  if (cancel()) {
16632
- reject(error);
16632
+ reject2(error);
16633
16633
  }
16634
16634
  });
16635
16635
  }
@@ -16653,19 +16653,19 @@ var init_lib28 = __esm({
16653
16653
  resolve(value);
16654
16654
  });
16655
16655
  }
16656
- return new (P || (P = Promise))(function(resolve, reject) {
16656
+ return new (P || (P = Promise))(function(resolve, reject2) {
16657
16657
  function fulfilled(value) {
16658
16658
  try {
16659
16659
  step(generator.next(value));
16660
16660
  } catch (e) {
16661
- reject(e);
16661
+ reject2(e);
16662
16662
  }
16663
16663
  }
16664
16664
  function rejected(value) {
16665
16665
  try {
16666
16666
  step(generator["throw"](value));
16667
16667
  } catch (e) {
16668
- reject(e);
16668
+ reject2(e);
16669
16669
  }
16670
16670
  }
16671
16671
  function step(result) {
@@ -17035,6 +17035,7 @@ import {
17035
17035
  prepareSession,
17036
17036
  completeSessionSetup,
17037
17037
  validatePersistedSession,
17038
+ validateSessionGrant,
17038
17039
  ensureEip55,
17039
17040
  makeSpaceId,
17040
17041
  createDelegation,
@@ -17084,6 +17085,9 @@ var _NodeWasmBindings = class _NodeWasmBindings {
17084
17085
  validatePersistedSession(proof) {
17085
17086
  return validatePersistedSession(proof);
17086
17087
  }
17088
+ validateSessionGrant(proof) {
17089
+ return validateSessionGrant(proof);
17090
+ }
17087
17091
  createSessionManager() {
17088
17092
  return new TCWSessionManager();
17089
17093
  }
@@ -17163,6 +17167,7 @@ import {
17163
17167
  TinyCloud,
17164
17168
  activateSessionWithHost as activateSessionWithHost2,
17165
17169
  authorizationVerdictOf,
17170
+ httpResponseError,
17166
17171
  KVService as KVService2,
17167
17172
  SQLService as SQLService2,
17168
17173
  DuckDbService as DuckDbService2,
@@ -17196,6 +17201,7 @@ import {
17196
17201
  recapCaveatsEqual,
17197
17202
  expandPermissionEntries as expandPermissionEntriesCore,
17198
17203
  isCapabilitySubset,
17204
+ isExplicitOnlyAction,
17199
17205
  parseRecapCapabilities,
17200
17206
  SERVICE_LONG_TO_SHORT,
17201
17207
  SERVICE_SHORT_TO_LONG,
@@ -17218,7 +17224,10 @@ import {
17218
17224
  CREDENTIAL_INVITATION_REQUEST_DOMAIN,
17219
17225
  validateShareDeliveryAuthorizationV3Bytes,
17220
17226
  verifyEip191MessageSignature,
17221
- signCompactUcanRootAuthorization
17227
+ signCompactUcanRootAuthorization,
17228
+ isStorageFullError,
17229
+ STORAGE_FULL_MESSAGE,
17230
+ STORAGE_WRITE_TOO_LARGE_MESSAGE
17222
17231
  } from "@tinycloud/sdk-core";
17223
17232
  import {
17224
17233
  parsePermissionHint
@@ -17338,6 +17347,10 @@ var MemorySessionStorage = class {
17338
17347
  // src/authorization/NodeUserAuthorization.ts
17339
17348
  var DECRYPT_ACTION = ENCRYPTION.DECRYPT;
17340
17349
  var NETWORK_CREATE_ACTION = ENCRYPTION.NETWORK_CREATE;
17350
+ function describeHostFailure(result) {
17351
+ const text = result.error?.trim();
17352
+ return text ? `${result.status} - ${text}` : `${result.status}`;
17353
+ }
17341
17354
  function canonicalizeOpenKeyManifestJson(value) {
17342
17355
  const json = JSON.stringify(value);
17343
17356
  if (json === void 0) {
@@ -17866,10 +17879,12 @@ var NodeUserAuthorization = class {
17866
17879
  return;
17867
17880
  }
17868
17881
  try {
17869
- const created = (await this.hostSpace()).success;
17870
- if (!created) {
17871
- const err = new Error(`Failed to create space: ${primarySpaceId}`);
17872
- handler.onSpaceCreationFailed?.(creationContext, err);
17882
+ const created = await this.hostSpace();
17883
+ if (!created.success) {
17884
+ const err = Object.assign(
17885
+ new Error(`Failed to create space ${primarySpaceId}: ${describeHostFailure(created)}`),
17886
+ { cause: created }
17887
+ );
17873
17888
  throw err;
17874
17889
  }
17875
17890
  } catch (error) {
@@ -17885,8 +17900,9 @@ var NodeUserAuthorization = class {
17885
17900
  this._tinyCloudSession.delegationHeader
17886
17901
  );
17887
17902
  if (!retryResult.success) {
17888
- const err = new Error(
17889
- `Failed to activate session after creating space: ${retryResult.error}`
17903
+ const err = Object.assign(
17904
+ new Error(`Failed to activate session after creating space: ${describeHostFailure(retryResult)}`),
17905
+ { cause: retryResult }
17890
17906
  );
17891
17907
  handler.onSpaceCreationFailed?.(creationContext, err);
17892
17908
  throw err;
@@ -17903,10 +17919,12 @@ var NodeUserAuthorization = class {
17903
17919
  return;
17904
17920
  }
17905
17921
  try {
17906
- const created = (await this.hostSpace()).success;
17907
- if (!created) {
17908
- const err = new Error(`Failed to create space: ${primarySpaceId}`);
17909
- handler.onSpaceCreationFailed?.(creationContext, err);
17922
+ const created = await this.hostSpace();
17923
+ if (!created.success) {
17924
+ const err = Object.assign(
17925
+ new Error(`Failed to create space ${primarySpaceId}: ${describeHostFailure(created)}`),
17926
+ { cause: created }
17927
+ );
17910
17928
  throw err;
17911
17929
  }
17912
17930
  } catch (error) {
@@ -17922,8 +17940,9 @@ var NodeUserAuthorization = class {
17922
17940
  this._tinyCloudSession.delegationHeader
17923
17941
  );
17924
17942
  if (!retryResult.success) {
17925
- const err = new Error(
17926
- `Failed to activate session after creating space: ${retryResult.error}`
17943
+ const err = Object.assign(
17944
+ new Error(`Failed to activate session after creating space: ${describeHostFailure(retryResult)}`),
17945
+ { cause: retryResult }
17927
17946
  );
17928
17947
  handler.onSpaceCreationFailed?.(creationContext, err);
17929
17948
  throw err;
@@ -17931,7 +17950,10 @@ var NodeUserAuthorization = class {
17931
17950
  handler.onSpaceCreated?.(creationContext);
17932
17951
  return;
17933
17952
  }
17934
- throw new Error(`Failed to activate session: ${result.error}`);
17953
+ throw Object.assign(
17954
+ new Error(`Failed to activate session: ${describeHostFailure(result)}`),
17955
+ { cause: result }
17956
+ );
17935
17957
  }
17936
17958
  recordActivationSkippedSpaces(result, primarySpaceId) {
17937
17959
  if (result.success) {
@@ -18721,14 +18743,14 @@ var NodeUserAuthorization = class {
18721
18743
  * Request signature via event emitter with timeout.
18722
18744
  */
18723
18745
  requestSignatureViaEmitter(request, emitter, timeout) {
18724
- return new Promise((resolve, reject) => {
18746
+ return new Promise((resolve, reject2) => {
18725
18747
  const timeoutId = setTimeout(() => {
18726
- reject(new Error("Sign request timed out"));
18748
+ reject2(new Error("Sign request timed out"));
18727
18749
  }, timeout);
18728
18750
  const respond = async (response) => {
18729
18751
  clearTimeout(timeoutId);
18730
18752
  if (!response.approved) {
18731
- reject(
18753
+ reject2(
18732
18754
  new Error(response.reason ?? "Sign request rejected via emitter")
18733
18755
  );
18734
18756
  } else {
@@ -19323,6 +19345,25 @@ function jsonFromVerifier(value) {
19323
19345
  function verifierRecapEntries(entries) {
19324
19346
  return entries.map((entry) => Array.isArray(entry.caveats) ? { ...entry, caveats: entry.caveats.map((caveat) => jsonFromVerifier(caveat)) } : entry);
19325
19347
  }
19348
+ function exactVerifiedRecap(verified) {
19349
+ const exactRecap = Array.isArray(verified.verifiedRecap) ? verifierRecapEntries(verified.verifiedRecap) : verified.verifiedRecap;
19350
+ if (!Array.isArray(exactRecap) || !exactRecap.every(
19351
+ (entry) => entry !== null && typeof entry === "object" && typeof entry.service === "string" && typeof entry.space === "string" && typeof entry.path === "string" && Array.isArray(entry.actions) && entry.actions.every((action) => typeof action === "string") && Array.isArray(entry.caveats) && entry.caveats.every(
19352
+ (caveat) => caveat !== null && typeof caveat === "object" && !Array.isArray(caveat)
19353
+ )
19354
+ )) {
19355
+ throw new UnsupportedSessionRestoreError(
19356
+ "it cannot reconstruct caveat-preserving persisted ReCap authority"
19357
+ );
19358
+ }
19359
+ return exactRecap.map((entry) => ({
19360
+ service: entry.service,
19361
+ space: entry.space,
19362
+ path: entry.path,
19363
+ actions: [...entry.actions],
19364
+ caveats: cloneRecapCaveats(entry.caveats)
19365
+ }));
19366
+ }
19326
19367
  var ServiceGraphLifetime = class {
19327
19368
  constructor(invokeFn, invokeAnyFn, fetchFn) {
19328
19369
  this.invokeFn = invokeFn;
@@ -19418,7 +19459,7 @@ function persistedExpiry(value) {
19418
19459
  function sameInstant(left, right) {
19419
19460
  return left.getTime() === right.getTime();
19420
19461
  }
19421
- function describeHostFailure(result) {
19462
+ function describeHostFailure2(result) {
19422
19463
  const text = result.error?.trim();
19423
19464
  return text ? `${result.status} - ${text}` : `${result.status}`;
19424
19465
  }
@@ -20164,12 +20205,13 @@ var _TinyCloudNode = class _TinyCloudNode {
20164
20205
  if (!auth) {
20165
20206
  throw new Error("Account bootstrap requires an active wallet session");
20166
20207
  }
20208
+ const accountSpaceId = this.ownedSpaceId(ACCOUNT_REGISTRY_SPACE2);
20167
20209
  const skipped = auth.lastActivationSkippedSpaceIds;
20210
+ if (skipped.includes(accountSpaceId)) return { action: "run", mode: "fresh" };
20168
20211
  if (skipped.some((spaceId) => enshrinedSpaceIds.has(spaceId))) {
20169
- return { action: "run", mode: "fresh" };
20212
+ return { action: "run", mode: "repair" };
20170
20213
  }
20171
20214
  try {
20172
- const accountSpaceId = this.ownedSpaceId(ACCOUNT_REGISTRY_SPACE2);
20173
20215
  const markerPermission = {
20174
20216
  service: "tinycloud.kv",
20175
20217
  space: accountSpaceId,
@@ -20181,7 +20223,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20181
20223
  }
20182
20224
  const marker = await this.readBootstrapCompletionMarker();
20183
20225
  if (marker.ok) {
20184
- if (this.isAcceptedBootstrapCompletionMarker(marker.data.data)) {
20226
+ if (this.isAcceptedBootstrapCompletionMarker(marker.data.data, steps.map((step) => step.id))) {
20185
20227
  return { action: "skip" };
20186
20228
  }
20187
20229
  return { action: "run", mode: "repair" };
@@ -20225,15 +20267,22 @@ var _TinyCloudNode = class _TinyCloudNode {
20225
20267
  marker
20226
20268
  );
20227
20269
  if (!written.ok) {
20228
- throw new Error(`Failed to write bootstrap completion marker: ${written.error.message}`);
20270
+ throw Object.assign(
20271
+ new Error(`Failed to write bootstrap completion marker: ${written.error.message}`),
20272
+ { cause: written.error }
20273
+ );
20229
20274
  }
20230
20275
  }
20231
- isAcceptedBootstrapCompletionMarker(value) {
20276
+ /**
20277
+ * A marker written before a canonical space was added triggers one bounded repair.
20278
+ */
20279
+ isAcceptedBootstrapCompletionMarker(value, canonicalStepIds) {
20232
20280
  if (typeof value !== "object" || value === null) return false;
20233
20281
  const entries = Object.entries(value);
20234
20282
  const markerValue = (name) => entries.find(([key2]) => key2 === name)?.[1];
20235
20283
  const version23 = markerValue("v");
20236
- return typeof version23 === "number" && Number.isInteger(version23) && ACCEPTED_MARKER_VERSIONS.some((acceptedVersion) => acceptedVersion === version23);
20284
+ const stepIds = markerValue("stepIds");
20285
+ return typeof version23 === "number" && Number.isInteger(version23) && ACCEPTED_MARKER_VERSIONS.some((acceptedVersion) => acceptedVersion === version23) && Array.isArray(stepIds) && canonicalStepIds.every((stepId) => stepIds.includes(stepId));
20237
20286
  }
20238
20287
  markerReadIsUnhostedSpace(meta) {
20239
20288
  return meta?.status === 404;
@@ -20271,17 +20320,23 @@ var _TinyCloudNode = class _TinyCloudNode {
20271
20320
  rawAbilities
20272
20321
  });
20273
20322
  } catch (err) {
20274
- throw new Error(
20275
- `Account bootstrap aborted: signature rejected for space "${step.space}". Cause: ${err instanceof Error ? err.message : String(err)}`
20323
+ throw Object.assign(
20324
+ new Error(
20325
+ `Account bootstrap aborted: signature rejected for space "${step.space}". Cause: ${err instanceof Error ? err.message : String(err)}`
20326
+ ),
20327
+ { cause: err }
20276
20328
  );
20277
20329
  }
20278
20330
  sessions.set(step.space, session);
20279
20331
  }
20280
20332
  for (const step of steps) {
20281
20333
  if (step.kind !== "host") continue;
20282
- const hosted = await auth.hostOwnedSpace(step.spaceId, "bootstrap-host");
20283
- if (!hosted) {
20284
- throw new Error(`Failed to host bootstrap space: ${step.spaceId}`);
20334
+ const hosted = await auth.hostOwnedSpaceResult(step.spaceId, "bootstrap-host");
20335
+ if (!hosted.success) {
20336
+ throw Object.assign(
20337
+ new Error(`Failed to host bootstrap space ${step.spaceId}: ${describeHostFailure2(hosted)}`),
20338
+ { cause: hosted }
20339
+ );
20285
20340
  }
20286
20341
  }
20287
20342
  await new Promise((resolve) => setTimeout(resolve, 100));
@@ -20293,8 +20348,11 @@ var _TinyCloudNode = class _TinyCloudNode {
20293
20348
  }
20294
20349
  const activated = await activateSessionWithHost2(host, session.delegationHeader);
20295
20350
  if (!activated.success || activated.skipped?.includes(step.spaceId)) {
20296
- throw new Error(
20297
- `Failed to activate bootstrap session for ${step.spaceId}: ${activated.error ?? "space was skipped"}`
20351
+ throw Object.assign(
20352
+ new Error(
20353
+ `Failed to activate bootstrap session for ${step.spaceId}: ${activated.success ? "space was skipped" : describeHostFailure2(activated)}`
20354
+ ),
20355
+ { cause: activated }
20298
20356
  );
20299
20357
  }
20300
20358
  this.registerBootstrapRuntimeGrant(
@@ -20307,33 +20365,43 @@ var _TinyCloudNode = class _TinyCloudNode {
20307
20365
  if (step.kind === "account-index-schema") {
20308
20366
  const ensured = await this.account.index.ensure();
20309
20367
  if (!ensured.ok) {
20310
- throw new Error(`Failed to create account index schema: ${ensured.error.message}`);
20368
+ throw Object.assign(new Error(`Failed to create account index schema: ${ensured.error.message}`), { cause: ensured.error });
20311
20369
  }
20312
20370
  }
20313
20371
  if (step.kind === "seed-spaces") {
20314
- const registered = await this.account.spaces.registerBatch(
20315
- step.spaces.map((space) => ({
20316
- spaceId: space.spaceId,
20317
- name: space.name,
20318
- ownerDid: this.did,
20319
- type: "owned",
20320
- permissions: ["*"],
20321
- status: "active"
20322
- }))
20323
- );
20324
- if (!registered.ok) {
20325
- throw new Error(
20326
- `Failed to seed account spaces: ${registered.error.message}`
20327
- );
20328
- }
20329
- const batchError = registered.data.recoveredFromBatchError;
20330
- if (batchError) {
20331
- warnings.push({
20332
- stepId: step.id,
20333
- kind: "batch-write-reconciled",
20334
- code: batchError.code,
20335
- message: batchError.message
20336
- });
20372
+ const inputs = step.spaces.map((space) => ({
20373
+ spaceId: space.spaceId,
20374
+ name: space.name,
20375
+ ownerDid: this.did,
20376
+ type: "owned",
20377
+ permissions: ["*"],
20378
+ status: "active"
20379
+ }));
20380
+ if (mode === "fresh") {
20381
+ const registered = await this.account.spaces.registerBatch(inputs);
20382
+ if (!registered.ok) {
20383
+ throw Object.assign(
20384
+ new Error(`Failed to seed account spaces: ${registered.error.message}`),
20385
+ { cause: registered.error }
20386
+ );
20387
+ }
20388
+ const batchError = registered.data.recoveredFromBatchError;
20389
+ if (batchError) {
20390
+ warnings.push({
20391
+ stepId: step.id,
20392
+ kind: "batch-write-reconciled",
20393
+ code: batchError.code,
20394
+ message: batchError.message
20395
+ });
20396
+ }
20397
+ } else {
20398
+ const ensured = await this.account.spaces.registerMissing(inputs);
20399
+ if (!ensured.ok) {
20400
+ throw Object.assign(
20401
+ new Error(`Failed to seed account spaces: ${ensured.error.message}`),
20402
+ { cause: ensured.error }
20403
+ );
20404
+ }
20337
20405
  }
20338
20406
  }
20339
20407
  if (step.kind === "seed-applications") {
@@ -20344,7 +20412,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20344
20412
  { assumeUnregistered: true }
20345
20413
  );
20346
20414
  if (!registered.ok) {
20347
- throw new Error(`Failed to seed bootstrap applications: ${registered.error.message}`);
20415
+ throw Object.assign(new Error(`Failed to seed bootstrap applications: ${registered.error.message}`), { cause: registered.error });
20348
20416
  }
20349
20417
  }
20350
20418
  if (step.kind === "encryption-network-create") {
@@ -20362,8 +20430,9 @@ var _TinyCloudNode = class _TinyCloudNode {
20362
20430
  ]
20363
20431
  });
20364
20432
  if (!migrated.ok) {
20365
- throw new Error(
20366
- `Failed to create secret_records schema: ${migrated.error.message}`
20433
+ throw Object.assign(
20434
+ new Error(`Failed to create secret_records schema: ${migrated.error.message}`),
20435
+ { cause: migrated.error }
20367
20436
  );
20368
20437
  }
20369
20438
  }
@@ -20630,6 +20699,10 @@ var _TinyCloudNode = class _TinyCloudNode {
20630
20699
  );
20631
20700
  return;
20632
20701
  }
20702
+ if (isStorageFullError(error) || isStorageFullError(error?.cause) || message.includes(STORAGE_FULL_MESSAGE) || message.includes(STORAGE_WRITE_TOO_LARGE_MESSAGE)) {
20703
+ console.warn("TinyCloud account registry sync stopped: storage is full", error);
20704
+ return;
20705
+ }
20633
20706
  lastError = error;
20634
20707
  if (attempt < delays.length - 1) {
20635
20708
  await new Promise((resolve) => setTimeout(resolve, delays[attempt]));
@@ -20704,14 +20777,14 @@ var _TinyCloudNode = class _TinyCloudNode {
20704
20777
  }
20705
20778
  if (!activation.success && activation.status !== 404) {
20706
20779
  throw Object.assign(
20707
- new Error(`Failed to check owned space ${spaceId}: ${describeHostFailure(activation)}`),
20780
+ new Error(`Failed to check owned space ${spaceId}: ${describeHostFailure2(activation)}`),
20708
20781
  { cause: activation }
20709
20782
  );
20710
20783
  }
20711
20784
  const created = await this.auth.hostOwnedSpaceResult(spaceId);
20712
20785
  if (!created.success) {
20713
20786
  throw Object.assign(
20714
- new Error(`Failed to create owned space ${spaceId}: ${describeHostFailure(created)}`),
20787
+ new Error(`Failed to create owned space ${spaceId}: ${describeHostFailure2(created)}`),
20715
20788
  { cause: created }
20716
20789
  );
20717
20790
  }
@@ -20720,7 +20793,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20720
20793
  if (!retry.success || retry.skipped?.includes(spaceId)) {
20721
20794
  throw Object.assign(
20722
20795
  new Error(
20723
- `Failed to activate session after creating owned space ${spaceId}: ${retry.success ? "space was skipped" : describeHostFailure(retry)}`
20796
+ `Failed to activate session after creating owned space ${spaceId}: ${retry.success ? "space was skipped" : describeHostFailure2(retry)}`
20724
20797
  ),
20725
20798
  { cause: retry }
20726
20799
  );
@@ -20757,19 +20830,23 @@ var _TinyCloudNode = class _TinyCloudNode {
20757
20830
  if (!host) {
20758
20831
  throw new Error("Owned space hosting requires a TinyCloud host");
20759
20832
  }
20760
- const hosted = await this.auth.hostOwnedSpace(
20761
- spaceId
20762
- );
20763
- if (!hosted) {
20764
- throw new Error(`Failed to host owned space: ${spaceId}`);
20833
+ const hosted = await this.auth.hostOwnedSpaceResult(spaceId);
20834
+ if (!hosted.success) {
20835
+ throw Object.assign(
20836
+ new Error(`Failed to host owned space ${spaceId}: ${describeHostFailure2(hosted)}`),
20837
+ { cause: hosted }
20838
+ );
20765
20839
  }
20766
20840
  const activation = await activateSessionWithHost2(
20767
20841
  host,
20768
20842
  session.delegationHeader
20769
20843
  );
20770
20844
  if (!activation.success || activation.skipped?.includes(spaceId)) {
20771
- throw new Error(
20772
- `Failed to activate session for owned space ${spaceId}: ${activation.error ?? "space was skipped"}`
20845
+ throw Object.assign(
20846
+ new Error(
20847
+ `Failed to activate session for owned space ${spaceId}: ${activation.success ? "space was skipped" : describeHostFailure2(activation)}`
20848
+ ),
20849
+ { cause: activation }
20773
20850
  );
20774
20851
  }
20775
20852
  try {
@@ -20965,23 +21042,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20965
21042
  throw new InvalidRestoredSessionError(error instanceof Error ? error.message : String(error));
20966
21043
  }
20967
21044
  })();
20968
- const exactRecap = Array.isArray(verified.verifiedRecap) ? verifierRecapEntries(verified.verifiedRecap) : verified.verifiedRecap;
20969
- if (!Array.isArray(exactRecap) || !exactRecap.every(
20970
- (entry) => entry !== null && typeof entry === "object" && typeof entry.service === "string" && typeof entry.space === "string" && typeof entry.path === "string" && Array.isArray(entry.actions) && entry.actions.every((action) => typeof action === "string") && Array.isArray(entry.caveats) && entry.caveats.every(
20971
- (caveat) => caveat !== null && typeof caveat === "object" && !Array.isArray(caveat)
20972
- )
20973
- )) {
20974
- throw new UnsupportedSessionRestoreError(
20975
- "it cannot reconstruct caveat-preserving persisted ReCap authority"
20976
- );
20977
- }
20978
- stagedRecap = exactRecap.map((entry) => ({
20979
- service: entry.service,
20980
- space: entry.space,
20981
- path: entry.path,
20982
- actions: [...entry.actions],
20983
- caveats: cloneRecapCaveats(entry.caveats)
20984
- }));
21045
+ stagedRecap = exactVerifiedRecap(verified);
20985
21046
  const signedExpiry = verified.expiresAt === void 0 ? void 0 : persistedExpiry(verified.expiresAt);
20986
21047
  const persistedPolicyExpiry = sessionData.expiresAt === void 0 ? void 0 : persistedExpiry(sessionData.expiresAt);
20987
21048
  if (signedExpiry && persistedPolicyExpiry && !sameInstant(signedExpiry, persistedPolicyExpiry)) {
@@ -21785,7 +21846,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21785
21846
  if (cached) return cached;
21786
21847
  const response = await fetch(`${this.config.host}/info`);
21787
21848
  if (!response.ok) {
21788
- throw new Error(`Failed to fetch node info: HTTP ${response.status}`);
21849
+ throw await httpResponseError(response, "Failed to fetch node info");
21789
21850
  }
21790
21851
  const info = await response.json();
21791
21852
  if (typeof info.nodeId !== "string" || info.nodeId.length === 0) {
@@ -21835,9 +21896,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21835
21896
  );
21836
21897
  if (response.status === 404) return null;
21837
21898
  if (!response.ok) {
21838
- throw new Error(
21839
- `Failed to fetch encryption network ${networkId}: HTTP ${response.status} ${await response.text()}`
21840
- );
21899
+ throw await httpResponseError(response, `Failed to fetch encryption network ${networkId}`);
21841
21900
  }
21842
21901
  const body = await response.json();
21843
21902
  return "descriptor" in body && body.descriptor ? body.descriptor : body;
@@ -22338,7 +22397,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22338
22397
  headers: { accept: "application/json", "content-type": "application/json", authorization },
22339
22398
  body: canonicalizeEncryptionJson(request)
22340
22399
  });
22341
- if (!response.ok) throw new Error(`V3 share delivery authorization failed: ${response.status}`);
22400
+ if (!response.ok) throw await httpResponseError(response, "V3 share delivery authorization failed");
22342
22401
  const verified = validateShareDeliveryAuthorizationV3Bytes(new Uint8Array(await response.arrayBuffer()), {
22343
22402
  request,
22344
22403
  senderKeyDid: this.credentialHolderDid,
@@ -22560,9 +22619,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22560
22619
  );
22561
22620
  }
22562
22621
  if (!response.ok) {
22563
- throw new Error(
22564
- `Failed to create encryption network ${networkId}: HTTP ${response.status} ${await response.text()}`
22565
- );
22622
+ throw await httpResponseError(response, `Failed to create encryption network ${networkId}`);
22566
22623
  }
22567
22624
  const created = await response.json();
22568
22625
  return created.descriptor;
@@ -22846,6 +22903,42 @@ var _TinyCloudNode = class _TinyCloudNode {
22846
22903
  (left, right) => left.service.localeCompare(right.service) || (left.space ?? "").localeCompare(right.space ?? "") || left.path.localeCompare(right.path) || left.actions.join("\0").localeCompare(right.actions.join("\0"))
22847
22904
  );
22848
22905
  }
22906
+ /**
22907
+ * Verify a wallet-signed session grant (a CACAO built from a SIWE and its
22908
+ * EIP-191 signature) issued to this instance's live session key. The
22909
+ * verifier rebuilds the CACAO from `siwe` and `signature`, so the grant is
22910
+ * accepted only when its authorization bytes and CID are exactly that CACAO,
22911
+ * its signer is `address`, its audience is this session key, it is valid
22912
+ * now, and its ReCap covers `spaceId` or names only raw encryption networks
22913
+ * (a decrypt-only grant has no space). Returns the signed ReCap and expiry.
22914
+ * Bindings without `validateSessionGrant` fall back to the session verifier,
22915
+ * which also refuses decrypt-only grants.
22916
+ */
22917
+ verifySessionGrant(grant) {
22918
+ const bindings = this.wasmBindings;
22919
+ const validate5 = typeof bindings.validateSessionGrant === "function" ? bindings.validateSessionGrant.bind(bindings) : bindings.validatePersistedSession?.bind(bindings);
22920
+ if (validate5 === void 0) {
22921
+ throw new UnsupportedSessionRestoreError("it cannot verify persisted SIWE authority");
22922
+ }
22923
+ const verified = validate5({
22924
+ delegationHeader: { Authorization: grant.delegationHeader.Authorization },
22925
+ delegationCid: grant.delegationCid,
22926
+ spaceId: grant.spaceId,
22927
+ jwk: this.sessionKeyJwk,
22928
+ address: canonicalizeAddress2(grant.address),
22929
+ chainId: grant.chainId,
22930
+ siwe: grant.siwe,
22931
+ signature: grant.signature
22932
+ });
22933
+ if (typeof verified.expiresAt !== "string") {
22934
+ throw new Error("Session grant has no signed expiry.");
22935
+ }
22936
+ const expiresAt = new Date(verified.expiresAt);
22937
+ if (!Number.isFinite(expiresAt.getTime())) {
22938
+ throw new Error("Session grant has an invalid signed expiry.");
22939
+ }
22940
+ return { recap: exactVerifiedRecap(verified), expiresAt };
22941
+ }
22849
22942
  /**
22850
22943
  * Install a portable runtime permission delegation into this SDK instance so
22851
22944
  * matching service calls and downstream `delegateTo()` calls can use it.
@@ -22870,8 +22963,9 @@ var _TinyCloudNode = class _TinyCloudNode {
22870
22963
  delegation.delegationHeader
22871
22964
  );
22872
22965
  if (!activateResult.success) {
22873
- throw new Error(
22874
- `Failed to activate runtime permission delegation: ${activateResult.error}`
22966
+ throw Object.assign(
22967
+ new Error(`Failed to activate runtime permission delegation: ${describeHostFailure2(activateResult)}`),
22968
+ { cause: activateResult }
22875
22969
  );
22876
22970
  }
22877
22971
  this.runtimePermissionGrants = this.runtimePermissionGrants.filter(
@@ -22967,8 +23061,9 @@ var _TinyCloudNode = class _TinyCloudNode {
22967
23061
  delegatedSession.delegationHeader
22968
23062
  );
22969
23063
  if (!activateResult.success) {
22970
- throw new Error(
22971
- `Failed to activate runtime permission delegation: ${activateResult.error}`
23064
+ throw Object.assign(
23065
+ new Error(`Failed to activate runtime permission delegation: ${describeHostFailure2(activateResult)}`),
23066
+ { cause: activateResult }
22972
23067
  );
22973
23068
  }
22974
23069
  const delegation = this.runtimeDelegationFromSession(
@@ -22976,7 +23071,8 @@ var _TinyCloudNode = class _TinyCloudNode {
22976
23071
  delegatedEntries,
22977
23072
  spaceId,
22978
23073
  session,
22979
- expiresAt
23074
+ expiresAt,
23075
+ { siwe: prepared.siwe, signature: signature2 }
22980
23076
  );
22981
23077
  this.runtimePermissionGrants.push({
22982
23078
  session: {
@@ -23153,7 +23249,10 @@ var _TinyCloudNode = class _TinyCloudNode {
23153
23249
  delegationSession.delegationHeader
23154
23250
  );
23155
23251
  if (!activateResult.success) {
23156
- throw new Error(`Failed to activate public space delegation: ${activateResult.error}`);
23252
+ throw Object.assign(
23253
+ new Error(`Failed to activate public space delegation: ${describeHostFailure2(activateResult)}`),
23254
+ { cause: activateResult }
23255
+ );
23157
23256
  }
23158
23257
  if (this._capabilityRegistry && this.session) {
23159
23258
  const sessionKey = {
@@ -23506,8 +23605,9 @@ var _TinyCloudNode = class _TinyCloudNode {
23506
23605
  delegationHeader
23507
23606
  );
23508
23607
  if (!activateResult.success) {
23509
- throw new Error(
23510
- `Failed to activate delegation with host: ${activateResult.error}`
23608
+ throw Object.assign(
23609
+ new Error(`Failed to activate delegation with host: ${describeHostFailure2(activateResult)}`),
23610
+ { cause: activateResult }
23511
23611
  );
23512
23612
  }
23513
23613
  return {
@@ -23543,8 +23643,9 @@ var _TinyCloudNode = class _TinyCloudNode {
23543
23643
  delegationHeader
23544
23644
  );
23545
23645
  if (!activateResult.success) {
23546
- throw new Error(
23547
- `Failed to activate delegation with host: ${activateResult.error}`
23646
+ throw Object.assign(
23647
+ new Error(`Failed to activate delegation with host: ${describeHostFailure2(activateResult)}`),
23648
+ { cause: activateResult }
23548
23649
  );
23549
23650
  }
23550
23651
  return {
@@ -23757,7 +23858,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23757
23858
  }
23758
23859
  return grants;
23759
23860
  }
23760
- runtimeDelegationFromSession(delegatedSession, entries, spaceId, session, expiresAt) {
23861
+ runtimeDelegationFromSession(delegatedSession, entries, spaceId, session, expiresAt, siweProof) {
23761
23862
  const resources = this.delegatedResourcesForEntries(entries, spaceId);
23762
23863
  const primary = resources[0];
23763
23864
  return {
@@ -23772,7 +23873,8 @@ var _TinyCloudNode = class _TinyCloudNode {
23772
23873
  delegateDID: session.verificationMethod,
23773
23874
  ownerAddress: session.address,
23774
23875
  chainId: session.chainId,
23775
- host: this.config.host
23876
+ host: this.config.host,
23877
+ siweProof
23776
23878
  };
23777
23879
  }
23778
23880
  runtimeGrantFromDelegation(delegation, session) {
@@ -23965,6 +24067,9 @@ var _TinyCloudNode = class _TinyCloudNode {
23965
24067
  if (grantedAction === requestedAction) {
23966
24068
  return true;
23967
24069
  }
24070
+ if (isExplicitOnlyAction(requestedAction)) {
24071
+ return false;
24072
+ }
23968
24073
  if (grantedAction.endsWith("/*")) {
23969
24074
  const prefix = grantedAction.slice(0, -2);
23970
24075
  return requestedAction.startsWith(`${prefix}/`);
@@ -24151,7 +24256,10 @@ var _TinyCloudNode = class _TinyCloudNode {
24151
24256
  delegationSession.delegationHeader
24152
24257
  );
24153
24258
  if (!activateResult.success) {
24154
- throw new Error(`Failed to activate delegation: ${activateResult.error}`);
24259
+ throw Object.assign(
24260
+ new Error(`Failed to activate delegation: ${describeHostFailure2(activateResult)}`),
24261
+ { cause: activateResult }
24262
+ );
24155
24263
  }
24156
24264
  const result = {
24157
24265
  cid: delegationSession.delegationCid,
@@ -24301,7 +24409,10 @@ var _TinyCloudNode = class _TinyCloudNode {
24301
24409
  invokerSession.delegationHeader
24302
24410
  );
24303
24411
  if (!activateResult.success) {
24304
- throw new Error(`Failed to activate delegated session: ${activateResult.error}`);
24412
+ throw Object.assign(
24413
+ new Error(`Failed to activate delegated session: ${describeHostFailure2(activateResult)}`),
24414
+ { cause: activateResult }
24415
+ );
24305
24416
  }
24306
24417
  const session = {
24307
24418
  address: mySession.address,
@@ -24418,7 +24529,10 @@ var _TinyCloudNode = class _TinyCloudNode {
24418
24529
  subDelegationSession.delegationHeader
24419
24530
  );
24420
24531
  if (!activateResult.success) {
24421
- throw new Error(`Failed to activate sub-delegation: ${activateResult.error}`);
24532
+ throw Object.assign(
24533
+ new Error(`Failed to activate sub-delegation: ${describeHostFailure2(activateResult)}`),
24534
+ { cause: activateResult }
24535
+ );
24422
24536
  }
24423
24537
  return {
24424
24538
  cid: subDelegationSession.delegationCid,
@@ -24487,7 +24601,10 @@ import {
24487
24601
  disableTinyCloudDebug,
24488
24602
  getTinyCloudDebugLogs,
24489
24603
  clearTinyCloudDebugLogs,
24490
- installTinyCloudDebugGlobals
24604
+ installTinyCloudDebugGlobals,
24605
+ isStorageFullError as isStorageFullError2,
24606
+ STORAGE_FULL_MESSAGE as STORAGE_FULL_MESSAGE2,
24607
+ STORAGE_WRITE_TOO_LARGE_MESSAGE as STORAGE_WRITE_TOO_LARGE_MESSAGE2
24491
24608
  } from "@tinycloud/sdk-core";
24492
24609
 
24493
24610
  // src/storage/FileSessionStorage.ts
@@ -24683,6 +24800,29 @@ import {
24683
24800
  decodeBase64Url,
24684
24801
  principalDidEquals as principalDidEquals3
24685
24802
  } from "@tinycloud/sdk-core";
24803
+ var RUNTIME_DELEGATION_REJECTIONS = [
24804
+ "host_mismatch",
24805
+ "expired",
24806
+ "cid_mismatch",
24807
+ "authority_invalid",
24808
+ "proof_missing",
24809
+ "proof_invalid",
24810
+ "owner_mismatch",
24811
+ "audience_mismatch",
24812
+ "resources_mismatch",
24813
+ "unsupported",
24814
+ "activation_rejected"
24815
+ ];
24816
+ var RuntimeDelegationRejectedError = class extends Error {
24817
+ constructor(reason, message) {
24818
+ super(message);
24819
+ this.name = "RuntimeDelegationRejectedError";
24820
+ this.reason = reason;
24821
+ }
24822
+ };
24823
+ function reject(reason, message) {
24824
+ throw new RuntimeDelegationRejectedError(reason, message);
24825
+ }
24686
24826
  var SERVICE_BY_SHORT_NAME = {
24687
24827
  kv: "tinycloud.kv",
24688
24828
  sql: "tinycloud.sql",
@@ -24829,6 +24969,15 @@ function signedAuthorityFromCompactUcan(authorization) {
24829
24969
  abilities
24830
24970
  ));
24831
24971
  }
24972
+ return canonicalSignedAuthority({
24973
+ issuer: payload.iss,
24974
+ audience: payload.aud,
24975
+ expiry,
24976
+ proofs: [...payload.prf],
24977
+ ...remainingRedelegationDepth === void 0 ? {} : { remainingRedelegationDepth }
24978
+ }, permissions);
24979
+ }
24980
+ function canonicalSignedAuthority(signed2, permissions) {
24832
24981
  if (permissions.length === 0) {
24833
24982
  throw new Error("Validated runtime delegation has no signed capabilities.");
24834
24983
  }
@@ -24840,15 +24989,84 @@ function signedAuthorityFromCompactUcan(authorization) {
24840
24989
  actions: [...permission.actions],
24841
24990
  ...permission.caveats === void 0 ? {} : { caveats: permission.caveats }
24842
24991
  }));
24843
- return {
24844
- issuer: payload.iss,
24845
- audience: payload.aud,
24846
- expiry,
24847
- proofs: [...payload.prf],
24848
- ...remainingRedelegationDepth === void 0 ? {} : { remainingRedelegationDepth },
24849
- permissions: canonicalPermissions,
24850
- resources: canonicalResources
24851
- };
24992
+ return { ...signed2, permissions: canonicalPermissions, resources: canonicalResources };
24993
+ }
24994
+ var RAW_ENCRYPTION_PREFIX = "urn:tinycloud:encryption:";
24995
+ var PKH_SPACE = /^tinycloud:pkh:eip155:(\d+):(0x[0-9a-fA-F]{40}):(.+)$/;
24996
+ function comparableSpace(space) {
24997
+ const match = PKH_SPACE.exec(space);
24998
+ return match ? `tinycloud:pkh:eip155:${match[1]}:${match[2].toLowerCase()}:${match[3]}` : space;
24999
+ }
25000
+ function signedAuthorityFromSessionGrant(node, delegation, authorization, cid) {
25001
+ const proof = delegation.siweProof;
25002
+ if (proof === void 0 || proof === null || typeof proof !== "object" || typeof proof.siwe !== "string" || typeof proof.signature !== "string") {
25003
+ reject(
25004
+ "proof_missing",
25005
+ "Runtime delegation is a wallet-signed session grant stored without its signed SIWE proof, so its authority cannot be verified."
25006
+ );
25007
+ }
25008
+ if (typeof node.verifySessionGrant !== "function") {
25009
+ reject("unsupported", "This runtime cannot verify wallet-signed session grants.");
25010
+ }
25011
+ const owner = `did:pkh:eip155:${delegation.chainId}:${delegation.ownerAddress}`;
25012
+ if (typeof node.did !== "string" || !didPrincipalsMatch(owner, node.did)) {
25013
+ reject("owner_mismatch", "Runtime delegation is not signed by this session's owner.");
25014
+ }
25015
+ let verified;
25016
+ try {
25017
+ verified = node.verifySessionGrant({
25018
+ delegationHeader: { Authorization: authorization },
25019
+ delegationCid: cid,
25020
+ spaceId: delegation.spaceId,
25021
+ address: delegation.ownerAddress,
25022
+ chainId: delegation.chainId,
25023
+ siwe: proof.siwe,
25024
+ signature: proof.signature
25025
+ });
25026
+ } catch (error) {
25027
+ reject("proof_invalid", error instanceof Error ? error.message : String(error));
25028
+ }
25029
+ const space = comparableSpace(delegation.spaceId);
25030
+ const spaceOwner = PKH_SPACE.exec(delegation.spaceId);
25031
+ if (!spaceOwner || !didPrincipalsMatch(`did:pkh:eip155:${spaceOwner[1]}:${spaceOwner[2]}`, owner)) {
25032
+ reject("authority_invalid", "Runtime delegation space is not owned by its signer.");
25033
+ }
25034
+ const groups = /* @__PURE__ */ new Map();
25035
+ for (const entry of verified.recap) {
25036
+ const service = entry.service.startsWith("tinycloud.") ? entry.service : `tinycloud.${entry.service}`;
25037
+ const raw = entry.space === "encryption";
25038
+ if (raw) {
25039
+ if (service !== "tinycloud.encryption" || !entry.path.startsWith(RAW_ENCRYPTION_PREFIX)) {
25040
+ reject("authority_invalid", "Runtime delegation has an unsupported signed raw resource.");
25041
+ }
25042
+ const networkOwner = entry.path.slice(RAW_ENCRYPTION_PREFIX.length, entry.path.lastIndexOf(":"));
25043
+ if (!didPrincipalsMatch(networkOwner, owner)) {
25044
+ reject("authority_invalid", "Runtime delegation names an encryption network its signer does not own.");
25045
+ }
25046
+ } else if (service === "tinycloud.encryption" || comparableSpace(entry.space) !== space) {
25047
+ reject("authority_invalid", "Runtime delegation has signed authority outside its space.");
25048
+ }
25049
+ const caveats = signedCaveats(entry.caveats ?? []);
25050
+ const key2 = JSON.stringify([service, raw ? "" : entry.space, entry.path, canonicalizeRecapCaveats2(caveats)]);
25051
+ const group = groups.get(key2) ?? {
25052
+ service,
25053
+ ...raw ? {} : { space: entry.space },
25054
+ path: entry.path,
25055
+ actions: [],
25056
+ ...caveats === void 0 ? {} : { caveats }
25057
+ };
25058
+ for (const action of entry.actions) {
25059
+ if (!group.actions.includes(action)) group.actions.push(action);
25060
+ }
25061
+ groups.set(key2, group);
25062
+ }
25063
+ return canonicalSignedAuthority({
25064
+ issuer: owner,
25065
+ // The verifier bound the SIWE audience to this runtime's own session key.
25066
+ audience: node.sessionDid,
25067
+ expiry: verified.expiresAt,
25068
+ proofs: []
25069
+ }, [...groups.values()]);
24852
25070
  }
24853
25071
  function canonicalResourcesFromPortableDelegation(delegation) {
24854
25072
  if (delegation.resources !== void 0 && delegation.resources.length > 0) {
@@ -24884,46 +25102,58 @@ function resourcesMatch(actual, expected) {
24884
25102
  async function activateValidatedRuntimeDelegation(node, delegation, options) {
24885
25103
  const host = normalizedHost(options.host);
24886
25104
  if (delegation.host !== void 0 && normalizedHost(delegation.host) !== host) {
24887
- throw new Error(
25105
+ reject(
25106
+ "host_mismatch",
24888
25107
  `Runtime delegation host '${delegation.host}' does not match expected host '${options.host}'.`
24889
25108
  );
24890
25109
  }
24891
25110
  if (!(delegation.expiry instanceof Date) || Number.isNaN(delegation.expiry.getTime())) {
24892
- throw new Error("Runtime delegation has an invalid expiry.");
25111
+ reject("authority_invalid", "Runtime delegation has an invalid expiry.");
24893
25112
  }
24894
25113
  if (delegation.expiry.getTime() <= Date.now()) {
24895
- throw new Error("Runtime delegation is expired.");
25114
+ reject("expired", "Runtime delegation is expired.");
24896
25115
  }
24897
25116
  const authorization = delegation.delegationHeader?.Authorization;
24898
25117
  if (typeof authorization !== "string" || authorization.length === 0) {
24899
- throw new Error("Runtime delegation is missing authorization bytes.");
25118
+ reject("authority_invalid", "Runtime delegation is missing authorization bytes.");
24900
25119
  }
24901
25120
  const cid = node.computeDelegationCid(authorization);
24902
25121
  if (cid !== delegation.cid) {
24903
- throw new Error("Runtime delegation CID does not match authorization bytes.");
25122
+ reject("cid_mismatch", "Runtime delegation CID does not match authorization bytes.");
25123
+ }
25124
+ const compact = authorizationWithoutBearer(authorization).split(".").length === 3;
25125
+ let signed2;
25126
+ try {
25127
+ signed2 = compact ? signedAuthorityFromCompactUcan(authorization) : signedAuthorityFromSessionGrant(node, delegation, authorization, cid);
25128
+ } catch (error) {
25129
+ if (error instanceof RuntimeDelegationRejectedError) throw error;
25130
+ reject("authority_invalid", error instanceof Error ? error.message : String(error));
24904
25131
  }
24905
- const signed2 = signedAuthorityFromCompactUcan(authorization);
24906
25132
  if (signed2.expiry.getTime() <= Date.now()) {
24907
- throw new Error("Runtime delegation is expired.");
25133
+ reject("expired", "Runtime delegation is expired.");
24908
25134
  }
24909
25135
  if (delegation.expiry.getTime() !== signed2.expiry.getTime()) {
24910
- throw new Error("Runtime delegation expiry does not match signed authority.");
25136
+ reject("authority_invalid", "Runtime delegation expiry does not match signed authority.");
24911
25137
  }
24912
25138
  if (!didPrincipalsMatch(signed2.audience, node.sessionDid)) {
24913
- throw new Error(
25139
+ reject(
25140
+ "audience_mismatch",
24914
25141
  `Runtime delegation targets ${signed2.audience} but this session is ${node.sessionDid}.`
24915
25142
  );
24916
25143
  }
24917
25144
  if (!didPrincipalsMatch(delegation.delegateDID, signed2.audience)) {
24918
- throw new Error("Runtime delegation audience does not match signed authority.");
25145
+ reject("audience_mismatch", "Runtime delegation audience does not match signed authority.");
24919
25146
  }
24920
- const declaredResources = canonicalResourcesFromPortableDelegation(delegation);
24921
- if (!resourcesMatch(declaredResources, signed2.resources)) {
24922
- throw new Error("Runtime delegation resources do not match signed authority.");
25147
+ if (compact && !resourcesMatch(canonicalResourcesFromPortableDelegation(delegation), signed2.resources)) {
25148
+ reject("resources_mismatch", "Runtime delegation resources do not match signed authority.");
25149
+ }
25150
+ if (options.authorize !== void 0 && !options.authorize(signed2.permissions)) {
25151
+ throw new Error("Runtime delegation is not authorized for this runtime.");
24923
25152
  }
24924
25153
  const previouslyInstalled = node.getRuntimePermissionDelegations().find((candidate) => candidate.cid === cid);
24925
25154
  if (previouslyInstalled !== void 0 && previouslyInstalled.delegationHeader.Authorization !== authorization) {
24926
- throw new Error(
25155
+ reject(
25156
+ "cid_mismatch",
24927
25157
  "A different authorization is already installed for this runtime delegation CID."
24928
25158
  );
24929
25159
  }
@@ -24953,22 +25183,28 @@ async function activateValidatedRuntimeDelegation(node, delegation, options) {
24953
25183
  })),
24954
25184
  expiry: new Date(signed2.expiry),
24955
25185
  delegateDID: signed2.audience,
24956
- host
25186
+ host,
25187
+ ...compact ? {} : { siweProof: delegation.siweProof }
24957
25188
  };
24958
- if (node.isSessionOnly === true && typeof node.did === "string" && principalDidEquals3(node.did, node.sessionDid) && typeof node.useDelegation === "function") {
24959
- await node.useDelegation(installedCandidate);
24960
- } else {
24961
- await node.useRuntimeDelegation(installedCandidate);
25189
+ try {
25190
+ if (node.isSessionOnly === true && typeof node.did === "string" && principalDidEquals3(node.did, node.sessionDid) && typeof node.useDelegation === "function") {
25191
+ await node.useDelegation(installedCandidate);
25192
+ } else {
25193
+ await node.useRuntimeDelegation(installedCandidate);
25194
+ }
25195
+ } catch (error) {
25196
+ reject("activation_rejected", error instanceof Error ? error.message : String(error));
24962
25197
  }
24963
25198
  const installed = node.getRuntimePermissionDelegations().find((candidate) => candidate.cid === cid);
24964
25199
  if (!installed) {
24965
- throw new Error("Runtime delegation activation did not install the validated authority.");
25200
+ reject("activation_rejected", "Runtime delegation activation did not install the validated authority.");
24966
25201
  }
24967
25202
  if (installed.delegationHeader.Authorization !== authorization || !didPrincipalsMatch(installed.delegateDID, signed2.audience) || installed.expiry.getTime() !== signed2.expiry.getTime() || !resourcesMatch(
24968
25203
  canonicalResourcesFromPortableDelegation(installed),
24969
25204
  signed2.resources
24970
25205
  ) || normalizedHost(installed.host ?? "") !== host) {
24971
- throw new Error(
25206
+ reject(
25207
+ "activation_rejected",
24972
25208
  "Runtime delegation activation installed authority that differs from the validated authority."
24973
25209
  );
24974
25210
  }
@@ -25199,9 +25435,13 @@ export {
25199
25435
  PrefixedKVService,
25200
25436
  PrivateKeySigner,
25201
25437
  ProtocolMismatchError,
25438
+ RUNTIME_DELEGATION_REJECTIONS,
25439
+ RuntimeDelegationRejectedError,
25202
25440
  SECRET_NAME_RE,
25203
25441
  SQLAction,
25204
25442
  SQLService3 as SQLService,
25443
+ STORAGE_FULL_MESSAGE2 as STORAGE_FULL_MESSAGE,
25444
+ STORAGE_WRITE_TOO_LARGE_MESSAGE2 as STORAGE_WRITE_TOO_LARGE_MESSAGE,
25205
25445
  SecretsService2 as SecretsService,
25206
25446
  ServiceContext3 as ServiceContext,
25207
25447
  SessionExpiredError2 as SessionExpiredError,
@@ -25277,6 +25517,7 @@ export {
25277
25517
  isCapabilitySubset2 as isCapabilitySubset,
25278
25518
  isEvmAddress,
25279
25519
  isNetworkId,
25520
+ isStorageFullError2 as isStorageFullError,
25280
25521
  loadManifest,
25281
25522
  makePkhSpaceId2 as makePkhSpaceId,
25282
25523
  makePublicSpaceId2 as makePublicSpaceId,