@tinycloud/sdk-services 3.11.0-beta.2 → 3.12.0-beta.3

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 (71) hide show
  1. package/dist/{BaseService-Ma2MwJAd.d.ts → BaseService-BRDG69KR.d.ts} +1 -1
  2. package/dist/{BaseService-O0iyuFLk.d.cts → BaseService-CdBkfPGE.d.cts} +1 -1
  3. package/dist/{IHooksService-4QNODVy6.d.cts → IHooksService-C9p3stsB.d.cts} +1 -1
  4. package/dist/{IHooksService-CvTpJbQD.d.ts → IHooksService-D6eyZat1.d.ts} +1 -1
  5. package/dist/{ISQLService-Aly1CBsW.d.ts → ISQLService-B_4KcGA-.d.ts} +1 -1
  6. package/dist/{ISQLService-BOgWzHLT.d.cts → ISQLService-C6nNpcls.d.cts} +1 -1
  7. package/dist/context.cjs +4 -0
  8. package/dist/context.cjs.map +1 -1
  9. package/dist/context.d.cts +1 -1
  10. package/dist/context.d.ts +1 -1
  11. package/dist/context.js +4 -0
  12. package/dist/context.js.map +1 -1
  13. package/dist/encryption/index.cjs +60 -3
  14. package/dist/encryption/index.cjs.map +1 -1
  15. package/dist/encryption/index.d.cts +12 -22
  16. package/dist/encryption/index.d.ts +12 -22
  17. package/dist/encryption/index.js +60 -3
  18. package/dist/encryption/index.js.map +1 -1
  19. package/dist/encryption/named-keys.cjs +2 -0
  20. package/dist/encryption/named-keys.cjs.map +1 -1
  21. package/dist/encryption/named-keys.d.cts +2 -2
  22. package/dist/encryption/named-keys.d.ts +2 -2
  23. package/dist/encryption/named-keys.js +2 -0
  24. package/dist/encryption/named-keys.js.map +1 -1
  25. package/dist/encryption/resource.cjs.map +1 -1
  26. package/dist/encryption/resource.js.map +1 -1
  27. package/dist/feed/index.cjs +4 -0
  28. package/dist/feed/index.cjs.map +1 -1
  29. package/dist/feed/index.d.cts +3 -3
  30. package/dist/feed/index.d.ts +3 -3
  31. package/dist/feed/index.js +4 -0
  32. package/dist/feed/index.js.map +1 -1
  33. package/dist/index.cjs +260 -7
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +14 -12
  36. package/dist/index.d.ts +14 -12
  37. package/dist/index.js +253 -7
  38. package/dist/index.js.map +1 -1
  39. package/dist/internal/decrypt-transport-response-error.d.cts +1 -1
  40. package/dist/internal/decrypt-transport-response-error.d.ts +1 -1
  41. package/dist/kv/index.cjs +34 -0
  42. package/dist/kv/index.cjs.map +1 -1
  43. package/dist/kv/index.d.cts +4 -4
  44. package/dist/kv/index.d.ts +4 -4
  45. package/dist/kv/index.js +34 -0
  46. package/dist/kv/index.js.map +1 -1
  47. package/dist/kv/replication/index.cjs +34 -0
  48. package/dist/kv/replication/index.cjs.map +1 -1
  49. package/dist/kv/replication/index.d.cts +3 -3
  50. package/dist/kv/replication/index.d.ts +3 -3
  51. package/dist/kv/replication/index.js +34 -0
  52. package/dist/kv/replication/index.js.map +1 -1
  53. package/dist/{scope-DEgc9f-W.d.cts → scope-DtcbyRKY.d.cts} +1 -1
  54. package/dist/{scope-BZr0QwxX.d.ts → scope-J20PQP3u.d.ts} +1 -1
  55. package/dist/sql/index.cjs +36 -0
  56. package/dist/sql/index.cjs.map +1 -1
  57. package/dist/sql/index.d.cts +4 -4
  58. package/dist/sql/index.d.ts +4 -4
  59. package/dist/sql/index.js +36 -0
  60. package/dist/sql/index.js.map +1 -1
  61. package/dist/telemetry/requestLog.cjs +4 -0
  62. package/dist/telemetry/requestLog.cjs.map +1 -1
  63. package/dist/telemetry/requestLog.d.cts +1 -1
  64. package/dist/telemetry/requestLog.d.ts +1 -1
  65. package/dist/telemetry/requestLog.js +4 -0
  66. package/dist/telemetry/requestLog.js.map +1 -1
  67. package/dist/{types-CSd0RYir.d.ts → types-DjAP8dve.d.cts} +4 -0
  68. package/dist/{types-CSd0RYir.d.cts → types-DjAP8dve.d.ts} +4 -0
  69. package/dist/{types-D4XbIfFJ.d.cts → types-XE4tyBLH.d.ts} +60 -3
  70. package/dist/{types-Bf91gup6.d.ts → types-cWtQmCCw.d.cts} +60 -3
  71. package/package.json +1 -1
@@ -1,25 +1,9 @@
1
- import { B as BaseService } from '../BaseService-O0iyuFLk.cjs';
2
- import { c as IService, f as Result } from '../types-CSd0RYir.cjs';
3
- import { N as NetworkDescriptor, n as EncryptionError, I as InlineEncryptedEnvelope, D as DecryptCapabilityProof, j as DecryptResponseBody, E as EncryptionCrypto, h as DecryptInvocationSigner, p as ReceiverKeySigner, R as ReceiverKeyPair, i as DecryptRequestBody, g as DecryptInvocationFact, B as BuildDecryptInvocationInput, a as BuiltDecryptInvocation } from '../types-D4XbIfFJ.cjs';
4
- export { C as CanonicalJson, b as DECRYPT_ACTION, c as DECRYPT_FACT_TYPE, d as DECRYPT_RESULT_TYPE, e as DEFAULT_ENCRYPTION_ALG, f as DEFAULT_KEY_VERSION, k as ENCRYPTION_SERVICE, l as ENCRYPTION_SERVICE_SHORT, m as ENVELOPE_VERSION, o as EncryptionErrorInput, J as Json, q as base64Decode, r as base64Encode, s as canonicalHashHex, t as canonicalize, u as encryptionError, v as hexDecode, w as hexEncode, x as utf8Decode, y as utf8Encode } from '../types-D4XbIfFJ.cjs';
1
+ import { B as BaseService } from '../BaseService-CdBkfPGE.cjs';
2
+ import { c as IService, f as Result } from '../types-DjAP8dve.cjs';
3
+ import { N as NetworkDescriptor, n as EncryptionError, I as InlineEncryptedEnvelope, D as DecryptCapabilityProof, j as DecryptResponseBody, E as EncryptionCrypto, h as DecryptInvocationSigner, s as ReceiverKeySigner, r as ReceiverKeyPair, i as DecryptRequestBody, g as DecryptInvocationFact, B as BuildDecryptInvocationInput, a as BuiltDecryptInvocation } from '../types-cWtQmCCw.cjs';
4
+ export { C as CanonicalJson, b as DECRYPT_ACTION, c as DECRYPT_FACT_TYPE, d as DECRYPT_RESULT_TYPE, e as DEFAULT_ENCRYPTION_ALG, f as DEFAULT_KEY_VERSION, k as ENCRYPTION_SERVICE, l as ENCRYPTION_SERVICE_SHORT, m as ENVELOPE_VERSION, o as EncryptionErrorInput, J as Json, x as base64Decode, y as base64Encode, z as canonicalHashHex, A as canonicalize, G as encryptionError, H as hexDecode, K as hexEncode, M as utf8Decode, O as utf8Encode } from '../types-cWtQmCCw.cjs';
5
5
  export { DecryptTransportResponseError } from '@tinycloud/sdk-services/internal/decrypt-transport-response-error';
6
6
 
7
- /**
8
- * Network-descriptor discovery.
9
- *
10
- * Resolution order (per architecture):
11
- *
12
- * 1. The node's authoritative endpoint
13
- * `GET /encryption/networks/<networkId>` returns the current
14
- * descriptor (`state`, `publicEncryptionKey`, `keyVersion`, ...).
15
- * 2. If the node is unreachable, fall back to the cached discovery
16
- * record at `.well-known/encryption/network/<name>` inside the
17
- * owner's public space.
18
- *
19
- * The node DB is authoritative on conflict; cached records are
20
- * advisory only.
21
- */
22
-
23
7
  type DiscoverySource = "node" | "well-known";
24
8
  interface DiscoveredNetwork {
25
9
  descriptor: NetworkDescriptor;
@@ -45,8 +29,8 @@ interface DiscoverNetworkInput {
45
29
  wellKnown?: WellKnownDescriptorFetcher;
46
30
  }
47
31
  /**
48
- * Resolve a network descriptor. The node fetcher is preferred; the
49
- * well-known fallback is used only on transport failure.
32
+ * Resolve a network descriptor. The node fetcher is preferred. An optional
33
+ * well-known cache cannot override a typed registry, identity, or transport failure.
50
34
  *
51
35
  * The returned descriptor is sanity-checked: `networkId`, `ownerDid`,
52
36
  * and `name` must agree with the URN, and the public key field must
@@ -131,6 +115,10 @@ interface IEncryptionService extends IService {
131
115
  *
132
116
  * The capability proof must root at the network owner DID embedded
133
117
  * in the envelope's networkId.
118
+ *
119
+ * Unresponsive decrypt transports use DECRYPTION_DEPENDENCY_UNAVAILABLE.
120
+ * HTTP failure, identity, registry and caller-cancellation classifications
121
+ * remain distinct; a failed request never returns partial plaintext.
134
122
  */
135
123
  decryptEnvelope(envelope: InlineEncryptedEnvelope, capabilityProof: DecryptCapabilityProof, options?: DecryptEnvelopeOptions): Promise<Result<Uint8Array, EncryptionError>>;
136
124
  }
@@ -173,6 +161,8 @@ interface EncryptionServiceConfig {
173
161
  transport: DecryptTransport;
174
162
  node?: NodeDescriptorFetcher;
175
163
  wellKnown?: WellKnownDescriptorFetcher;
164
+ /** Verified registry destination; overrides descriptor order and caller hints. */
165
+ resolveTargetNode?: (networkId: string) => Promise<string>;
176
166
  /** Bound by an owning service graph to prevent cross-session authority use. */
177
167
  assertActive?: () => void;
178
168
  [key: string]: unknown;
@@ -1,25 +1,9 @@
1
- import { B as BaseService } from '../BaseService-Ma2MwJAd.js';
2
- import { c as IService, f as Result } from '../types-CSd0RYir.js';
3
- import { N as NetworkDescriptor, n as EncryptionError, I as InlineEncryptedEnvelope, D as DecryptCapabilityProof, j as DecryptResponseBody, E as EncryptionCrypto, h as DecryptInvocationSigner, p as ReceiverKeySigner, R as ReceiverKeyPair, i as DecryptRequestBody, g as DecryptInvocationFact, B as BuildDecryptInvocationInput, a as BuiltDecryptInvocation } from '../types-Bf91gup6.js';
4
- export { C as CanonicalJson, b as DECRYPT_ACTION, c as DECRYPT_FACT_TYPE, d as DECRYPT_RESULT_TYPE, e as DEFAULT_ENCRYPTION_ALG, f as DEFAULT_KEY_VERSION, k as ENCRYPTION_SERVICE, l as ENCRYPTION_SERVICE_SHORT, m as ENVELOPE_VERSION, o as EncryptionErrorInput, J as Json, q as base64Decode, r as base64Encode, s as canonicalHashHex, t as canonicalize, u as encryptionError, v as hexDecode, w as hexEncode, x as utf8Decode, y as utf8Encode } from '../types-Bf91gup6.js';
1
+ import { B as BaseService } from '../BaseService-BRDG69KR.js';
2
+ import { c as IService, f as Result } from '../types-DjAP8dve.js';
3
+ import { N as NetworkDescriptor, n as EncryptionError, I as InlineEncryptedEnvelope, D as DecryptCapabilityProof, j as DecryptResponseBody, E as EncryptionCrypto, h as DecryptInvocationSigner, s as ReceiverKeySigner, r as ReceiverKeyPair, i as DecryptRequestBody, g as DecryptInvocationFact, B as BuildDecryptInvocationInput, a as BuiltDecryptInvocation } from '../types-XE4tyBLH.js';
4
+ export { C as CanonicalJson, b as DECRYPT_ACTION, c as DECRYPT_FACT_TYPE, d as DECRYPT_RESULT_TYPE, e as DEFAULT_ENCRYPTION_ALG, f as DEFAULT_KEY_VERSION, k as ENCRYPTION_SERVICE, l as ENCRYPTION_SERVICE_SHORT, m as ENVELOPE_VERSION, o as EncryptionErrorInput, J as Json, x as base64Decode, y as base64Encode, z as canonicalHashHex, A as canonicalize, G as encryptionError, H as hexDecode, K as hexEncode, M as utf8Decode, O as utf8Encode } from '../types-XE4tyBLH.js';
5
5
  export { DecryptTransportResponseError } from '@tinycloud/sdk-services/internal/decrypt-transport-response-error';
6
6
 
7
- /**
8
- * Network-descriptor discovery.
9
- *
10
- * Resolution order (per architecture):
11
- *
12
- * 1. The node's authoritative endpoint
13
- * `GET /encryption/networks/<networkId>` returns the current
14
- * descriptor (`state`, `publicEncryptionKey`, `keyVersion`, ...).
15
- * 2. If the node is unreachable, fall back to the cached discovery
16
- * record at `.well-known/encryption/network/<name>` inside the
17
- * owner's public space.
18
- *
19
- * The node DB is authoritative on conflict; cached records are
20
- * advisory only.
21
- */
22
-
23
7
  type DiscoverySource = "node" | "well-known";
24
8
  interface DiscoveredNetwork {
25
9
  descriptor: NetworkDescriptor;
@@ -45,8 +29,8 @@ interface DiscoverNetworkInput {
45
29
  wellKnown?: WellKnownDescriptorFetcher;
46
30
  }
47
31
  /**
48
- * Resolve a network descriptor. The node fetcher is preferred; the
49
- * well-known fallback is used only on transport failure.
32
+ * Resolve a network descriptor. The node fetcher is preferred. An optional
33
+ * well-known cache cannot override a typed registry, identity, or transport failure.
50
34
  *
51
35
  * The returned descriptor is sanity-checked: `networkId`, `ownerDid`,
52
36
  * and `name` must agree with the URN, and the public key field must
@@ -131,6 +115,10 @@ interface IEncryptionService extends IService {
131
115
  *
132
116
  * The capability proof must root at the network owner DID embedded
133
117
  * in the envelope's networkId.
118
+ *
119
+ * Unresponsive decrypt transports use DECRYPTION_DEPENDENCY_UNAVAILABLE.
120
+ * HTTP failure, identity, registry and caller-cancellation classifications
121
+ * remain distinct; a failed request never returns partial plaintext.
134
122
  */
135
123
  decryptEnvelope(envelope: InlineEncryptedEnvelope, capabilityProof: DecryptCapabilityProof, options?: DecryptEnvelopeOptions): Promise<Result<Uint8Array, EncryptionError>>;
136
124
  }
@@ -173,6 +161,8 @@ interface EncryptionServiceConfig {
173
161
  transport: DecryptTransport;
174
162
  node?: NodeDescriptorFetcher;
175
163
  wellKnown?: WellKnownDescriptorFetcher;
164
+ /** Verified registry destination; overrides descriptor order and caller hints. */
165
+ resolveTargetNode?: (networkId: string) => Promise<string>;
176
166
  /** Bound by an owning service graph to prevent cross-session authority use. */
177
167
  assertActive?: () => void;
178
168
  [key: string]: unknown;
@@ -10,6 +10,10 @@ var ErrorCodes = {
10
10
  /** HTTP 401: a delegation the cited one rests on was revoked. */
11
11
  AUTH_DELEGATION_ANCESTOR_REVOKED: "AUTH_DELEGATION_ANCESTOR_REVOKED",
12
12
  NETWORK_ERROR: "NETWORK_ERROR",
13
+ NODE_NOT_RESPONDING: "NODE_NOT_RESPONDING",
14
+ NODE_IDENTITY_MISMATCH: "NODE_IDENTITY_MISMATCH",
15
+ PARTIAL_NODE_WRITE: "PARTIAL_NODE_WRITE",
16
+ RESOURCE_NOT_ROUTED: "RESOURCE_NOT_ROUTED",
13
17
  TIMEOUT: "TIMEOUT",
14
18
  ABORTED: "ABORTED",
15
19
  INVALID_INPUT: "INVALID_INPUT",
@@ -206,6 +210,34 @@ function networkDiscoveryKey(name) {
206
210
  var ENCRYPTION_NETWORK_URN_PREFIX = URN_PREFIX;
207
211
  var NETWORK_NAME_PATTERN = NETWORK_NAME_RE;
208
212
 
213
+ // src/resourceRouting.ts
214
+ var ROUTING_FAILURE_CODES = {
215
+ NODE_NOT_RESPONDING: true,
216
+ PARTIAL_NODE_WRITE: true,
217
+ NODE_IDENTITY_MISMATCH: true,
218
+ RESOURCE_NOT_ROUTED: true,
219
+ DECRYPTION_DEPENDENCY_UNAVAILABLE: true,
220
+ registry_unavailable: true,
221
+ node_not_found: true,
222
+ node_registry_entry_exists: true
223
+ };
224
+ function isRoutingFailureCode(code) {
225
+ return Object.prototype.hasOwnProperty.call(ROUTING_FAILURE_CODES, code);
226
+ }
227
+ function routingFailure(error) {
228
+ if (typeof error === "object" && error !== null && "code" in error && "message" in error && typeof error.code === "string" && typeof error.message === "string" && isRoutingFailureCode(error.code)) {
229
+ const candidate = "meta" in error ? error.meta : void 0;
230
+ let meta = typeof candidate === "object" && candidate !== null && !Array.isArray(candidate) ? candidate : void 0;
231
+ if (error.code === "NODE_NOT_RESPONDING" && "hosts" in error && Array.isArray(error.hosts)) {
232
+ meta = { ...meta, hosts: error.hosts };
233
+ } else if (error.code === "PARTIAL_NODE_WRITE" && "succeeded" in error && Array.isArray(error.succeeded) && "failed" in error && Array.isArray(error.failed)) {
234
+ meta = { ...meta, succeeded: error.succeeded, failed: error.failed };
235
+ }
236
+ return { code: error.code, message: error.message, ...error instanceof Error ? { cause: error } : {}, ...meta ? { meta } : {} };
237
+ }
238
+ return void 0;
239
+ }
240
+
209
241
  // src/errors.ts
210
242
  var RequestTimeoutError = class extends Error {
211
243
  constructor(timeoutMs) {
@@ -248,6 +280,8 @@ var capabilityServices = new Set(
248
280
  CAPABILITY_REGISTRY.map(({ service }) => service.slice("tinycloud.".length))
249
281
  );
250
282
  function wrapError(service, error, defaultCode = ErrorCodes.NETWORK_ERROR) {
283
+ const routing = routingFailure(error);
284
+ if (routing) return { ...routing, service };
251
285
  if (error instanceof Error) {
252
286
  if (isRequestTimeoutError(error)) {
253
287
  return timeoutError(service, error.timeoutMs, error);
@@ -695,6 +729,8 @@ function defaultEncryptionMessage(input) {
695
729
  return input.message ?? input.cause.message;
696
730
  case "INVALID_INPUT":
697
731
  return input.message;
732
+ default:
733
+ return input.message ?? input.code;
698
734
  }
699
735
  }
700
736
  function encryptionError(input) {
@@ -759,6 +795,8 @@ async function discoverNetwork(input) {
759
795
  return { ok: true, data: { descriptor: validated.data, source: "node" } };
760
796
  }
761
797
  } catch (err2) {
798
+ const routing = routingFailure(err2);
799
+ if (routing) return { ok: false, error: encryptionError(routing) };
762
800
  }
763
801
  }
764
802
  if (input.wellKnown !== void 0) {
@@ -776,6 +814,8 @@ async function discoverNetwork(input) {
776
814
  };
777
815
  }
778
816
  } catch (err2) {
817
+ const routing = routingFailure(err2);
818
+ if (routing) return { ok: false, error: encryptionError(routing) };
779
819
  }
780
820
  }
781
821
  return {
@@ -1360,6 +1400,14 @@ function encOk(data) {
1360
1400
  function encErr(error) {
1361
1401
  return { ok: false, error };
1362
1402
  }
1403
+ function decryptionError(input) {
1404
+ const unavailable = input.code === "NODE_NOT_RESPONDING" || input.code === "TRANSPORT_ERROR" && input.cause.name !== "AbortError";
1405
+ return encryptionError(unavailable ? {
1406
+ ...input,
1407
+ code: "DECRYPTION_DEPENDENCY_UNAVAILABLE",
1408
+ message: "The decryption service isn't responding right now. Please try again."
1409
+ } : input);
1410
+ }
1363
1411
  var EncryptionService = class extends BaseService {
1364
1412
  constructor(config) {
1365
1413
  super();
@@ -1407,6 +1455,8 @@ var EncryptionService = class extends BaseService {
1407
1455
  });
1408
1456
  return encOk(result.envelope);
1409
1457
  } catch (error) {
1458
+ const routing = routingFailure(error);
1459
+ if (routing) return encErr(encryptionError(routing));
1410
1460
  return encErr(
1411
1461
  encryptionError({
1412
1462
  code: "TRANSPORT_ERROR",
@@ -1433,12 +1483,12 @@ var EncryptionService = class extends BaseService {
1433
1483
  descriptor = options.descriptor;
1434
1484
  } else {
1435
1485
  const discovered = await this.discoverNetwork(envelope.networkId);
1436
- if (!discovered.ok) return discovered;
1486
+ if (!discovered.ok) return encErr(decryptionError(discovered.error));
1437
1487
  descriptor = discovered.data;
1438
1488
  }
1439
1489
  const usable = ensureNetworkUsableForDecrypt(descriptor);
1440
1490
  if (!usable.ok) return usable;
1441
- const targetNode = options?.targetNode ?? descriptor.members[0]?.nodeId;
1491
+ const targetNode = this._config.resolveTargetNode ? await this._config.resolveTargetNode(envelope.networkId) : options?.targetNode ?? descriptor.members[0]?.nodeId;
1442
1492
  if (targetNode === void 0) {
1443
1493
  return encErr(
1444
1494
  encryptionError({
@@ -1447,6 +1497,9 @@ var EncryptionService = class extends BaseService {
1447
1497
  })
1448
1498
  );
1449
1499
  }
1500
+ if (this._config.resolveTargetNode && (options?.targetNode !== void 0 && options.targetNode !== targetNode || !descriptor.members.some((member) => member.nodeId === targetNode))) {
1501
+ return encErr(encryptionError({ code: "INVALID_INPUT", message: "Encryption destination does not match the registry" }));
1502
+ }
1450
1503
  const receiverKey = generateRandomReceiverKey({ crypto: this.crypto });
1451
1504
  const receiverPublicKey = base64Encode(receiverKey.publicKey);
1452
1505
  const receiverPublicKeyHash = canonicalHashHex(
@@ -1505,6 +1558,8 @@ var EncryptionService = class extends BaseService {
1505
1558
  });
1506
1559
  this.assertActive();
1507
1560
  } catch (error) {
1561
+ const routing = routingFailure(error);
1562
+ if (routing) return encErr(decryptionError(routing));
1508
1563
  if (error instanceof DecryptTransportResponseError) {
1509
1564
  return encErr(
1510
1565
  encryptionError(
@@ -1521,7 +1576,7 @@ var EncryptionService = class extends BaseService {
1521
1576
  );
1522
1577
  }
1523
1578
  return encErr(
1524
- encryptionError({
1579
+ decryptionError({
1525
1580
  code: "TRANSPORT_ERROR",
1526
1581
  cause: toError(error)
1527
1582
  })
@@ -1548,6 +1603,8 @@ var EncryptionService = class extends BaseService {
1548
1603
  );
1549
1604
  return encOk(plaintext);
1550
1605
  } catch (error) {
1606
+ const routing = routingFailure(error);
1607
+ if (routing) return encErr(decryptionError(routing));
1551
1608
  return encErr(
1552
1609
  encryptionError({
1553
1610
  code: "INVALID_RESPONSE",