@tinycloud/node-sdk 3.10.0 → 3.11.0-beta.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.
package/dist/core.d.cts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { ReplicationOptions, Manifest, PermissionEntry } from '@tinycloud/sdk-core';
2
2
  export { ACCOUNT_REGISTRY_PATH, ACCOUNT_REGISTRY_SPACE, AccountApplication, AccountApplicationListOptions, AccountApplicationRegisterOptions, AccountDelegation, AccountDelegationListOptions, AccountDelegationRevokeOptions, AccountIndexEnsureResult, AccountIndexRebuildResult, AccountIndexStatus, AccountIndexedReadOptions, AccountService, AccountServiceConfig, AccountSpace, AccountSpaceListOptions, AccountStatus, AuthorityRefusal, AutoApproveSpaceCreationHandler, AutoRejectStrategy, AutoSignStrategy, BatchOptions, BatchResponse, CallbackStrategy, CanonicalAddress, CanonicalParsedNetworkId, CapabilityEntry, CapabilityKeyRegistry, CapabilityKeyRegistryErrorCode, CapabilityKeyRegistryErrorCodes, CaveatedDelegationUnsupportedError, ClientSession, ColumnInfo, ComposeManifestOptions, ComposedManifestRequest, CreateDelegationParams, DEFAULT_MANIFEST_SPACE, DEFAULT_MANIFEST_VERSION, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, DataVaultConfig, DataVaultService, DatabaseHandle, DelegateReceivedShareParams, DelegatedShareAccess, Delegation, DelegationChain, DelegationChainV2, DelegationDirection, DelegationError, DelegationErrorCode, DelegationErrorCodes, DelegationFilters, DelegationManager, DelegationManagerConfig, DelegationRecord, DelegationResult, DidCacheKeyOptions, DidEqualsOptions, DuckDbAction, DuckDbActionType, DuckDbBatchOptions, DuckDbBatchResponse, DuckDbDatabaseHandle, DuckDbExecuteOptions, DuckDbExecuteResponse, DuckDbOptions, DuckDbQueryOptions, DuckDbQueryResponse, DuckDbService, DuckDbServiceConfig, DuckDbStatement, DuckDbValue, EncodedShareData, ExecuteOptions, ExecuteResponse, Extension, FetchFunction, GenerateShareParams, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, IKVService, INotificationHandler, IPrefixedKVService, ISQLService, ISecretsService, ISessionManager, ISessionStorage, ISharingService, ISigner, ISpace, ISpaceCreationHandler, ISpaceScopedDelegations, ISpaceScopedSharing, ISpaceService, IUserAuthorization, IWasmBindings, IdentityParseError, IngestOptions, InvokeFunction, JWK, KVBatchReadResponse, KVCreateSignedReadUrlOptions, KVListPage, KVReadThrough, KVReplicaHandle, KVReplicaSpec, KVReplicaStorage, KVReplicationController, KVReplicationDeps, KVResponse, KVService, KVServiceConfig, KVSignedReadUrlResponse, KeyInfo, KeyProvider, KeyType, LocalGetResult, LocalListResult, LocalReadMeta, LocalReplicaStatus, LocalSyncResult, Manifest, ManifestDefaults, ManifestRegistryRecord, ManifestSecretActions, ManifestValidationError, OpenKeyCallbackStrategy, OpenKeySigningRequestBody, OpenKeySigningResponseBody, OpenKeySigningStrategyOptions, ParsedSecretCatalogKey, PendingWriteRecord, PendingWriteState, PendingWriteStore, PermissionEntry, PermissionNotInManifestError, PersistedSessionData, PinnedKey, PkhDidParts, PrefixedKVService, ProtocolMismatchError, PurgeTarget, QueryOptions, QueryResponse, ReceiveOptions, RegisterBatchSuccess, RegisterPolicyV3Input, RegisterPolicyV3Receipt, ReplicaAuthorityState, ReplicaCoverage, ReplicaDevice, ReplicaGatedHandle, ReplicaGrantInfo, ReplicaInspectedStatus, ReplicaState, ReplicaStatusEntry, ReplicationAuthority, ReplicationControl, ReplicationEvent, ReplicationIdentity, ReplicationOptions, ReplicationPurgeReport, ReplicationReason, ReplicationScheduler, ResolvedCapabilities, ResolvedDelegate, ResolvedReplicationOptions, ResolvedSecretPath, ResourceCapability, SECRET_NAME_RE, SQLAction, SQLActionType, SQLService, SQLServiceConfig, SchemaInfo, SecretCatalogEntry, SecretPayload, SecretScopeOptions, SecretsError, SecretsService, ServiceContext, ServiceContextConfig, ServiceSession, SessionExpiredError, ShareAccess, ShareLink, ShareLinkData, ShareSchema, SharingService, SharingServiceConfig, SignCallback, SignInOptions, SignRequest, SignResponse, SilentNotificationHandler, Space, SpaceAbilitiesMap, SpaceConfig, SpaceCreationContext, SpaceErrorCode, SpaceErrorCodes, SpaceInfo, SpaceOwnership, SpaceService, SpaceServiceConfig, SqlStatement, SqlValue, StoredDelegationChain, TableInfo, TelemetryConfig, TelemetryEventHandler, TinyCloud, TinyCloudConfig, TinyCloudDebugEnableOptions, TinyCloudDebugEvent, TinyCloudDebugLevel, TinyCloudDebugLogger, TinyCloudDebugTimer, TinyCloudSession, UnsupportedFeatureError, VAULT_PERMISSION_SERVICE, VaultCrypto, VaultEntry, VaultError, VaultGetOptions, VaultGrantOptions, VaultHeaders, VaultListOptions, VaultNetworkReadResult, VaultPublicSpaceKVActions, VaultPutOptions, VersionCheckError, ViewInfo, WasmVaultFunctions, addressStorageKey, buildSpaceUri, canonicalizeAddress, canonicalizeDid, canonicalizeDidUrl, canonicalizeNetworkId, canonicalizeSecretScope, checkNodeInfo, clearTinyCloudDebugLogs, composeManifestRequest, createCapabilityKeyRegistry, createOpenKeyCallbackSigningStrategy, createSharingService, createSpaceService, createVaultCrypto, defaultSpaceCreationHandler, didCacheKey, didEquals, disableTinyCloudDebug, enableTinyCloudDebug, expandActionShortNames, expandPermissionEntries, expandPermissionEntry, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, isCapabilitySubset, isEvmAddress, loadManifest, makePkhSpaceId, makePublicSpaceId, parseCanonicalNetworkId, parseExpiry, parsePkhDid, parseSecretCatalogKey, parseSpaceUri, pkhDid, principalDid, principalDidEquals, resolveManifest, resolveSecretListPrefix, resolveSecretPath, resourceCapabilitiesToSpaceAbilitiesMap, tinyCloudDebugLogger, validateManifest } from '@tinycloud/sdk-core';
3
3
  import { _ as __gated_network } from './gated-network-BEF2XSTC.cjs';
4
- import { _ as __authority } from './authority-WCJA3phs.cjs';
4
+ import { _ as __authority } from './authority-C0JKqTwY.cjs';
5
5
  import { _ as __runtime } from './runtime-mRhSu-vJ.cjs';
6
6
  import { ReplicaDenyInput } from '@tinycloud/sdk-services/kv/replication';
7
7
  export { F as FileSessionStorage, M as MemorySessionStorage, W as WasmKeyProvider, a as WasmKeyProviderConfig, c as createWasmKeyProvider, i as isAppKeyHostBound } from './WasmKeyProvider-BKCPRC-c.cjs';
8
- export { B as BootstrapWarning, C as CreateOwnerDelegationParams, D as DelegateToOptions, a as DelegateToResult, b as DelegatedAccess, E as EnsureEncryptionNetworkOptions, I as InvalidRestoredSessionError, N as NodeEventEmitterStrategy, c as NodeUserAuthorization, d as NodeUserAuthorizationConfig, O as OpenKeyAuthorizeTinyCloud, e as OwnerDelegationReceipt, P as PreparedOpenKeyAuthorization, R as RuntimePermissionGrantOptions, S as SecretPermissionHint, f as SecretReadInput, g as SecretReadResult, h as SignStrategy, T as TinyCloudNode, i as TinyCloudNodeConfig, U as UnifiedOwnerRootInput, j as UnifiedOwnerRootReceipt, k as UnsupportedSessionRestoreError, l as defaultSignStrategy, w as wireOpenKeyAuthorize } from './TinyCloudNode-BhWBbCay.cjs';
8
+ export { B as BootstrapWarning, C as CreateOwnerDelegationParams, D as DelegateToOptions, a as DelegateToResult, b as DelegatedAccess, E as EnsureEncryptionNetworkOptions, I as InvalidRestoredSessionError, N as NodeEventEmitterStrategy, c as NodeUserAuthorization, d as NodeUserAuthorizationConfig, O as OpenKeyAuthorizeTinyCloud, e as OwnerDelegationReceipt, P as PreparedOpenKeyAuthorization, R as RuntimePermissionGrantOptions, S as SecretPermissionHint, f as SecretReadInput, g as SecretReadResult, h as SignStrategy, T as TinyCloudNode, i as TinyCloudNodeConfig, U as UnifiedOwnerRootInput, j as UnifiedOwnerRootReceipt, k as UnsupportedSessionRestoreError, l as defaultSignStrategy, w as wireOpenKeyAuthorize } from './TinyCloudNode-wAQN1Ndh.cjs';
9
9
  export { C as CompactRuntimeDelegationInput, P as PortableDelegation, R as RuntimeDelegationRejectedError, a as RuntimeDelegationRejection, V as ValidatedRuntimeDelegation, b as activateCompactRuntimeDelegation, c as activateValidatedRuntimeDelegation, d as deserializeDelegation, s as serializeDelegation } from './delegation-Ckc3UETl.cjs';
10
10
  import '@tinycloud/sdk-services';
11
11
  import '@tinycloud/sdk-services/encryption/named-keys';
package/dist/core.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { ReplicationOptions, Manifest, PermissionEntry } from '@tinycloud/sdk-core';
2
2
  export { ACCOUNT_REGISTRY_PATH, ACCOUNT_REGISTRY_SPACE, AccountApplication, AccountApplicationListOptions, AccountApplicationRegisterOptions, AccountDelegation, AccountDelegationListOptions, AccountDelegationRevokeOptions, AccountIndexEnsureResult, AccountIndexRebuildResult, AccountIndexStatus, AccountIndexedReadOptions, AccountService, AccountServiceConfig, AccountSpace, AccountSpaceListOptions, AccountStatus, AuthorityRefusal, AutoApproveSpaceCreationHandler, AutoRejectStrategy, AutoSignStrategy, BatchOptions, BatchResponse, CallbackStrategy, CanonicalAddress, CanonicalParsedNetworkId, CapabilityEntry, CapabilityKeyRegistry, CapabilityKeyRegistryErrorCode, CapabilityKeyRegistryErrorCodes, CaveatedDelegationUnsupportedError, ClientSession, ColumnInfo, ComposeManifestOptions, ComposedManifestRequest, CreateDelegationParams, DEFAULT_MANIFEST_SPACE, DEFAULT_MANIFEST_VERSION, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, DataVaultConfig, DataVaultService, DatabaseHandle, DelegateReceivedShareParams, DelegatedShareAccess, Delegation, DelegationChain, DelegationChainV2, DelegationDirection, DelegationError, DelegationErrorCode, DelegationErrorCodes, DelegationFilters, DelegationManager, DelegationManagerConfig, DelegationRecord, DelegationResult, DidCacheKeyOptions, DidEqualsOptions, DuckDbAction, DuckDbActionType, DuckDbBatchOptions, DuckDbBatchResponse, DuckDbDatabaseHandle, DuckDbExecuteOptions, DuckDbExecuteResponse, DuckDbOptions, DuckDbQueryOptions, DuckDbQueryResponse, DuckDbService, DuckDbServiceConfig, DuckDbStatement, DuckDbValue, EncodedShareData, ExecuteOptions, ExecuteResponse, Extension, FetchFunction, GenerateShareParams, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, IKVService, INotificationHandler, IPrefixedKVService, ISQLService, ISecretsService, ISessionManager, ISessionStorage, ISharingService, ISigner, ISpace, ISpaceCreationHandler, ISpaceScopedDelegations, ISpaceScopedSharing, ISpaceService, IUserAuthorization, IWasmBindings, IdentityParseError, IngestOptions, InvokeFunction, JWK, KVBatchReadResponse, KVCreateSignedReadUrlOptions, KVListPage, KVReadThrough, KVReplicaHandle, KVReplicaSpec, KVReplicaStorage, KVReplicationController, KVReplicationDeps, KVResponse, KVService, KVServiceConfig, KVSignedReadUrlResponse, KeyInfo, KeyProvider, KeyType, LocalGetResult, LocalListResult, LocalReadMeta, LocalReplicaStatus, LocalSyncResult, Manifest, ManifestDefaults, ManifestRegistryRecord, ManifestSecretActions, ManifestValidationError, OpenKeyCallbackStrategy, OpenKeySigningRequestBody, OpenKeySigningResponseBody, OpenKeySigningStrategyOptions, ParsedSecretCatalogKey, PendingWriteRecord, PendingWriteState, PendingWriteStore, PermissionEntry, PermissionNotInManifestError, PersistedSessionData, PinnedKey, PkhDidParts, PrefixedKVService, ProtocolMismatchError, PurgeTarget, QueryOptions, QueryResponse, ReceiveOptions, RegisterBatchSuccess, RegisterPolicyV3Input, RegisterPolicyV3Receipt, ReplicaAuthorityState, ReplicaCoverage, ReplicaDevice, ReplicaGatedHandle, ReplicaGrantInfo, ReplicaInspectedStatus, ReplicaState, ReplicaStatusEntry, ReplicationAuthority, ReplicationControl, ReplicationEvent, ReplicationIdentity, ReplicationOptions, ReplicationPurgeReport, ReplicationReason, ReplicationScheduler, ResolvedCapabilities, ResolvedDelegate, ResolvedReplicationOptions, ResolvedSecretPath, ResourceCapability, SECRET_NAME_RE, SQLAction, SQLActionType, SQLService, SQLServiceConfig, SchemaInfo, SecretCatalogEntry, SecretPayload, SecretScopeOptions, SecretsError, SecretsService, ServiceContext, ServiceContextConfig, ServiceSession, SessionExpiredError, ShareAccess, ShareLink, ShareLinkData, ShareSchema, SharingService, SharingServiceConfig, SignCallback, SignInOptions, SignRequest, SignResponse, SilentNotificationHandler, Space, SpaceAbilitiesMap, SpaceConfig, SpaceCreationContext, SpaceErrorCode, SpaceErrorCodes, SpaceInfo, SpaceOwnership, SpaceService, SpaceServiceConfig, SqlStatement, SqlValue, StoredDelegationChain, TableInfo, TelemetryConfig, TelemetryEventHandler, TinyCloud, TinyCloudConfig, TinyCloudDebugEnableOptions, TinyCloudDebugEvent, TinyCloudDebugLevel, TinyCloudDebugLogger, TinyCloudDebugTimer, TinyCloudSession, UnsupportedFeatureError, VAULT_PERMISSION_SERVICE, VaultCrypto, VaultEntry, VaultError, VaultGetOptions, VaultGrantOptions, VaultHeaders, VaultListOptions, VaultNetworkReadResult, VaultPublicSpaceKVActions, VaultPutOptions, VersionCheckError, ViewInfo, WasmVaultFunctions, addressStorageKey, buildSpaceUri, canonicalizeAddress, canonicalizeDid, canonicalizeDidUrl, canonicalizeNetworkId, canonicalizeSecretScope, checkNodeInfo, clearTinyCloudDebugLogs, composeManifestRequest, createCapabilityKeyRegistry, createOpenKeyCallbackSigningStrategy, createSharingService, createSpaceService, createVaultCrypto, defaultSpaceCreationHandler, didCacheKey, didEquals, disableTinyCloudDebug, enableTinyCloudDebug, expandActionShortNames, expandPermissionEntries, expandPermissionEntry, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, isCapabilitySubset, isEvmAddress, loadManifest, makePkhSpaceId, makePublicSpaceId, parseCanonicalNetworkId, parseExpiry, parsePkhDid, parseSecretCatalogKey, parseSpaceUri, pkhDid, principalDid, principalDidEquals, resolveManifest, resolveSecretListPrefix, resolveSecretPath, resourceCapabilitiesToSpaceAbilitiesMap, tinyCloudDebugLogger, validateManifest } from '@tinycloud/sdk-core';
3
3
  import { _ as __gated_network } from './gated-network-BEF2XSTC.js';
4
- import { _ as __authority } from './authority-BzqKNzOr.js';
4
+ import { _ as __authority } from './authority-Cj8MLCkr.js';
5
5
  import { _ as __runtime } from './runtime-CO4VXnPq.js';
6
6
  import { ReplicaDenyInput } from '@tinycloud/sdk-services/kv/replication';
7
7
  export { F as FileSessionStorage, M as MemorySessionStorage, W as WasmKeyProvider, a as WasmKeyProviderConfig, c as createWasmKeyProvider, i as isAppKeyHostBound } from './WasmKeyProvider-BKCPRC-c.js';
8
- export { B as BootstrapWarning, C as CreateOwnerDelegationParams, D as DelegateToOptions, a as DelegateToResult, b as DelegatedAccess, E as EnsureEncryptionNetworkOptions, I as InvalidRestoredSessionError, N as NodeEventEmitterStrategy, c as NodeUserAuthorization, d as NodeUserAuthorizationConfig, O as OpenKeyAuthorizeTinyCloud, e as OwnerDelegationReceipt, P as PreparedOpenKeyAuthorization, R as RuntimePermissionGrantOptions, S as SecretPermissionHint, f as SecretReadInput, g as SecretReadResult, h as SignStrategy, T as TinyCloudNode, i as TinyCloudNodeConfig, U as UnifiedOwnerRootInput, j as UnifiedOwnerRootReceipt, k as UnsupportedSessionRestoreError, l as defaultSignStrategy, w as wireOpenKeyAuthorize } from './TinyCloudNode-BjJJIifr.js';
8
+ export { B as BootstrapWarning, C as CreateOwnerDelegationParams, D as DelegateToOptions, a as DelegateToResult, b as DelegatedAccess, E as EnsureEncryptionNetworkOptions, I as InvalidRestoredSessionError, N as NodeEventEmitterStrategy, c as NodeUserAuthorization, d as NodeUserAuthorizationConfig, O as OpenKeyAuthorizeTinyCloud, e as OwnerDelegationReceipt, P as PreparedOpenKeyAuthorization, R as RuntimePermissionGrantOptions, S as SecretPermissionHint, f as SecretReadInput, g as SecretReadResult, h as SignStrategy, T as TinyCloudNode, i as TinyCloudNodeConfig, U as UnifiedOwnerRootInput, j as UnifiedOwnerRootReceipt, k as UnsupportedSessionRestoreError, l as defaultSignStrategy, w as wireOpenKeyAuthorize } from './TinyCloudNode-BpolXzu5.js';
9
9
  export { C as CompactRuntimeDelegationInput, P as PortableDelegation, R as RuntimeDelegationRejectedError, a as RuntimeDelegationRejection, V as ValidatedRuntimeDelegation, b as activateCompactRuntimeDelegation, c as activateValidatedRuntimeDelegation, d as deserializeDelegation, s as serializeDelegation } from './delegation-Ckc3UETl.js';
10
10
  import '@tinycloud/sdk-services';
11
11
  import '@tinycloud/sdk-services/encryption/named-keys';
package/dist/core.js CHANGED
@@ -261,6 +261,7 @@ import {
261
261
  pkhDid,
262
262
  extractImmutableSiweFields,
263
263
  diffImmutableSiweFields,
264
+ checkChangedExpiration,
264
265
  extractRecapAttenuations,
265
266
  unauthorizedRecapCapabilities,
266
267
  parseCanonicalRecapResource,
@@ -384,6 +385,16 @@ import { createOpenKeyCallbackSigningStrategy } from "@tinycloud/sdk-core";
384
385
  var defaultSignStrategy = { type: "auto-sign" };
385
386
 
386
387
  // src/authorization/NodeUserAuthorization.ts
388
+ function assertMaxExpiresAt(value) {
389
+ if (value === void 0 || typeof value === "function") return;
390
+ const ms = value instanceof Date ? value.getTime() : value;
391
+ if (typeof ms !== "number" || !Number.isFinite(new Date(ms).getTime())) {
392
+ throw new Error("maxExpiresAt must be a finite number of epoch milliseconds, a valid Date, or a function returning one");
393
+ }
394
+ }
395
+ function lastAnchoredLine(siwe, pattern) {
396
+ return [...siwe.matchAll(pattern)].at(-1)?.[1];
397
+ }
387
398
  function pkhSpaceIdentity(spaceId) {
388
399
  const match = /^(tinycloud:pkh:eip155:\d+:)(0x[0-9a-fA-F]{40})(:.+)$/.exec(spaceId);
389
400
  return match === null ? spaceId : `${match[1]}${match[2].toLowerCase()}${match[3]}`;
@@ -1676,10 +1687,8 @@ var NodeUserAuthorization = class {
1676
1687
  siwe: prepared.siwe,
1677
1688
  signature
1678
1689
  };
1679
- const expirationMatch = prepared.siwe?.match(/Expiration Time: (.+)/);
1680
- const issuedAtMatch = prepared.siwe?.match(/Issued At: (.+)/);
1681
- const expiresAt = expirationMatch?.[1] ?? new Date(Date.now() + this.sessionExpirationMs).toISOString();
1682
- const createdAt = issuedAtMatch?.[1] ?? (/* @__PURE__ */ new Date()).toISOString();
1690
+ const expiresAt = lastAnchoredLine(prepared.siwe ?? "", /^Expiration Time: (.+)$/gm) ?? new Date(Date.now() + this.sessionExpirationMs).toISOString();
1691
+ const createdAt = lastAnchoredLine(prepared.siwe ?? "", /^Issued At: (.+)$/gm) ?? (/* @__PURE__ */ new Date()).toISOString();
1683
1692
  const replicaStamp = await this.establishReplicaStamp?.(tinyCloudSession);
1684
1693
  const persistedData = this.persistedData(tinyCloudSession, expiresAt, createdAt, replicaStamp);
1685
1694
  await this.sessionStorage.save(address, persistedData);
@@ -1738,6 +1747,7 @@ var NodeUserAuthorization = class {
1738
1747
  /** Finish address, host and SIWE preparation before an approval click. */
1739
1748
  async prepareOpenKeySignIn(options) {
1740
1749
  refuseCaveated(this.getCapabilityRequest()?.manifests);
1750
+ assertMaxExpiresAt(options?.maxExpiresAt);
1741
1751
  if (options?.host !== void 0) {
1742
1752
  const overrideHost = options.host.trim();
1743
1753
  if (!overrideHost) {
@@ -1758,7 +1768,9 @@ var NodeUserAuthorization = class {
1758
1768
  verificationMethod: prepared.verificationMethod,
1759
1769
  host: hostHint,
1760
1770
  keyId: options?.openkeyKeyId,
1761
- presentation
1771
+ presentation,
1772
+ // Present only when set, so the default request shape is unchanged.
1773
+ ...options?.expiryChangeable === true ? { expiryChangeable: true } : {}
1762
1774
  };
1763
1775
  return {
1764
1776
  request: originalRequest,
@@ -1768,7 +1780,10 @@ var NodeUserAuthorization = class {
1768
1780
  address,
1769
1781
  chainId,
1770
1782
  generation: this.sessionGeneration,
1771
- createdAt: Date.now()
1783
+ createdAt: Date.now(),
1784
+ // Kept in memory with the pending request. It is not part of `request`, so it is never sent to OpenKey, and
1785
+ // nothing here is persisted.
1786
+ ...options?.maxExpiresAt === void 0 ? {} : { maxExpiresAt: options.maxExpiresAt }
1772
1787
  };
1773
1788
  }
1774
1789
  /** Complete a prepared approval. The caller starts authorization before awaiting this method. */
@@ -1786,7 +1801,11 @@ var NodeUserAuthorization = class {
1786
1801
  for (let attempt = 0; ; ) {
1787
1802
  try {
1788
1803
  result ?? (result = await authorization);
1789
- signed = await this.verifyOpenKeyResult(result, prepared);
1804
+ signed = await this.verifyOpenKeyResult(result, prepared, {
1805
+ // Relax only for a request that actually carried the opt-in.
1806
+ allowExpirationChange: originalRequest.expiryChangeable === true,
1807
+ maxExpiresAt: pending.maxExpiresAt
1808
+ });
1790
1809
  signature = result.signature;
1791
1810
  break;
1792
1811
  } catch (error) {
@@ -1878,13 +1897,23 @@ var NodeUserAuthorization = class {
1878
1897
  * in the original prepared SIWE — narrowing OK, broadening rejected.
1879
1898
  * 5. Every `result.selectedActionKeys` entry corresponds to a
1880
1899
  * (resource, action) pair in the returned SIWE.
1881
- */
1882
- async signInWithOpenKeyResult(result, prepared, keyId, jwk) {
1883
- const signed = await this.verifyOpenKeyResult(result, prepared);
1900
+ *
1901
+ * `options.expiryChangeable` is true only when the request sent to OpenKey
1902
+ * carried `expiryChangeable: true`. Then (and only then) the signed
1903
+ * `Expiration Time` may differ from the prepared one and is the expiry the
1904
+ * session is built with; the changed expiry must pass
1905
+ * `checkChangedExpiration` and every other field in (3) must still match.
1906
+ * Without it, any expiry difference is refused as in (3).
1907
+ */
1908
+ async signInWithOpenKeyResult(result, prepared, keyId, jwk, options) {
1909
+ const signed = await this.verifyOpenKeyResult(result, prepared, {
1910
+ allowExpirationChange: options?.expiryChangeable === true,
1911
+ maxExpiresAt: options?.maxExpiresAt
1912
+ });
1884
1913
  return this.signInWithPreparedSession(signed, result.signature, keyId, jwk);
1885
1914
  }
1886
1915
  /** Validate a candidate without activating a network session, so paste retries reuse one preparation. */
1887
- async verifyOpenKeyResult(result, prepared) {
1916
+ async verifyOpenKeyResult(result, prepared, options) {
1888
1917
  if (result.protocolVersion !== 1) {
1889
1918
  throw new Error(`Unsupported OpenKey protocol version ${result.protocolVersion}`);
1890
1919
  }
@@ -1927,16 +1956,39 @@ var NodeUserAuthorization = class {
1927
1956
  `OpenKey signedMessage.address (${parsedSignedSiwe.address}) does not match local signer address (${expectedAddress})`
1928
1957
  );
1929
1958
  }
1959
+ const parsedExpiry = parsedSignedSiwe.expirationTime;
1960
+ const lineExpiry = lastAnchoredLine(result.signedMessage, /^Expiration Time: (.+)$/gm);
1961
+ if (parsedExpiry === void 0 || parsedExpiry === null || lineExpiry === void 0) {
1962
+ throw new Error("OpenKey signedMessage has no Expiration Time line of its own");
1963
+ }
1964
+ const parsedExpiryMs = Date.parse(parsedExpiry);
1965
+ if (!Number.isFinite(parsedExpiryMs) || parsedExpiryMs !== Date.parse(lineExpiry)) {
1966
+ throw new Error("OpenKey signedMessage Expiration Time line does not match the message's own expiry");
1967
+ }
1930
1968
  const originalHasRecap = /(?:^|\n)-\s+urn:recap:/i.test(prepared.siwe);
1931
1969
  const originalFields = extractImmutableSiweFields(prepared.siwe);
1932
1970
  const signedFields = extractImmutableSiweFields(result.signedMessage);
1933
- const changedFields = diffImmutableSiweFields(originalFields, signedFields, {
1934
- originalHasRecap
1935
- });
1936
- if (changedFields.length > 0) {
1937
- throw new Error(
1938
- `OpenKey signedMessage altered immutable SIWE fields: ${changedFields.join(", ")}`
1939
- );
1971
+ if (options?.allowExpirationChange === true) {
1972
+ const maxExpiresAt = typeof options.maxExpiresAt === "function" ? options.maxExpiresAt() : options.maxExpiresAt;
1973
+ const refusal = checkChangedExpiration({
1974
+ preparedSiwe: prepared.siwe,
1975
+ signedSiwe: result.signedMessage,
1976
+ now: Date.now(),
1977
+ originalHasRecap,
1978
+ ...maxExpiresAt === void 0 ? {} : { maxExpiresAt }
1979
+ });
1980
+ if (refusal !== null) {
1981
+ throw new Error(`OpenKey signedMessage ${refusal}`);
1982
+ }
1983
+ } else {
1984
+ const changedFields = diffImmutableSiweFields(originalFields, signedFields, {
1985
+ originalHasRecap
1986
+ });
1987
+ if (changedFields.length > 0) {
1988
+ throw new Error(
1989
+ `OpenKey signedMessage altered immutable SIWE fields: ${changedFields.join(", ")}`
1990
+ );
1991
+ }
1940
1992
  }
1941
1993
  let originalCaps;
1942
1994
  let signedCaps;
@@ -2217,7 +2269,9 @@ function wireOpenKeyAuthorize(openkey, opts) {
2217
2269
  host: input.host,
2218
2270
  // Forward the presentation envelope verbatim — the OpenKey SDK
2219
2271
  // validates and size-bounds it before use.
2220
- presentation: input.presentation
2272
+ presentation: input.presentation,
2273
+ // Sent only when true, so a request without it keeps its prior shape.
2274
+ ...input.expiryChangeable === true ? { expiryChangeable: true } : {}
2221
2275
  }, opts);
2222
2276
  if (result.protocolVersion !== 1) {
2223
2277
  throw new Error(
@@ -4921,14 +4975,14 @@ var _TinyCloudNode = class _TinyCloudNode {
4921
4975
  await this.signInWith(() => this.auth.signInWithOpenKey(authorizeFn, options));
4922
4976
  }
4923
4977
  /** Prepare the OpenKey request before the approval click. */
4924
- async prepareOpenKeySignIn() {
4978
+ async prepareOpenKeySignIn(options) {
4925
4979
  if (!this.signer || !this.tc || !this.auth) {
4926
4980
  throw new Error("Cannot prepare OpenKey sign-in in session-only mode. Provide a signer in config.");
4927
4981
  }
4928
4982
  await this.signOutInFlight;
4929
4983
  await this.accountRegistryTail;
4930
4984
  await this.wasmBindings.ensureInitialized?.();
4931
- return this.auth.prepareOpenKeySignIn();
4985
+ return this.auth.prepareOpenKeySignIn(options);
4932
4986
  }
4933
4987
  /** Start OpenKey authorization synchronously, then complete normal session setup. */
4934
4988
  signInWithPreparedOpenKey(pending, authorizeFn) {
@@ -7512,7 +7566,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7512
7566
  path: "",
7513
7567
  // Root access
7514
7568
  actions: [...ROOT_DELEGATION_ACTIONS],
7515
- expiry: this.getSessionExpiry(),
7569
+ expiry: this.getSignedSessionExpiry(),
7516
7570
  isRevoked: false,
7517
7571
  allowSubDelegation: true
7518
7572
  };
@@ -7525,7 +7579,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7525
7579
  spaceId,
7526
7580
  path: "",
7527
7581
  actions: [...ROOT_DELEGATION_ACTIONS],
7528
- expiry: this.getSessionExpiry(),
7582
+ expiry: this.getSignedSessionExpiry(),
7529
7583
  isRevoked: false,
7530
7584
  allowSubDelegation: true
7531
7585
  });
@@ -7617,7 +7671,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7617
7671
  assertActive: () => graph.assertActive(),
7618
7672
  keyProvider: this._keyProvider,
7619
7673
  registry: this._capabilityRegistry,
7620
- sessionExpiry: this.getSessionExpiry(),
7674
+ sessionExpiry: this.getSignedSessionExpiry(),
7621
7675
  createDelegationWasm: (params) => {
7622
7676
  graph.assertActive();
7623
7677
  return this.createDelegationWrapper(params);
@@ -7664,6 +7718,29 @@ var _TinyCloudNode = class _TinyCloudNode {
7664
7718
  const expirationMs = this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS;
7665
7719
  return new Date(Date.now() + expirationMs);
7666
7720
  }
7721
+ /**
7722
+ * The expiry of the session that was actually signed, so the registry root
7723
+ * and the sharing service never outlive or undercut what the SIWE grants
7724
+ * (a user may change the expiry in the OpenKey approval).
7725
+ *
7726
+ * Any expiry the SIWE parses to is used exactly as signed, however near or
7727
+ * far. The configured lifetime is used only when the SIWE cannot be parsed
7728
+ * (the session is already established, so failing sign-in here would be
7729
+ * worse; real sign-ins verify the SIWE first) or when a valid SIWE carries
7730
+ * no `Expiration Time` line, as the other `extractSiweExpiration` callers do.
7731
+ * @internal
7732
+ */
7733
+ getSignedSessionExpiry() {
7734
+ const siwe = this.auth?.tinyCloudSession?.siwe;
7735
+ if (!siwe) return this.getSessionExpiry();
7736
+ let signed;
7737
+ try {
7738
+ signed = extractSiweExpiration(siwe);
7739
+ } catch {
7740
+ return this.getSessionExpiry();
7741
+ }
7742
+ return signed ?? this.getSessionExpiry();
7743
+ }
7667
7744
  /**
7668
7745
  * Wrapper for the WASM createDelegation function.
7669
7746
  *