@tinycloud/sdk-services 2.7.0-beta.3 → 2.7.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.
Files changed (35) hide show
  1. package/dist/BaseService-BwBU5CQ4.d.cts +158 -0
  2. package/dist/BaseService-CnPTKR5G.d.ts +158 -0
  3. package/dist/encryption/index.cjs +46 -6
  4. package/dist/encryption/index.cjs.map +1 -1
  5. package/dist/encryption/index.d.cts +9 -1
  6. package/dist/encryption/index.d.ts +9 -1
  7. package/dist/encryption/index.js +45 -6
  8. package/dist/encryption/index.js.map +1 -1
  9. package/dist/index.cjs +299 -21
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +58 -9
  12. package/dist/index.d.ts +58 -9
  13. package/dist/index.js +293 -18
  14. package/dist/index.js.map +1 -1
  15. package/dist/internal/decrypt-transport-response-error.cjs +38 -0
  16. package/dist/internal/decrypt-transport-response-error.cjs.map +1 -0
  17. package/dist/internal/decrypt-transport-response-error.d.cts +10 -0
  18. package/dist/internal/decrypt-transport-response-error.d.ts +10 -0
  19. package/dist/internal/decrypt-transport-response-error.js +13 -0
  20. package/dist/internal/decrypt-transport-response-error.js.map +1 -0
  21. package/dist/kv/index.cjs +46 -4
  22. package/dist/kv/index.cjs.map +1 -1
  23. package/dist/kv/index.d.cts +2 -1
  24. package/dist/kv/index.d.ts +2 -1
  25. package/dist/kv/index.js +46 -4
  26. package/dist/kv/index.js.map +1 -1
  27. package/dist/sql/index.cjs +6 -2
  28. package/dist/sql/index.cjs.map +1 -1
  29. package/dist/sql/index.d.cts +2 -1
  30. package/dist/sql/index.d.ts +2 -1
  31. package/dist/sql/index.js +6 -2
  32. package/dist/sql/index.js.map +1 -1
  33. package/dist/{BaseService-C-EsEeGo.d.cts → types-DAY1O1kW.d.cts} +12 -156
  34. package/dist/{BaseService-C-EsEeGo.d.ts → types-DAY1O1kW.d.ts} +12 -156
  35. package/package.json +11 -3
package/dist/index.js CHANGED
@@ -67,6 +67,63 @@ function serviceError(code, message, service, options) {
67
67
  };
68
68
  }
69
69
 
70
+ // src/diagnostics.ts
71
+ var REDACTED = "[REDACTED]";
72
+ var SAFE_NUMBER_FIELDS = /* @__PURE__ */ new Set([
73
+ "duration",
74
+ "durationMs",
75
+ "endedAt",
76
+ "startedAt",
77
+ "status",
78
+ "timestamp"
79
+ ]);
80
+ var SAFE_BOOLEAN_FIELDS = /* @__PURE__ */ new Set(["authenticated", "ok", "persisted"]);
81
+ function finiteNumber(value) {
82
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
83
+ }
84
+ function isBinaryData(value) {
85
+ try {
86
+ return Array.isArray(value) || ArrayBuffer.isView(value) || value instanceof ArrayBuffer;
87
+ } catch {
88
+ return true;
89
+ }
90
+ }
91
+ function read(value, key) {
92
+ try {
93
+ return value[key];
94
+ } catch {
95
+ return REDACTED;
96
+ }
97
+ }
98
+ function projectDiagnosticError(error) {
99
+ if (typeof error !== "object" || error === null) return {};
100
+ const status = finiteNumber(read(error, "status"));
101
+ return status !== void 0 && status >= 100 && status <= 599 ? { status } : {};
102
+ }
103
+ function projectDiagnosticData(value) {
104
+ if (value === null || value === void 0) return value;
105
+ if (typeof value !== "object") return REDACTED;
106
+ try {
107
+ if (isBinaryData(value)) return REDACTED;
108
+ const projected = {};
109
+ for (const key of SAFE_NUMBER_FIELDS) {
110
+ const number = finiteNumber(read(value, key));
111
+ if (number !== void 0) projected[key] = number;
112
+ }
113
+ for (const key of SAFE_BOOLEAN_FIELDS) {
114
+ const boolean = read(value, key);
115
+ if (typeof boolean === "boolean") projected[key] = boolean;
116
+ }
117
+ const url = read(value, "url");
118
+ if (url !== void 0) projected.url = REDACTED;
119
+ const error = read(value, "error");
120
+ if (error !== void 0) projected.error = projectDiagnosticError(error);
121
+ return projected;
122
+ } catch {
123
+ return REDACTED;
124
+ }
125
+ }
126
+
70
127
  // src/debug.ts
71
128
  var DEBUG_FLAG = "TinyCloud_debug";
72
129
  var MAX_EVENTS = 1e3;
@@ -225,6 +282,8 @@ var TinyCloudDebugLogger = class {
225
282
  record(event) {
226
283
  const debugEvent = {
227
284
  ...event,
285
+ ...event.data === void 0 ? {} : { data: projectDiagnosticData(event.data) },
286
+ ...event.message === void 0 ? {} : { message: "[REDACTED]" },
228
287
  sequence: ++this.sequence
229
288
  };
230
289
  this.events.push(debugEvent);
@@ -504,6 +563,7 @@ var ServiceContext = class {
504
563
  this._services = /* @__PURE__ */ new Map();
505
564
  this._eventHandlers = /* @__PURE__ */ new Map();
506
565
  this._abortController = new AbortController();
566
+ this._retired = false;
507
567
  this._invoke = this.wrapInvoke(config.invoke);
508
568
  this._invokeAny = config.invokeAny ? this.wrapInvokeAny(config.invokeAny) : void 0;
509
569
  this._fetch = this.wrapFetch(config.fetch ?? globalThis.fetch.bind(globalThis));
@@ -523,13 +583,13 @@ var ServiceContext = class {
523
583
  * Get the current session.
524
584
  */
525
585
  get session() {
526
- return this._session;
586
+ return this._retired ? null : this._session;
527
587
  }
528
588
  /**
529
589
  * Check if the context has an authenticated session.
530
590
  */
531
591
  get isAuthenticated() {
532
- return this._session !== null;
592
+ return !this._retired && this._session !== null;
533
593
  }
534
594
  /**
535
595
  * Update the session and notify all registered services.
@@ -537,6 +597,7 @@ var ServiceContext = class {
537
597
  * @param session - New session or null to clear
538
598
  */
539
599
  setSession(session) {
600
+ this.assertActive();
540
601
  this._session = session;
541
602
  this.emit("session.changed", { authenticated: session !== null });
542
603
  for (const service of this._services.values()) {
@@ -550,24 +611,28 @@ var ServiceContext = class {
550
611
  * Get the invoke function for WASM operations.
551
612
  */
552
613
  get invoke() {
614
+ this.assertActive();
553
615
  return this._invoke;
554
616
  }
555
617
  /**
556
618
  * Get the multi-resource invoke function when available.
557
619
  */
558
620
  get invokeAny() {
621
+ this.assertActive();
559
622
  return this._invokeAny;
560
623
  }
561
624
  /**
562
625
  * Get the fetch function for HTTP requests.
563
626
  */
564
627
  get fetch() {
628
+ this.assertActive();
565
629
  return this._fetch;
566
630
  }
567
631
  /**
568
632
  * Get the list of TinyCloud host URLs.
569
633
  */
570
634
  get hosts() {
635
+ this.assertActive();
571
636
  return this._hosts;
572
637
  }
573
638
  // ============================================================
@@ -612,7 +677,7 @@ var ServiceContext = class {
612
677
  tinyCloudDebugLogger.log(event, data);
613
678
  if (this._telemetryEnabled && this._telemetryHandler) {
614
679
  try {
615
- this._telemetryHandler(event, data);
680
+ this._telemetryHandler(event, projectDiagnosticData(data));
616
681
  } catch (error) {
617
682
  console.error(`Error in telemetry handler for "${event}":`, error);
618
683
  }
@@ -671,21 +736,45 @@ var ServiceContext = class {
671
736
  get abortSignal() {
672
737
  return this._abortController.signal;
673
738
  }
739
+ /**
740
+ * Permanently retire this graph after its owner installs a replacement.
741
+ * Unlike `abort()`, retirement never creates a fresh controller, so captured
742
+ * services cannot resume calls under a superseded session.
743
+ */
744
+ retire() {
745
+ if (this._retired) return;
746
+ this._retired = true;
747
+ this._session = null;
748
+ this._abortController.abort();
749
+ for (const service of this._services.values()) {
750
+ try {
751
+ service.onSignOut();
752
+ } catch (error) {
753
+ console.error("Error retiring service:", error);
754
+ }
755
+ }
756
+ }
674
757
  /**
675
758
  * Abort all pending operations and notify services.
676
759
  * Creates a new AbortController for future operations.
677
760
  */
678
761
  abort() {
762
+ if (this._retired) return;
679
763
  this._abortController.abort();
680
764
  this._abortController = new AbortController();
681
765
  for (const service of this._services.values()) {
682
- service.onSignOut();
766
+ try {
767
+ service.onSignOut();
768
+ } catch (error) {
769
+ console.error("Error signing out service:", error);
770
+ }
683
771
  }
684
772
  }
685
773
  /**
686
774
  * Sign out - abort operations and clear session.
687
775
  */
688
776
  signOut() {
777
+ if (this._retired) return;
689
778
  this.abort();
690
779
  this.setSession(null);
691
780
  this.emit("session.expired", {});
@@ -701,6 +790,7 @@ var ServiceContext = class {
701
790
  }
702
791
  wrapInvoke(invoke) {
703
792
  return (session, service, path, action, facts) => {
793
+ this.assertActive();
704
794
  if (!tinyCloudDebugLogger.isEnabled()) {
705
795
  return invoke(session, service, path, action, facts);
706
796
  }
@@ -720,8 +810,14 @@ var ServiceContext = class {
720
810
  }
721
811
  };
722
812
  }
813
+ assertActive() {
814
+ if (this._retired) {
815
+ throw new Error("Service graph has been retired by session replacement.");
816
+ }
817
+ }
723
818
  wrapInvokeAny(invokeAny) {
724
819
  return (session, entries, facts) => {
820
+ this.assertActive();
725
821
  if (!tinyCloudDebugLogger.isEnabled()) {
726
822
  return invokeAny(session, entries, facts);
727
823
  }
@@ -741,20 +837,25 @@ var ServiceContext = class {
741
837
  }
742
838
  wrapFetch(fetchFn) {
743
839
  return async (url, init) => {
840
+ this.assertActive();
841
+ const request = {
842
+ ...init,
843
+ signal: this.combineSignals(init?.signal)
844
+ };
744
845
  if (!tinyCloudDebugLogger.isEnabled()) {
745
- return fetchFn(url, init);
846
+ return fetchFn(url, request);
746
847
  }
747
848
  const timer = tinyCloudDebugLogger.startTimer("sdk.fetch", {
748
849
  url,
749
- method: init?.method ?? "GET",
750
- init
850
+ method: request.method ?? "GET",
851
+ init: request
751
852
  });
752
853
  try {
753
- const response = await fetchFn(url, init);
854
+ const response = await fetchFn(url, request);
754
855
  timer.stop({
755
856
  ok: response.ok,
756
857
  url,
757
- method: init?.method ?? "GET",
858
+ method: request.method ?? "GET",
758
859
  status: response.status,
759
860
  statusText: response.statusText
760
861
  });
@@ -763,16 +864,70 @@ var ServiceContext = class {
763
864
  timer.stop({
764
865
  ok: false,
765
866
  url,
766
- method: init?.method ?? "GET",
867
+ method: request.method ?? "GET",
767
868
  error
768
869
  });
769
870
  throw error;
770
871
  }
771
872
  };
772
873
  }
874
+ combineSignals(signal) {
875
+ if (!signal) return this._abortController.signal;
876
+ const combined = new AbortController();
877
+ const abort = (source) => combined.abort(source.reason);
878
+ if (signal.aborted) {
879
+ abort(signal);
880
+ } else if (this._abortController.signal.aborted) {
881
+ abort(this._abortController.signal);
882
+ } else {
883
+ signal.addEventListener("abort", () => abort(signal), { once: true });
884
+ this._abortController.signal.addEventListener(
885
+ "abort",
886
+ () => abort(this._abortController.signal),
887
+ { once: true }
888
+ );
889
+ }
890
+ return combined.signal;
891
+ }
773
892
  };
774
893
 
775
894
  // src/errors.ts
895
+ function parsePermissionHint(value) {
896
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
897
+ const candidate = value;
898
+ const keys = Object.keys(candidate).sort();
899
+ if (keys.some((key) => !["actions", "path", "service", "space"].includes(key))) return void 0;
900
+ if (candidate.service !== "tinycloud.kv" && candidate.service !== "tinycloud.encryption") return void 0;
901
+ if (typeof candidate.path !== "string" || candidate.path.length === 0 || candidate.path.includes("*")) return void 0;
902
+ if (candidate.service === "tinycloud.kv" && (typeof candidate.space !== "string" || candidate.space.length === 0 || !candidate.path.startsWith("vault/") || candidate.path.endsWith("/"))) {
903
+ return void 0;
904
+ }
905
+ if (candidate.service === "tinycloud.encryption" && (candidate.space !== void 0 || !candidate.path.startsWith("urn:tinycloud:encryption:") || candidate.path.endsWith(":"))) {
906
+ return void 0;
907
+ }
908
+ if (!Array.isArray(candidate.actions) || candidate.actions.length !== 1 || typeof candidate.actions[0] !== "string" || candidate.actions[0].includes("*")) return void 0;
909
+ const expectedAction = candidate.service === "tinycloud.kv" ? "tinycloud.kv/get" : "tinycloud.encryption/decrypt";
910
+ if (candidate.actions[0] !== expectedAction) return void 0;
911
+ const space = typeof candidate.space === "string" ? candidate.space : void 0;
912
+ return {
913
+ service: candidate.service,
914
+ ...space === void 0 ? {} : { space },
915
+ path: candidate.path,
916
+ actions: [candidate.actions[0]]
917
+ };
918
+ }
919
+ function parsePermissionHintFromErrorText(text) {
920
+ try {
921
+ const parsed = JSON.parse(text);
922
+ if (typeof parsed !== "object" || parsed === null) return void 0;
923
+ const root = parsed;
924
+ const nested = root.error;
925
+ const nestedRecord = typeof nested === "object" && nested !== null ? nested : void 0;
926
+ return parsePermissionHint(root.permissionHint) ?? parsePermissionHint(nestedRecord?.permissionHint);
927
+ } catch {
928
+ return void 0;
929
+ }
930
+ }
776
931
  function authRequiredError(service) {
777
932
  return {
778
933
  code: ErrorCodes.AUTH_REQUIRED,
@@ -923,7 +1078,7 @@ var BaseService = class {
923
1078
  * Combines the service-level abort with context-level abort.
924
1079
  */
925
1080
  get abortSignal() {
926
- return this.abortController.signal;
1081
+ return this.combineSignals();
927
1082
  }
928
1083
  /**
929
1084
  * Check if the service is authenticated.
@@ -1039,7 +1194,11 @@ var BaseService = class {
1039
1194
  */
1040
1195
  combineSignals(...signals) {
1041
1196
  const controller = new AbortController();
1042
- const allSignals = [this.abortSignal, ...signals.filter(Boolean)];
1197
+ const allSignals = [
1198
+ this.abortController.signal,
1199
+ this.context?.abortSignal,
1200
+ ...signals.filter(Boolean)
1201
+ ].filter(Boolean);
1043
1202
  for (const signal of allSignals) {
1044
1203
  if (signal.aborted) {
1045
1204
  controller.abort(signal.reason);
@@ -1512,13 +1671,15 @@ var KVService = class extends BaseService {
1512
1671
  options?.signal
1513
1672
  );
1514
1673
  if (!response.ok) {
1515
- if (response.status === 401) {
1674
+ if (response.status === 401 || response.status === 403) {
1516
1675
  const errorText2 = await response.text();
1517
1676
  const { resource, action } = parseAuthError(errorText2);
1677
+ const permissionHint = parsePermissionHintFromErrorText(errorText2);
1518
1678
  return err(authUnauthorizedError("kv", errorText2, {
1519
1679
  status: response.status,
1520
1680
  ...action && { requiredAction: action },
1521
- ...resource && { resource }
1681
+ ...resource && { resource },
1682
+ ...permissionHint === void 0 ? {} : { permissionHint }
1522
1683
  }));
1523
1684
  }
1524
1685
  if (response.status === 404) {
@@ -3744,6 +3905,9 @@ function unwrapKVData(value) {
3744
3905
  }
3745
3906
  return value;
3746
3907
  }
3908
+ function hasHttpResponse(error) {
3909
+ return typeof error.meta?.status === "number";
3910
+ }
3747
3911
  function isUnlockSigner(signer) {
3748
3912
  return typeof signer === "object" && signer !== null && typeof signer.signMessage === "function";
3749
3913
  }
@@ -4117,6 +4281,80 @@ var DataVaultService = class extends BaseService {
4117
4281
  });
4118
4282
  }
4119
4283
  }
4284
+ /**
4285
+ * Read a network-encrypted entry while preserving safe failure phases.
4286
+ *
4287
+ * Unlike {@link getNetworkEncrypted}, this is intentionally message-free so
4288
+ * an operation layer can distinguish an authorized absence from a failed
4289
+ * read without receiving node, envelope, plaintext, or key material.
4290
+ */
4291
+ async readNetworkEncrypted(key, options) {
4292
+ const config = this.networkEncryption;
4293
+ if (!config || !this.requireAuth()) {
4294
+ return { status: "read_failed" };
4295
+ }
4296
+ let valueResult;
4297
+ try {
4298
+ valueResult = await this.tc.kv.get(`vault/${key}`, { raw: true });
4299
+ } catch {
4300
+ return { status: "node_unreachable" };
4301
+ }
4302
+ if (!valueResult.ok) {
4303
+ const permissionHint = parsePermissionHint(valueResult.error.meta?.permissionHint);
4304
+ if (valueResult.error.code === "AUTH_UNAUTHORIZED" && permissionHint !== void 0) {
4305
+ return { status: "permission_required", hint: permissionHint };
4306
+ }
4307
+ if ((valueResult.error.code === "NOT_FOUND" || valueResult.error.code === "KV_NOT_FOUND") && !hasHttpResponse(valueResult.error)) {
4308
+ return { status: "not_found" };
4309
+ }
4310
+ if (valueResult.error.code === "NETWORK_ERROR" || valueResult.error.code === "TIMEOUT" || valueResult.error.code === "ABORTED") {
4311
+ return hasHttpResponse(valueResult.error) ? { status: "read_failed" } : { status: "node_unreachable" };
4312
+ }
4313
+ return { status: "read_failed" };
4314
+ }
4315
+ let envelope;
4316
+ try {
4317
+ const rawEnvelope = unwrapKVData(valueResult.data);
4318
+ envelope = typeof rawEnvelope === "string" ? JSON.parse(rawEnvelope) : rawEnvelope;
4319
+ } catch {
4320
+ return { status: "corrupt_envelope" };
4321
+ }
4322
+ let plaintextResult;
4323
+ try {
4324
+ const proof = await this.decryptCapabilityProof();
4325
+ plaintextResult = await config.service.decryptEnvelope(envelope, proof);
4326
+ } catch {
4327
+ return { status: "decrypt_failed" };
4328
+ }
4329
+ if (!plaintextResult.ok) {
4330
+ const permissionHint = parsePermissionHint(
4331
+ plaintextResult.error.permissionHint
4332
+ );
4333
+ if (plaintextResult.error.code === "DECRYPT_DENIED" && permissionHint !== void 0) {
4334
+ return { status: "permission_required", hint: permissionHint };
4335
+ }
4336
+ if (plaintextResult.error.code === "INVALID_ENVELOPE") {
4337
+ return { status: "corrupt_envelope" };
4338
+ }
4339
+ if (plaintextResult.error.code === "TRANSPORT_ERROR") {
4340
+ return { status: "node_unreachable" };
4341
+ }
4342
+ return { status: "decrypt_failed" };
4343
+ }
4344
+ try {
4345
+ const metadata = envelope.metadata ?? {};
4346
+ const contentType = metadata[VaultHeaders.CONTENT_TYPE] ?? "application/json";
4347
+ const keyId = metadata[VaultHeaders.KEY_ID] ?? envelope.encryptedSymmetricKeyHash.slice(0, 16);
4348
+ const value = this.deserializeValue(
4349
+ plaintextResult.data,
4350
+ contentType,
4351
+ options
4352
+ );
4353
+ return { status: "ok", entry: { value, metadata, keyId } };
4354
+ } catch {
4355
+ return { status: "invalid_payload" };
4356
+ }
4357
+ }
4120
4358
  async headNetworkEncrypted(key) {
4121
4359
  if (!this.requireAuth()) {
4122
4360
  return vaultError({
@@ -5944,6 +6182,8 @@ function openWrappedKey(crypto2, receiverPrivateKey, response) {
5944
6182
  }
5945
6183
 
5946
6184
  // src/encryption/EncryptionService.ts
6185
+ import { DecryptTransportResponseError } from "@tinycloud/sdk-services/internal/decrypt-transport-response-error";
6186
+ import { DecryptTransportResponseError as DecryptTransportResponseError2 } from "@tinycloud/sdk-services/internal/decrypt-transport-response-error";
5947
6187
  function encOk(data) {
5948
6188
  return { ok: true, data };
5949
6189
  }
@@ -5962,17 +6202,20 @@ var EncryptionService = class extends BaseService {
5962
6202
  return this._config.crypto;
5963
6203
  }
5964
6204
  async discoverNetwork(identifier, ownerDid) {
6205
+ this.assertActive();
5965
6206
  const result = await discoverNetwork({
5966
6207
  identifier,
5967
6208
  ...ownerDid !== void 0 ? { ownerDid } : {},
5968
6209
  ...this._config.node !== void 0 ? { node: this._config.node } : {},
5969
6210
  ...this._config.wellKnown !== void 0 ? { wellKnown: this._config.wellKnown } : {}
5970
6211
  });
6212
+ this.assertActive();
5971
6213
  if (!result.ok) return result;
5972
6214
  return encOk(result.data.descriptor);
5973
6215
  }
5974
6216
  async encryptToNetwork(networkId, plaintext, options) {
5975
6217
  try {
6218
+ this.assertActive();
5976
6219
  const discovered = await this.discoverNetwork(networkId);
5977
6220
  if (!discovered.ok) return discovered;
5978
6221
  const usable = ensureNetworkUsableForDecrypt(discovered.data);
@@ -6000,6 +6243,7 @@ var EncryptionService = class extends BaseService {
6000
6243
  }
6001
6244
  async decryptEnvelope(envelope, capabilityProof, options) {
6002
6245
  try {
6246
+ this.assertActive();
6003
6247
  const validated = validateEnvelope(this.crypto, envelope);
6004
6248
  if (!validated.ok) return validated;
6005
6249
  if (options?.aad !== void 0 && validated.data.aad !== base64Encode2(options.aad)) {
@@ -6065,16 +6309,38 @@ var EncryptionService = class extends BaseService {
6065
6309
  facts,
6066
6310
  proof: capabilityProof
6067
6311
  });
6068
- if (!built.ok) return built;
6312
+ this.assertActive();
6313
+ if (!built.ok) {
6314
+ if (built.error.code !== "TRANSPORT_ERROR") return built;
6315
+ return encErr(
6316
+ encryptionError({
6317
+ code: "INVALID_INPUT",
6318
+ message: "Unable to build decrypt request"
6319
+ })
6320
+ );
6321
+ }
6069
6322
  let response;
6070
6323
  try {
6071
6324
  response = await this._config.transport.postDecrypt({
6072
6325
  targetNode,
6073
6326
  networkId: envelope.networkId,
6074
6327
  authorization: built.data.authorization,
6075
- canonicalBody: built.data.canonicalBody
6328
+ canonicalBody: built.data.canonicalBody,
6329
+ signal: this.abortSignal
6076
6330
  });
6331
+ this.assertActive();
6077
6332
  } catch (error) {
6333
+ if (error instanceof DecryptTransportResponseError) {
6334
+ return encErr(
6335
+ encryptionError(
6336
+ error.status === 401 || error.status === 403 ? {
6337
+ code: "DECRYPT_DENIED",
6338
+ message: "Node denied decrypt request",
6339
+ ...error.permissionHint === void 0 ? {} : { permissionHint: error.permissionHint }
6340
+ } : { code: "INVALID_RESPONSE", message: "Node decrypt request failed" }
6341
+ )
6342
+ );
6343
+ }
6078
6344
  return encErr(
6079
6345
  encryptionError({
6080
6346
  code: "TRANSPORT_ERROR",
@@ -6105,14 +6371,20 @@ var EncryptionService = class extends BaseService {
6105
6371
  } catch (error) {
6106
6372
  return encErr(
6107
6373
  encryptionError({
6108
- code: "TRANSPORT_ERROR",
6109
- cause: toError2(error)
6374
+ code: "INVALID_RESPONSE",
6375
+ message: "Local decryption failed"
6110
6376
  })
6111
6377
  );
6112
6378
  }
6113
6379
  }
6380
+ assertActive() {
6381
+ this._config.assertActive?.();
6382
+ }
6114
6383
  };
6115
6384
  EncryptionService.serviceName = "encryption";
6385
+
6386
+ // src/encryption/index.ts
6387
+ import { DecryptTransportResponseError as DecryptTransportResponseError3 } from "@tinycloud/sdk-services/internal/decrypt-transport-response-error";
6116
6388
  export {
6117
6389
  BaseService,
6118
6390
  DECRYPT_ACTION,
@@ -6123,6 +6395,7 @@ export {
6123
6395
  DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
6124
6396
  DataVaultService,
6125
6397
  DatabaseHandle,
6398
+ DecryptTransportResponseError3 as DecryptTransportResponseError,
6126
6399
  DuckDbAction,
6127
6400
  DuckDbDatabaseHandle,
6128
6401
  DuckDbService,
@@ -6206,6 +6479,8 @@ export {
6206
6479
  openWrappedKey,
6207
6480
  parseAuthError,
6208
6481
  parseNetworkId,
6482
+ parsePermissionHint,
6483
+ parsePermissionHintFromErrorText,
6209
6484
  permissionDeniedError,
6210
6485
  resolveSecretListPrefix,
6211
6486
  resolveSecretPath,