@tinycloud/node-sdk 3.8.0-beta.7 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +6 -0
  2. package/dist/{TinyCloudNode-jPL2UqH5.d.ts → TinyCloudNode-DaD5vJhL.d.cts} +38 -5
  3. package/dist/{TinyCloudNode-C0LgPzzJ.d.cts → TinyCloudNode-k3TbBwwj.d.ts} +38 -5
  4. package/dist/{WasmKeyProvider-5Ee7fcAw.d.cts → WasmKeyProvider-BKCPRC-c.d.cts} +21 -1
  5. package/dist/{WasmKeyProvider-5Ee7fcAw.d.ts → WasmKeyProvider-BKCPRC-c.d.ts} +21 -1
  6. package/dist/{authority-DvHTgPC4.d.ts → authority-C_fWaxAu.d.ts} +1 -1
  7. package/dist/{authority-Dkhr6n-f.d.cts → authority-DJdbZM6k.d.cts} +1 -1
  8. package/dist/core.cjs +238 -29
  9. package/dist/core.cjs.map +1 -1
  10. package/dist/core.d.cts +4 -4
  11. package/dist/core.d.ts +4 -4
  12. package/dist/core.js +239 -30
  13. package/dist/core.js.map +1 -1
  14. package/dist/credentials-core.d.cts +1 -1
  15. package/dist/credentials-core.d.ts +1 -1
  16. package/dist/credentials.d.cts +1 -1
  17. package/dist/credentials.d.ts +1 -1
  18. package/dist/{delegation-0LKZkmP2.d.cts → delegation-Ckc3UETl.d.cts} +1 -1
  19. package/dist/{delegation-0LKZkmP2.d.ts → delegation-Ckc3UETl.d.ts} +1 -1
  20. package/dist/encryption-keys.d.cts +2 -2
  21. package/dist/encryption-keys.d.ts +2 -2
  22. package/dist/index.cjs +194 -30
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +3 -3
  25. package/dist/index.d.ts +3 -3
  26. package/dist/index.js +199 -32
  27. package/dist/index.js.map +1 -1
  28. package/dist/replication/authority.cjs +3 -0
  29. package/dist/replication/authority.cjs.map +1 -1
  30. package/dist/replication/authority.d.cts +3 -3
  31. package/dist/replication/authority.d.ts +3 -3
  32. package/dist/replication/authority.js +3 -0
  33. package/dist/replication/authority.js.map +1 -1
  34. package/dist/replication/runtime.cjs +1 -0
  35. package/dist/replication/runtime.cjs.map +1 -1
  36. package/dist/replication/runtime.js +1 -0
  37. package/dist/replication/runtime.js.map +1 -1
  38. package/dist/share-receive.cjs +775 -0
  39. package/dist/share-receive.cjs.map +1 -0
  40. package/dist/share-receive.d.cts +32 -0
  41. package/dist/share-receive.d.ts +32 -0
  42. package/dist/share-receive.js +777 -0
  43. package/dist/share-receive.js.map +1 -0
  44. package/package.json +11 -4
@@ -1,5 +1,5 @@
1
1
  import { CredentialFlowDescriptor, CredentialRequirement, CredentialHolderBinding, IssuedCredentialEnvelope, CredentialIssuerMetadata, ClientSession, IKVService, StoredCredentialRecord, VerifiedCredential, CredentialProgressEvent, CredentialStorageReceipt, UnifiedPolicyV2, UnifiedPolicyCapability, PolicyCredentialAdmissionV3 } from '@tinycloud/sdk-core';
2
- import { V as ValidatedRuntimeDelegation } from './delegation-0LKZkmP2.cjs';
2
+ import { V as ValidatedRuntimeDelegation } from './delegation-Ckc3UETl.cjs';
3
3
 
4
4
  interface CredentialClient {
5
5
  readonly sessionDid: string;
@@ -1,5 +1,5 @@
1
1
  import { CredentialFlowDescriptor, CredentialRequirement, CredentialHolderBinding, IssuedCredentialEnvelope, CredentialIssuerMetadata, ClientSession, IKVService, StoredCredentialRecord, VerifiedCredential, CredentialProgressEvent, CredentialStorageReceipt, UnifiedPolicyV2, UnifiedPolicyCapability, PolicyCredentialAdmissionV3 } from '@tinycloud/sdk-core';
2
- import { V as ValidatedRuntimeDelegation } from './delegation-0LKZkmP2.js';
2
+ import { V as ValidatedRuntimeDelegation } from './delegation-Ckc3UETl.js';
3
3
 
4
4
  interface CredentialClient {
5
5
  readonly sessionDid: string;
@@ -1,4 +1,4 @@
1
1
  export { CredentialAcquisitionTheme, CredentialAcquisitionTransport, CredentialBrowserInteractionAdapter, CredentialClient, CredentialInlineInteractionAdapter, CredentialInputRequest, CredentialInteractionAdapter, CredentialInteractionKind, CredentialInteractionSurface, CredentialProofSubject, CredentialRedirectResumeState, CredentialRedirectStore, CredentialRequestState, CredentialSigningAdapter, CredentialsAcquireOptions, CredentialsEnsureOptions, CredentialsEnsureResult, CredentialsOperationOptions, CredentialsPolicyAdmissionOptions, CredentialsPolicyAdmissionResult, HolderSignatureKey, InlineCredentialProofHandler, InlineCredentialProofRequest, OpenCredentialsHttpTransport, PrimitiveStepHandler, PrimitiveStepResult, ReceiverCredentialCustody, interpretCredentialFlow, mailboxSubject } from './credentials-core.cjs';
2
2
  export { D as DEFAULT_EMAIL_PROOF_PROFILE, E as EMAIL_PROOF_CREDENTIAL_TYPE, a as EMAIL_PROOF_PENDING_MAX_MS, b as EmailProofAcquireInput, c as EmailProofAcquisition, d as EmailProofError, e as EmailProofErrorCode, f as EmailProofOptions, g as EmailProofPending, h as EmailProofPendingStore, i as EmailProofProfileId, j as EmailProofRequestInput, k as EmailProofResult, l as EmailProofStep, H as HolderAlgorithm, m as HolderSigner, S as StoredEmailProofInput, n as StoredEmailProofRecord, o as acquireEmailProof, p as completeEmailProof, q as createEd25519HolderSigner, r as createMemoryEmailProofPendingStore, s as emailProofRequirement, t as requestEmailProofCode, v as verifyStoredEmailProof } from './email-proof-GXXQhIff.cjs';
3
3
  import '@tinycloud/sdk-core';
4
- import './delegation-0LKZkmP2.cjs';
4
+ import './delegation-Ckc3UETl.cjs';
@@ -1,4 +1,4 @@
1
1
  export { CredentialAcquisitionTheme, CredentialAcquisitionTransport, CredentialBrowserInteractionAdapter, CredentialClient, CredentialInlineInteractionAdapter, CredentialInputRequest, CredentialInteractionAdapter, CredentialInteractionKind, CredentialInteractionSurface, CredentialProofSubject, CredentialRedirectResumeState, CredentialRedirectStore, CredentialRequestState, CredentialSigningAdapter, CredentialsAcquireOptions, CredentialsEnsureOptions, CredentialsEnsureResult, CredentialsOperationOptions, CredentialsPolicyAdmissionOptions, CredentialsPolicyAdmissionResult, HolderSignatureKey, InlineCredentialProofHandler, InlineCredentialProofRequest, OpenCredentialsHttpTransport, PrimitiveStepHandler, PrimitiveStepResult, ReceiverCredentialCustody, interpretCredentialFlow, mailboxSubject } from './credentials-core.js';
2
2
  export { D as DEFAULT_EMAIL_PROOF_PROFILE, E as EMAIL_PROOF_CREDENTIAL_TYPE, a as EMAIL_PROOF_PENDING_MAX_MS, b as EmailProofAcquireInput, c as EmailProofAcquisition, d as EmailProofError, e as EmailProofErrorCode, f as EmailProofOptions, g as EmailProofPending, h as EmailProofPendingStore, i as EmailProofProfileId, j as EmailProofRequestInput, k as EmailProofResult, l as EmailProofStep, H as HolderAlgorithm, m as HolderSigner, S as StoredEmailProofInput, n as StoredEmailProofRecord, o as acquireEmailProof, p as completeEmailProof, q as createEd25519HolderSigner, r as createMemoryEmailProofPendingStore, s as emailProofRequirement, t as requestEmailProofCode, v as verifyStoredEmailProof } from './email-proof-GXXQhIff.js';
3
3
  import '@tinycloud/sdk-core';
4
- import './delegation-0LKZkmP2.js';
4
+ import './delegation-Ckc3UETl.js';
@@ -248,4 +248,4 @@ declare function serializeDelegation(delegation: PortableDelegation): string;
248
248
  */
249
249
  declare function deserializeDelegation(data: string): PortableDelegation;
250
250
 
251
- export { type AuthDelegationArtifact as A, type CompactRuntimeDelegationInput as C, type DelegationAuthority as D, type PortableDelegation as P, RUNTIME_DELEGATION_REJECTIONS as R, type SessionGrantProof as S, type ValidatedRuntimeDelegation as V, activateCompactRuntimeDelegation as a, type AuthRequestArtifact as b, type RuntimeDelegationActivator as c, deserializeDelegation as d, RuntimeDelegationRejectedError as e, type RuntimeDelegationRejection as f, type VerifiedSessionGrant as g, activateValidatedRuntimeDelegation as h, grantAuthRequest as i, signedCompactUcanExpiry as j, siweRuntimeDelegation as k, serializeDelegation as s };
251
+ export { type AuthDelegationArtifact as A, type CompactRuntimeDelegationInput as C, type DelegationAuthority as D, type PortableDelegation as P, RuntimeDelegationRejectedError as R, type SessionGrantProof as S, type ValidatedRuntimeDelegation as V, type RuntimeDelegationRejection as a, activateCompactRuntimeDelegation as b, activateValidatedRuntimeDelegation as c, deserializeDelegation as d, type AuthRequestArtifact as e, RUNTIME_DELEGATION_REJECTIONS as f, type RuntimeDelegationActivator as g, type VerifiedSessionGrant as h, grantAuthRequest as i, signedCompactUcanExpiry as j, siweRuntimeDelegation as k, serializeDelegation as s };
@@ -248,4 +248,4 @@ declare function serializeDelegation(delegation: PortableDelegation): string;
248
248
  */
249
249
  declare function deserializeDelegation(data: string): PortableDelegation;
250
250
 
251
- export { type AuthDelegationArtifact as A, type CompactRuntimeDelegationInput as C, type DelegationAuthority as D, type PortableDelegation as P, RUNTIME_DELEGATION_REJECTIONS as R, type SessionGrantProof as S, type ValidatedRuntimeDelegation as V, activateCompactRuntimeDelegation as a, type AuthRequestArtifact as b, type RuntimeDelegationActivator as c, deserializeDelegation as d, RuntimeDelegationRejectedError as e, type RuntimeDelegationRejection as f, type VerifiedSessionGrant as g, activateValidatedRuntimeDelegation as h, grantAuthRequest as i, signedCompactUcanExpiry as j, siweRuntimeDelegation as k, serializeDelegation as s };
251
+ export { type AuthDelegationArtifact as A, type CompactRuntimeDelegationInput as C, type DelegationAuthority as D, type PortableDelegation as P, RuntimeDelegationRejectedError as R, type SessionGrantProof as S, type ValidatedRuntimeDelegation as V, type RuntimeDelegationRejection as a, activateCompactRuntimeDelegation as b, activateValidatedRuntimeDelegation as c, deserializeDelegation as d, type AuthRequestArtifact as e, RUNTIME_DELEGATION_REJECTIONS as f, type RuntimeDelegationActivator as g, type VerifiedSessionGrant as h, grantAuthRequest as i, signedCompactUcanExpiry as j, siweRuntimeDelegation as k, serializeDelegation as s };
@@ -1,11 +1,11 @@
1
1
  import { NamedKeyClient } from '@tinycloud/sdk-services/encryption/named-keys';
2
2
  export { DecryptManyResult, KeyCallOptions, KeyDescriptor, KeyEncryptOptions, NamedKeyClient, NamedKeyEnvelope, NamedKeyError, NamedKeyErrorCode, PublicKeyDescriptor, buildKeyAdminFacts, buildKeyDescribeFacts } from '@tinycloud/sdk-services/encryption/named-keys';
3
- import { T as TinyCloudNode } from './TinyCloudNode-C0LgPzzJ.cjs';
3
+ import { T as TinyCloudNode } from './TinyCloudNode-DaD5vJhL.cjs';
4
4
  import '@tinycloud/sdk-core';
5
5
  import '@tinycloud/sdk-services/kv/replication';
6
6
  import '@tinycloud/sdk-services';
7
7
  import 'events';
8
- import './delegation-0LKZkmP2.cjs';
8
+ import './delegation-Ckc3UETl.cjs';
9
9
 
10
10
  /**
11
11
  * Named encryption keys for a signed-in {@link TinyCloudNode}.
@@ -1,11 +1,11 @@
1
1
  import { NamedKeyClient } from '@tinycloud/sdk-services/encryption/named-keys';
2
2
  export { DecryptManyResult, KeyCallOptions, KeyDescriptor, KeyEncryptOptions, NamedKeyClient, NamedKeyEnvelope, NamedKeyError, NamedKeyErrorCode, PublicKeyDescriptor, buildKeyAdminFacts, buildKeyDescribeFacts } from '@tinycloud/sdk-services/encryption/named-keys';
3
- import { T as TinyCloudNode } from './TinyCloudNode-jPL2UqH5.js';
3
+ import { T as TinyCloudNode } from './TinyCloudNode-k3TbBwwj.js';
4
4
  import '@tinycloud/sdk-core';
5
5
  import '@tinycloud/sdk-services/kv/replication';
6
6
  import '@tinycloud/sdk-services';
7
7
  import 'events';
8
- import './delegation-0LKZkmP2.js';
8
+ import './delegation-Ckc3UETl.js';
9
9
 
10
10
  /**
11
11
  * Named encryption keys for a signed-in {@link TinyCloudNode}.
package/dist/index.cjs CHANGED
@@ -17089,6 +17089,9 @@ function assertValidReplicationConfig(replication) {
17089
17089
  if (replication?.syncScope !== void 0 && replication.syncScope !== "prefixes") {
17090
17090
  throw new TypeError('replication.syncScope must be "prefixes"');
17091
17091
  }
17092
+ if (replication?.contentFetch !== void 0 && replication.contentFetch !== "eager" && replication.contentFetch !== "lazy") {
17093
+ throw new TypeError('replication.contentFetch must be "eager" or "lazy"');
17094
+ }
17092
17095
  if (replication === void 0 || !replication.enabled) return;
17093
17096
  if (replication.storage === void 0 || replication.storage === null) {
17094
17097
  throw new TypeError("replication.enabled requires replication.storage");
@@ -17143,6 +17146,7 @@ function resolvedOptions(options) {
17143
17146
  maxStalenessMs: options.maxStalenessMs ?? 12e4,
17144
17147
  staleSyncTimeoutMs: options.staleSyncTimeoutMs ?? 5e3,
17145
17148
  allowSecrets: options.allowSecrets === true,
17149
+ contentFetch: options.contentFetch ?? "eager",
17146
17150
  verify: options.verify === true
17147
17151
  };
17148
17152
  }
@@ -17964,6 +17968,7 @@ __export(src_exports, {
17964
17968
  hexDecode: () => import_sdk_core22.hexDecode,
17965
17969
  hexEncode: () => import_sdk_core22.hexEncode,
17966
17970
  installTinyCloudDebugGlobals: () => import_sdk_core16.installTinyCloudDebugGlobals,
17971
+ isAppKeyHostBound: () => isAppKeyHostBound,
17967
17972
  isCapabilitySubset: () => import_sdk_core17.isCapabilitySubset,
17968
17973
  isEvmAddress: () => import_sdk_core16.isEvmAddress,
17969
17974
  isNetworkId: () => import_sdk_core22.isNetworkId,
@@ -18809,6 +18814,7 @@ function deserializeDelegation(data) {
18809
18814
 
18810
18815
  // src/TinyCloudNode.ts
18811
18816
  var import_siwe2 = require("siwe");
18817
+ var import_share_envelope = require("@tinycloud/share-envelope");
18812
18818
 
18813
18819
  // src/replication/module-registry.ts
18814
18820
  var nodeLoaders;
@@ -18858,6 +18864,18 @@ function appKeyHostBinding(domain, appId) {
18858
18864
  const reversed = labels.reverse().join(".");
18859
18865
  return appId === reversed || appId.startsWith(`${reversed}.`);
18860
18866
  }
18867
+ function isAppKeyHostBound(keysAppId, origin) {
18868
+ if (typeof origin === "string" && !origin.includes("://")) {
18869
+ return appKeyHostBinding(origin, keysAppId);
18870
+ }
18871
+ let url;
18872
+ try {
18873
+ url = typeof origin === "string" ? new URL(origin) : origin;
18874
+ } catch {
18875
+ return false;
18876
+ }
18877
+ return appKeyHostBinding(url.host, keysAppId);
18878
+ }
18861
18879
 
18862
18880
  // src/authorization/NodeUserAuthorization.ts
18863
18881
  init_authority_sign_in();
@@ -19015,6 +19033,7 @@ function cloneAbilitiesMap(actions) {
19015
19033
  var NodeUserAuthorization = class {
19016
19034
  constructor(config) {
19017
19035
  this.activeSessionKeyId = "default";
19036
+ this.preparedSessionCounter = 0;
19018
19037
  /** Incremented by resetSession; a sign-in started earlier publishes nothing. */
19019
19038
  this.sessionGeneration = 0;
19020
19039
  /**
@@ -19597,7 +19616,8 @@ var NodeUserAuthorization = class {
19597
19616
  return true;
19598
19617
  }
19599
19618
  const parsed = entry.path.includes("/") ? (0, import_resource.parseEncryptionResource)(entry.path) : { ...(0, import_sdk_services3.parseNetworkId)(entry.path), kind: "network" };
19600
- if (parsed.kind !== "network") {
19619
+ const sharePrefix = parsed.kind === "prefix" && parsed.network === "default" && parsed.prefix === "share" && entry.actions.length === 1 && entry.actions[0] === DECRYPT_ACTION && didPrincipalMatches(parsed.ownerDid, currentDid);
19620
+ if (parsed.kind !== "network" && !sharePrefix) {
19601
19621
  throw new import_sdk_core5.ManifestValidationError("named keys go in manifest.keys");
19602
19622
  }
19603
19623
  for (const action of entry.actions) {
@@ -19640,8 +19660,7 @@ var NodeUserAuthorization = class {
19640
19660
  /**
19641
19661
  * Build SIWE overrides from the top-level nonce and siweConfig.
19642
19662
  * - Top-level `nonce` is seeded first so `siweConfig.nonce` wins if both are set.
19643
- * - statement is prepended to the default statement
19644
- * - resources are appended to the default resources
19663
+ * - resources are inserted after WASM preparation, before the final ReCap
19645
19664
  * - uri triggers a warning (overwriting delegation target)
19646
19665
  * - all other fields override directly
19647
19666
  * - per-call nonce overrides siweConfig.nonce when provided
@@ -19659,9 +19678,6 @@ var NodeUserAuthorization = class {
19659
19678
  if (statement) {
19660
19679
  overrides.statement = this.statement ? `${statement} ${this.statement}` : statement;
19661
19680
  }
19662
- if (resources && resources.length > 0) {
19663
- overrides.resources = resources;
19664
- }
19665
19681
  if (uri) {
19666
19682
  console.warn(
19667
19683
  "[tinycloud] siweConfig.uri is overwriting the delegation target URI. This may break delegation chain validation if the URI does not match the session key DID."
@@ -19673,6 +19689,29 @@ var NodeUserAuthorization = class {
19673
19689
  }
19674
19690
  return overrides;
19675
19691
  }
19692
+ prepareSessionWithResources(params) {
19693
+ const resources = this.siweConfig?.resources;
19694
+ if (resources?.some((resource) => typeof resource !== "string" || !/^urn:tinycloud:recipients:[A-Za-z0-9_-]+$/.test(resource))) {
19695
+ throw new Error("SIWE metadata resources must be base64url recipients URIs");
19696
+ }
19697
+ const prepared = this.wasm.prepareSession(params);
19698
+ if (!resources?.length) return prepared;
19699
+ const recapLines = /^- urn:recap:[^\r\n]+$/gim;
19700
+ const recaps = prepared.siwe.match(recapLines);
19701
+ const recap = recaps?.[0];
19702
+ if (recaps?.length !== 1 || !prepared.siwe.endsWith(recap)) {
19703
+ throw new Error("Prepared SIWE must end with exactly one ReCap");
19704
+ }
19705
+ const insertedLines = resources.map((resource) => `- ${resource}`);
19706
+ const siwe = prepared.siwe.slice(0, -recap.length) + insertedLines.join("\n") + "\n" + recap;
19707
+ const expectedFields = (0, import_sdk_core5.extractImmutableSiweFields)(prepared.siwe);
19708
+ expectedFields.nonRecapResources = [expectedFields.nonRecapResources, ...insertedLines].filter(Boolean).join("\n");
19709
+ const actualRecaps = siwe.match(recapLines);
19710
+ if (actualRecaps?.length !== 1 || actualRecaps[0] !== recap || (0, import_sdk_core5.diffImmutableSiweFields)(expectedFields, (0, import_sdk_core5.extractImmutableSiweFields)(siwe)).length) {
19711
+ throw new Error("SIWE metadata insertion changed the prepared message");
19712
+ }
19713
+ return { ...prepared, siwe };
19714
+ }
19676
19715
  /**
19677
19716
  * Add an extension to the authorization flow.
19678
19717
  */
@@ -19920,7 +19959,7 @@ var NodeUserAuthorization = class {
19920
19959
  spaceAbilities[spaceId] = (0, import_sdk_core5.resourceCapabilitiesToAbilitiesMap)(resources);
19921
19960
  }
19922
19961
  const abilities = spaceAbilities[options.spaceId] ?? (0, import_sdk_core5.resourceCapabilitiesToAbilitiesMap)([]);
19923
- const prepared = this.wasm.prepareSession({
19962
+ const prepared = this.prepareSessionWithResources({
19924
19963
  abilities,
19925
19964
  spaceAbilities,
19926
19965
  ...options.rawAbilities !== void 0 ? { rawAbilities: options.rawAbilities } : {},
@@ -20001,8 +20040,8 @@ var NodeUserAuthorization = class {
20001
20040
  this.assertSignInCurrent(generation);
20002
20041
  await this.refreshNamedKeyFeatureForSignIn(address, chainId);
20003
20042
  this.assertSignInCurrent(generation);
20004
- const keyId = `session-${Date.now()}`;
20005
- this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
20043
+ const keyId = `session-${Date.now()}-${Math.random().toString(36).slice(2)}`;
20044
+ this.sessionManager.createSessionKey(keyId);
20006
20045
  this.activeSessionKeyId = keyId;
20007
20046
  const jwkString = this.sessionManager.jwk(keyId);
20008
20047
  if (!jwkString) {
@@ -20013,7 +20052,7 @@ var NodeUserAuthorization = class {
20013
20052
  const spaceId = capabilityPlan.spaceId;
20014
20053
  const now = /* @__PURE__ */ new Date();
20015
20054
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
20016
- const prepared = this.wasm.prepareSession({
20055
+ const prepared = this.prepareSessionWithResources({
20017
20056
  abilities: capabilityPlan.abilities,
20018
20057
  ...capabilityPlan.spaceAbilities !== void 0 ? { spaceAbilities: capabilityPlan.spaceAbilities } : {},
20019
20058
  ...capabilityPlan.rawAbilities !== void 0 ? { rawAbilities: capabilityPlan.rawAbilities } : {},
@@ -20148,9 +20187,8 @@ var NodeUserAuthorization = class {
20148
20187
  const address = (0, import_sdk_core5.canonicalizeAddress)(await this.signer.getAddress());
20149
20188
  const chainId = await this.signer.getChainId();
20150
20189
  await this.refreshNamedKeyFeatureForSignIn(address, chainId);
20151
- const keyId = `session-${Date.now()}`;
20152
- this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
20153
- this.activeSessionKeyId = keyId;
20190
+ const keyId = `openkey-session-${Date.now()}-${++this.preparedSessionCounter}`;
20191
+ this.sessionManager.createSessionKey(keyId);
20154
20192
  const jwkString = this.sessionManager.jwk(keyId);
20155
20193
  if (!jwkString) {
20156
20194
  throw new Error("Failed to create session key");
@@ -20160,7 +20198,7 @@ var NodeUserAuthorization = class {
20160
20198
  const spaceId = capabilityPlan.spaceId;
20161
20199
  const now = /* @__PURE__ */ new Date();
20162
20200
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
20163
- const prepared = this.wasm.prepareSession({
20201
+ const prepared = this.prepareSessionWithResources({
20164
20202
  abilities: capabilityPlan.abilities,
20165
20203
  ...capabilityPlan.spaceAbilities !== void 0 ? { spaceAbilities: capabilityPlan.spaceAbilities } : {},
20166
20204
  ...capabilityPlan.rawAbilities !== void 0 ? { rawAbilities: capabilityPlan.rawAbilities } : {},
@@ -20231,6 +20269,7 @@ var NodeUserAuthorization = class {
20231
20269
  await this.sessionStorage.save(address, persistedData);
20232
20270
  this._session = clientSession;
20233
20271
  this._tinyCloudSession = tinyCloudSession;
20272
+ this.activeSessionKeyId = keyId;
20234
20273
  this._address = address;
20235
20274
  this._chainId = chainId;
20236
20275
  await this.refreshNodeInfo();
@@ -20277,6 +20316,11 @@ var NodeUserAuthorization = class {
20277
20316
  * @param options Optional overrides for the OpenKey request.
20278
20317
  */
20279
20318
  async signInWithOpenKey(authorizeFn, options) {
20319
+ const pending = await this.prepareOpenKeySignIn(options);
20320
+ return this.completeOpenKeySignIn(pending, authorizeFn(pending.request), options);
20321
+ }
20322
+ /** Finish address, host and SIWE preparation before an approval click. */
20323
+ async prepareOpenKeySignIn(options) {
20280
20324
  refuseCaveated(this.getCapabilityRequest()?.manifests);
20281
20325
  if (options?.host !== void 0) {
20282
20326
  const overrideHost = options.host.trim();
@@ -20288,7 +20332,7 @@ var NodeUserAuthorization = class {
20288
20332
  const signingAddress = (0, import_sdk_core5.canonicalizeAddress)(await this.signer.getAddress());
20289
20333
  const signingChainId = await this.signer.getChainId();
20290
20334
  await this.resolveTinyCloudHostsForSignIn(signingAddress, signingChainId);
20291
- const { prepared, keyId, jwk } = await this.prepareSessionForSigning();
20335
+ const { prepared, keyId, jwk, address, chainId } = await this.prepareSessionForSigning();
20292
20336
  const presentation = this.buildPresentationEnvelope(options?.reason);
20293
20337
  const hostHint = this.primaryTinyCloudHost;
20294
20338
  const originalRequest = {
@@ -20300,12 +20344,32 @@ var NodeUserAuthorization = class {
20300
20344
  keyId: options?.openkeyKeyId,
20301
20345
  presentation
20302
20346
  };
20347
+ return {
20348
+ request: originalRequest,
20349
+ prepared,
20350
+ keyId,
20351
+ jwk,
20352
+ address,
20353
+ chainId,
20354
+ generation: this.sessionGeneration,
20355
+ createdAt: Date.now()
20356
+ };
20357
+ }
20358
+ /** Complete a prepared approval. The caller starts authorization before awaiting this method. */
20359
+ async completeOpenKeySignIn(pending, authorization, options) {
20360
+ if (Date.now() - pending.createdAt > 5 * 6e4) {
20361
+ throw new Error("Prepared OpenKey sign-in expired; prepare again");
20362
+ }
20363
+ if (pending.generation !== this.sessionGeneration) {
20364
+ throw new Error("Prepared OpenKey sign-in expired after sign-out");
20365
+ }
20366
+ const { request: originalRequest, prepared, keyId, jwk } = pending;
20303
20367
  let result;
20304
20368
  let signed2;
20305
20369
  let signature2;
20306
20370
  for (let attempt = 0; ; ) {
20307
20371
  try {
20308
- result ?? (result = await authorizeFn(originalRequest));
20372
+ result ?? (result = await authorization);
20309
20373
  signed2 = await this.verifyOpenKeyResult(result, prepared);
20310
20374
  signature2 = result.signature;
20311
20375
  break;
@@ -21699,6 +21763,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21699
21763
  constructor(config = {}) {
21700
21764
  this.signer = null;
21701
21765
  this.auth = null;
21766
+ this.consumedOpenKeyPendings = /* @__PURE__ */ new WeakSet();
21702
21767
  this.tc = null;
21703
21768
  this._chainId = 1;
21704
21769
  this.replicaPurgeFailedHandlers = /* @__PURE__ */ new Set();
@@ -22639,6 +22704,37 @@ var _TinyCloudNode = class _TinyCloudNode {
22639
22704
  }
22640
22705
  await this.signInWith(() => this.auth.signInWithOpenKey(authorizeFn, options));
22641
22706
  }
22707
+ /** Prepare the OpenKey request before the approval click. */
22708
+ async prepareOpenKeySignIn() {
22709
+ if (!this.signer || !this.tc || !this.auth) {
22710
+ throw new Error("Cannot prepare OpenKey sign-in in session-only mode. Provide a signer in config.");
22711
+ }
22712
+ await this.signOutInFlight;
22713
+ await this.accountRegistryTail;
22714
+ await this.wasmBindings.ensureInitialized?.();
22715
+ return this.auth.prepareOpenKeySignIn();
22716
+ }
22717
+ /** Start OpenKey authorization synchronously, then complete normal session setup. */
22718
+ signInWithPreparedOpenKey(pending, authorizeFn) {
22719
+ if (!this.signer || !this.tc || !this.auth || this.signOutInFlight) {
22720
+ throw new Error("Prepared OpenKey sign-in is unavailable");
22721
+ }
22722
+ if (this.consumedOpenKeyPendings.has(pending)) {
22723
+ throw new Error("Prepared OpenKey sign-in was already used");
22724
+ }
22725
+ if (Date.now() - pending.createdAt > 5 * 6e4) {
22726
+ throw new Error("Prepared OpenKey sign-in expired; prepare again");
22727
+ }
22728
+ this.consumedOpenKeyPendings.add(pending);
22729
+ const authorization = authorizeFn(pending.request);
22730
+ void authorization.catch(() => void 0);
22731
+ return this.signInWith(() => {
22732
+ if (this._address !== pending.address || this._chainId !== pending.chainId) {
22733
+ throw new Error("OpenKey account changed after sign-in preparation");
22734
+ }
22735
+ return this.auth.completeOpenKeySignIn(pending, authorization);
22736
+ });
22737
+ }
22642
22738
  async signInWith(performSignIn) {
22643
22739
  refuseCaveated(this.auth?.capabilityRequest?.manifests);
22644
22740
  const epoch = this.sessionEpoch;
@@ -24280,6 +24376,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24280
24376
  invoke: graph.invoke,
24281
24377
  invokeAny: graph.invokeAny,
24282
24378
  signOwnerRevocation: this.signer ? (cid) => this.signOwnerRevocation(cid) : void 0,
24379
+ sessionInvocationSigner: this.sessionInvocationSignerFor(input.serviceSession),
24283
24380
  fetch: graph.fetch
24284
24381
  });
24285
24382
  const keyProvider = new WasmKeyProvider({ sessionManager: input.manager });
@@ -24495,6 +24592,31 @@ var _TinyCloudNode = class _TinyCloudNode {
24495
24592
  if (session === void 0) throw new Error("Not signed in. Call signIn() first.");
24496
24593
  return signBytesWithJwk(bytes, session.jwk);
24497
24594
  }
24595
+ /**
24596
+ * Signs proofless invocations with `session`'s own did:key, for the node's
24597
+ * issued-delegation list and revocation by the delegator. The audience is
24598
+ * this Node's DID; each invocation lives 60 seconds.
24599
+ */
24600
+ sessionInvocationSignerFor(session) {
24601
+ return {
24602
+ did: () => session.verificationMethod.split("#", 1)[0],
24603
+ sign: async (attenuation) => {
24604
+ const now = Math.floor(Date.now() / 1e3);
24605
+ const invocation = await (0, import_sdk_core10.signCompactUcanAuthorization)({
24606
+ issuerDid: session.verificationMethod.split("#", 1)[0],
24607
+ audienceDid: await this.fetchNodeId(),
24608
+ attenuation,
24609
+ facts: [{}],
24610
+ proofs: [],
24611
+ notBefore: now,
24612
+ expiresAt: now + 60,
24613
+ nonce: `urn:uuid:${crypto.randomUUID()}`,
24614
+ sign: (bytes) => signBytesWithJwk(bytes, session.jwk)
24615
+ });
24616
+ return invocation.authorization;
24617
+ }
24618
+ };
24619
+ }
24498
24620
  /** Author a proofless Policy/v3 owner root with the authenticated holder key. */
24499
24621
  async createUnifiedOwnerRoot(input) {
24500
24622
  const ownerDid = this.credentialHolderDid;
@@ -25029,7 +25151,7 @@ var _TinyCloudNode = class _TinyCloudNode {
25029
25151
  graph.assertActive();
25030
25152
  const signed2 = await this.signRawNetworkAuthorization({
25031
25153
  targetNode: input.targetNode,
25032
- networkId: input.networkId,
25154
+ networkId: input.body.keyPath === void 0 ? input.networkId : `${input.networkId}/${input.body.keyPath}`,
25033
25155
  action: DECRYPT_ACTION2,
25034
25156
  facts: input.facts
25035
25157
  }, { graph, session });
@@ -25202,6 +25324,7 @@ var _TinyCloudNode = class _TinyCloudNode {
25202
25324
  invoke: graph.invoke,
25203
25325
  invokeAny: graph.invokeAny,
25204
25326
  signOwnerRevocation: this.signer ? (cid) => this.signOwnerRevocation(cid) : void 0,
25327
+ sessionInvocationSigner: this.sessionInvocationSignerFor(serviceSession),
25205
25328
  fetch: graph.fetch
25206
25329
  });
25207
25330
  this._spaceService = new import_sdk_core10.SpaceService({
@@ -25985,7 +26108,7 @@ var _TinyCloudNode = class _TinyCloudNode {
25985
26108
  if (!session || !Array.isArray(permissions) || permissions.length === 0) {
25986
26109
  return false;
25987
26110
  }
25988
- const expanded = this.expandPermissionEntries(permissions);
26111
+ const expanded = (0, import_sdk_core10.expandRuntimePermissionEntries)(permissions, (0, import_sdk_core10.pkhDid)(session.address, session.chainId));
25989
26112
  if (this.sessionCoversPermissionEntries(session, expanded)) {
25990
26113
  return true;
25991
26114
  }
@@ -26005,7 +26128,7 @@ var _TinyCloudNode = class _TinyCloudNode {
26005
26128
  if (!session || !Array.isArray(permissions) || permissions.length === 0) {
26006
26129
  return [];
26007
26130
  }
26008
- const expanded = this.expandPermissionEntries(permissions);
26131
+ const expanded = (0, import_sdk_core10.expandRuntimePermissionEntries)(permissions, (0, import_sdk_core10.pkhDid)(session.address, session.chainId));
26009
26132
  return this.findRuntimeGrantsForPermissionEntries(expanded, session).map(
26010
26133
  (grant) => grant.delegation
26011
26134
  );
@@ -26180,7 +26303,28 @@ var _TinyCloudNode = class _TinyCloudNode {
26180
26303
  throw new import_sdk_core10.SessionExpiredError(sessionExpiry);
26181
26304
  }
26182
26305
  }
26183
- const expanded = this.expandPermissionEntries(permissions);
26306
+ const expanded = (0, import_sdk_core10.expandRuntimePermissionEntries)(permissions, (0, import_sdk_core10.pkhDid)(session.address, session.chainId));
26307
+ const bindsShareKey = expanded.some((entry) => entry.service === import_sdk_core10.ENCRYPTION_PERMISSION_SERVICE && entry.actions.includes("tinycloud.encryption/key.create"));
26308
+ const captured = bindsShareKey ? { ...session, jwk: { ...options?.expectedSessionKey ?? session.jwk } } : session;
26309
+ const assertCapturedKey = bindsShareKey ? () => {
26310
+ const live = session.jwk;
26311
+ const key2 = captured.jwk;
26312
+ if (this.currentTinyCloudSession() !== session || session.verificationMethod !== captured.verificationMethod || session.delegationCid !== captured.delegationCid || session.spaceId !== captured.spaceId || session.address !== captured.address || session.chainId !== captured.chainId || live?.kty !== key2.kty || live?.crv !== key2.crv || live?.x !== key2.x || live?.y !== key2.y || live?.d !== key2.d) {
26313
+ throw new Error("Runtime permission request cancelled because the session key changed.");
26314
+ }
26315
+ } : void 0;
26316
+ const sessionKeyDid = bindsShareKey ? this.sessionDid : void 0;
26317
+ if (bindsShareKey) {
26318
+ const key2 = captured.jwk;
26319
+ if (key2.kty !== "OKP" || key2.crv !== "Ed25519" || typeof key2.x !== "string") {
26320
+ throw new Error("Runtime permission session key does not match its signed identity.");
26321
+ }
26322
+ const keyDid = (0, import_share_envelope.didKeyFromEd25519PublicKey)(base64UrlDecode(key2.x));
26323
+ if (!didPrincipalMatches2(keyDid, sessionKeyDid) || !didPrincipalMatches2(keyDid, captured.verificationMethod) || !didPrincipalMatches2(keyDid, new import_siwe2.SiweMessage(session.siwe).uri)) {
26324
+ throw new Error("Runtime permission session key does not match its signed identity.");
26325
+ }
26326
+ assertCapturedKey();
26327
+ }
26184
26328
  if (this.sessionCoversPermissionEntries(session, expanded)) {
26185
26329
  return [];
26186
26330
  }
@@ -26230,13 +26374,13 @@ var _TinyCloudNode = class _TinyCloudNode {
26230
26374
  return this.wasmBindings.prepareSession({
26231
26375
  abilities,
26232
26376
  ...rawForDelegation.length > 0 ? { rawAbilities: this.permissionsToRawAbilities(rawForDelegation) } : {},
26233
- address: this.wasmBindings.ensureEip55(session.address),
26234
- chainId: session.chainId,
26377
+ address: this.wasmBindings.ensureEip55(captured.address),
26378
+ chainId: captured.chainId,
26235
26379
  domain: this.siweDomain,
26236
26380
  issuedAt: now.toISOString(),
26237
26381
  expirationTime: expiresAt.toISOString(),
26238
26382
  spaceId,
26239
- jwk: session.jwk
26383
+ jwk: captured.jwk
26240
26384
  });
26241
26385
  } catch (error) {
26242
26386
  if (rawForDelegation.some((entry) => this.isRawRevocationPermissionEntry(entry)) && /invalid ReCap resource URI/i.test(error instanceof Error ? error.message : String(error))) {
@@ -26248,8 +26392,13 @@ var _TinyCloudNode = class _TinyCloudNode {
26248
26392
  throw error;
26249
26393
  }
26250
26394
  })();
26395
+ if (bindsShareKey && !didPrincipalMatches2(new import_siwe2.SiweMessage(prepared.siwe).uri, sessionKeyDid)) {
26396
+ throw new Error("Prepared runtime permission targets a different session key.");
26397
+ }
26398
+ assertCapturedKey?.();
26251
26399
  const signature2 = await this.signer.signMessage(prepared.siwe);
26252
26400
  graph.assertActive();
26401
+ assertCapturedKey?.();
26253
26402
  const delegatedSession = this.wasmBindings.completeSessionSetup({
26254
26403
  ...prepared,
26255
26404
  signature: signature2
@@ -26278,18 +26427,19 @@ var _TinyCloudNode = class _TinyCloudNode {
26278
26427
  delegatedSession,
26279
26428
  delegatedEntries,
26280
26429
  spaceId,
26281
- session,
26430
+ captured,
26282
26431
  expiresAt,
26283
26432
  { siwe: prepared.siwe, signature: signature2 }
26284
26433
  );
26285
26434
  graph.assertActive();
26435
+ assertCapturedKey?.();
26286
26436
  this.runtimePermissionGrants.push({
26287
26437
  session: {
26288
26438
  delegationHeader: delegatedSession.delegationHeader,
26289
26439
  delegationCid: delegatedSession.delegationCid,
26290
26440
  spaceId,
26291
- verificationMethod: session.verificationMethod,
26292
- jwk: session.jwk
26441
+ verificationMethod: captured.verificationMethod,
26442
+ jwk: captured.jwk
26293
26443
  },
26294
26444
  delegation,
26295
26445
  operations: this.permissionOperations(delegatedEntries, spaceId),
@@ -26618,7 +26768,19 @@ var _TinyCloudNode = class _TinyCloudNode {
26618
26768
  "delegateTo requires a non-empty permissions array"
26619
26769
  );
26620
26770
  }
26621
- const expandedEntries = this.expandPermissionEntries(permissions);
26771
+ const expandedEntries = (0, import_sdk_core10.expandDelegationPermissionEntries)(permissions);
26772
+ const namedKeyEntries = expandedEntries.filter((entry) => entry.service === import_sdk_core10.ENCRYPTION_PERMISSION_SERVICE && entry.path.includes("/"));
26773
+ if (namedKeyEntries.length > 0) {
26774
+ if (expandedEntries.some((entry) => entry.service === import_sdk_core10.ENCRYPTION_PERMISSION_SERVICE && !entry.path.includes("/"))) {
26775
+ throw new import_sdk_core10.ManifestValidationError("named-key delegation cannot include bare-network permissions");
26776
+ }
26777
+ if (options?.forceWalletSign) {
26778
+ throw new import_sdk_core10.ManifestValidationError("named-key delegation requires a signed session grant");
26779
+ }
26780
+ const granted = this.projectSignedRecapCapabilities(session.siwe);
26781
+ const { subset, missing } = this.signedCapabilitySubset(namedKeyEntries, granted);
26782
+ if (!subset) throw new import_sdk_core10.PermissionNotInManifestError(missing, granted);
26783
+ }
26622
26784
  const now = /* @__PURE__ */ new Date();
26623
26785
  const expiryMs = resolveExpiryMs(options?.expiry);
26624
26786
  const expirationTime = new Date(now.getTime() + expiryMs);
@@ -28137,7 +28299,7 @@ var FileSessionStorage = class {
28137
28299
  };
28138
28300
 
28139
28301
  // src/authorization/openKeyBridge.ts
28140
- function wireOpenKeyAuthorize(openkey) {
28302
+ function wireOpenKeyAuthorize(openkey, opts) {
28141
28303
  return async (input) => {
28142
28304
  const result = await openkey.authorizeTinyCloud({
28143
28305
  protocolVersion: 1,
@@ -28148,7 +28310,7 @@ function wireOpenKeyAuthorize(openkey) {
28148
28310
  // Forward the presentation envelope verbatim — the OpenKey SDK
28149
28311
  // validates and size-bounds it before use.
28150
28312
  presentation: input.presentation
28151
- });
28313
+ }, opts);
28152
28314
  if (result.protocolVersion !== 1) {
28153
28315
  throw new Error(
28154
28316
  `wireOpenKeyAuthorize: OpenKey returned unsupported protocolVersion ${result.protocolVersion}`
@@ -29224,7 +29386,8 @@ var SqliteReplicaHandle = class {
29224
29386
  options.signal.addEventListener("abort", onAbort, { once: true });
29225
29387
  const engine = new (__privateGet(this, _replica)).Replica({
29226
29388
  store: __privateGet(this, _store),
29227
- transportFor
29389
+ transportFor,
29390
+ ...this.spec.contentFetch === void 0 ? {} : { contentFetch: this.spec.contentFetch }
29228
29391
  });
29229
29392
  const running = engine.sync({ signal: abort.signal });
29230
29393
  const registration = { promise: running, abort: () => abort.abort() };
@@ -30841,6 +31004,7 @@ function sqliteReplicaStorage(options) {
30841
31004
  hexDecode,
30842
31005
  hexEncode,
30843
31006
  installTinyCloudDebugGlobals,
31007
+ isAppKeyHostBound,
30844
31008
  isCapabilitySubset,
30845
31009
  isEvmAddress,
30846
31010
  isNetworkId,