@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.
- package/CHANGELOG.md +5484 -0
- package/README.md +43 -0
- package/THIRD-PARTY-NOTICES.md +1511 -276
- package/dist/aggregate.js +1 -2
- package/dist/aggregateExtrema.js +1 -2
- package/dist/aggregateIvm.js +1 -2
- package/dist/analyticsMirror.js +1 -2
- package/dist/analyticsSink.js +9 -16
- package/dist/apiKeyUsage.js +1 -2
- package/dist/apiKeys.js +83 -80
- package/dist/apiKeysWiring.js +1 -2
- package/dist/apiRoleBucketSampler.js +63 -0
- package/dist/apiRoleWorkloadHistory.js +55 -0
- package/dist/apiRoleWorkloadMetrics.js +77 -0
- package/dist/apiRoleWorkloadStorage.js +94 -0
- package/dist/approvalBuiltins.js +1 -2
- package/dist/approvals.js +68 -76
- package/dist/authMiddlewareLayer.js +8 -8
- package/dist/bindEvent.js +49 -30
- package/dist/boot-refusal.d.ts +10 -0
- package/dist/{bootRefusal.js → boot-refusal.js} +1 -2
- package/dist/bootListener.js +203 -47
- package/dist/bootStoreCodec.js +39 -39
- package/dist/businessRules.js +1 -2
- package/dist/changeClaimsTable.js +1 -2
- package/dist/circuitBreaker.js +1 -72
- package/dist/columnOnUpdate.js +1 -2
- package/dist/composeAnalytics.js +32 -12
- package/dist/computedQuery.js +1 -2
- package/dist/computedQueryCache.js +289 -0
- package/dist/connectionBuiltins.js +1 -2
- package/dist/connectionCredentials.js +1 -2
- package/dist/connectionState.js +1 -2
- package/dist/connectionVault.js +1 -2
- package/dist/connectionsFacade.js +33 -32
- package/dist/coordinatedSchedule.js +85 -80
- package/dist/crdtHistory.js +1 -2
- package/dist/crdtMerge.js +1 -2
- package/dist/crdtVersionsTable.js +1 -2
- package/dist/credentialBound.js +1 -2
- package/dist/crud.js +1 -2
- package/dist/dataStore.js +155 -123
- package/dist/dataloader.js +1 -2
- package/dist/declaredTablesGuard.js +3 -3
- package/dist/defineExecutor.js +1 -2
- package/dist/dependencyGraph.js +1 -2
- package/dist/devices.js +1 -2
- package/dist/devicesWiring.js +1 -2
- package/dist/dialectReplicationAdapter.js +1 -2
- package/dist/dispatcher.js +404 -330
- package/dist/effectStore.js +3 -4
- package/dist/engineClients.js +23 -0
- package/dist/eventBus.js +1 -2
- package/dist/eventPublish.js +1 -2
- package/dist/events.js +1 -2
- package/dist/expectation.js +1 -2
- package/dist/expectationEvaluator.js +2 -3
- package/dist/experiment.js +1 -2
- package/dist/experimentEvaluator.js +1 -2
- package/dist/externalizedTasks.js +20 -8
- package/dist/fieldCipher.js +110 -42
- package/dist/fieldKeyRegistry.js +294 -0
- package/dist/fieldKeyRekey.js +285 -0
- package/dist/fieldKeyScan.js +135 -0
- package/dist/fieldKeyring.js +76 -0
- package/dist/fingerprint.js +1 -2
- package/dist/finops.js +1 -2
- package/dist/finopsAccountant.js +1 -2
- package/dist/handlerBody.js +1 -2
- package/dist/healthProbes.js +1 -2
- package/dist/hot.d.ts +56 -0
- package/dist/hot.js +3 -0
- package/dist/hotDataStore.js +147 -0
- package/dist/hotDataStoreSnapshot.js +97 -0
- package/dist/hotDataStoreTables.js +17 -0
- package/dist/http-range.d.ts +53 -0
- package/dist/http-range.js +51 -0
- package/dist/httpClientSsrf.js +13 -39
- package/dist/httpClientTracing.js +13 -11
- package/dist/httpCompression.js +18 -19
- package/dist/httpInputStream.js +81 -0
- package/dist/httpKeepAlive.js +1 -2
- package/dist/httpRouteMounts.js +2 -2
- package/dist/idempotencyStore.js +93 -54
- package/dist/idleDetector.js +1 -2
- package/dist/index.d.ts +1185 -452
- package/dist/index.js +144 -134
- package/dist/insertRequiredColumns.js +1 -2
- package/dist/instanceMembership.js +1 -2
- package/dist/ivm.js +1 -2
- package/dist/kvDataStore.js +1 -2
- package/dist/kvFacade.js +24 -19
- package/dist/matcher.js +1 -2
- package/dist/memoryColumnDefaults.js +1 -2
- package/dist/memoryQueryJoins.js +17 -18
- package/dist/memorySetOperations.js +42 -0
- package/dist/metrics.js +39 -26
- package/dist/observability.js +2 -3
- package/dist/observedGraph.js +1 -2
- package/dist/originGuard.js +1 -2
- package/dist/outbox.js +2 -3
- package/dist/pluginRefRules.js +1 -2
- package/dist/policyGuardResolver.js +1 -2
- package/dist/preview.js +1 -2
- package/dist/projectedRows.js +1 -2
- package/dist/provenance.js +1 -2
- package/dist/rangeIndex.js +1 -2
- package/dist/rawReadScope.js +2 -3
- package/dist/reaction.js +1 -2
- package/dist/reactiveConfig.js +1 -2
- package/dist/readClassification.js +1 -2
- package/dist/readRecorder.js +36 -36
- package/dist/readScopePredicate.js +11 -0
- package/dist/rebac.js +1 -2
- package/dist/rebacInterceptor.js +1 -2
- package/dist/registry.js +1 -2
- package/dist/relevantFields.js +1 -2
- package/dist/replicaHealth.js +1 -2
- package/dist/replicaLocality.js +1 -2
- package/dist/replicaObservations.js +1 -2
- package/dist/replicaSelection.js +1 -2
- package/dist/replicatedDataStore.js +23 -6
- package/dist/requestLoader.js +1 -2
- package/dist/resumeCensus.js +1 -2
- package/dist/revalidation.js +1 -2
- package/dist/rowFilter.js +57 -41
- package/dist/rowStateBytes.js +1 -2
- package/dist/rpcBodyCap.js +1 -2
- package/dist/rpcConnections.js +9 -10
- package/dist/rpcDefectDiagnostics.js +1 -2
- package/dist/rpcServer.js +523 -451
- package/dist/rpcWorkloadAdmission.js +49 -0
- package/dist/runAsSystem.js +1 -2
- package/dist/rywPositionStore.js +83 -49
- package/dist/schedule.js +1 -2
- package/dist/scheduleBackfillRequests.js +1 -2
- package/dist/scheduleClaimsTable.js +1 -2
- package/dist/scheduleRunsTable.js +1 -2
- package/dist/scheduler.js +7 -3
- package/dist/schemaRegistry.js +1 -2
- package/dist/secretsResolver.js +1 -2
- package/dist/securityHeaders.js +1 -2
- package/dist/servePipeline.js +238 -154
- package/dist/serverOnlyAudit.js +1 -2
- package/dist/serverTracer.js +1 -2
- package/dist/serviceCredentials.js +1 -2
- package/dist/setReadScopes.js +27 -0
- package/dist/singleNodeOrchestrator.js +1 -2
- package/dist/snapshotValueCodec.js +45 -0
- package/dist/sourceResolution.js +35 -26
- package/dist/storeMiddleware.js +213 -212
- package/dist/storeQuery.js +1 -2
- package/dist/storeRead.js +1 -2
- package/dist/subscriber.js +2 -2
- package/dist/subscriptionOutbox.js +1 -2
- package/dist/subscriptionRegistry.js +1 -2
- package/dist/subscriptionResume.js +1 -2
- package/dist/subscriptionSocketMetrics.js +1 -2
- package/dist/systemSubject.js +1 -2
- package/dist/tenantScope.js +9 -22
- package/dist/tenantSelection.js +1 -2
- package/dist/timeline.js +1 -2
- package/dist/traceContext.js +1 -2
- package/dist/traceSink.js +1 -2
- package/dist/traceSpansTable.js +1 -2
- package/dist/traceparent.js +9 -21
- package/dist/transactionSubject.js +1 -2
- package/dist/trustedProxy.js +2 -3
- package/dist/undo.js +1 -2
- package/dist/undoBuiltins.js +1 -2
- package/dist/undoCapture.js +1 -2
- package/dist/undoLogTable.js +1 -2
- package/dist/upsertBinding.js +1 -2
- package/dist/wakeOrchestrator.js +1 -2
- package/dist/wakeRegistry.js +1 -2
- package/dist/wakeRouter.js +1 -2
- package/dist/wakeSupervisor.js +1 -2
- package/dist/wakeupsTable.js +1 -2
- package/dist/webSocketGatewayRuntime.js +112 -73
- package/dist/webhookVerification.js +1 -2
- package/dist/wireColumnStrip.js +1 -2
- package/dist/workflowReadBuiltins.js +1 -2
- package/dist/workflowRuntime.js +10 -11
- package/package.json +36 -17
package/dist/effectStore.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Context as e, Effect as t, Exit as n, Layer as r } from "effect";
|
|
|
2
2
|
import { authoredError as i, describeDriverError as a, wireSafeCause as o } from "@voltro/database";
|
|
3
3
|
import { StoreOperationFailed as s } from "@voltro/protocol";
|
|
4
4
|
import { createLogger as c } from "@voltro/logger";
|
|
5
|
-
|
|
5
|
+
// src/effectStore.ts
|
|
6
6
|
var l = c({ scope: "store" }), u = class extends e.Service()("@voltro/EffectStore") {}, d = {
|
|
7
7
|
TenantScopeViolation: !0,
|
|
8
8
|
TenantRowNotFound: !0,
|
|
@@ -35,7 +35,7 @@ var l = c({ scope: "store" }), u = class extends e.Service()("@voltro/EffectStor
|
|
|
35
35
|
}, v = (e) => ({
|
|
36
36
|
query: ((t) => m("query", t.table, () => e.query(t))),
|
|
37
37
|
insert: (t, n) => m("insert", t, () => e.insert(t, n)),
|
|
38
|
-
insertMany: (t, n) => m("insertMany", t, () => e.insertMany(t, n)),
|
|
38
|
+
insertMany: (t, n, r) => m("insertMany", t, () => e.insertMany(t, n, r)),
|
|
39
39
|
patchJson: (t, n, r, i, a) => m("patchJson", t, () => e.patchJson(t, n, r, i, a)),
|
|
40
40
|
update: (t, n, r) => m("update", t, () => e.update(t, n, r)),
|
|
41
41
|
updateMany: (t, n, r) => m("updateMany", t, () => e.updateMany(t, n, r)),
|
|
@@ -66,6 +66,5 @@ var l = c({ scope: "store" }), u = class extends e.Service()("@voltro/EffectStor
|
|
|
66
66
|
conflictColumns: e.conflictColumns,
|
|
67
67
|
...e.update === void 0 ? {} : { update: e.update },
|
|
68
68
|
...e.updateValues === void 0 ? {} : { updateValues: e.updateValues }
|
|
69
|
-
}), x = (e, t, n) => e.insert(t.tableName, n), S = (e, t, n) => e.insertMany(t.tableName, n), C = (e, t, n, r) => e.upsert(t.tableName, n, b(r)), w = (e, t, n, r) => e.upsertWithOutcome(t.tableName, n, b(r)), T = (e, t, n, r) => e.insertIgnoreWithOutcome(t.tableName, n, { conflictColumns: r.conflictColumns });
|
|
70
|
-
//#endregion
|
|
69
|
+
}), x = (e, t, n) => e.insert(t.tableName, n), S = (e, t, n, r) => e.insertMany(t.tableName, n, r), C = (e, t, n, r) => e.upsert(t.tableName, n, b(r)), w = (e, t, n, r) => e.upsertWithOutcome(t.tableName, n, b(r)), T = (e, t, n, r) => e.insertIgnoreWithOutcome(t.tableName, n, { conflictColumns: r.conflictColumns });
|
|
71
70
|
export { u as EffectStore, T as insertIgnoreRowOutcomeEffect, S as insertManyRowsEffect, x as insertRowEffect, y as makeEffectStoreLayer, C as upsertRowEffect, w as upsertRowOutcomeEffect };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/engineClients.ts
|
|
2
|
+
var e = /* @__PURE__ */ new Map(), t = 0, n = (e) => {
|
|
3
|
+
let t = /^([a-z]{1,16})\/([0-9A-Za-z.+-]{1,100})(?:; surface=([0-9a-f]{64}))?$/.exec(e.trim());
|
|
4
|
+
return t ? {
|
|
5
|
+
target: t[1],
|
|
6
|
+
version: t[2],
|
|
7
|
+
surface: t[3] ?? null
|
|
8
|
+
} : null;
|
|
9
|
+
}, r = (r, i) => {
|
|
10
|
+
let a = r.headers["x-voltro-sdk"];
|
|
11
|
+
if (typeof a != "string" || e.size >= 1024) return;
|
|
12
|
+
let o = n(a);
|
|
13
|
+
if (!o) return;
|
|
14
|
+
let s = "client-" + String(++t);
|
|
15
|
+
e.set(s, Object.freeze({
|
|
16
|
+
id: s,
|
|
17
|
+
...o,
|
|
18
|
+
connectedAt: Date.now()
|
|
19
|
+
})), i.once("close", () => {
|
|
20
|
+
e.delete(s);
|
|
21
|
+
});
|
|
22
|
+
}, i = () => [...e.values()];
|
|
23
|
+
export { i as engineClientsSnapshot, n as parseEngineSdkHeader, r as trackEngineClient };
|
package/dist/eventBus.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { recordEventDropped as e, recordEventPublished as t, recordEventSubscribers as n } from "./metrics.js";
|
|
2
2
|
import { eventRoute as r, parseEventRoute as i } from "@voltro/protocol";
|
|
3
3
|
import { createLogger as a } from "@voltro/logger";
|
|
4
|
-
|
|
4
|
+
// src/eventBus.ts
|
|
5
5
|
var o = a({ scope: "voltro:events" }), s = 64, c = 3e5, l = 1e4, u = class {
|
|
6
6
|
routes = /* @__PURE__ */ new Map();
|
|
7
7
|
origin;
|
|
@@ -256,5 +256,4 @@ var o = a({ scope: "voltro:events" }), s = 64, c = 3e5, l = 1e4, u = class {
|
|
|
256
256
|
this.routes.clear();
|
|
257
257
|
}
|
|
258
258
|
};
|
|
259
|
-
//#endregion
|
|
260
259
|
export { u as EventBus };
|
package/dist/eventPublish.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Context as e, Effect as t, Schema as n } from "effect";
|
|
2
2
|
import { EventKeyInvalid as r, EventPayloadInvalid as i, EventPayloadTooLarge as a, MAX_EVENT_ENVELOPE_BYTES as o } from "@voltro/protocol";
|
|
3
|
-
|
|
3
|
+
// src/eventPublish.ts
|
|
4
4
|
var s = (e) => e instanceof Error ? e.message : String(e), c = (e, c, l, u) => t.gen(function* () {
|
|
5
5
|
let d = n.encodeEffect(c.key), f = n.encodeEffect(c.payload), p = yield* d(l).pipe(t.mapError((e) => new r({
|
|
6
6
|
event: c.name,
|
|
@@ -45,5 +45,4 @@ var s = (e) => e instanceof Error ? e.message : String(e), c = (e, c, l, u) => t
|
|
|
45
45
|
let n;
|
|
46
46
|
return Object.assign(e, { then: (r, i) => (n ??= t.runPromise(e), n.then(r, i)) });
|
|
47
47
|
}, d = (e) => ({ publish: (t, n, r) => u(c(e, t, n, r)) });
|
|
48
|
-
//#endregion
|
|
49
48
|
export { l as OutboxEventPublisher, d as makeEventPublisher, c as publishEvent };
|
package/dist/events.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { boolean as e, eq as t, id as n, json as r, table as i, text as a, timestamp as o } from "@voltro/database";
|
|
2
|
-
|
|
2
|
+
// src/events.ts
|
|
3
3
|
var s = (e) => {
|
|
4
4
|
if ("on" in e) {
|
|
5
5
|
let { on: t, ...n } = e;
|
|
@@ -189,5 +189,4 @@ var s = (e) => {
|
|
|
189
189
|
};
|
|
190
190
|
} };
|
|
191
191
|
};
|
|
192
|
-
//#endregion
|
|
193
192
|
export { m as _voltroWorkflowEventDeliveriesTable, p as _voltroWorkflowEventsTable, c as defineEventTrigger, l as isWorkflowEventTriggerDefinition, h as makeEventsFacade, s as triggerWorkflow };
|
package/dist/expectation.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Context as e, Effect as t } from "effect";
|
|
2
|
-
|
|
2
|
+
// src/expectation.ts
|
|
3
3
|
var n = /* @__PURE__ */ new Set([
|
|
4
4
|
"info",
|
|
5
5
|
"warn",
|
|
@@ -48,5 +48,4 @@ var n = /* @__PURE__ */ new Set([
|
|
|
48
48
|
}, a = (e) => typeof e == "object" && !!e && e._voltroExpectation === !0, o = class extends e.Service()("@voltro/ExpectationRegistry") {}, s = (e) => t.gen(function* () {
|
|
49
49
|
return (yield* o).get(e.name);
|
|
50
50
|
});
|
|
51
|
-
//#endregion
|
|
52
51
|
export { o as ExpectationRegistry, i as defineExpectation, a as isExpectationDefinition, s as useExpectation };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AggregateMaintainer as e } from "./aggregateIvm.js";
|
|
2
2
|
import { collectProjectedRows as t } from "./projectedRows.js";
|
|
3
|
-
|
|
3
|
+
// src/expectationEvaluator.ts
|
|
4
4
|
var n = (e) => {
|
|
5
5
|
if (e instanceof Date) return e.getTime();
|
|
6
6
|
if (typeof e == "number" && Number.isFinite(e)) return e;
|
|
@@ -287,7 +287,7 @@ var n = (e) => {
|
|
|
287
287
|
let t = e ? [] : Array(i.size), n = 0;
|
|
288
288
|
return i.forEach((r) => {
|
|
289
289
|
let i = r.state();
|
|
290
|
-
|
|
290
|
+
e && i.status !== "violated" || (t[n++] = i);
|
|
291
291
|
}), t;
|
|
292
292
|
};
|
|
293
293
|
return {
|
|
@@ -304,5 +304,4 @@ var n = (e) => {
|
|
|
304
304
|
runTick: d
|
|
305
305
|
};
|
|
306
306
|
};
|
|
307
|
-
//#endregion
|
|
308
307
|
export { u as ExpectationEvaluator, d as attachExpectations };
|
package/dist/experiment.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Context as e, Effect as t } from "effect";
|
|
2
|
-
|
|
2
|
+
// src/experiment.ts
|
|
3
3
|
var n = "holdout", r = (e, t) => /* @__PURE__ */ Error(`defineExperiment(${JSON.stringify(e)}): ${t}`), i = (e) => {
|
|
4
4
|
if (e == null) return null;
|
|
5
5
|
if (typeof e == "number") return Number.isFinite(e) ? String(e) : null;
|
|
@@ -92,5 +92,4 @@ var n = "holdout", r = (e, t) => /* @__PURE__ */ Error(`defineExperiment(${JSON.
|
|
|
92
92
|
}, l = (e) => e.holdout > 0 ? [...e.variants.map((e) => e.name), n] : e.variants.map((e) => e.name), u = class extends e.Service()("@voltro/ExperimentRegistry") {}, d = (e) => t.gen(function* () {
|
|
93
93
|
return (yield* u).get(e.name);
|
|
94
94
|
});
|
|
95
|
-
//#endregion
|
|
96
95
|
export { u as ExperimentRegistry, n as HOLDOUT_VARIANT, c as assignVariant, a as defineExperiment, s as hashUnitInterval, o as isExperimentDefinition, l as resultVariantNames, d as useExperiment };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AggregateMaintainer as e } from "./aggregateIvm.js";
|
|
2
2
|
import { collectProjectedRows as t } from "./projectedRows.js";
|
|
3
3
|
import { assignVariant as n, resultVariantNames as r } from "./experiment.js";
|
|
4
|
-
|
|
4
|
+
// src/experimentEvaluator.ts
|
|
5
5
|
var i = "__voltro_variant", a = "__voltro_metric", o = class {
|
|
6
6
|
project;
|
|
7
7
|
maintainer;
|
|
@@ -241,5 +241,4 @@ var i = "__voltro_variant", a = "__voltro_metric", o = class {
|
|
|
241
241
|
registered: [...i.keys()]
|
|
242
242
|
};
|
|
243
243
|
};
|
|
244
|
-
//#endregion
|
|
245
244
|
export { f as ExperimentEvaluator, p as attachExperiments };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/externalizedTasks.ts
|
|
2
2
|
var e = 6e4, t = (e) => {
|
|
3
3
|
if (!Number.isFinite(e) || e < 6e4 || e % 6e4 != 0) return;
|
|
4
4
|
let t = e / 6e4;
|
|
@@ -16,10 +16,22 @@ var e = 6e4, t = (e) => {
|
|
|
16
16
|
if (t !== void 0) return t;
|
|
17
17
|
let n = /* @__PURE__ */ new Map();
|
|
18
18
|
return e[r] = n, n;
|
|
19
|
-
}, a = (e) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
}, a = (e) => Object.freeze({
|
|
20
|
+
register: (t) => {
|
|
21
|
+
let n = Object.freeze({
|
|
22
|
+
name: t.name,
|
|
23
|
+
intervalMs: t.intervalMs,
|
|
24
|
+
cron: t.cron,
|
|
25
|
+
run: t.run
|
|
26
|
+
});
|
|
27
|
+
if (e.has(n.name)) throw Error("Externalized task name is already registered: " + n.name);
|
|
28
|
+
e.set(n.name, n);
|
|
29
|
+
let r = !1;
|
|
30
|
+
return () => {
|
|
31
|
+
r || (r = !0, e.get(n.name) === n && e.delete(n.name));
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
get: (t) => e.get(t),
|
|
35
|
+
names: () => [...e.keys()].sort()
|
|
36
|
+
}), o = () => a(/* @__PURE__ */ new Map()), s = (e) => a(i()).register(e), c = (e) => i().get(e), l = () => [...i().keys()].sort();
|
|
37
|
+
export { e as MIN_EXTERNALIZABLE_INTERVAL_MS, t as cronForInterval, n as externalizationRefusal, c as externalizedTask, l as externalizedTaskNames, o as makeExternalizedTaskRegistry, s as registerExternalizedTask };
|
package/dist/fieldCipher.js
CHANGED
|
@@ -1,61 +1,129 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { recordFieldDecrypt as e } from "./metrics.js";
|
|
2
|
+
import { BOUND_ENCRYPTED_PREFIX as t, ENCRYPTED_PREFIX as n, FIELD_KEY_ID_PATTERN as r, ciphertextKeyId as i, decodeFieldValue as a, encodeFieldValue as o, isEncrypted as s } from "@voltro/database";
|
|
3
|
+
import { createCipheriv as c, createDecipheriv as l, createHmac as u, randomBytes as d, scryptSync as f } from "node:crypto";
|
|
4
|
+
// src/fieldCipher.ts
|
|
5
|
+
var p = (e) => /^[0-9a-f]{64}$/i.test(e) ? Buffer.from(e, "hex") : f(e, "voltro:field-encryption:v1", 32), m = (e, t) => {
|
|
5
6
|
let n = e === "r" ? t?.row : e === "c" ? t?.column : void 0;
|
|
6
7
|
if (n === void 0) throw Error(e === "r" || e === "c" ? `field cipher: ciphertext is bound to its ${e === "r" ? "row" : "column"} and was read without that binding` : "field cipher: malformed ciphertext");
|
|
7
8
|
return Buffer.from(n, "utf8");
|
|
8
|
-
},
|
|
9
|
-
if (
|
|
9
|
+
}, h = (e, i) => {
|
|
10
|
+
if (e.length !== 32) throw Error(`field cipher key must be 32 bytes, got ${e.length}`);
|
|
11
|
+
if (i !== void 0 && !r.test(i)) throw Error(`field cipher: "${i}" is not a key id (a short lowercase slug)`);
|
|
12
|
+
let a = i === void 0 ? "" : `:${i}`;
|
|
10
13
|
return {
|
|
11
14
|
encrypt: (r, i) => {
|
|
12
|
-
let o =
|
|
13
|
-
l !== void 0 &&
|
|
14
|
-
let
|
|
15
|
-
return l === void 0 ? `${
|
|
15
|
+
let o = d(12), s = c("aes-256-gcm", e, o), l = i === void 0 ? void 0 : i.row === void 0 ? "c" : "r";
|
|
16
|
+
l !== void 0 && s.setAAD(m(l, i));
|
|
17
|
+
let u = Buffer.concat([s.update(r, "utf8"), s.final()]), f = s.getAuthTag(), p = `${o.toString("base64")}:${f.toString("base64")}:${u.toString("base64")}`;
|
|
18
|
+
return l === void 0 ? `${n}${p}${a}` : `${t}${l}:${p}${a}`;
|
|
16
19
|
},
|
|
17
|
-
decrypt: (
|
|
18
|
-
let
|
|
19
|
-
if (!
|
|
20
|
-
let
|
|
21
|
-
return c !== void 0 &&
|
|
20
|
+
decrypt: (i, a) => {
|
|
21
|
+
let o = i.startsWith(t), s = i.slice(o ? t.length : n.length).split(":"), c = o ? s.shift() ?? "" : void 0, [u, d, f, ...p] = s;
|
|
22
|
+
if (!u || !d || f === void 0 || p.length > 1 || p.length === 1 && !r.test(p[0])) throw Error("field cipher: malformed ciphertext");
|
|
23
|
+
let h = l("aes-256-gcm", e, Buffer.from(u, "base64"));
|
|
24
|
+
return c !== void 0 && h.setAAD(m(c, a)), h.setAuthTag(Buffer.from(d, "base64")), Buffer.concat([h.update(Buffer.from(f, "base64")), h.final()]).toString("utf8");
|
|
22
25
|
}
|
|
23
26
|
};
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
}, g = (e) => `k${u("sha256", p(e)).update("voltro:field-key-id:v1").digest("hex").slice(0, 10)}`, _ = class extends Error {
|
|
28
|
+
_tag = "FieldKeyringConfigError";
|
|
29
|
+
constructor(e) {
|
|
30
|
+
super(e), this.name = "FieldKeyringConfigError";
|
|
31
|
+
}
|
|
32
|
+
}, v = (e) => e !== void 0 && typeof e.sealWith == "function" && typeof e.activate == "function", y = (t, n = {}) => {
|
|
33
|
+
let a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
|
|
34
|
+
for (let e of t.keys) {
|
|
35
|
+
if (!r.test(e.id)) throw new _(`field encryption: "${e.id}" is not a key id — use a short lowercase slug (letters, digits, "-", at most 16)`);
|
|
36
|
+
if (e.secret.trim() === "") throw new _(`field encryption: key "${e.id}" is empty`);
|
|
37
|
+
if (a.has(e.id)) throw new _(`field encryption: key id "${e.id}" is configured twice`);
|
|
38
|
+
let t = p(e.secret).toString("hex"), n = o.get(t);
|
|
39
|
+
if (n !== void 0) throw new _(`field encryption: keys "${n}" and "${e.id}" are the same key — a rotation needs a NEW key, and two ids for one key make every count per key wrong`);
|
|
40
|
+
a.set(e.id, e.secret), o.set(t, e.id);
|
|
41
|
+
}
|
|
42
|
+
if (!a.has(t.active)) throw new _(`field encryption: the active key "${t.active}" is not one of the configured keys (${[...a.keys()].join(", ") || "none"})`);
|
|
43
|
+
let s = new Map([...a].map(([e, t]) => [e, h(p(t), e)])), c = t.active, l = n.sealOnlyOnceActivated !== !0, u = [], d = () => {
|
|
44
|
+
u = [[c, s.get(c)], ...[...s].filter(([e]) => e !== c)];
|
|
45
|
+
};
|
|
46
|
+
d();
|
|
47
|
+
let f = (e, t, n) => {
|
|
28
48
|
try {
|
|
29
49
|
return e.decrypt(t, n), !0;
|
|
30
50
|
} catch {
|
|
31
51
|
return !1;
|
|
32
52
|
}
|
|
53
|
+
}, m = (e, t) => {
|
|
54
|
+
let n = i(e), r = n === void 0 ? void 0 : s.get(n);
|
|
55
|
+
return r !== void 0 && f(r, e, t) ? n : u.find(([, n]) => n !== r && f(n, e, t))?.[0];
|
|
33
56
|
};
|
|
34
57
|
return {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
get activeKeyId() {
|
|
59
|
+
return c;
|
|
60
|
+
},
|
|
61
|
+
requestedKeyId: t.active,
|
|
62
|
+
keyIds: u.map(([e]) => e),
|
|
63
|
+
fingerprints: Object.freeze(Object.fromEntries([...a].map(([e, t]) => [e, g(t)]))),
|
|
64
|
+
encrypt: (e, t) => {
|
|
65
|
+
if (!l) throw Error("field cipher: nothing may be sealed before the boot has checked the keys against the database (verifyFieldKeyring decides which key is active) — a write reached an .encrypted() column during boot, before that check");
|
|
66
|
+
return s.get(c).encrypt(e, t);
|
|
67
|
+
},
|
|
68
|
+
sealWith: (e, t, n) => {
|
|
69
|
+
let r = s.get(e);
|
|
70
|
+
if (r === void 0) throw Error(`field cipher: this keyring does not hold key "${e}"`);
|
|
71
|
+
return r.encrypt(t, n);
|
|
72
|
+
},
|
|
73
|
+
opensWith: (e, t, n) => {
|
|
74
|
+
let r = s.get(e);
|
|
75
|
+
return r !== void 0 && f(r, t, n);
|
|
76
|
+
},
|
|
77
|
+
activate: (e) => {
|
|
78
|
+
if (!s.has(e)) throw Error(`field cipher: cannot activate key "${e}", which this keyring does not hold`);
|
|
79
|
+
c = e, l = !0, d();
|
|
80
|
+
},
|
|
81
|
+
decrypt: (t, n) => {
|
|
82
|
+
let r = i(t), a = r === void 0 ? void 0 : s.get(r), o = n?.column ?? "unbound";
|
|
83
|
+
if (r !== void 0 && a === void 0 && u.every(([, e]) => !f(e, t, n))) throw e(r, o, "failed"), Error(`field cipher: the value is sealed under key "${r}", which this keyring does not hold (it holds ${u.map(([e]) => e).join(", ")})`);
|
|
84
|
+
let c;
|
|
85
|
+
if (a !== void 0) try {
|
|
86
|
+
let i = a.decrypt(t, n);
|
|
87
|
+
return e(r, o, "ok"), i;
|
|
88
|
+
} catch (e) {
|
|
89
|
+
c = e;
|
|
44
90
|
}
|
|
91
|
+
for (let [r, i] of u) if (i !== a) try {
|
|
92
|
+
let a = i.decrypt(t, n);
|
|
93
|
+
return e(r, o, "ok"), a;
|
|
94
|
+
} catch (e) {
|
|
95
|
+
c ??= e;
|
|
96
|
+
}
|
|
97
|
+
throw e(r ?? "unnamed", o, "failed"), c ?? /* @__PURE__ */ Error("field cipher: malformed ciphertext");
|
|
45
98
|
},
|
|
46
|
-
|
|
99
|
+
keyIdOf: m,
|
|
100
|
+
sealedWithPreviousKey: (e, t) => {
|
|
101
|
+
let n = m(e, t);
|
|
102
|
+
return n !== void 0 && n !== c;
|
|
103
|
+
}
|
|
47
104
|
};
|
|
48
|
-
},
|
|
49
|
-
p = e;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
105
|
+
}, b = (e, t = []) => {
|
|
106
|
+
let n = p(e).toString("hex"), r = [...new Map(t.filter((e) => e.trim() !== "" && p(e).toString("hex") !== n).map((e) => [p(e).toString("hex"), e])).values()];
|
|
107
|
+
return y({
|
|
108
|
+
active: g(e),
|
|
109
|
+
keys: [{
|
|
110
|
+
id: g(e),
|
|
111
|
+
secret: e
|
|
112
|
+
}, ...r.map((e) => ({
|
|
113
|
+
id: g(e),
|
|
114
|
+
secret: e
|
|
115
|
+
}))]
|
|
116
|
+
});
|
|
117
|
+
}, x, S = (e) => {
|
|
118
|
+
x = e;
|
|
119
|
+
}, C = () => x, w = "no field cipher registered — set VOLTRO_FIELD_ENCRYPTION_KEY (`voltro secret generate field-encryption`; `voltro dev` mints one), or call setFieldCipher.", T = (e, t) => {
|
|
120
|
+
let n = C();
|
|
121
|
+
if (!n) throw Error(`encryptField: ${w}`);
|
|
122
|
+
return o(n, e, t);
|
|
123
|
+
}, E = (e, t) => {
|
|
124
|
+
if (!s(e)) return e;
|
|
125
|
+
let n = C();
|
|
126
|
+
if (!n) throw Error(`decryptField: ${w}`);
|
|
127
|
+
return a(n, e, void 0, t);
|
|
59
128
|
};
|
|
60
|
-
|
|
61
|
-
export { v as decryptField, l as deriveKey, _ as encryptField, h as getFieldCipher, d as makeAesCipher, f as makeFieldCipher, m as setFieldCipher };
|
|
129
|
+
export { _ as FieldKeyringConfigError, E as decryptField, p as deriveKey, T as encryptField, g as fieldKeyIdOf, C as getFieldCipher, v as isFieldKeyring, h as makeAesCipher, b as makeFieldCipher, y as makeFieldKeyring, S as setFieldCipher };
|