@tinycloud/node-sdk 3.1.0-beta.6 → 3.1.0-beta.8

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
  }
@@ -18738,14 +18742,14 @@ var NodeUserAuthorization = class {
18738
18742
  * Request signature via event emitter with timeout.
18739
18743
  */
18740
18744
  requestSignatureViaEmitter(request, emitter, timeout) {
18741
- return new Promise((resolve, reject) => {
18745
+ return new Promise((resolve, reject2) => {
18742
18746
  const timeoutId = setTimeout(() => {
18743
- reject(new Error("Sign request timed out"));
18747
+ reject2(new Error("Sign request timed out"));
18744
18748
  }, timeout);
18745
18749
  const respond = async (response) => {
18746
18750
  clearTimeout(timeoutId);
18747
18751
  if (!response.approved) {
18748
- reject(
18752
+ reject2(
18749
18753
  new Error(response.reason ?? "Sign request rejected via emitter")
18750
18754
  );
18751
18755
  } else {
@@ -19340,6 +19344,25 @@ function jsonFromVerifier(value) {
19340
19344
  function verifierRecapEntries(entries) {
19341
19345
  return entries.map((entry) => Array.isArray(entry.caveats) ? { ...entry, caveats: entry.caveats.map((caveat) => jsonFromVerifier(caveat)) } : entry);
19342
19346
  }
19347
+ function exactVerifiedRecap(verified) {
19348
+ const exactRecap = Array.isArray(verified.verifiedRecap) ? verifierRecapEntries(verified.verifiedRecap) : verified.verifiedRecap;
19349
+ if (!Array.isArray(exactRecap) || !exactRecap.every(
19350
+ (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(
19351
+ (caveat) => caveat !== null && typeof caveat === "object" && !Array.isArray(caveat)
19352
+ )
19353
+ )) {
19354
+ throw new UnsupportedSessionRestoreError(
19355
+ "it cannot reconstruct caveat-preserving persisted ReCap authority"
19356
+ );
19357
+ }
19358
+ return exactRecap.map((entry) => ({
19359
+ service: entry.service,
19360
+ space: entry.space,
19361
+ path: entry.path,
19362
+ actions: [...entry.actions],
19363
+ caveats: cloneRecapCaveats(entry.caveats)
19364
+ }));
19365
+ }
19343
19366
  var ServiceGraphLifetime = class {
19344
19367
  constructor(invokeFn, invokeAnyFn, fetchFn) {
19345
19368
  this.invokeFn = invokeFn;
@@ -21004,23 +21027,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21004
21027
  throw new InvalidRestoredSessionError(error instanceof Error ? error.message : String(error));
21005
21028
  }
21006
21029
  })();
21007
- const exactRecap = Array.isArray(verified.verifiedRecap) ? verifierRecapEntries(verified.verifiedRecap) : verified.verifiedRecap;
21008
- if (!Array.isArray(exactRecap) || !exactRecap.every(
21009
- (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(
21010
- (caveat) => caveat !== null && typeof caveat === "object" && !Array.isArray(caveat)
21011
- )
21012
- )) {
21013
- throw new UnsupportedSessionRestoreError(
21014
- "it cannot reconstruct caveat-preserving persisted ReCap authority"
21015
- );
21016
- }
21017
- stagedRecap = exactRecap.map((entry) => ({
21018
- service: entry.service,
21019
- space: entry.space,
21020
- path: entry.path,
21021
- actions: [...entry.actions],
21022
- caveats: cloneRecapCaveats(entry.caveats)
21023
- }));
21030
+ stagedRecap = exactVerifiedRecap(verified);
21024
21031
  const signedExpiry = verified.expiresAt === void 0 ? void 0 : persistedExpiry(verified.expiresAt);
21025
21032
  const persistedPolicyExpiry = sessionData.expiresAt === void 0 ? void 0 : persistedExpiry(sessionData.expiresAt);
21026
21033
  if (signedExpiry && persistedPolicyExpiry && !sameInstant(signedExpiry, persistedPolicyExpiry)) {
@@ -22881,6 +22888,42 @@ var _TinyCloudNode = class _TinyCloudNode {
22881
22888
  (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"))
22882
22889
  );
22883
22890
  }
22891
+ /**
22892
+ * Verify a wallet-signed session grant (a CACAO built from a SIWE and its
22893
+ * EIP-191 signature) issued to this instance's live session key. The
22894
+ * verifier rebuilds the CACAO from `siwe` and `signature`, so the grant is
22895
+ * accepted only when its authorization bytes and CID are exactly that CACAO,
22896
+ * its signer is `address`, its audience is this session key, it is valid
22897
+ * now, and its ReCap covers `spaceId` or names only raw encryption networks
22898
+ * (a decrypt-only grant has no space). Returns the signed ReCap and expiry.
22899
+ * Bindings without `validateSessionGrant` fall back to the session verifier,
22900
+ * which also refuses decrypt-only grants.
22901
+ */
22902
+ verifySessionGrant(grant) {
22903
+ const bindings = this.wasmBindings;
22904
+ const validate5 = typeof bindings.validateSessionGrant === "function" ? bindings.validateSessionGrant.bind(bindings) : bindings.validatePersistedSession?.bind(bindings);
22905
+ if (validate5 === void 0) {
22906
+ throw new UnsupportedSessionRestoreError("it cannot verify persisted SIWE authority");
22907
+ }
22908
+ const verified = validate5({
22909
+ delegationHeader: { Authorization: grant.delegationHeader.Authorization },
22910
+ delegationCid: grant.delegationCid,
22911
+ spaceId: grant.spaceId,
22912
+ jwk: this.sessionKeyJwk,
22913
+ address: canonicalizeAddress2(grant.address),
22914
+ chainId: grant.chainId,
22915
+ siwe: grant.siwe,
22916
+ signature: grant.signature
22917
+ });
22918
+ if (typeof verified.expiresAt !== "string") {
22919
+ throw new Error("Session grant has no signed expiry.");
22920
+ }
22921
+ const expiresAt = new Date(verified.expiresAt);
22922
+ if (!Number.isFinite(expiresAt.getTime())) {
22923
+ throw new Error("Session grant has an invalid signed expiry.");
22924
+ }
22925
+ return { recap: exactVerifiedRecap(verified), expiresAt };
22926
+ }
22884
22927
  /**
22885
22928
  * Install a portable runtime permission delegation into this SDK instance so
22886
22929
  * matching service calls and downstream `delegateTo()` calls can use it.
@@ -23013,7 +23056,8 @@ var _TinyCloudNode = class _TinyCloudNode {
23013
23056
  delegatedEntries,
23014
23057
  spaceId,
23015
23058
  session,
23016
- expiresAt
23059
+ expiresAt,
23060
+ { siwe: prepared.siwe, signature: signature2 }
23017
23061
  );
23018
23062
  this.runtimePermissionGrants.push({
23019
23063
  session: {
@@ -23799,7 +23843,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23799
23843
  }
23800
23844
  return grants;
23801
23845
  }
23802
- runtimeDelegationFromSession(delegatedSession, entries, spaceId, session, expiresAt) {
23846
+ runtimeDelegationFromSession(delegatedSession, entries, spaceId, session, expiresAt, siweProof) {
23803
23847
  const resources = this.delegatedResourcesForEntries(entries, spaceId);
23804
23848
  const primary = resources[0];
23805
23849
  return {
@@ -23814,7 +23858,8 @@ var _TinyCloudNode = class _TinyCloudNode {
23814
23858
  delegateDID: session.verificationMethod,
23815
23859
  ownerAddress: session.address,
23816
23860
  chainId: session.chainId,
23817
- host: this.config.host
23861
+ host: this.config.host,
23862
+ siweProof
23818
23863
  };
23819
23864
  }
23820
23865
  runtimeGrantFromDelegation(delegation, session) {
@@ -24737,6 +24782,29 @@ import {
24737
24782
  decodeBase64Url,
24738
24783
  principalDidEquals as principalDidEquals3
24739
24784
  } from "@tinycloud/sdk-core";
24785
+ var RUNTIME_DELEGATION_REJECTIONS = [
24786
+ "host_mismatch",
24787
+ "expired",
24788
+ "cid_mismatch",
24789
+ "authority_invalid",
24790
+ "proof_missing",
24791
+ "proof_invalid",
24792
+ "owner_mismatch",
24793
+ "audience_mismatch",
24794
+ "resources_mismatch",
24795
+ "unsupported",
24796
+ "activation_rejected"
24797
+ ];
24798
+ var RuntimeDelegationRejectedError = class extends Error {
24799
+ constructor(reason, message) {
24800
+ super(message);
24801
+ this.name = "RuntimeDelegationRejectedError";
24802
+ this.reason = reason;
24803
+ }
24804
+ };
24805
+ function reject(reason, message) {
24806
+ throw new RuntimeDelegationRejectedError(reason, message);
24807
+ }
24740
24808
  var SERVICE_BY_SHORT_NAME = {
24741
24809
  kv: "tinycloud.kv",
24742
24810
  sql: "tinycloud.sql",
@@ -24883,6 +24951,15 @@ function signedAuthorityFromCompactUcan(authorization) {
24883
24951
  abilities
24884
24952
  ));
24885
24953
  }
24954
+ return canonicalSignedAuthority({
24955
+ issuer: payload.iss,
24956
+ audience: payload.aud,
24957
+ expiry,
24958
+ proofs: [...payload.prf],
24959
+ ...remainingRedelegationDepth === void 0 ? {} : { remainingRedelegationDepth }
24960
+ }, permissions);
24961
+ }
24962
+ function canonicalSignedAuthority(signed2, permissions) {
24886
24963
  if (permissions.length === 0) {
24887
24964
  throw new Error("Validated runtime delegation has no signed capabilities.");
24888
24965
  }
@@ -24894,15 +24971,84 @@ function signedAuthorityFromCompactUcan(authorization) {
24894
24971
  actions: [...permission.actions],
24895
24972
  ...permission.caveats === void 0 ? {} : { caveats: permission.caveats }
24896
24973
  }));
24897
- return {
24898
- issuer: payload.iss,
24899
- audience: payload.aud,
24900
- expiry,
24901
- proofs: [...payload.prf],
24902
- ...remainingRedelegationDepth === void 0 ? {} : { remainingRedelegationDepth },
24903
- permissions: canonicalPermissions,
24904
- resources: canonicalResources
24905
- };
24974
+ return { ...signed2, permissions: canonicalPermissions, resources: canonicalResources };
24975
+ }
24976
+ var RAW_ENCRYPTION_PREFIX = "urn:tinycloud:encryption:";
24977
+ var PKH_SPACE = /^tinycloud:pkh:eip155:(\d+):(0x[0-9a-fA-F]{40}):(.+)$/;
24978
+ function comparableSpace(space) {
24979
+ const match = PKH_SPACE.exec(space);
24980
+ return match ? `tinycloud:pkh:eip155:${match[1]}:${match[2].toLowerCase()}:${match[3]}` : space;
24981
+ }
24982
+ function signedAuthorityFromSessionGrant(node, delegation, authorization, cid) {
24983
+ const proof = delegation.siweProof;
24984
+ if (proof === void 0 || proof === null || typeof proof !== "object" || typeof proof.siwe !== "string" || typeof proof.signature !== "string") {
24985
+ reject(
24986
+ "proof_missing",
24987
+ "Runtime delegation is a wallet-signed session grant stored without its signed SIWE proof, so its authority cannot be verified."
24988
+ );
24989
+ }
24990
+ if (typeof node.verifySessionGrant !== "function") {
24991
+ reject("unsupported", "This runtime cannot verify wallet-signed session grants.");
24992
+ }
24993
+ const owner = `did:pkh:eip155:${delegation.chainId}:${delegation.ownerAddress}`;
24994
+ if (typeof node.did !== "string" || !didPrincipalsMatch(owner, node.did)) {
24995
+ reject("owner_mismatch", "Runtime delegation is not signed by this session's owner.");
24996
+ }
24997
+ let verified;
24998
+ try {
24999
+ verified = node.verifySessionGrant({
25000
+ delegationHeader: { Authorization: authorization },
25001
+ delegationCid: cid,
25002
+ spaceId: delegation.spaceId,
25003
+ address: delegation.ownerAddress,
25004
+ chainId: delegation.chainId,
25005
+ siwe: proof.siwe,
25006
+ signature: proof.signature
25007
+ });
25008
+ } catch (error) {
25009
+ reject("proof_invalid", error instanceof Error ? error.message : String(error));
25010
+ }
25011
+ const space = comparableSpace(delegation.spaceId);
25012
+ const spaceOwner = PKH_SPACE.exec(delegation.spaceId);
25013
+ if (!spaceOwner || !didPrincipalsMatch(`did:pkh:eip155:${spaceOwner[1]}:${spaceOwner[2]}`, owner)) {
25014
+ reject("authority_invalid", "Runtime delegation space is not owned by its signer.");
25015
+ }
25016
+ const groups = /* @__PURE__ */ new Map();
25017
+ for (const entry of verified.recap) {
25018
+ const service = entry.service.startsWith("tinycloud.") ? entry.service : `tinycloud.${entry.service}`;
25019
+ const raw = entry.space === "encryption";
25020
+ if (raw) {
25021
+ if (service !== "tinycloud.encryption" || !entry.path.startsWith(RAW_ENCRYPTION_PREFIX)) {
25022
+ reject("authority_invalid", "Runtime delegation has an unsupported signed raw resource.");
25023
+ }
25024
+ const networkOwner = entry.path.slice(RAW_ENCRYPTION_PREFIX.length, entry.path.lastIndexOf(":"));
25025
+ if (!didPrincipalsMatch(networkOwner, owner)) {
25026
+ reject("authority_invalid", "Runtime delegation names an encryption network its signer does not own.");
25027
+ }
25028
+ } else if (service === "tinycloud.encryption" || comparableSpace(entry.space) !== space) {
25029
+ reject("authority_invalid", "Runtime delegation has signed authority outside its space.");
25030
+ }
25031
+ const caveats = signedCaveats(entry.caveats ?? []);
25032
+ const key2 = JSON.stringify([service, raw ? "" : entry.space, entry.path, canonicalizeRecapCaveats2(caveats)]);
25033
+ const group = groups.get(key2) ?? {
25034
+ service,
25035
+ ...raw ? {} : { space: entry.space },
25036
+ path: entry.path,
25037
+ actions: [],
25038
+ ...caveats === void 0 ? {} : { caveats }
25039
+ };
25040
+ for (const action of entry.actions) {
25041
+ if (!group.actions.includes(action)) group.actions.push(action);
25042
+ }
25043
+ groups.set(key2, group);
25044
+ }
25045
+ return canonicalSignedAuthority({
25046
+ issuer: owner,
25047
+ // The verifier bound the SIWE audience to this runtime's own session key.
25048
+ audience: node.sessionDid,
25049
+ expiry: verified.expiresAt,
25050
+ proofs: []
25051
+ }, [...groups.values()]);
24906
25052
  }
24907
25053
  function canonicalResourcesFromPortableDelegation(delegation) {
24908
25054
  if (delegation.resources !== void 0 && delegation.resources.length > 0) {
@@ -24938,49 +25084,58 @@ function resourcesMatch(actual, expected) {
24938
25084
  async function activateValidatedRuntimeDelegation(node, delegation, options) {
24939
25085
  const host = normalizedHost(options.host);
24940
25086
  if (delegation.host !== void 0 && normalizedHost(delegation.host) !== host) {
24941
- throw new Error(
25087
+ reject(
25088
+ "host_mismatch",
24942
25089
  `Runtime delegation host '${delegation.host}' does not match expected host '${options.host}'.`
24943
25090
  );
24944
25091
  }
24945
25092
  if (!(delegation.expiry instanceof Date) || Number.isNaN(delegation.expiry.getTime())) {
24946
- throw new Error("Runtime delegation has an invalid expiry.");
25093
+ reject("authority_invalid", "Runtime delegation has an invalid expiry.");
24947
25094
  }
24948
25095
  if (delegation.expiry.getTime() <= Date.now()) {
24949
- throw new Error("Runtime delegation is expired.");
25096
+ reject("expired", "Runtime delegation is expired.");
24950
25097
  }
24951
25098
  const authorization = delegation.delegationHeader?.Authorization;
24952
25099
  if (typeof authorization !== "string" || authorization.length === 0) {
24953
- throw new Error("Runtime delegation is missing authorization bytes.");
25100
+ reject("authority_invalid", "Runtime delegation is missing authorization bytes.");
24954
25101
  }
24955
25102
  const cid = node.computeDelegationCid(authorization);
24956
25103
  if (cid !== delegation.cid) {
24957
- throw new Error("Runtime delegation CID does not match authorization bytes.");
25104
+ reject("cid_mismatch", "Runtime delegation CID does not match authorization bytes.");
25105
+ }
25106
+ const compact = authorizationWithoutBearer(authorization).split(".").length === 3;
25107
+ let signed2;
25108
+ try {
25109
+ signed2 = compact ? signedAuthorityFromCompactUcan(authorization) : signedAuthorityFromSessionGrant(node, delegation, authorization, cid);
25110
+ } catch (error) {
25111
+ if (error instanceof RuntimeDelegationRejectedError) throw error;
25112
+ reject("authority_invalid", error instanceof Error ? error.message : String(error));
24958
25113
  }
24959
- const signed2 = signedAuthorityFromCompactUcan(authorization);
24960
25114
  if (signed2.expiry.getTime() <= Date.now()) {
24961
- throw new Error("Runtime delegation is expired.");
25115
+ reject("expired", "Runtime delegation is expired.");
24962
25116
  }
24963
25117
  if (delegation.expiry.getTime() !== signed2.expiry.getTime()) {
24964
- throw new Error("Runtime delegation expiry does not match signed authority.");
25118
+ reject("authority_invalid", "Runtime delegation expiry does not match signed authority.");
24965
25119
  }
24966
25120
  if (!didPrincipalsMatch(signed2.audience, node.sessionDid)) {
24967
- throw new Error(
25121
+ reject(
25122
+ "audience_mismatch",
24968
25123
  `Runtime delegation targets ${signed2.audience} but this session is ${node.sessionDid}.`
24969
25124
  );
24970
25125
  }
24971
25126
  if (!didPrincipalsMatch(delegation.delegateDID, signed2.audience)) {
24972
- throw new Error("Runtime delegation audience does not match signed authority.");
25127
+ reject("audience_mismatch", "Runtime delegation audience does not match signed authority.");
24973
25128
  }
24974
- const declaredResources = canonicalResourcesFromPortableDelegation(delegation);
24975
- if (!resourcesMatch(declaredResources, signed2.resources)) {
24976
- throw new Error("Runtime delegation resources do not match signed authority.");
25129
+ if (compact && !resourcesMatch(canonicalResourcesFromPortableDelegation(delegation), signed2.resources)) {
25130
+ reject("resources_mismatch", "Runtime delegation resources do not match signed authority.");
24977
25131
  }
24978
25132
  if (options.authorize !== void 0 && !options.authorize(signed2.permissions)) {
24979
25133
  throw new Error("Runtime delegation is not authorized for this runtime.");
24980
25134
  }
24981
25135
  const previouslyInstalled = node.getRuntimePermissionDelegations().find((candidate) => candidate.cid === cid);
24982
25136
  if (previouslyInstalled !== void 0 && previouslyInstalled.delegationHeader.Authorization !== authorization) {
24983
- throw new Error(
25137
+ reject(
25138
+ "cid_mismatch",
24984
25139
  "A different authorization is already installed for this runtime delegation CID."
24985
25140
  );
24986
25141
  }
@@ -25010,22 +25165,28 @@ async function activateValidatedRuntimeDelegation(node, delegation, options) {
25010
25165
  })),
25011
25166
  expiry: new Date(signed2.expiry),
25012
25167
  delegateDID: signed2.audience,
25013
- host
25168
+ host,
25169
+ ...compact ? {} : { siweProof: delegation.siweProof }
25014
25170
  };
25015
- if (node.isSessionOnly === true && typeof node.did === "string" && principalDidEquals3(node.did, node.sessionDid) && typeof node.useDelegation === "function") {
25016
- await node.useDelegation(installedCandidate);
25017
- } else {
25018
- await node.useRuntimeDelegation(installedCandidate);
25171
+ try {
25172
+ if (node.isSessionOnly === true && typeof node.did === "string" && principalDidEquals3(node.did, node.sessionDid) && typeof node.useDelegation === "function") {
25173
+ await node.useDelegation(installedCandidate);
25174
+ } else {
25175
+ await node.useRuntimeDelegation(installedCandidate);
25176
+ }
25177
+ } catch (error) {
25178
+ reject("activation_rejected", error instanceof Error ? error.message : String(error));
25019
25179
  }
25020
25180
  const installed = node.getRuntimePermissionDelegations().find((candidate) => candidate.cid === cid);
25021
25181
  if (!installed) {
25022
- throw new Error("Runtime delegation activation did not install the validated authority.");
25182
+ reject("activation_rejected", "Runtime delegation activation did not install the validated authority.");
25023
25183
  }
25024
25184
  if (installed.delegationHeader.Authorization !== authorization || !didPrincipalsMatch(installed.delegateDID, signed2.audience) || installed.expiry.getTime() !== signed2.expiry.getTime() || !resourcesMatch(
25025
25185
  canonicalResourcesFromPortableDelegation(installed),
25026
25186
  signed2.resources
25027
25187
  ) || normalizedHost(installed.host ?? "") !== host) {
25028
- throw new Error(
25188
+ reject(
25189
+ "activation_rejected",
25029
25190
  "Runtime delegation activation installed authority that differs from the validated authority."
25030
25191
  );
25031
25192
  }
@@ -25256,6 +25417,8 @@ export {
25256
25417
  PrefixedKVService,
25257
25418
  PrivateKeySigner,
25258
25419
  ProtocolMismatchError,
25420
+ RUNTIME_DELEGATION_REJECTIONS,
25421
+ RuntimeDelegationRejectedError,
25259
25422
  SECRET_NAME_RE,
25260
25423
  SQLAction,
25261
25424
  SQLService3 as SQLService,