@voltro/runtime 0.86.0 → 0.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/CHANGELOG.md +5484 -0
  2. package/README.md +43 -0
  3. package/THIRD-PARTY-NOTICES.md +1511 -276
  4. package/dist/aggregate.js +1 -2
  5. package/dist/aggregateExtrema.js +1 -2
  6. package/dist/aggregateIvm.js +1 -2
  7. package/dist/analyticsMirror.js +1 -2
  8. package/dist/analyticsSink.js +9 -16
  9. package/dist/apiKeyUsage.js +1 -2
  10. package/dist/apiKeys.js +83 -80
  11. package/dist/apiKeysWiring.js +1 -2
  12. package/dist/apiRoleBucketSampler.js +63 -0
  13. package/dist/apiRoleWorkloadHistory.js +55 -0
  14. package/dist/apiRoleWorkloadMetrics.js +77 -0
  15. package/dist/apiRoleWorkloadStorage.js +94 -0
  16. package/dist/approvalBuiltins.js +1 -2
  17. package/dist/approvals.js +68 -76
  18. package/dist/authMiddlewareLayer.js +8 -8
  19. package/dist/bindEvent.js +49 -30
  20. package/dist/boot-refusal.d.ts +10 -0
  21. package/dist/{bootRefusal.js → boot-refusal.js} +1 -2
  22. package/dist/bootListener.js +203 -47
  23. package/dist/bootStoreCodec.js +39 -39
  24. package/dist/businessRules.js +1 -2
  25. package/dist/changeClaimsTable.js +1 -2
  26. package/dist/circuitBreaker.js +1 -72
  27. package/dist/columnOnUpdate.js +1 -2
  28. package/dist/composeAnalytics.js +32 -12
  29. package/dist/computedQuery.js +1 -2
  30. package/dist/computedQueryCache.js +289 -0
  31. package/dist/connectionBuiltins.js +1 -2
  32. package/dist/connectionCredentials.js +1 -2
  33. package/dist/connectionState.js +1 -2
  34. package/dist/connectionVault.js +1 -2
  35. package/dist/connectionsFacade.js +33 -32
  36. package/dist/coordinatedSchedule.js +85 -80
  37. package/dist/crdtHistory.js +1 -2
  38. package/dist/crdtMerge.js +1 -2
  39. package/dist/crdtVersionsTable.js +1 -2
  40. package/dist/credentialBound.js +1 -2
  41. package/dist/crud.js +1 -2
  42. package/dist/dataStore.js +155 -123
  43. package/dist/dataloader.js +1 -2
  44. package/dist/declaredTablesGuard.js +3 -3
  45. package/dist/defineExecutor.js +1 -2
  46. package/dist/dependencyGraph.js +1 -2
  47. package/dist/devices.js +1 -2
  48. package/dist/devicesWiring.js +1 -2
  49. package/dist/dialectReplicationAdapter.js +1 -2
  50. package/dist/dispatcher.js +404 -330
  51. package/dist/effectStore.js +3 -4
  52. package/dist/engineClients.js +23 -0
  53. package/dist/eventBus.js +1 -2
  54. package/dist/eventPublish.js +1 -2
  55. package/dist/events.js +1 -2
  56. package/dist/expectation.js +1 -2
  57. package/dist/expectationEvaluator.js +2 -3
  58. package/dist/experiment.js +1 -2
  59. package/dist/experimentEvaluator.js +1 -2
  60. package/dist/externalizedTasks.js +20 -8
  61. package/dist/fieldCipher.js +110 -42
  62. package/dist/fieldKeyRegistry.js +294 -0
  63. package/dist/fieldKeyRekey.js +285 -0
  64. package/dist/fieldKeyScan.js +135 -0
  65. package/dist/fieldKeyring.js +76 -0
  66. package/dist/fingerprint.js +1 -2
  67. package/dist/finops.js +1 -2
  68. package/dist/finopsAccountant.js +1 -2
  69. package/dist/handlerBody.js +1 -2
  70. package/dist/healthProbes.js +1 -2
  71. package/dist/hot.d.ts +56 -0
  72. package/dist/hot.js +3 -0
  73. package/dist/hotDataStore.js +147 -0
  74. package/dist/hotDataStoreSnapshot.js +97 -0
  75. package/dist/hotDataStoreTables.js +17 -0
  76. package/dist/http-range.d.ts +53 -0
  77. package/dist/http-range.js +51 -0
  78. package/dist/httpClientSsrf.js +13 -39
  79. package/dist/httpClientTracing.js +13 -11
  80. package/dist/httpCompression.js +18 -19
  81. package/dist/httpInputStream.js +81 -0
  82. package/dist/httpKeepAlive.js +1 -2
  83. package/dist/httpRouteMounts.js +2 -2
  84. package/dist/idempotencyStore.js +93 -54
  85. package/dist/idleDetector.js +1 -2
  86. package/dist/index.d.ts +1185 -452
  87. package/dist/index.js +144 -134
  88. package/dist/insertRequiredColumns.js +1 -2
  89. package/dist/instanceMembership.js +1 -2
  90. package/dist/ivm.js +1 -2
  91. package/dist/kvDataStore.js +1 -2
  92. package/dist/kvFacade.js +24 -19
  93. package/dist/matcher.js +1 -2
  94. package/dist/memoryColumnDefaults.js +1 -2
  95. package/dist/memoryQueryJoins.js +17 -18
  96. package/dist/memorySetOperations.js +42 -0
  97. package/dist/metrics.js +39 -26
  98. package/dist/observability.js +2 -3
  99. package/dist/observedGraph.js +1 -2
  100. package/dist/originGuard.js +1 -2
  101. package/dist/outbox.js +2 -3
  102. package/dist/pluginRefRules.js +1 -2
  103. package/dist/policyGuardResolver.js +1 -2
  104. package/dist/preview.js +1 -2
  105. package/dist/projectedRows.js +1 -2
  106. package/dist/provenance.js +1 -2
  107. package/dist/rangeIndex.js +1 -2
  108. package/dist/rawReadScope.js +2 -3
  109. package/dist/reaction.js +1 -2
  110. package/dist/reactiveConfig.js +1 -2
  111. package/dist/readClassification.js +1 -2
  112. package/dist/readRecorder.js +36 -36
  113. package/dist/readScopePredicate.js +11 -0
  114. package/dist/rebac.js +1 -2
  115. package/dist/rebacInterceptor.js +1 -2
  116. package/dist/registry.js +1 -2
  117. package/dist/relevantFields.js +1 -2
  118. package/dist/replicaHealth.js +1 -2
  119. package/dist/replicaLocality.js +1 -2
  120. package/dist/replicaObservations.js +1 -2
  121. package/dist/replicaSelection.js +1 -2
  122. package/dist/replicatedDataStore.js +23 -6
  123. package/dist/requestLoader.js +1 -2
  124. package/dist/resumeCensus.js +1 -2
  125. package/dist/revalidation.js +1 -2
  126. package/dist/rowFilter.js +57 -41
  127. package/dist/rowStateBytes.js +1 -2
  128. package/dist/rpcBodyCap.js +1 -2
  129. package/dist/rpcConnections.js +9 -10
  130. package/dist/rpcDefectDiagnostics.js +1 -2
  131. package/dist/rpcServer.js +523 -451
  132. package/dist/rpcWorkloadAdmission.js +49 -0
  133. package/dist/runAsSystem.js +1 -2
  134. package/dist/rywPositionStore.js +83 -49
  135. package/dist/schedule.js +1 -2
  136. package/dist/scheduleBackfillRequests.js +1 -2
  137. package/dist/scheduleClaimsTable.js +1 -2
  138. package/dist/scheduleRunsTable.js +1 -2
  139. package/dist/scheduler.js +7 -3
  140. package/dist/schemaRegistry.js +1 -2
  141. package/dist/secretsResolver.js +1 -2
  142. package/dist/securityHeaders.js +1 -2
  143. package/dist/servePipeline.js +238 -154
  144. package/dist/serverOnlyAudit.js +1 -2
  145. package/dist/serverTracer.js +1 -2
  146. package/dist/serviceCredentials.js +1 -2
  147. package/dist/setReadScopes.js +27 -0
  148. package/dist/singleNodeOrchestrator.js +1 -2
  149. package/dist/snapshotValueCodec.js +45 -0
  150. package/dist/sourceResolution.js +35 -26
  151. package/dist/storeMiddleware.js +213 -212
  152. package/dist/storeQuery.js +1 -2
  153. package/dist/storeRead.js +1 -2
  154. package/dist/subscriber.js +2 -2
  155. package/dist/subscriptionOutbox.js +1 -2
  156. package/dist/subscriptionRegistry.js +1 -2
  157. package/dist/subscriptionResume.js +1 -2
  158. package/dist/subscriptionSocketMetrics.js +1 -2
  159. package/dist/systemSubject.js +1 -2
  160. package/dist/tenantScope.js +9 -22
  161. package/dist/tenantSelection.js +1 -2
  162. package/dist/timeline.js +1 -2
  163. package/dist/traceContext.js +1 -2
  164. package/dist/traceSink.js +1 -2
  165. package/dist/traceSpansTable.js +1 -2
  166. package/dist/traceparent.js +9 -21
  167. package/dist/transactionSubject.js +1 -2
  168. package/dist/trustedProxy.js +2 -3
  169. package/dist/undo.js +1 -2
  170. package/dist/undoBuiltins.js +1 -2
  171. package/dist/undoCapture.js +1 -2
  172. package/dist/undoLogTable.js +1 -2
  173. package/dist/upsertBinding.js +1 -2
  174. package/dist/wakeOrchestrator.js +1 -2
  175. package/dist/wakeRegistry.js +1 -2
  176. package/dist/wakeRouter.js +1 -2
  177. package/dist/wakeSupervisor.js +1 -2
  178. package/dist/wakeupsTable.js +1 -2
  179. package/dist/webSocketGatewayRuntime.js +112 -73
  180. package/dist/webhookVerification.js +1 -2
  181. package/dist/wireColumnStrip.js +1 -2
  182. package/dist/workflowReadBuiltins.js +1 -2
  183. package/dist/workflowRuntime.js +10 -11
  184. package/package.json +36 -17
package/dist/aggregate.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { classifyShape as e } from "./ivm.js";
2
2
  import { Context as t, Effect as n, Schema as r } from "effect";
3
- //#region src/aggregate.ts
3
+ // src/aggregate.ts
4
4
  var i = (t) => {
5
5
  let n = typeof t.refresh == "string" ? { interval: t.refresh } : t.refresh, r = t.strategy ?? "replace";
6
6
  if (r === "merge" && (t.mergeKey === void 0 || t.mergeKey.length === 0)) throw Error(`defineAggregate("${t.name}"): strategy: 'merge' requires mergeKey — the property on each row to upsert by`);
@@ -38,5 +38,4 @@ var i = (t) => {
38
38
  }) {}, l = class extends t.Service()("@voltro/AggregateRegistry") {}, u = (e) => n.gen(function* () {
39
39
  return (yield* l).getHandle(e);
40
40
  });
41
- //#endregion
42
41
  export { c as AggregateError, s as AggregateNotFound, l as AggregateRegistry, o as AggregateStale, i as defineAggregate, a as isAggregateDefinition, u as useAggregate };
@@ -1,6 +1,6 @@
1
1
  import { RangeIndex as e } from "./rangeIndex.js";
2
2
  import { groupKeyOf as t } from "./ivm.js";
3
- //#region src/aggregateExtrema.ts
3
+ // src/aggregateExtrema.ts
4
4
  var n = Symbol("unavailable"), r = (e, r) => {
5
5
  let i = Object.getPrototypeOf(r);
6
6
  if (i !== Object.prototype && i !== null) return;
@@ -76,5 +76,4 @@ var n = Symbol("unavailable"), r = (e, r) => {
76
76
  return this.groups.get(e)?.numericExtreme(this.shape.op);
77
77
  }
78
78
  };
79
- //#endregion
80
79
  export { i as AggregateExtrema };
@@ -1,6 +1,6 @@
1
1
  import { applyDeltaInto as e, buildIvmState as t, groupKeyOf as n, ivmValue as r, materializeIvm as i, resolveRescanInto as a } from "./ivm.js";
2
2
  import { AggregateExtrema as o } from "./aggregateExtrema.js";
3
- //#region src/aggregateIvm.ts
3
+ // src/aggregateIvm.ts
4
4
  var s = class {
5
5
  shape;
6
6
  state = /* @__PURE__ */ new Map();
@@ -111,5 +111,4 @@ var s = class {
111
111
  return n;
112
112
  }
113
113
  };
114
- //#endregion
115
114
  export { s as AggregateMaintainer };
@@ -1,6 +1,6 @@
1
1
  import { Cause as e, Duration as t, Effect as n, Metric as r, Schedule as i } from "effect";
2
2
  import { eq as a } from "@voltro/database";
3
- //#region src/analyticsMirror.ts
3
+ // src/analyticsMirror.ts
4
4
  var o = r.counter("voltro_analytics_mirror_forwarded_total", { description: "Reactive-table changes successfully applied to the analytics mirror." }), s = r.counter("voltro_analytics_mirror_retries_total", { description: "Analytics-mirror write attempts that failed (each is retried until the budget runs out)." }), c = r.counter("voltro_analytics_mirror_repair_queued_total", { description: "Analytics-mirror changes whose retries were exhausted and were queued for repair." }), l = r.counter("voltro_analytics_mirror_dropped_total", { description: "Analytics-mirror changes provably lost (repair queue overflow)." }), u = (e) => {
5
5
  n.runSync(r.update(e, 1));
6
6
  }, d = (t) => e.pretty(t), f = {
@@ -224,5 +224,4 @@ var o = r.counter("voltro_analytics_mirror_forwarded_total", { description: "Rea
224
224
  })
225
225
  };
226
226
  };
227
- //#endregion
228
227
  export { f as DEFAULT_ANALYTICS_MIRROR_TUNABLES, _ as attachAnalyticsMirror };
@@ -1,14 +1,8 @@
1
- import { Context as e, Effect as t, Option as n, Schema as r } from "effect";
2
- import { SubjectService as i } from "@voltro/protocol";
3
- //#region src/analyticsSink.ts
4
- var a = class extends r.TaggedError()("AnalyticsError", {
5
- provider: r.String,
6
- operation: r.String,
7
- cause: r.String
8
- }) {}, o = class extends r.TaggedError()("AnalyticsCapabilityNotSupported", {
9
- provider: r.String,
10
- capability: r.String
11
- }) {}, s = class extends e.Service()("@voltro/AnalyticsSink") {}, c = (e, t) => ({
1
+ import { Context as e, Effect as t, Option as n } from "effect";
2
+ import { SubjectService as r } from "@voltro/protocol";
3
+ import { AnalyticsCapabilityNotSupported as i, AnalyticsError as a } from "@voltro/kv/analytics";
4
+ // src/analyticsSink.ts
5
+ var o = class extends e.Service()("@voltro/AnalyticsSink") {}, s = (e, t) => ({
12
6
  info: e.info,
13
7
  track: (n) => e.track(n.tenantId === void 0 ? {
14
8
  ...n,
@@ -27,12 +21,11 @@ var a = class extends r.TaggedError()("AnalyticsError", {
27
21
  tenantId: t
28
22
  } : n),
29
23
  ...e.mirror === void 0 ? {} : { mirror: e.mirror }
30
- }), l = () => t.gen(function* () {
31
- let e = yield* s, r = yield* t.serviceOption(i), a = n.match(r, {
24
+ }), c = () => t.gen(function* () {
25
+ let e = yield* o, i = yield* t.serviceOption(r), a = n.match(i, {
32
26
  onNone: () => null,
33
27
  onSome: (e) => e.tenantId ?? null
34
28
  });
35
- return a === null ? e : c(e, a);
29
+ return a === null ? e : s(e, a);
36
30
  });
37
- //#endregion
38
- export { o as AnalyticsCapabilityNotSupported, a as AnalyticsError, s as AnalyticsSink, l as useAnalytics };
31
+ export { i as AnalyticsCapabilityNotSupported, a as AnalyticsError, o as AnalyticsSink, c as useAnalytics };
@@ -1,4 +1,4 @@
1
- //#region src/apiKeyUsage.ts
1
+ // src/apiKeyUsage.ts
2
2
  var e = (e) => {
3
3
  let t = e.now ?? Date.now, n = e.intervalMs ?? 3e4, r = e.maxPending ?? 500, i = /* @__PURE__ */ new Map(), a = !1, o = async () => {
4
4
  if (i.size === 0) return;
@@ -29,5 +29,4 @@ var e = (e) => {
29
29
  pending: () => i.size
30
30
  };
31
31
  };
32
- //#endregion
33
32
  export { e as makeApiKeyUsageBuffer };
package/dist/apiKeys.js CHANGED
@@ -1,7 +1,7 @@
1
- import { eq as e, generateId as t, inSet as n } from "@voltro/database";
2
- import { createHash as r, randomBytes as i } from "node:crypto";
3
- //#region src/apiKeys.ts
4
- var a = "_voltro_api_keys", o = "actors", s = (e) => r("sha256").update(e, "utf8").digest("hex"), c = (e = "voltro_") => `${e}${i(30).toString("base64url")}`, l = (e) => ({
1
+ import { and as e, eq as t, generateId as n, inSet as r } from "@voltro/database";
2
+ import { createHash as i, randomBytes as a } from "node:crypto";
3
+ // src/apiKeys.ts
4
+ var o = "_voltro_api_keys", s = "actors", c = (e) => i("sha256").update(e, "utf8").digest("hex"), l = (e = "voltro_") => `${e}${a(30).toString("base64url")}`, u = (e) => ({
5
5
  id: e.id,
6
6
  name: e.name,
7
7
  keyPrefix: e.keyPrefix,
@@ -14,41 +14,41 @@ var a = "_voltro_api_keys", o = "actors", s = (e) => r("sha256").update(e, "utf8
14
14
  createdBy: e.createdBy ?? null,
15
15
  onBehalfOf: e.onBehalfOf ?? null,
16
16
  ...e.metadata == null ? {} : { metadata: e.metadata }
17
- }), u = (e, t) => e.revokedAt === null && (e.expiresAt === null || e.expiresAt > t), d = (e, n = {}) => {
18
- let r = n.prefix ?? "voltro_", i = n.usage, o = async (n) => {
19
- let i = c(r), o = t({
17
+ }), d = (e, t) => e.revokedAt === null && (e.expiresAt === null || e.expiresAt > t), f = (e, t = {}) => {
18
+ let r = t.prefix ?? "voltro_", i = t.usage, a = async (t) => {
19
+ let i = l(r), a = n({
20
20
  kind: "typeid",
21
21
  prefix: "apikey"
22
- }, a), l = n.scopes ?? [], u = n.expiresAt == null ? null : n.expiresAt instanceof Date ? n.expiresAt.getTime() : n.expiresAt;
22
+ }, o), s = t.scopes ?? [], u = t.expiresAt == null ? null : t.expiresAt instanceof Date ? t.expiresAt.getTime() : t.expiresAt;
23
23
  return await e.ensureActor({
24
- id: o,
25
- displayName: n.name,
26
- input: n
24
+ id: a,
25
+ displayName: t.name,
26
+ input: t
27
27
  }), await e.insert({
28
- id: o,
29
- tenantId: n.tenantId ?? null,
30
- name: n.name,
31
- onBehalfOf: n.onBehalfOf ?? null,
32
- hashedKey: s(i),
28
+ id: a,
29
+ tenantId: t.tenantId ?? null,
30
+ name: t.name,
31
+ onBehalfOf: t.onBehalfOf ?? null,
32
+ hashedKey: c(i),
33
33
  keyPrefix: i.slice(0, r.length + 6),
34
- scopes: l,
34
+ scopes: s,
35
35
  lastUsedAt: null,
36
36
  expiresAt: u,
37
37
  revokedAt: null,
38
- createdBy: n.createdBy ?? null,
38
+ createdBy: t.createdBy ?? null,
39
39
  createdAt: Date.now(),
40
- ...n.metadata == null ? {} : { metadata: n.metadata }
40
+ ...t.metadata == null ? {} : { metadata: t.metadata }
41
41
  }), {
42
- id: o,
42
+ id: a,
43
43
  token: i,
44
44
  keyPrefix: i.slice(0, r.length + 6),
45
- name: n.name,
46
- tenantId: n.tenantId ?? null,
47
- scopes: l
45
+ name: t.name,
46
+ tenantId: t.tenantId ?? null,
47
+ scopes: s
48
48
  };
49
- }, d = async (t, n = Date.now()) => {
49
+ }, s = async (t, n = Date.now()) => {
50
50
  let r = await e.findByHash(t);
51
- return !r || !u(r, n) ? null : (i === void 0 ? await e.patch(r.id, { lastUsedAt: n }) : i.touch(r.id, n), {
51
+ return !r || !d(r, n) ? null : (i === void 0 ? await e.patch(r.id, { lastUsedAt: n }) : i.touch(r.id, n), {
52
52
  id: r.id,
53
53
  tenantId: r.tenantId ?? "",
54
54
  createdBy: r.createdBy ?? null,
@@ -58,16 +58,16 @@ var a = "_voltro_api_keys", o = "actors", s = (e) => r("sha256").update(e, "utf8
58
58
  });
59
59
  };
60
60
  return {
61
- issue: o,
62
- resolveByHash: d,
63
- verify: (e, t) => d(s(e), t),
61
+ issue: a,
62
+ resolveByHash: s,
63
+ verify: (e, t) => s(c(e), t),
64
64
  revoke: async (t, n, r = Date.now()) => {
65
65
  let i = await e.findById(t);
66
66
  return !i || (i.tenantId ?? null) !== n ? !1 : (await e.patch(t, { revokedAt: r }), !0);
67
67
  },
68
68
  rotate: async (t, n, r = Date.now()) => {
69
69
  let i = await e.findById(t);
70
- return !i || (i.tenantId ?? null) !== n ? null : (await e.patch(t, { revokedAt: r }), o({
70
+ return !i || (i.tenantId ?? null) !== n ? null : (await e.patch(t, { revokedAt: r }), a({
71
71
  tenantId: i.tenantId,
72
72
  name: i.name,
73
73
  scopes: i.scopes ?? [],
@@ -76,9 +76,9 @@ var a = "_voltro_api_keys", o = "actors", s = (e) => r("sha256").update(e, "utf8
76
76
  ...i.metadata == null ? {} : { metadata: i.metadata }
77
77
  }));
78
78
  },
79
- list: async (t) => (await e.listByTenant(t)).map(l)
79
+ list: async (t) => (await e.listByTenant(t)).map(u)
80
80
  };
81
- }, f = () => {
81
+ }, p = () => {
82
82
  let e = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Map();
83
83
  return {
84
84
  actors: t,
@@ -110,56 +110,67 @@ var a = "_voltro_api_keys", o = "actors", s = (e) => r("sha256").update(e, "utf8
110
110
  });
111
111
  }
112
112
  };
113
- }, p = (e) => e == null ? null : e instanceof Date ? e.getTime() : typeof e == "number" ? e : typeof e == "string" ? new Date(e).getTime() : null, m = (e) => ({
113
+ }, m = (e) => e == null ? null : e instanceof Date ? e.getTime() : typeof e == "number" ? e : typeof e == "string" ? new Date(e).getTime() : null, h = (e) => ({
114
114
  id: String(e.id),
115
115
  tenantId: e.tenantId ?? null,
116
116
  name: String(e.name),
117
117
  hashedKey: String(e.hashedKey),
118
118
  keyPrefix: String(e.keyPrefix),
119
119
  scopes: e.scopes ?? null,
120
- lastUsedAt: p(e.lastUsedAt),
121
- expiresAt: p(e.expiresAt),
122
- revokedAt: p(e.revokedAt),
120
+ lastUsedAt: m(e.lastUsedAt),
121
+ expiresAt: m(e.expiresAt),
122
+ revokedAt: m(e.revokedAt),
123
123
  createdBy: e.createdBy ?? null,
124
124
  onBehalfOf: e.onBehalfOf ?? null,
125
- createdAt: p(e.createdAt) ?? 0,
125
+ createdAt: m(e.createdAt) ?? 0,
126
126
  ...e.metadata == null ? {} : { metadata: e.metadata }
127
- }), h = async (e) => {
127
+ }), g = async (e, t, n = !1) => await e.query({
128
+ table: o,
129
+ predicate: t,
130
+ order: [],
131
+ take: void 0,
132
+ skip: void 0,
133
+ projection: void 0,
134
+ ...n ? { lock: "update" } : {}
135
+ }), _ = async (n, r, i) => {
136
+ let a = await g(n, e(t("id", r), t("tenantId", i)), !0);
137
+ return a[0] ? h(a[0]) : null;
138
+ }, v = async (e) => {
128
139
  let t = await e.keys();
129
140
  if (t.length === 0) return {
130
141
  keys: 0,
131
142
  planted: 0,
132
143
  failed: []
133
144
  };
134
- let r = /* @__PURE__ */ new Set();
145
+ let n = /* @__PURE__ */ new Set();
135
146
  for (let i = 0; i < t.length; i += 500) {
136
- let a = t.slice(i, i + 500).map((e) => e.id), s = await e.store.query({
137
- table: o,
138
- predicate: n("id", a),
147
+ let a = t.slice(i, i + 500).map((e) => e.id), o = await e.store.query({
148
+ table: s,
149
+ predicate: r("id", a),
139
150
  order: [],
140
151
  take: void 0,
141
152
  skip: void 0,
142
153
  projection: void 0
143
154
  });
144
- for (let e of s) typeof e.id == "string" && r.add(e.id);
155
+ for (let e of o) typeof e.id == "string" && n.add(e.id);
145
156
  }
146
157
  let i = 0, a = [];
147
- for (let n of t) if (!r.has(n.id)) try {
158
+ for (let r of t) if (!n.has(r.id)) try {
148
159
  await e.apiKeyStore.ensureActor({
149
- id: n.id,
150
- displayName: n.name,
160
+ id: r.id,
161
+ displayName: r.name,
151
162
  input: {
152
- tenantId: n.tenantId,
153
- name: n.name,
154
- scopes: n.scopes ?? [],
155
- createdBy: n.createdBy,
156
- onBehalfOf: n.onBehalfOf ?? null,
157
- ...n.metadata == null ? {} : { metadata: n.metadata }
163
+ tenantId: r.tenantId,
164
+ name: r.name,
165
+ scopes: r.scopes ?? [],
166
+ createdBy: r.createdBy,
167
+ onBehalfOf: r.onBehalfOf ?? null,
168
+ ...r.metadata == null ? {} : { metadata: r.metadata }
158
169
  }
159
170
  }), i++;
160
171
  } catch (e) {
161
172
  a.push({
162
- id: n.id,
173
+ id: r.id,
163
174
  reason: e instanceof Error ? e.message : String(e)
164
175
  });
165
176
  }
@@ -168,7 +179,7 @@ var a = "_voltro_api_keys", o = "actors", s = (e) => r("sha256").update(e, "utf8
168
179
  planted: i,
169
180
  failed: a
170
181
  };
171
- }, g = (e) => async (t, n) => {
182
+ }, y = (e) => async (t, n) => {
172
183
  let r = await e.findById(t);
173
184
  if (r === null) return;
174
185
  let i = r.requestCount ?? 0, a = r.lastUsedAt ?? 0;
@@ -176,15 +187,8 @@ var a = "_voltro_api_keys", o = "actors", s = (e) => r("sha256").update(e, "utf8
176
187
  requestCount: i + n.requests,
177
188
  lastUsedAt: Math.max(a, n.lastUsedAt)
178
189
  });
179
- }, _ = (t, n = {}) => {
180
- let r = n.ensureActor, i = async (e) => await t.query({
181
- table: a,
182
- predicate: e,
183
- order: [],
184
- take: void 0,
185
- skip: void 0,
186
- projection: void 0
187
- }), s = (e) => {
190
+ }, b = (e, n = {}) => {
191
+ let r = n.ensureActor, i = (t) => g(e, t), a = (e) => {
188
192
  let t = { ...e };
189
193
  for (let e of [
190
194
  "lastUsedAt",
@@ -195,29 +199,28 @@ var a = "_voltro_api_keys", o = "actors", s = (e) => r("sha256").update(e, "utf8
195
199
  return t;
196
200
  };
197
201
  return {
198
- ensureActor: r === void 0 ? async (e) => {
199
- await t.insertIgnore(o, {
200
- id: e.id,
202
+ ensureActor: r === void 0 ? async (t) => {
203
+ await e.insertIgnore(s, {
204
+ id: t.id,
201
205
  kind: "apiKey",
202
- displayName: e.displayName
206
+ displayName: t.displayName
203
207
  }, { conflictColumns: ["id"] });
204
- } : (e) => r(e, t),
205
- insert: async (e) => {
206
- await t.insert(a, s(e));
208
+ } : (t) => r(t, e),
209
+ insert: async (t) => {
210
+ await e.insert(o, a(t));
207
211
  },
208
- findByHash: async (t) => {
209
- let n = await i(e("hashedKey", t));
210
- return n[0] ? m(n[0]) : null;
212
+ findByHash: async (e) => {
213
+ let n = await i(t("hashedKey", e));
214
+ return n[0] ? h(n[0]) : null;
211
215
  },
212
- findById: async (t) => {
213
- let n = await i(e("id", t));
214
- return n[0] ? m(n[0]) : null;
216
+ findById: async (e) => {
217
+ let n = await i(t("id", e));
218
+ return n[0] ? h(n[0]) : null;
215
219
  },
216
- listByTenant: async (t) => (await i(t === null ? void 0 : e("tenantId", t))).map(m).filter((e) => t === null || e.tenantId === t),
217
- patch: async (e, n) => {
218
- await t.update(a, e, s(n));
220
+ listByTenant: async (e) => (await i(e === null ? void 0 : t("tenantId", e))).map(h).filter((t) => e === null || t.tenantId === e),
221
+ patch: async (t, n) => {
222
+ await e.update(o, t, a(n));
219
223
  }
220
224
  };
221
225
  };
222
- //#endregion
223
- export { o as ACTORS_TABLE, a as API_KEYS_TABLE, _ as dataStoreApiKeyStore, c as generateApiKeyToken, d as makeApiKeyService, g as makeApiKeyUsageFlusher, f as memoryApiKeyStore, h as plantMissingApiKeyActors, s as sha256Hex };
226
+ export { s as ACTORS_TABLE, o as API_KEYS_TABLE, b as dataStoreApiKeyStore, l as generateApiKeyToken, _ as lockApiKeyById, f as makeApiKeyService, y as makeApiKeyUsageFlusher, p as memoryApiKeyStore, v as plantMissingApiKeyActors, c as sha256Hex };
@@ -2,7 +2,7 @@ import { Schema as e } from "effect";
2
2
  import { ADMIN_SCOPE as t, APIKEY_ISSUE_ORG_SCOPE as n, APIKEY_ISSUE_OTHER_SCOPE as r, APIKEY_ISSUE_SELF_SCOPE as i, ScopeError as a } from "@voltro/protocol";
3
3
  import { defineRestRoute as o, requireAnyScope as s, requireScope as c } from "@voltro/protocol/rest";
4
4
  import { apiKeyStrategy as l } from "@voltro/protocol/apikey";
5
- //#region src/apiKeysWiring.ts
5
+ // src/apiKeysWiring.ts
6
6
  var u = (e, t = {}) => l({
7
7
  id: "voltro-apikey",
8
8
  ...t.prefix ? { prefix: t.prefix } : {},
@@ -110,5 +110,4 @@ var u = (e, t = {}) => l({
110
110
  })
111
111
  ];
112
112
  };
113
- //#endregion
114
113
  export { f as apiKeyManagementRoutes, u as frameworkApiKeyStrategy };
@@ -0,0 +1,63 @@
1
+ import { API_ROLE_BUCKET_MS as e } from "./apiRoleWorkloadHistory.js";
2
+ import { API_WORKLOADS as t } from "@voltro/protocol";
3
+ // src/apiRoleBucketSampler.ts
4
+ var n = (n) => {
5
+ let r = [...new Set(n.workloads)];
6
+ if (!n.replicaId || n.replicaId.length > 191 || !n.role || n.role.length > 2080 || n.startedAt < 0 || n.epochNow < 0 || n.monotonicNow < 0 || !r.length || r.some((e) => !t.includes(e)) || !Number.isFinite(n.monotonicNow) || !Number.isSafeInteger(n.epochNow) || !Number.isSafeInteger(n.startedAt) || n.startedAt > n.epochNow) throw Error("Invalid role sampler configuration");
7
+ let i = n.epochNow - n.monotonicNow, a = (t) => Math.floor(t / e) * e, o = /* @__PURE__ */ new Map(), s = a(n.epochNow), c = n.epochNow, l = 0, u = 0, d = n.monotonicNow, f = (e) => {
8
+ let t = o.get(e);
9
+ return t || (t = {
10
+ from: e,
11
+ continuous: e >= n.epochNow,
12
+ seconds: /* @__PURE__ */ new Map()
13
+ }, o.set(e, t), o.size > 290 && (o.delete(Math.min(...o.keys())), l++)), t;
14
+ }, p = (t) => ({
15
+ replicaId: n.replicaId,
16
+ startedAt: n.startedAt,
17
+ role: n.role,
18
+ from: t.from,
19
+ until: t.from + e,
20
+ continuous: t.continuous,
21
+ workloads: Object.fromEntries(r.map((e) => [e, {
22
+ coverage: "partial",
23
+ seconds: t.seconds.get(e) ?? 0
24
+ }]))
25
+ });
26
+ return {
27
+ record(t) {
28
+ let n = i + t.from, o = i + t.until;
29
+ if (!r.includes(t.workload) || !Number.isFinite(n) || !Number.isFinite(o) || o <= n || t.from < d || n < s || o - n > 87e6) u++;
30
+ else {
31
+ d = t.until;
32
+ for (let r = a(n); r < o; r += e) {
33
+ let i = f(r), a = (Math.min(o, r + e) - Math.max(n, r)) / 1e3;
34
+ i.seconds.set(t.workload, (i.seconds.get(t.workload) ?? 0) + a);
35
+ }
36
+ }
37
+ },
38
+ advance(t, n) {
39
+ let r = i + t;
40
+ if (!Number.isFinite(r) || r < c || !Number.isFinite(n)) return;
41
+ let o = a(r), u = Math.max(s, o - 290 * e);
42
+ u > s && (l += (u - s) / e);
43
+ let d = r - c > 6e4 || Math.abs(n - r) > 1e3;
44
+ for (let t = u; t < o; t += e) {
45
+ let e = f(t);
46
+ d && (e.continuous = !1);
47
+ }
48
+ d && (f(o).continuous = !1), s = o, c = r;
49
+ },
50
+ pending() {
51
+ return [...o.values()].filter((t) => t.from + e <= s).sort((e, t) => e.from - t.from).map(p);
52
+ },
53
+ acknowledge(e) {
54
+ e + 3e5 <= s && o.delete(e);
55
+ },
56
+ status: () => ({
57
+ pendingBuckets: [...o.keys()].filter((t) => t + e <= s).length,
58
+ droppedBuckets: l,
59
+ rejectedSegments: u
60
+ })
61
+ };
62
+ };
63
+ export { n as makeApiRoleBucketSampler };
@@ -0,0 +1,55 @@
1
+ import { API_WORKLOADS as e } from "@voltro/protocol";
2
+ // src/apiRoleWorkloadHistory.ts
3
+ var t = 3e5, n = 864e5, r = (r) => {
4
+ if (!Number.isSafeInteger(r.startedAt) || r.startedAt < 0 || r.startedAt > r.now || !r.replicaId || !r.role || !Number.isSafeInteger(r.now) || r.now < 864e5) throw Error("Invalid role observation time");
5
+ let i = Math.floor(r.now / t) * t, a = i - n, o = n / t, s = [...new Set(r.requiredWorkloads)];
6
+ if (!s.length || s.some((t) => !e.includes(t))) throw Error("Invalid required workloads");
7
+ let c = (e, t, n = s) => ({
8
+ from: a,
9
+ until: i,
10
+ complete: !1,
11
+ reason: e,
12
+ missingBuckets: t,
13
+ incompleteWorkloads: n,
14
+ totals: [],
15
+ splitCandidates: []
16
+ });
17
+ if (r.buckets.length > 290) return c("invalid-observation", o);
18
+ let l = /* @__PURE__ */ new Map();
19
+ for (let t of r.buckets) {
20
+ if (t.replicaId !== r.replicaId || t.startedAt !== r.startedAt || t.role !== r.role || !Number.isSafeInteger(t.from) || t.from < 0 || t.from % 3e5 != 0 || t.until !== t.from + 3e5 || typeof t.continuous != "boolean") return c("invalid-observation", o);
21
+ let n = 0;
22
+ for (let [r, i] of Object.entries(t.workloads)) {
23
+ if (!e.includes(r) || !s.includes(r) || !i || !["partial", "complete"].includes(i.coverage) || !Number.isFinite(i.seconds) || i.seconds < 0) return c("invalid-observation", o);
24
+ n += i.seconds;
25
+ }
26
+ if (n > 300) return c("invalid-observation", o);
27
+ if (!(t.until <= a || t.from >= i)) {
28
+ if (l.has(t.from)) return c("invalid-observation", o);
29
+ l.set(t.from, t);
30
+ }
31
+ }
32
+ let u = /* @__PURE__ */ new Set(), d = new Map(s.map((e) => [e, 0]));
33
+ for (let e of l.values()) for (let t of s) {
34
+ let n = e.workloads[t];
35
+ (!e.continuous || e.from < r.startedAt || n?.coverage !== "complete") && u.add(t), n && d.set(t, d.get(t) + n.seconds);
36
+ }
37
+ let f = o - l.size;
38
+ if (f || u.size) return c("incomplete", f, [...u]);
39
+ let p = [...d.values()].reduce((e, t) => e + t, 0), m = [...d].map(([e, t]) => ({
40
+ workload: e,
41
+ seconds: t,
42
+ share: p === 0 ? 0 : t / p
43
+ })), h = m.filter((e) => e.share > .3).map((e) => e.workload);
44
+ return {
45
+ from: a,
46
+ until: i,
47
+ complete: !0,
48
+ missingBuckets: 0,
49
+ incompleteWorkloads: [],
50
+ reason: p === 0 ? "idle" : "observed",
51
+ totals: m,
52
+ splitCandidates: h.length >= 2 ? h : []
53
+ };
54
+ };
55
+ export { t as API_ROLE_BUCKET_MS, n as API_ROLE_WINDOW_MS, r as assessApiRoleWorkloadWindow };
@@ -0,0 +1,77 @@
1
+ import { Effect as e, Metric as t, Tracer as n } from "effect";
2
+ import { API_WORKLOADS as r } from "@voltro/protocol";
3
+ // src/apiRoleWorkloadMetrics.ts
4
+ var i = t.counter("api_role_workload_seconds_total", { description: "Measured active synchronous loop seconds by selected API role set and workload; excludes asynchronous waits." }), a = (e) => {
5
+ if (e.length === 0 || e.length > 32 || e.some((e) => !/^[a-z][a-z0-9-]{0,63}$/.test(e))) throw Error("Invalid API metric roles");
6
+ return [...new Set(e)].sort().join(",");
7
+ }, o = (o, s = {}) => {
8
+ let c = a(o), l = s.now ?? (() => performance.now()), u = new Map(r.map((e) => [e, i.pipe(t.withAttributes({
9
+ role: c,
10
+ workload: e
11
+ }))])), d = /* @__PURE__ */ new Map(), f = 0, p = [], m = (n, r) => {
12
+ let i = (r - n.since) / 1e3;
13
+ if (!(!Number.isFinite(i) || i <= 0)) {
14
+ try {
15
+ s.onSegment?.({
16
+ workload: n.workload,
17
+ from: n.since,
18
+ until: r
19
+ });
20
+ } catch {
21
+ f++;
22
+ }
23
+ d.set(n.workload, (d.get(n.workload) ?? 0) + i), e.runSync(t.update(u.get(n.workload), i));
24
+ }
25
+ }, h = (e) => {
26
+ if (!u.has(e)) throw Error("Unknown API metric workload");
27
+ let t = p[p.length - 1];
28
+ t && m(t, l());
29
+ let n = {
30
+ workload: e,
31
+ since: l()
32
+ };
33
+ return p.push(n), n;
34
+ }, g = (e) => {
35
+ let t = l();
36
+ p.pop(), m(e, t);
37
+ let n = p[p.length - 1];
38
+ n && (n.since = l());
39
+ };
40
+ return {
41
+ role: c,
42
+ observationErrors: () => f,
43
+ observeEffect(t, r) {
44
+ if (!u.has(r)) throw Error("Unknown API metric workload");
45
+ return e.withFiber((i) => {
46
+ let a = i.getRef(n.Tracer), o = n.make({
47
+ span: (e) => a.span(e),
48
+ context: (e, t) => {
49
+ let n = h(r);
50
+ try {
51
+ return a.context === void 0 ? e["~effect/Effect/evaluate"](t) : a.context(e, t);
52
+ } finally {
53
+ g(n);
54
+ }
55
+ }
56
+ });
57
+ return t.pipe(e.provideService(n.Tracer, o));
58
+ });
59
+ },
60
+ measureSync(e, t) {
61
+ let n = h(e);
62
+ try {
63
+ return t();
64
+ } finally {
65
+ g(n);
66
+ }
67
+ },
68
+ snapshot() {
69
+ return [...d].map(([e, t]) => ({
70
+ role: c,
71
+ workload: e,
72
+ seconds: t
73
+ }));
74
+ }
75
+ };
76
+ }, s = (e, t, n) => t.observeEffect(e, n);
77
+ export { a as apiRoleMetricLabel, o as makeApiRoleWorkloadMetrics, s as observeApiRoleEffect };