@tinycloud/node-sdk 3.8.0-beta.2 → 3.8.0-beta.4

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.
@@ -2,6 +2,7 @@ import * as _tinycloud_sdk_core from '@tinycloud/sdk-core';
2
2
  import { AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, CapabilityPresentationEnvelopeV1, IUserAuthorization, ISigner, ISessionStorage, ISpaceCreationHandler, RegistryPolicy, RegistrySequenceStore, OnNodeNotFound, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ReplicationOptions, TinyCloudSession, PersistedSessionData, ClientSession, PermissionEntry, Extension, SignRequest, SpaceHostResult, SignInOptions, TelemetryConfig, ServiceContext, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, Delegation, StorageFullEvent, IStorageService, INotificationHandler, IENSResolver, RetryPolicy, KVReplicaStorage, AccountService, InvokeAnyFunction as InvokeAnyFunction$1, UnifiedPolicyCapability, RegisterPolicyV3Input, RegisterPolicyV3Receipt, CanonicalJson, ShareDeliveryAuthorizationV3Receipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ServiceSession, ReplicationControl, ResolvedDelegate } from '@tinycloud/sdk-core';
3
3
  import { ReplicaPurgeFailedEvent, ReplicaSessionStamp } from '@tinycloud/sdk-services/kv/replication';
4
4
  import { InvokeFunction, InvokeAnyFunction, FetchFunction, RequestSink, RequestLogReader } from '@tinycloud/sdk-services';
5
+ import { NamedKeyClient } from '@tinycloud/sdk-services/encryption/named-keys';
5
6
  import { EventEmitter } from 'events';
6
7
  import { P as PortableDelegation, S as SessionGrantProof, g as VerifiedSessionGrant } from './delegation-0LKZkmP2.js';
7
8
 
@@ -515,6 +516,9 @@ declare class NodeUserAuthorization implements IUserAuthorization {
515
516
  * @internal
516
517
  */
517
518
  private getCapabilityRequest;
519
+ private refreshNamedKeyFeatureForSignIn;
520
+ /** Manifest key paths that this sign-in cannot grant. */
521
+ get unavailableKeyPaths(): string[];
518
522
  private resolveSpaceName;
519
523
  /**
520
524
  * The plain-session primary abilities: `defaultActions` (the shared table)
@@ -1301,6 +1305,8 @@ declare class TinyCloudNode {
1301
1305
  private _hooks?;
1302
1306
  private _vault?;
1303
1307
  private _encryption?;
1308
+ private _namedKeyClient?;
1309
+ private _keysUnavailable;
1304
1310
  private _baseVaults;
1305
1311
  private _baseSecrets;
1306
1312
  private _secrets;
@@ -2162,6 +2168,10 @@ declare class TinyCloudNode {
2162
2168
  * Network-scoped encryption/decrypt service.
2163
2169
  */
2164
2170
  get encryption(): IEncryptionService;
2171
+ /** Named keys bound to the current session. */
2172
+ get keys(): NamedKeyClient;
2173
+ /** Manifest key paths unavailable during the latest `signIn()` attempt. */
2174
+ get keysUnavailable(): readonly string[];
2165
2175
  getEncryptionNetwork(nameOrNetworkId?: string): Promise<NetworkDescriptor | null>;
2166
2176
  createEncryptionNetwork(name?: string): Promise<NetworkDescriptor>;
2167
2177
  /**
@@ -2,6 +2,7 @@ import * as _tinycloud_sdk_core from '@tinycloud/sdk-core';
2
2
  import { AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, CapabilityPresentationEnvelopeV1, IUserAuthorization, ISigner, ISessionStorage, ISpaceCreationHandler, RegistryPolicy, RegistrySequenceStore, OnNodeNotFound, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ReplicationOptions, TinyCloudSession, PersistedSessionData, ClientSession, PermissionEntry, Extension, SignRequest, SpaceHostResult, SignInOptions, TelemetryConfig, ServiceContext, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, Delegation, StorageFullEvent, IStorageService, INotificationHandler, IENSResolver, RetryPolicy, KVReplicaStorage, AccountService, InvokeAnyFunction as InvokeAnyFunction$1, UnifiedPolicyCapability, RegisterPolicyV3Input, RegisterPolicyV3Receipt, CanonicalJson, ShareDeliveryAuthorizationV3Receipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ServiceSession, ReplicationControl, ResolvedDelegate } from '@tinycloud/sdk-core';
3
3
  import { ReplicaPurgeFailedEvent, ReplicaSessionStamp } from '@tinycloud/sdk-services/kv/replication';
4
4
  import { InvokeFunction, InvokeAnyFunction, FetchFunction, RequestSink, RequestLogReader } from '@tinycloud/sdk-services';
5
+ import { NamedKeyClient } from '@tinycloud/sdk-services/encryption/named-keys';
5
6
  import { EventEmitter } from 'events';
6
7
  import { P as PortableDelegation, S as SessionGrantProof, g as VerifiedSessionGrant } from './delegation-0LKZkmP2.cjs';
7
8
 
@@ -515,6 +516,9 @@ declare class NodeUserAuthorization implements IUserAuthorization {
515
516
  * @internal
516
517
  */
517
518
  private getCapabilityRequest;
519
+ private refreshNamedKeyFeatureForSignIn;
520
+ /** Manifest key paths that this sign-in cannot grant. */
521
+ get unavailableKeyPaths(): string[];
518
522
  private resolveSpaceName;
519
523
  /**
520
524
  * The plain-session primary abilities: `defaultActions` (the shared table)
@@ -1301,6 +1305,8 @@ declare class TinyCloudNode {
1301
1305
  private _hooks?;
1302
1306
  private _vault?;
1303
1307
  private _encryption?;
1308
+ private _namedKeyClient?;
1309
+ private _keysUnavailable;
1304
1310
  private _baseVaults;
1305
1311
  private _baseSecrets;
1306
1312
  private _secrets;
@@ -2162,6 +2168,10 @@ declare class TinyCloudNode {
2162
2168
  * Network-scoped encryption/decrypt service.
2163
2169
  */
2164
2170
  get encryption(): IEncryptionService;
2171
+ /** Named keys bound to the current session. */
2172
+ get keys(): NamedKeyClient;
2173
+ /** Manifest key paths unavailable during the latest `signIn()` attempt. */
2174
+ get keysUnavailable(): readonly string[];
2165
2175
  getEncryptionNetwork(nameOrNetworkId?: string): Promise<NetworkDescriptor | null>;
2166
2176
  createEncryptionNetwork(name?: string): Promise<NetworkDescriptor>;
2167
2177
  /**
@@ -1,7 +1,7 @@
1
1
  import { ReplicationOptions, PermissionEntry, TinyCloudSession, KVReplicaStorage, ServiceContext, IWasmBindings, WasmRecapEntry } from '@tinycloud/sdk-core';
2
2
  import { ReplicaConsentAnchor, AuthorityRefusal, ReplicationAuthority } from '@tinycloud/sdk-services';
3
3
  import { ReplicaLocalEraseOutcome, ReplicaPurgeLocalCopyResult, ReplicaPurgeTrigger, ReplicaPurgeFailedEvent, ReplicaSessionStamp, ReplicaDenyInput } from '@tinycloud/sdk-services/kv/replication';
4
- import { T as TinyCloudNode } from './TinyCloudNode-B6VOBrCb.js';
4
+ import { T as TinyCloudNode } from './TinyCloudNode-BKFo3t4u.js';
5
5
 
6
6
  /** Constructor-time validation; the space-dependent secrets check runs at sign-in and open. */
7
7
  declare function assertValidReplicationConfig(replication: (ReplicationOptions & {
@@ -1,7 +1,7 @@
1
1
  import { ReplicationOptions, PermissionEntry, TinyCloudSession, KVReplicaStorage, ServiceContext, IWasmBindings, WasmRecapEntry } from '@tinycloud/sdk-core';
2
2
  import { ReplicaConsentAnchor, AuthorityRefusal, ReplicationAuthority } from '@tinycloud/sdk-services';
3
3
  import { ReplicaLocalEraseOutcome, ReplicaPurgeLocalCopyResult, ReplicaPurgeTrigger, ReplicaPurgeFailedEvent, ReplicaSessionStamp, ReplicaDenyInput } from '@tinycloud/sdk-services/kv/replication';
4
- import { T as TinyCloudNode } from './TinyCloudNode-CVO41O12.cjs';
4
+ import { T as TinyCloudNode } from './TinyCloudNode-CxRHpusk.cjs';
5
5
 
6
6
  /** Constructor-time validation; the space-dependent secrets check runs at sign-in and open. */
7
7
  declare function assertValidReplicationConfig(replication: (ReplicationOptions & {
package/dist/core.cjs CHANGED
@@ -345,6 +345,32 @@ var FileSessionStorage = class {
345
345
  var import_node_crypto = require("crypto");
346
346
  var import_siwe = require("siwe");
347
347
  var import_sdk_core5 = require("@tinycloud/sdk-core");
348
+ var import_resource = require("@tinycloud/sdk-services/encryption/resource");
349
+ var import_sdk_services2 = require("@tinycloud/sdk-services");
350
+
351
+ // src/authorization/appKeyHostBinding.ts
352
+ var DOMAIN_LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
353
+ var IPV4 = /^\d+\.\d+\.\d+\.\d+$/;
354
+ var APP_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/;
355
+ function appKeyHostBinding(domain, appId) {
356
+ if (!APP_ID.test(appId)) return false;
357
+ if (domain.endsWith(":")) return false;
358
+ let url;
359
+ try {
360
+ url = new URL(`https://${domain}`);
361
+ } catch {
362
+ return false;
363
+ }
364
+ if (url.protocol !== "https:" || url.port !== "" || url.username !== "" || url.password !== "") return false;
365
+ if (url.pathname !== "/" || url.search !== "" || url.hash !== "") return false;
366
+ const host = url.hostname;
367
+ if (host.startsWith("[") || host.endsWith(".") || IPV4.test(host)) return false;
368
+ const labels = host.split(".");
369
+ if (labels.length < 2 || labels[labels.length - 1] === "localhost") return false;
370
+ if (!labels.every((label) => DOMAIN_LABEL.test(label))) return false;
371
+ const reversed = labels.reverse().join(".");
372
+ return appId === reversed || appId.startsWith(`${reversed}.`);
373
+ }
348
374
 
349
375
  // src/replication/authority-sign-in.ts
350
376
  var import_sdk_core2 = require("@tinycloud/sdk-core");
@@ -832,6 +858,23 @@ var NodeUserAuthorization = class {
832
858
  );
833
859
  return this._capabilityRequest;
834
860
  }
861
+ async refreshNamedKeyFeatureForSignIn(address, chainId) {
862
+ const request = this.getCapabilityRequest();
863
+ const siweDomain = this.siweConfig?.domain ?? this.domain;
864
+ const hasNamedKeys = request?.manifests.some((manifest) => manifest.keys?.length && appKeyHostBinding(siweDomain, manifest.keys_app_id ?? manifest.app_id));
865
+ if (hasNamedKeys) {
866
+ await this.resolveTinyCloudHostsForSignIn(address, chainId);
867
+ await this.refreshNodeInfo();
868
+ }
869
+ }
870
+ /** Manifest key paths that this sign-in cannot grant. */
871
+ get unavailableKeyPaths() {
872
+ const request = this.getCapabilityRequest();
873
+ const siweDomain = this.siweConfig?.domain ?? this.domain;
874
+ return (request?.manifests ?? []).flatMap(
875
+ (manifest) => this._nodeFeatures.includes("encryption-named-keys-v1") && appKeyHostBinding(siweDomain, manifest.keys_app_id ?? manifest.app_id) ? [] : (manifest.keys ?? []).map((entry) => "path" in entry ? entry.path : entry.prefix)
876
+ );
877
+ }
835
878
  resolveSpaceName(space, address, chainId) {
836
879
  if (space.startsWith("tinycloud:")) {
837
880
  return space;
@@ -1023,15 +1066,31 @@ var NodeUserAuthorization = class {
1023
1066
  }
1024
1067
  const rawAbilities = {};
1025
1068
  const currentDid = (0, import_sdk_core5.pkhDid)(address, chainId);
1069
+ if (this._nodeFeatures.includes("encryption-named-keys-v1")) {
1070
+ const siweDomain = this.siweConfig?.domain ?? this.domain;
1071
+ for (const manifest of request.manifests) {
1072
+ if (!appKeyHostBinding(siweDomain, manifest.keys_app_id ?? manifest.app_id)) continue;
1073
+ for (const declaration of manifest.keys ?? []) {
1074
+ const path = "path" in declaration ? declaration.path : declaration.prefix;
1075
+ const resource = `urn:tinycloud:encryption:${currentDid}:default/${path}`;
1076
+ for (const ability of declaration.abilities) {
1077
+ addRawAbility(rawAbilities, resource, `tinycloud.encryption/${ability}`);
1078
+ }
1079
+ }
1080
+ }
1081
+ }
1026
1082
  const spaceResources = request.resources.filter((entry) => {
1027
1083
  if (entry.service !== import_sdk_core5.ENCRYPTION_PERMISSION_SERVICE) {
1028
1084
  return true;
1029
1085
  }
1086
+ const parsed = entry.path.includes("/") ? (0, import_resource.parseEncryptionResource)(entry.path) : { ...(0, import_sdk_services2.parseNetworkId)(entry.path), kind: "network" };
1087
+ if (parsed.kind !== "network") {
1088
+ throw new import_sdk_core5.ManifestValidationError("named keys go in manifest.keys");
1089
+ }
1030
1090
  for (const action of entry.actions) {
1031
1091
  addRawAbility(rawAbilities, entry.path, action);
1032
1092
  }
1033
- if (entry.actions.includes(DECRYPT_ACTION)) {
1034
- const parsed = (0, import_sdk_core5.parseNetworkId)(entry.path);
1093
+ if (entry.actions.includes(DECRYPT_ACTION) && parsed.kind === "network") {
1035
1094
  if (didPrincipalMatches(parsed.ownerDid, currentDid)) {
1036
1095
  addRawAbility(rawAbilities, entry.path, NETWORK_CREATE_ACTION);
1037
1096
  }
@@ -1427,6 +1486,8 @@ var NodeUserAuthorization = class {
1427
1486
  this._chainId = chainId;
1428
1487
  await this.resolveTinyCloudHostsForSignIn(address, chainId);
1429
1488
  this.assertSignInCurrent(generation);
1489
+ await this.refreshNamedKeyFeatureForSignIn(address, chainId);
1490
+ this.assertSignInCurrent(generation);
1430
1491
  const keyId = `session-${Date.now()}`;
1431
1492
  this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
1432
1493
  this.activeSessionKeyId = keyId;
@@ -1573,6 +1634,7 @@ var NodeUserAuthorization = class {
1573
1634
  refuseCaveated(this.getCapabilityRequest()?.manifests);
1574
1635
  const address = (0, import_sdk_core5.canonicalizeAddress)(await this.signer.getAddress());
1575
1636
  const chainId = await this.signer.getChainId();
1637
+ await this.refreshNamedKeyFeatureForSignIn(address, chainId);
1576
1638
  const keyId = `session-${Date.now()}`;
1577
1639
  this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
1578
1640
  this.activeSessionKeyId = keyId;
@@ -2152,7 +2214,7 @@ var NodeUserAuthorization = class {
2152
2214
  };
2153
2215
 
2154
2216
  // src/recordingServiceContext.ts
2155
- var import_sdk_services2 = require("@tinycloud/sdk-services");
2217
+ var import_sdk_services3 = require("@tinycloud/sdk-services");
2156
2218
  var import_requestLog = require("@tinycloud/sdk-services/telemetry/requestLog");
2157
2219
 
2158
2220
  // src/recordingRegistry.ts
@@ -2197,9 +2259,9 @@ function replicationEvent(sample, op) {
2197
2259
  }
2198
2260
  function createServiceContext(config) {
2199
2261
  const { requestSink, ...base } = config;
2200
- return requestSink === void 0 ? new import_sdk_services2.ServiceContext(base) : new RecordingServiceContext(base, requestSink);
2262
+ return requestSink === void 0 ? new import_sdk_services3.ServiceContext(base) : new RecordingServiceContext(base, requestSink);
2201
2263
  }
2202
- var RecordingServiceContext = class extends import_sdk_services2.ServiceContext {
2264
+ var RecordingServiceContext = class extends import_sdk_services3.ServiceContext {
2203
2265
  constructor(config, sink) {
2204
2266
  const pending = {};
2205
2267
  super({
@@ -2793,8 +2855,9 @@ function deserializeDelegation(data) {
2793
2855
  // src/TinyCloudNode.ts
2794
2856
  var import_siwe2 = require("siwe");
2795
2857
  var import_sdk_core11 = require("@tinycloud/sdk-core");
2796
- var import_sdk_services3 = require("@tinycloud/sdk-services");
2858
+ var import_sdk_services4 = require("@tinycloud/sdk-services");
2797
2859
  var import_requestLog2 = require("@tinycloud/sdk-services/telemetry/requestLog");
2860
+ var import_resource2 = require("@tinycloud/sdk-services/encryption/resource");
2798
2861
 
2799
2862
  // src/account/AccountService.ts
2800
2863
  var import_sdk_core7 = require("@tinycloud/sdk-core");
@@ -3802,6 +3865,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3802
3865
  return void 0;
3803
3866
  }
3804
3867
  };
3868
+ this._keysUnavailable = [];
3805
3869
  this._baseVaults = /* @__PURE__ */ new Map();
3806
3870
  this._baseSecrets = /* @__PURE__ */ new Map();
3807
3871
  this._secrets = /* @__PURE__ */ new Map();
@@ -4629,6 +4693,8 @@ var _TinyCloudNode = class _TinyCloudNode {
4629
4693
  this._hooks = void 0;
4630
4694
  this._vault = void 0;
4631
4695
  this._encryption = void 0;
4696
+ this._namedKeyClient = void 0;
4697
+ this._keysUnavailable = [];
4632
4698
  this._baseVaults.clear();
4633
4699
  this._baseSecrets.clear();
4634
4700
  this._secrets.clear();
@@ -4751,6 +4817,8 @@ var _TinyCloudNode = class _TinyCloudNode {
4751
4817
  this._hooks = void 0;
4752
4818
  this._vault = void 0;
4753
4819
  this._encryption = void 0;
4820
+ this._namedKeyClient = void 0;
4821
+ this._keysUnavailable = [];
4754
4822
  this._baseVaults.clear();
4755
4823
  this._baseSecrets.clear();
4756
4824
  this._secrets.clear();
@@ -4803,6 +4871,26 @@ var _TinyCloudNode = class _TinyCloudNode {
4803
4871
  this.assertSessionEpoch(epoch, "Sign-in");
4804
4872
  await this.ensureRequestedEncryptionNetworks();
4805
4873
  this.assertSessionEpoch(epoch, "Sign-in");
4874
+ this._keysUnavailable = this.auth?.unavailableKeyPaths ?? [];
4875
+ if (this._keysUnavailable.length > 0) {
4876
+ this.notificationHandler.warning(`Named keys unavailable: ${this._keysUnavailable.join(", ")}`);
4877
+ }
4878
+ if (this.nodeFeatures.includes("encryption-named-keys-v1")) {
4879
+ for (const manifest of this.auth?.capabilityRequest?.manifests ?? []) {
4880
+ for (const declaration of manifest.keys ?? []) {
4881
+ if ("path" in declaration && declaration.abilities.includes("key.create") && !this._keysUnavailable.includes(declaration.path)) {
4882
+ try {
4883
+ await this.keys.ensureKey(declaration.path);
4884
+ } catch (error) {
4885
+ this._keysUnavailable.push(declaration.path);
4886
+ const code = error && typeof error === "object" && "code" in error && typeof error.code === "string" && /^[A-Z_]+$/.test(error.code) ? error.code : "UNKNOWN";
4887
+ this.notificationHandler.warning(`Named key unavailable: ${declaration.path} (${code})`);
4888
+ }
4889
+ this.assertSessionEpoch(epoch, "Sign-in");
4890
+ }
4891
+ }
4892
+ }
4893
+ }
4806
4894
  if (!bootstrapped && this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
4807
4895
  await this.ensureOwnedSpaceHostedById(this.ownedSpaceId(import_sdk_core11.SECRETS_SPACE));
4808
4896
  }
@@ -5379,7 +5467,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5379
5467
  if (!this.currentSessionCoversAccountRegistry()) {
5380
5468
  if (!_TinyCloudNode.accountRegistrySkipLogged) {
5381
5469
  _TinyCloudNode.accountRegistrySkipLogged = true;
5382
- import_sdk_services3.tinyCloudDebugLogger.log("registry.skip");
5470
+ import_sdk_services4.tinyCloudDebugLogger.log("registry.skip");
5383
5471
  }
5384
5472
  return;
5385
5473
  }
@@ -5590,7 +5678,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5590
5678
  const networkIds = /* @__PURE__ */ new Set();
5591
5679
  for (const resource of request.resources) {
5592
5680
  if (resource.service === import_sdk_core11.ENCRYPTION_PERMISSION_SERVICE && resource.path.startsWith("urn:tinycloud:encryption:") && resource.actions.includes(DECRYPT_ACTION2)) {
5593
- networkIds.add(resource.path);
5681
+ const parsed = resource.path.includes("/") ? (0, import_resource2.parseEncryptionResource)(resource.path) : { ...(0, import_sdk_core11.parseNetworkId)(resource.path), kind: "network" };
5682
+ if (parsed.kind === "network") networkIds.add(resource.path);
5594
5683
  }
5595
5684
  }
5596
5685
  return [...networkIds];
@@ -6140,6 +6229,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6140
6229
  this._hooks = stagedGraph.hooks;
6141
6230
  this._vault = stagedGraph.vault;
6142
6231
  this._encryption = stagedGraph.encryption;
6232
+ this._namedKeyClient = void 0;
6233
+ this._keysUnavailable = [];
6143
6234
  this._capabilityRegistry = stagedGraph.capabilityRegistry;
6144
6235
  this._keyProvider = stagedGraph.keyProvider;
6145
6236
  this._sharingService = stagedGraph.sharingService;
@@ -7049,7 +7140,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7049
7140
  );
7050
7141
  graph.assertActive();
7051
7142
  if (!response.ok) {
7052
- const permissionHint = response.status === 401 || response.status === 403 ? (0, import_sdk_services3.parsePermissionHint)({
7143
+ const permissionHint = response.status === 401 || response.status === 403 ? (0, import_sdk_services4.parsePermissionHint)({
7053
7144
  service: "tinycloud.encryption",
7054
7145
  path: networkId,
7055
7146
  actions: ["tinycloud.encryption/decrypt"]
@@ -7736,6 +7827,40 @@ var _TinyCloudNode = class _TinyCloudNode {
7736
7827
  get encryption() {
7737
7828
  return this.getEncryptionService();
7738
7829
  }
7830
+ /** Named keys bound to the current session. */
7831
+ get keys() {
7832
+ return new Proxy({}, {
7833
+ get: (_target, property) => {
7834
+ if (property === "refreshNodeInfo") {
7835
+ return () => {
7836
+ void this._namedKeyClient?.then((client) => client.refreshNodeInfo());
7837
+ };
7838
+ }
7839
+ if (typeof property !== "string" || ![
7840
+ "getPublicKey",
7841
+ "describeKey",
7842
+ "createKey",
7843
+ "blockKey",
7844
+ "unblockKey",
7845
+ "ensureKey",
7846
+ "encrypt",
7847
+ "decrypt",
7848
+ "decryptMany"
7849
+ ].includes(property)) return void 0;
7850
+ return (...args) => {
7851
+ this._namedKeyClient ?? (this._namedKeyClient = import("./encryption-keys.cjs").then(({ createNamedKeyClient }) => createNamedKeyClient(this)));
7852
+ return this._namedKeyClient.then((client) => {
7853
+ const method = client[property];
7854
+ return method.apply(client, args);
7855
+ });
7856
+ };
7857
+ }
7858
+ });
7859
+ }
7860
+ /** Manifest key paths unavailable during the latest `signIn()` attempt. */
7861
+ get keysUnavailable() {
7862
+ return this._keysUnavailable;
7863
+ }
7739
7864
  async getEncryptionNetwork(nameOrNetworkId = this.getDefaultEncryptionNetworkId()) {
7740
7865
  const networkId = nameOrNetworkId.startsWith("urn:tinycloud:encryption:") ? nameOrNetworkId : this.getDefaultEncryptionNetworkId(nameOrNetworkId);
7741
7866
  return this.fetchEncryptionNetworkAt(
@@ -7863,7 +7988,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7863
7988
  );
7864
7989
  if (result.status !== "ok") {
7865
7990
  if (result.status === "permission_required") {
7866
- const hint = (0, import_sdk_services3.parsePermissionHint)(result.hint);
7991
+ const hint = (0, import_sdk_services4.parsePermissionHint)(result.hint);
7867
7992
  if (hint === void 0) return { status: "read_failed" };
7868
7993
  return {
7869
7994
  status: "permission_required",