@tinycloud/node-sdk 3.8.0-beta.9 → 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 (36) 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 +188 -29
  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 +193 -31
  27. package/dist/index.js.map +1 -1
  28. package/dist/replication/authority.d.cts +3 -3
  29. package/dist/replication/authority.d.ts +3 -3
  30. package/dist/share-receive.cjs +775 -0
  31. package/dist/share-receive.cjs.map +1 -0
  32. package/dist/share-receive.d.cts +32 -0
  33. package/dist/share-receive.d.ts +32 -0
  34. package/dist/share-receive.js +777 -0
  35. package/dist/share-receive.js.map +1 -0
  36. 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
@@ -17968,6 +17968,7 @@ __export(src_exports, {
17968
17968
  hexDecode: () => import_sdk_core22.hexDecode,
17969
17969
  hexEncode: () => import_sdk_core22.hexEncode,
17970
17970
  installTinyCloudDebugGlobals: () => import_sdk_core16.installTinyCloudDebugGlobals,
17971
+ isAppKeyHostBound: () => isAppKeyHostBound,
17971
17972
  isCapabilitySubset: () => import_sdk_core17.isCapabilitySubset,
17972
17973
  isEvmAddress: () => import_sdk_core16.isEvmAddress,
17973
17974
  isNetworkId: () => import_sdk_core22.isNetworkId,
@@ -18813,6 +18814,7 @@ function deserializeDelegation(data) {
18813
18814
 
18814
18815
  // src/TinyCloudNode.ts
18815
18816
  var import_siwe2 = require("siwe");
18817
+ var import_share_envelope = require("@tinycloud/share-envelope");
18816
18818
 
18817
18819
  // src/replication/module-registry.ts
18818
18820
  var nodeLoaders;
@@ -18862,6 +18864,18 @@ function appKeyHostBinding(domain, appId) {
18862
18864
  const reversed = labels.reverse().join(".");
18863
18865
  return appId === reversed || appId.startsWith(`${reversed}.`);
18864
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
+ }
18865
18879
 
18866
18880
  // src/authorization/NodeUserAuthorization.ts
18867
18881
  init_authority_sign_in();
@@ -19019,6 +19033,7 @@ function cloneAbilitiesMap(actions) {
19019
19033
  var NodeUserAuthorization = class {
19020
19034
  constructor(config) {
19021
19035
  this.activeSessionKeyId = "default";
19036
+ this.preparedSessionCounter = 0;
19022
19037
  /** Incremented by resetSession; a sign-in started earlier publishes nothing. */
19023
19038
  this.sessionGeneration = 0;
19024
19039
  /**
@@ -19601,7 +19616,8 @@ var NodeUserAuthorization = class {
19601
19616
  return true;
19602
19617
  }
19603
19618
  const parsed = entry.path.includes("/") ? (0, import_resource.parseEncryptionResource)(entry.path) : { ...(0, import_sdk_services3.parseNetworkId)(entry.path), kind: "network" };
19604
- 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) {
19605
19621
  throw new import_sdk_core5.ManifestValidationError("named keys go in manifest.keys");
19606
19622
  }
19607
19623
  for (const action of entry.actions) {
@@ -19644,8 +19660,7 @@ var NodeUserAuthorization = class {
19644
19660
  /**
19645
19661
  * Build SIWE overrides from the top-level nonce and siweConfig.
19646
19662
  * - Top-level `nonce` is seeded first so `siweConfig.nonce` wins if both are set.
19647
- * - statement is prepended to the default statement
19648
- * - resources are appended to the default resources
19663
+ * - resources are inserted after WASM preparation, before the final ReCap
19649
19664
  * - uri triggers a warning (overwriting delegation target)
19650
19665
  * - all other fields override directly
19651
19666
  * - per-call nonce overrides siweConfig.nonce when provided
@@ -19663,9 +19678,6 @@ var NodeUserAuthorization = class {
19663
19678
  if (statement) {
19664
19679
  overrides.statement = this.statement ? `${statement} ${this.statement}` : statement;
19665
19680
  }
19666
- if (resources && resources.length > 0) {
19667
- overrides.resources = resources;
19668
- }
19669
19681
  if (uri) {
19670
19682
  console.warn(
19671
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."
@@ -19677,6 +19689,29 @@ var NodeUserAuthorization = class {
19677
19689
  }
19678
19690
  return overrides;
19679
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
+ }
19680
19715
  /**
19681
19716
  * Add an extension to the authorization flow.
19682
19717
  */
@@ -19924,7 +19959,7 @@ var NodeUserAuthorization = class {
19924
19959
  spaceAbilities[spaceId] = (0, import_sdk_core5.resourceCapabilitiesToAbilitiesMap)(resources);
19925
19960
  }
19926
19961
  const abilities = spaceAbilities[options.spaceId] ?? (0, import_sdk_core5.resourceCapabilitiesToAbilitiesMap)([]);
19927
- const prepared = this.wasm.prepareSession({
19962
+ const prepared = this.prepareSessionWithResources({
19928
19963
  abilities,
19929
19964
  spaceAbilities,
19930
19965
  ...options.rawAbilities !== void 0 ? { rawAbilities: options.rawAbilities } : {},
@@ -20005,8 +20040,8 @@ var NodeUserAuthorization = class {
20005
20040
  this.assertSignInCurrent(generation);
20006
20041
  await this.refreshNamedKeyFeatureForSignIn(address, chainId);
20007
20042
  this.assertSignInCurrent(generation);
20008
- const keyId = `session-${Date.now()}`;
20009
- this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
20043
+ const keyId = `session-${Date.now()}-${Math.random().toString(36).slice(2)}`;
20044
+ this.sessionManager.createSessionKey(keyId);
20010
20045
  this.activeSessionKeyId = keyId;
20011
20046
  const jwkString = this.sessionManager.jwk(keyId);
20012
20047
  if (!jwkString) {
@@ -20017,7 +20052,7 @@ var NodeUserAuthorization = class {
20017
20052
  const spaceId = capabilityPlan.spaceId;
20018
20053
  const now = /* @__PURE__ */ new Date();
20019
20054
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
20020
- const prepared = this.wasm.prepareSession({
20055
+ const prepared = this.prepareSessionWithResources({
20021
20056
  abilities: capabilityPlan.abilities,
20022
20057
  ...capabilityPlan.spaceAbilities !== void 0 ? { spaceAbilities: capabilityPlan.spaceAbilities } : {},
20023
20058
  ...capabilityPlan.rawAbilities !== void 0 ? { rawAbilities: capabilityPlan.rawAbilities } : {},
@@ -20152,9 +20187,8 @@ var NodeUserAuthorization = class {
20152
20187
  const address = (0, import_sdk_core5.canonicalizeAddress)(await this.signer.getAddress());
20153
20188
  const chainId = await this.signer.getChainId();
20154
20189
  await this.refreshNamedKeyFeatureForSignIn(address, chainId);
20155
- const keyId = `session-${Date.now()}`;
20156
- this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
20157
- this.activeSessionKeyId = keyId;
20190
+ const keyId = `openkey-session-${Date.now()}-${++this.preparedSessionCounter}`;
20191
+ this.sessionManager.createSessionKey(keyId);
20158
20192
  const jwkString = this.sessionManager.jwk(keyId);
20159
20193
  if (!jwkString) {
20160
20194
  throw new Error("Failed to create session key");
@@ -20164,7 +20198,7 @@ var NodeUserAuthorization = class {
20164
20198
  const spaceId = capabilityPlan.spaceId;
20165
20199
  const now = /* @__PURE__ */ new Date();
20166
20200
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
20167
- const prepared = this.wasm.prepareSession({
20201
+ const prepared = this.prepareSessionWithResources({
20168
20202
  abilities: capabilityPlan.abilities,
20169
20203
  ...capabilityPlan.spaceAbilities !== void 0 ? { spaceAbilities: capabilityPlan.spaceAbilities } : {},
20170
20204
  ...capabilityPlan.rawAbilities !== void 0 ? { rawAbilities: capabilityPlan.rawAbilities } : {},
@@ -20235,6 +20269,7 @@ var NodeUserAuthorization = class {
20235
20269
  await this.sessionStorage.save(address, persistedData);
20236
20270
  this._session = clientSession;
20237
20271
  this._tinyCloudSession = tinyCloudSession;
20272
+ this.activeSessionKeyId = keyId;
20238
20273
  this._address = address;
20239
20274
  this._chainId = chainId;
20240
20275
  await this.refreshNodeInfo();
@@ -20281,6 +20316,11 @@ var NodeUserAuthorization = class {
20281
20316
  * @param options Optional overrides for the OpenKey request.
20282
20317
  */
20283
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) {
20284
20324
  refuseCaveated(this.getCapabilityRequest()?.manifests);
20285
20325
  if (options?.host !== void 0) {
20286
20326
  const overrideHost = options.host.trim();
@@ -20292,7 +20332,7 @@ var NodeUserAuthorization = class {
20292
20332
  const signingAddress = (0, import_sdk_core5.canonicalizeAddress)(await this.signer.getAddress());
20293
20333
  const signingChainId = await this.signer.getChainId();
20294
20334
  await this.resolveTinyCloudHostsForSignIn(signingAddress, signingChainId);
20295
- const { prepared, keyId, jwk } = await this.prepareSessionForSigning();
20335
+ const { prepared, keyId, jwk, address, chainId } = await this.prepareSessionForSigning();
20296
20336
  const presentation = this.buildPresentationEnvelope(options?.reason);
20297
20337
  const hostHint = this.primaryTinyCloudHost;
20298
20338
  const originalRequest = {
@@ -20304,12 +20344,32 @@ var NodeUserAuthorization = class {
20304
20344
  keyId: options?.openkeyKeyId,
20305
20345
  presentation
20306
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;
20307
20367
  let result;
20308
20368
  let signed2;
20309
20369
  let signature2;
20310
20370
  for (let attempt = 0; ; ) {
20311
20371
  try {
20312
- result ?? (result = await authorizeFn(originalRequest));
20372
+ result ?? (result = await authorization);
20313
20373
  signed2 = await this.verifyOpenKeyResult(result, prepared);
20314
20374
  signature2 = result.signature;
20315
20375
  break;
@@ -21703,6 +21763,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21703
21763
  constructor(config = {}) {
21704
21764
  this.signer = null;
21705
21765
  this.auth = null;
21766
+ this.consumedOpenKeyPendings = /* @__PURE__ */ new WeakSet();
21706
21767
  this.tc = null;
21707
21768
  this._chainId = 1;
21708
21769
  this.replicaPurgeFailedHandlers = /* @__PURE__ */ new Set();
@@ -22643,6 +22704,37 @@ var _TinyCloudNode = class _TinyCloudNode {
22643
22704
  }
22644
22705
  await this.signInWith(() => this.auth.signInWithOpenKey(authorizeFn, options));
22645
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
+ }
22646
22738
  async signInWith(performSignIn) {
22647
22739
  refuseCaveated(this.auth?.capabilityRequest?.manifests);
22648
22740
  const epoch = this.sessionEpoch;
@@ -24284,6 +24376,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24284
24376
  invoke: graph.invoke,
24285
24377
  invokeAny: graph.invokeAny,
24286
24378
  signOwnerRevocation: this.signer ? (cid) => this.signOwnerRevocation(cid) : void 0,
24379
+ sessionInvocationSigner: this.sessionInvocationSignerFor(input.serviceSession),
24287
24380
  fetch: graph.fetch
24288
24381
  });
24289
24382
  const keyProvider = new WasmKeyProvider({ sessionManager: input.manager });
@@ -24499,6 +24592,31 @@ var _TinyCloudNode = class _TinyCloudNode {
24499
24592
  if (session === void 0) throw new Error("Not signed in. Call signIn() first.");
24500
24593
  return signBytesWithJwk(bytes, session.jwk);
24501
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
+ }
24502
24620
  /** Author a proofless Policy/v3 owner root with the authenticated holder key. */
24503
24621
  async createUnifiedOwnerRoot(input) {
24504
24622
  const ownerDid = this.credentialHolderDid;
@@ -25033,7 +25151,7 @@ var _TinyCloudNode = class _TinyCloudNode {
25033
25151
  graph.assertActive();
25034
25152
  const signed2 = await this.signRawNetworkAuthorization({
25035
25153
  targetNode: input.targetNode,
25036
- networkId: input.networkId,
25154
+ networkId: input.body.keyPath === void 0 ? input.networkId : `${input.networkId}/${input.body.keyPath}`,
25037
25155
  action: DECRYPT_ACTION2,
25038
25156
  facts: input.facts
25039
25157
  }, { graph, session });
@@ -25206,6 +25324,7 @@ var _TinyCloudNode = class _TinyCloudNode {
25206
25324
  invoke: graph.invoke,
25207
25325
  invokeAny: graph.invokeAny,
25208
25326
  signOwnerRevocation: this.signer ? (cid) => this.signOwnerRevocation(cid) : void 0,
25327
+ sessionInvocationSigner: this.sessionInvocationSignerFor(serviceSession),
25209
25328
  fetch: graph.fetch
25210
25329
  });
25211
25330
  this._spaceService = new import_sdk_core10.SpaceService({
@@ -25989,7 +26108,7 @@ var _TinyCloudNode = class _TinyCloudNode {
25989
26108
  if (!session || !Array.isArray(permissions) || permissions.length === 0) {
25990
26109
  return false;
25991
26110
  }
25992
- const expanded = this.expandPermissionEntries(permissions);
26111
+ const expanded = (0, import_sdk_core10.expandRuntimePermissionEntries)(permissions, (0, import_sdk_core10.pkhDid)(session.address, session.chainId));
25993
26112
  if (this.sessionCoversPermissionEntries(session, expanded)) {
25994
26113
  return true;
25995
26114
  }
@@ -26009,7 +26128,7 @@ var _TinyCloudNode = class _TinyCloudNode {
26009
26128
  if (!session || !Array.isArray(permissions) || permissions.length === 0) {
26010
26129
  return [];
26011
26130
  }
26012
- const expanded = this.expandPermissionEntries(permissions);
26131
+ const expanded = (0, import_sdk_core10.expandRuntimePermissionEntries)(permissions, (0, import_sdk_core10.pkhDid)(session.address, session.chainId));
26013
26132
  return this.findRuntimeGrantsForPermissionEntries(expanded, session).map(
26014
26133
  (grant) => grant.delegation
26015
26134
  );
@@ -26184,7 +26303,28 @@ var _TinyCloudNode = class _TinyCloudNode {
26184
26303
  throw new import_sdk_core10.SessionExpiredError(sessionExpiry);
26185
26304
  }
26186
26305
  }
26187
- 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
+ }
26188
26328
  if (this.sessionCoversPermissionEntries(session, expanded)) {
26189
26329
  return [];
26190
26330
  }
@@ -26234,13 +26374,13 @@ var _TinyCloudNode = class _TinyCloudNode {
26234
26374
  return this.wasmBindings.prepareSession({
26235
26375
  abilities,
26236
26376
  ...rawForDelegation.length > 0 ? { rawAbilities: this.permissionsToRawAbilities(rawForDelegation) } : {},
26237
- address: this.wasmBindings.ensureEip55(session.address),
26238
- chainId: session.chainId,
26377
+ address: this.wasmBindings.ensureEip55(captured.address),
26378
+ chainId: captured.chainId,
26239
26379
  domain: this.siweDomain,
26240
26380
  issuedAt: now.toISOString(),
26241
26381
  expirationTime: expiresAt.toISOString(),
26242
26382
  spaceId,
26243
- jwk: session.jwk
26383
+ jwk: captured.jwk
26244
26384
  });
26245
26385
  } catch (error) {
26246
26386
  if (rawForDelegation.some((entry) => this.isRawRevocationPermissionEntry(entry)) && /invalid ReCap resource URI/i.test(error instanceof Error ? error.message : String(error))) {
@@ -26252,8 +26392,13 @@ var _TinyCloudNode = class _TinyCloudNode {
26252
26392
  throw error;
26253
26393
  }
26254
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?.();
26255
26399
  const signature2 = await this.signer.signMessage(prepared.siwe);
26256
26400
  graph.assertActive();
26401
+ assertCapturedKey?.();
26257
26402
  const delegatedSession = this.wasmBindings.completeSessionSetup({
26258
26403
  ...prepared,
26259
26404
  signature: signature2
@@ -26282,18 +26427,19 @@ var _TinyCloudNode = class _TinyCloudNode {
26282
26427
  delegatedSession,
26283
26428
  delegatedEntries,
26284
26429
  spaceId,
26285
- session,
26430
+ captured,
26286
26431
  expiresAt,
26287
26432
  { siwe: prepared.siwe, signature: signature2 }
26288
26433
  );
26289
26434
  graph.assertActive();
26435
+ assertCapturedKey?.();
26290
26436
  this.runtimePermissionGrants.push({
26291
26437
  session: {
26292
26438
  delegationHeader: delegatedSession.delegationHeader,
26293
26439
  delegationCid: delegatedSession.delegationCid,
26294
26440
  spaceId,
26295
- verificationMethod: session.verificationMethod,
26296
- jwk: session.jwk
26441
+ verificationMethod: captured.verificationMethod,
26442
+ jwk: captured.jwk
26297
26443
  },
26298
26444
  delegation,
26299
26445
  operations: this.permissionOperations(delegatedEntries, spaceId),
@@ -26622,7 +26768,19 @@ var _TinyCloudNode = class _TinyCloudNode {
26622
26768
  "delegateTo requires a non-empty permissions array"
26623
26769
  );
26624
26770
  }
26625
- 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
+ }
26626
26784
  const now = /* @__PURE__ */ new Date();
26627
26785
  const expiryMs = resolveExpiryMs(options?.expiry);
26628
26786
  const expirationTime = new Date(now.getTime() + expiryMs);
@@ -28141,7 +28299,7 @@ var FileSessionStorage = class {
28141
28299
  };
28142
28300
 
28143
28301
  // src/authorization/openKeyBridge.ts
28144
- function wireOpenKeyAuthorize(openkey) {
28302
+ function wireOpenKeyAuthorize(openkey, opts) {
28145
28303
  return async (input) => {
28146
28304
  const result = await openkey.authorizeTinyCloud({
28147
28305
  protocolVersion: 1,
@@ -28152,7 +28310,7 @@ function wireOpenKeyAuthorize(openkey) {
28152
28310
  // Forward the presentation envelope verbatim — the OpenKey SDK
28153
28311
  // validates and size-bounds it before use.
28154
28312
  presentation: input.presentation
28155
- });
28313
+ }, opts);
28156
28314
  if (result.protocolVersion !== 1) {
28157
28315
  throw new Error(
28158
28316
  `wireOpenKeyAuthorize: OpenKey returned unsupported protocolVersion ${result.protocolVersion}`
@@ -30846,6 +31004,7 @@ function sqliteReplicaStorage(options) {
30846
31004
  hexDecode,
30847
31005
  hexEncode,
30848
31006
  installTinyCloudDebugGlobals,
31007
+ isAppKeyHostBound,
30849
31008
  isCapabilitySubset,
30850
31009
  isEvmAddress,
30851
31010
  isNetworkId,