@tinycloud/node-sdk 3.10.0 → 3.11.0-beta.1

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-B2SLx27M.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-CnVaWnAX.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-DHIk5QvV.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-BlNcvo1c.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
@@ -256,11 +256,13 @@ import {
256
256
  createInMemoryRegistrySequenceStore,
257
257
  registryOwnerSubjectV1,
258
258
  EXPIRY,
259
+ assertExpiryWithinTechnicalLimit,
259
260
  canonicalizeAddress,
260
261
  makePkhSpaceId,
261
262
  pkhDid,
262
263
  extractImmutableSiweFields,
263
264
  diffImmutableSiweFields,
265
+ checkChangedExpiration,
264
266
  extractRecapAttenuations,
265
267
  unauthorizedRecapCapabilities,
266
268
  parseCanonicalRecapResource,
@@ -384,6 +386,16 @@ import { createOpenKeyCallbackSigningStrategy } from "@tinycloud/sdk-core";
384
386
  var defaultSignStrategy = { type: "auto-sign" };
385
387
 
386
388
  // src/authorization/NodeUserAuthorization.ts
389
+ function assertMaxExpiresAt(value) {
390
+ if (value === void 0 || typeof value === "function") return;
391
+ const ms = value instanceof Date ? value.getTime() : value;
392
+ if (typeof ms !== "number" || !Number.isFinite(new Date(ms).getTime())) {
393
+ throw new Error("maxExpiresAt must be a finite number of epoch milliseconds, a valid Date, or a function returning one");
394
+ }
395
+ }
396
+ function lastAnchoredLine(siwe, pattern) {
397
+ return [...siwe.matchAll(pattern)].at(-1)?.[1];
398
+ }
387
399
  function pkhSpaceIdentity(spaceId) {
388
400
  const match = /^(tinycloud:pkh:eip155:\d+:)(0x[0-9a-fA-F]{40})(:.+)$/.exec(spaceId);
389
401
  return match === null ? spaceId : `${match[1]}${match[2].toLowerCase()}${match[3]}`;
@@ -1357,7 +1369,7 @@ var NodeUserAuthorization = class {
1357
1369
  }
1358
1370
  const jwk = JSON.parse(jwkString);
1359
1371
  const now = /* @__PURE__ */ new Date();
1360
- const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
1372
+ const expirationTime = this.sessionExpiryFrom(now);
1361
1373
  const primaryIdentity = pkhSpaceIdentity(options.spaceId);
1362
1374
  const resourcesBySpace = /* @__PURE__ */ new Map();
1363
1375
  for (const resource of options.capabilityRequest.resources) {
@@ -1412,6 +1424,17 @@ var NodeUserAuthorization = class {
1412
1424
  signature
1413
1425
  };
1414
1426
  }
1427
+ /**
1428
+ * When a session that starts at `now` ends. Refused with a dated message when
1429
+ * the configured lifetime reaches past what a sign-in message can carry,
1430
+ * instead of the bare `RangeError` or WASM parse error `toISOString()` and
1431
+ * `prepareSession` would otherwise give.
1432
+ */
1433
+ sessionExpiryFrom(now) {
1434
+ const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
1435
+ assertExpiryWithinTechnicalLimit(expirationTime, "siwe");
1436
+ return expirationTime;
1437
+ }
1415
1438
  persistedData(session, expiresAt, createdAt, replicaStamp) {
1416
1439
  return {
1417
1440
  address: session.address,
@@ -1467,7 +1490,7 @@ var NodeUserAuthorization = class {
1467
1490
  const capabilityPlan = this.resolveSignInCapabilities(address, chainId);
1468
1491
  const spaceId = capabilityPlan.spaceId;
1469
1492
  const now = /* @__PURE__ */ new Date();
1470
- const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
1493
+ const expirationTime = this.sessionExpiryFrom(now);
1471
1494
  const prepared = this.prepareSessionWithResources({
1472
1495
  abilities: capabilityPlan.abilities,
1473
1496
  ...capabilityPlan.spaceAbilities !== void 0 ? { spaceAbilities: capabilityPlan.spaceAbilities } : {},
@@ -1613,7 +1636,7 @@ var NodeUserAuthorization = class {
1613
1636
  const capabilityPlan = this.resolveSignInCapabilities(address, chainId);
1614
1637
  const spaceId = capabilityPlan.spaceId;
1615
1638
  const now = /* @__PURE__ */ new Date();
1616
- const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
1639
+ const expirationTime = this.sessionExpiryFrom(now);
1617
1640
  const prepared = this.prepareSessionWithResources({
1618
1641
  abilities: capabilityPlan.abilities,
1619
1642
  ...capabilityPlan.spaceAbilities !== void 0 ? { spaceAbilities: capabilityPlan.spaceAbilities } : {},
@@ -1676,10 +1699,8 @@ var NodeUserAuthorization = class {
1676
1699
  siwe: prepared.siwe,
1677
1700
  signature
1678
1701
  };
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();
1702
+ const expiresAt = lastAnchoredLine(prepared.siwe ?? "", /^Expiration Time: (.+)$/gm) ?? this.sessionExpiryFrom(/* @__PURE__ */ new Date()).toISOString();
1703
+ const createdAt = lastAnchoredLine(prepared.siwe ?? "", /^Issued At: (.+)$/gm) ?? (/* @__PURE__ */ new Date()).toISOString();
1683
1704
  const replicaStamp = await this.establishReplicaStamp?.(tinyCloudSession);
1684
1705
  const persistedData = this.persistedData(tinyCloudSession, expiresAt, createdAt, replicaStamp);
1685
1706
  await this.sessionStorage.save(address, persistedData);
@@ -1738,6 +1759,7 @@ var NodeUserAuthorization = class {
1738
1759
  /** Finish address, host and SIWE preparation before an approval click. */
1739
1760
  async prepareOpenKeySignIn(options) {
1740
1761
  refuseCaveated(this.getCapabilityRequest()?.manifests);
1762
+ assertMaxExpiresAt(options?.maxExpiresAt);
1741
1763
  if (options?.host !== void 0) {
1742
1764
  const overrideHost = options.host.trim();
1743
1765
  if (!overrideHost) {
@@ -1758,7 +1780,9 @@ var NodeUserAuthorization = class {
1758
1780
  verificationMethod: prepared.verificationMethod,
1759
1781
  host: hostHint,
1760
1782
  keyId: options?.openkeyKeyId,
1761
- presentation
1783
+ presentation,
1784
+ // Present only when set, so the default request shape is unchanged.
1785
+ ...options?.expiryChangeable === true ? { expiryChangeable: true } : {}
1762
1786
  };
1763
1787
  return {
1764
1788
  request: originalRequest,
@@ -1768,7 +1792,10 @@ var NodeUserAuthorization = class {
1768
1792
  address,
1769
1793
  chainId,
1770
1794
  generation: this.sessionGeneration,
1771
- createdAt: Date.now()
1795
+ createdAt: Date.now(),
1796
+ // Kept in memory with the pending request. It is not part of `request`, so it is never sent to OpenKey, and
1797
+ // nothing here is persisted.
1798
+ ...options?.maxExpiresAt === void 0 ? {} : { maxExpiresAt: options.maxExpiresAt }
1772
1799
  };
1773
1800
  }
1774
1801
  /** Complete a prepared approval. The caller starts authorization before awaiting this method. */
@@ -1786,7 +1813,11 @@ var NodeUserAuthorization = class {
1786
1813
  for (let attempt = 0; ; ) {
1787
1814
  try {
1788
1815
  result ?? (result = await authorization);
1789
- signed = await this.verifyOpenKeyResult(result, prepared);
1816
+ signed = await this.verifyOpenKeyResult(result, prepared, {
1817
+ // Relax only for a request that actually carried the opt-in.
1818
+ allowExpirationChange: originalRequest.expiryChangeable === true,
1819
+ maxExpiresAt: pending.maxExpiresAt
1820
+ });
1790
1821
  signature = result.signature;
1791
1822
  break;
1792
1823
  } catch (error) {
@@ -1878,13 +1909,23 @@ var NodeUserAuthorization = class {
1878
1909
  * in the original prepared SIWE — narrowing OK, broadening rejected.
1879
1910
  * 5. Every `result.selectedActionKeys` entry corresponds to a
1880
1911
  * (resource, action) pair in the returned SIWE.
1881
- */
1882
- async signInWithOpenKeyResult(result, prepared, keyId, jwk) {
1883
- const signed = await this.verifyOpenKeyResult(result, prepared);
1912
+ *
1913
+ * `options.expiryChangeable` is true only when the request sent to OpenKey
1914
+ * carried `expiryChangeable: true`. Then (and only then) the signed
1915
+ * `Expiration Time` may differ from the prepared one and is the expiry the
1916
+ * session is built with; the changed expiry must pass
1917
+ * `checkChangedExpiration` and every other field in (3) must still match.
1918
+ * Without it, any expiry difference is refused as in (3).
1919
+ */
1920
+ async signInWithOpenKeyResult(result, prepared, keyId, jwk, options) {
1921
+ const signed = await this.verifyOpenKeyResult(result, prepared, {
1922
+ allowExpirationChange: options?.expiryChangeable === true,
1923
+ maxExpiresAt: options?.maxExpiresAt
1924
+ });
1884
1925
  return this.signInWithPreparedSession(signed, result.signature, keyId, jwk);
1885
1926
  }
1886
1927
  /** Validate a candidate without activating a network session, so paste retries reuse one preparation. */
1887
- async verifyOpenKeyResult(result, prepared) {
1928
+ async verifyOpenKeyResult(result, prepared, options) {
1888
1929
  if (result.protocolVersion !== 1) {
1889
1930
  throw new Error(`Unsupported OpenKey protocol version ${result.protocolVersion}`);
1890
1931
  }
@@ -1927,16 +1968,39 @@ var NodeUserAuthorization = class {
1927
1968
  `OpenKey signedMessage.address (${parsedSignedSiwe.address}) does not match local signer address (${expectedAddress})`
1928
1969
  );
1929
1970
  }
1971
+ const parsedExpiry = parsedSignedSiwe.expirationTime;
1972
+ const lineExpiry = lastAnchoredLine(result.signedMessage, /^Expiration Time: (.+)$/gm);
1973
+ if (parsedExpiry === void 0 || parsedExpiry === null || lineExpiry === void 0) {
1974
+ throw new Error("OpenKey signedMessage has no Expiration Time line of its own");
1975
+ }
1976
+ const parsedExpiryMs = Date.parse(parsedExpiry);
1977
+ if (!Number.isFinite(parsedExpiryMs) || parsedExpiryMs !== Date.parse(lineExpiry)) {
1978
+ throw new Error("OpenKey signedMessage Expiration Time line does not match the message's own expiry");
1979
+ }
1930
1980
  const originalHasRecap = /(?:^|\n)-\s+urn:recap:/i.test(prepared.siwe);
1931
1981
  const originalFields = extractImmutableSiweFields(prepared.siwe);
1932
1982
  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
- );
1983
+ if (options?.allowExpirationChange === true) {
1984
+ const maxExpiresAt = typeof options.maxExpiresAt === "function" ? options.maxExpiresAt() : options.maxExpiresAt;
1985
+ const refusal = checkChangedExpiration({
1986
+ preparedSiwe: prepared.siwe,
1987
+ signedSiwe: result.signedMessage,
1988
+ now: Date.now(),
1989
+ originalHasRecap,
1990
+ ...maxExpiresAt === void 0 ? {} : { maxExpiresAt }
1991
+ });
1992
+ if (refusal !== null) {
1993
+ throw new Error(`OpenKey signedMessage ${refusal}`);
1994
+ }
1995
+ } else {
1996
+ const changedFields = diffImmutableSiweFields(originalFields, signedFields, {
1997
+ originalHasRecap
1998
+ });
1999
+ if (changedFields.length > 0) {
2000
+ throw new Error(
2001
+ `OpenKey signedMessage altered immutable SIWE fields: ${changedFields.join(", ")}`
2002
+ );
2003
+ }
1940
2004
  }
1941
2005
  let originalCaps;
1942
2006
  let signedCaps;
@@ -2217,7 +2281,9 @@ function wireOpenKeyAuthorize(openkey, opts) {
2217
2281
  host: input.host,
2218
2282
  // Forward the presentation envelope verbatim — the OpenKey SDK
2219
2283
  // validates and size-bounds it before use.
2220
- presentation: input.presentation
2284
+ presentation: input.presentation,
2285
+ // Sent only when true, so a request without it keeps its prior shape.
2286
+ ...input.expiryChangeable === true ? { expiryChangeable: true } : {}
2221
2287
  }, opts);
2222
2288
  if (result.protocolVersion !== 1) {
2223
2289
  throw new Error(
@@ -2953,6 +3019,7 @@ import {
2953
3019
  DUCKDB as DUCKDB2,
2954
3020
  ENCRYPTION as ENCRYPTION2,
2955
3021
  EXPIRY as EXPIRY3,
3022
+ assertExpiryWithinTechnicalLimit as assertExpiryWithinTechnicalLimit2,
2956
3023
  canonicalHashHex,
2957
3024
  canonicalizeEncryptionJson,
2958
3025
  verifyDidKeyEd25519Signature,
@@ -4921,14 +4988,14 @@ var _TinyCloudNode = class _TinyCloudNode {
4921
4988
  await this.signInWith(() => this.auth.signInWithOpenKey(authorizeFn, options));
4922
4989
  }
4923
4990
  /** Prepare the OpenKey request before the approval click. */
4924
- async prepareOpenKeySignIn() {
4991
+ async prepareOpenKeySignIn(options) {
4925
4992
  if (!this.signer || !this.tc || !this.auth) {
4926
4993
  throw new Error("Cannot prepare OpenKey sign-in in session-only mode. Provide a signer in config.");
4927
4994
  }
4928
4995
  await this.signOutInFlight;
4929
4996
  await this.accountRegistryTail;
4930
4997
  await this.wasmBindings.ensureInitialized?.();
4931
- return this.auth.prepareOpenKeySignIn();
4998
+ return this.auth.prepareOpenKeySignIn(options);
4932
4999
  }
4933
5000
  /** Start OpenKey authorization synchronously, then complete normal session setup. */
4934
5001
  signInWithPreparedOpenKey(pending, authorizeFn) {
@@ -7512,7 +7579,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7512
7579
  path: "",
7513
7580
  // Root access
7514
7581
  actions: [...ROOT_DELEGATION_ACTIONS],
7515
- expiry: this.getSessionExpiry(),
7582
+ expiry: this.getSignedSessionExpiry(),
7516
7583
  isRevoked: false,
7517
7584
  allowSubDelegation: true
7518
7585
  };
@@ -7525,7 +7592,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7525
7592
  spaceId,
7526
7593
  path: "",
7527
7594
  actions: [...ROOT_DELEGATION_ACTIONS],
7528
- expiry: this.getSessionExpiry(),
7595
+ expiry: this.getSignedSessionExpiry(),
7529
7596
  isRevoked: false,
7530
7597
  allowSubDelegation: true
7531
7598
  });
@@ -7617,7 +7684,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7617
7684
  assertActive: () => graph.assertActive(),
7618
7685
  keyProvider: this._keyProvider,
7619
7686
  registry: this._capabilityRegistry,
7620
- sessionExpiry: this.getSessionExpiry(),
7687
+ sessionExpiry: this.getSignedSessionExpiry(),
7621
7688
  createDelegationWasm: (params) => {
7622
7689
  graph.assertActive();
7623
7690
  return this.createDelegationWrapper(params);
@@ -7664,6 +7731,29 @@ var _TinyCloudNode = class _TinyCloudNode {
7664
7731
  const expirationMs = this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS;
7665
7732
  return new Date(Date.now() + expirationMs);
7666
7733
  }
7734
+ /**
7735
+ * The expiry of the session that was actually signed, so the registry root
7736
+ * and the sharing service never outlive or undercut what the SIWE grants
7737
+ * (a user may change the expiry in the OpenKey approval).
7738
+ *
7739
+ * Any expiry the SIWE parses to is used exactly as signed, however near or
7740
+ * far. The configured lifetime is used only when the SIWE cannot be parsed
7741
+ * (the session is already established, so failing sign-in here would be
7742
+ * worse; real sign-ins verify the SIWE first) or when a valid SIWE carries
7743
+ * no `Expiration Time` line, as the other `extractSiweExpiration` callers do.
7744
+ * @internal
7745
+ */
7746
+ getSignedSessionExpiry() {
7747
+ const siwe = this.auth?.tinyCloudSession?.siwe;
7748
+ if (!siwe) return this.getSessionExpiry();
7749
+ let signed;
7750
+ try {
7751
+ signed = extractSiweExpiration(siwe);
7752
+ } catch {
7753
+ return this.getSessionExpiry();
7754
+ }
7755
+ return signed ?? this.getSessionExpiry();
7756
+ }
7667
7757
  /**
7668
7758
  * Wrapper for the WASM createDelegation function.
7669
7759
  *
@@ -7693,6 +7783,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7693
7783
  // DID here and rejects the fragment as an invalid audience DID.
7694
7784
  verificationMethod: params.session.verificationMethod.split("#", 1)[0]
7695
7785
  };
7786
+ assertExpiryWithinTechnicalLimit2(params.expirationSecs * 1e3, "ucan");
7696
7787
  const result = this.wasmBindings.createDelegation(
7697
7788
  wasmSession,
7698
7789
  params.delegateDID,
@@ -7725,9 +7816,10 @@ var _TinyCloudNode = class _TinyCloudNode {
7725
7816
  }
7726
7817
  const permissions = ownerDelegationPermissions(params);
7727
7818
  const now = /* @__PURE__ */ new Date();
7728
- if (!(params.expiresAt instanceof Date) || params.expiresAt.getTime() <= now.getTime() || params.expiresAt.getTime() - now.getTime() > EXPIRY3.MAX_MS) {
7729
- throw new Error("Owner delegation expiry must be explicit, future, and within EXPIRY.MAX_MS");
7819
+ if (!(params.expiresAt instanceof Date) || params.expiresAt.getTime() <= now.getTime()) {
7820
+ throw new Error("Owner delegation expiry must be explicit, future, and a valid date");
7730
7821
  }
7822
+ assertExpiryWithinTechnicalLimit2(params.expiresAt, "siwe");
7731
7823
  if (!this.signer) throw new Error("Owner wallet signer is required");
7732
7824
  const session = this.currentTinyCloudSession();
7733
7825
  if (!session) throw new Error("Owner session is required");
@@ -7828,6 +7920,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7828
7920
  * not sent.
7829
7921
  */
7830
7922
  async authorizeShareDeliveryV3(input) {
7923
+ assertExpiryWithinTechnicalLimit2(new Date(input.expiresAt), "siwe");
7831
7924
  const envelopeRef = await shortDeliveryLinkBodyCid(input.shareUrl, input.trustedOrigins);
7832
7925
  const session = this.currentTinyCloudSession();
7833
7926
  const serviceSession = this._serviceContext?.session;
@@ -7880,6 +7973,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7880
7973
  };
7881
7974
  }
7882
7975
  async createRootDelegationForSharing(params, assertActive) {
7976
+ assertExpiryWithinTechnicalLimit2(params.requestedExpiry, "siwe");
7883
7977
  try {
7884
7978
  return (await this.createOwnerDelegation({
7885
7979
  delegateDid: params.shareKeyDID,
@@ -8576,6 +8670,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8576
8670
  if (sessionExpiry !== void 0 && sessionExpiry < expiresAt) {
8577
8671
  expiresAt = sessionExpiry;
8578
8672
  }
8673
+ assertExpiryWithinTechnicalLimit2(expiresAt, "siwe");
8579
8674
  const delegations = [];
8580
8675
  let rawEntriesAttached = false;
8581
8676
  for (const [spaceId, entries] of bySpace) {
@@ -10048,6 +10143,7 @@ var _TinyCloudNode = class _TinyCloudNode {
10048
10143
  const now = /* @__PURE__ */ new Date();
10049
10144
  const expiryMs = params.expiryMs ?? 60 * 60 * 1e3;
10050
10145
  const expirationTime = new Date(now.getTime() + expiryMs);
10146
+ assertExpiryWithinTechnicalLimit2(expirationTime, "siwe");
10051
10147
  const prepared = this.wasmBindings.prepareSession({
10052
10148
  abilities,
10053
10149
  address: this.wasmBindings.ensureEip55(session.address),
@@ -10202,6 +10298,7 @@ var _TinyCloudNode = class _TinyCloudNode {
10202
10298
  const { abilities, rawAbilities } = this.buildActivationAbilities(delegation);
10203
10299
  const now = /* @__PURE__ */ new Date();
10204
10300
  const expirationTime = delegation.expiry;
10301
+ assertExpiryWithinTechnicalLimit2(expirationTime, "siwe");
10205
10302
  const prepared = this.wasmBindings.prepareSession({
10206
10303
  abilities,
10207
10304
  address: this.wasmBindings.ensureEip55(mySession.address),
@@ -10321,6 +10418,7 @@ var _TinyCloudNode = class _TinyCloudNode {
10321
10418
  const now = /* @__PURE__ */ new Date();
10322
10419
  const requestedExpiry = params.expiryMs === void 0 ? parentDelegation.expiry : new Date(now.getTime() + params.expiryMs);
10323
10420
  const actualExpiry = requestedExpiry > parentDelegation.expiry ? parentDelegation.expiry : requestedExpiry;
10421
+ assertExpiryWithinTechnicalLimit2(actualExpiry, "siwe");
10324
10422
  const abilities = {};
10325
10423
  const rawAbilities = {};
10326
10424
  for (const resource of requestedResources) {