@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
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { API_ROLE_BUCKET_MS as e, API_ROLE_WINDOW_MS as t, assessApiRoleWorkloadWindow as n } from "./apiRoleWorkloadHistory.js";
|
|
2
|
+
// src/apiRoleWorkloadStorage.ts
|
|
3
|
+
var r = "_voltro_api_role_workload_buckets", i = 16384, a = (e) => e instanceof Date ? e.getTime() : typeof e == "number" ? e : NaN, o = async (e, t) => {
|
|
4
|
+
let a = Object.keys(t.workloads);
|
|
5
|
+
if (n({
|
|
6
|
+
now: Math.max(864e5, t.until),
|
|
7
|
+
replicaId: t.replicaId,
|
|
8
|
+
startedAt: t.startedAt,
|
|
9
|
+
role: t.role,
|
|
10
|
+
requiredWorkloads: a,
|
|
11
|
+
buckets: [t]
|
|
12
|
+
}).reason === "invalid-observation" || !t.replicaId || t.replicaId.length > 191 || t.role.length > 2080) throw Error("Invalid API role history bucket");
|
|
13
|
+
let o = JSON.stringify({
|
|
14
|
+
version: 1,
|
|
15
|
+
continuous: t.continuous,
|
|
16
|
+
workloads: t.workloads
|
|
17
|
+
});
|
|
18
|
+
if (new TextEncoder().encode(o).byteLength > i) throw Error("API role history payload too large");
|
|
19
|
+
await e.upsert(r, {
|
|
20
|
+
replicaId: t.replicaId,
|
|
21
|
+
startedAt: new Date(t.startedAt),
|
|
22
|
+
role: t.role,
|
|
23
|
+
bucketFrom: new Date(t.from),
|
|
24
|
+
bucketUntil: new Date(t.until),
|
|
25
|
+
payload: o
|
|
26
|
+
}, { conflictColumns: [
|
|
27
|
+
"replicaId",
|
|
28
|
+
"startedAt",
|
|
29
|
+
"bucketFrom"
|
|
30
|
+
] });
|
|
31
|
+
}, s = async (o, s) => {
|
|
32
|
+
let c = n({
|
|
33
|
+
...s,
|
|
34
|
+
buckets: []
|
|
35
|
+
}), l = (await o.query({
|
|
36
|
+
table: r,
|
|
37
|
+
predicate: { and: [
|
|
38
|
+
{
|
|
39
|
+
column: "replicaId",
|
|
40
|
+
op: "eq",
|
|
41
|
+
value: s.replicaId
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
column: "startedAt",
|
|
45
|
+
op: "eq",
|
|
46
|
+
value: new Date(s.startedAt)
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
column: "role",
|
|
50
|
+
op: "eq",
|
|
51
|
+
value: s.role
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
column: "bucketFrom",
|
|
55
|
+
op: "gte",
|
|
56
|
+
value: new Date(c.from)
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
column: "bucketFrom",
|
|
60
|
+
op: "lt",
|
|
61
|
+
value: new Date(c.until)
|
|
62
|
+
}
|
|
63
|
+
] },
|
|
64
|
+
order: [{
|
|
65
|
+
column: "bucketFrom",
|
|
66
|
+
direction: "asc"
|
|
67
|
+
}],
|
|
68
|
+
take: t / e + 1,
|
|
69
|
+
skip: void 0,
|
|
70
|
+
projection: void 0
|
|
71
|
+
})).map((e) => {
|
|
72
|
+
if (typeof e.payload != "string" || new TextEncoder().encode(e.payload).byteLength > i) throw Error("Invalid API role history payload");
|
|
73
|
+
let t = JSON.parse(e.payload);
|
|
74
|
+
if (!t || t.version !== 1 || typeof t.continuous != "boolean" || !t.workloads || typeof t.workloads != "object" || Array.isArray(t.workloads)) throw Error("Invalid API role history payload");
|
|
75
|
+
return {
|
|
76
|
+
replicaId: String(e.replicaId),
|
|
77
|
+
startedAt: a(e.startedAt),
|
|
78
|
+
role: String(e.role),
|
|
79
|
+
from: a(e.bucketFrom),
|
|
80
|
+
until: a(e.bucketUntil),
|
|
81
|
+
continuous: t.continuous,
|
|
82
|
+
workloads: t.workloads
|
|
83
|
+
};
|
|
84
|
+
}), u = n({
|
|
85
|
+
...s,
|
|
86
|
+
buckets: l
|
|
87
|
+
});
|
|
88
|
+
if (u.reason === "invalid-observation") throw Error("Invalid API role history observations");
|
|
89
|
+
return {
|
|
90
|
+
buckets: l,
|
|
91
|
+
assessment: u
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
export { r as API_ROLE_WORKLOAD_BUCKETS_TABLE, s as readApiRoleWorkloadWindow, o as writeApiRoleWorkloadBucket };
|
package/dist/approvalBuiltins.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { decideApproval as e, pendingApprovalsFor as t } from "./approvals.js";
|
|
2
|
-
|
|
2
|
+
// src/approvalBuiltins.ts
|
|
3
3
|
var n = (e) => e.request?.subject ?? null, r = async (e, r) => t(r.store, n(r), { limit: e.limit ?? 50 }), i = async (t, r) => e(r.store, {
|
|
4
4
|
approvalId: t.approvalId,
|
|
5
5
|
decision: t.decision,
|
|
6
6
|
approver: n(r),
|
|
7
7
|
...t.note === void 0 ? {} : { note: t.note }
|
|
8
8
|
});
|
|
9
|
-
//#endregion
|
|
10
9
|
export { r as approvalsPendingExecutor, i as decideApprovalInvocation };
|
package/dist/approvals.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Effect as e } from "effect";
|
|
2
2
|
import { and as t, eq as n, generateId as r, id as i, inSet as a, registerRetention as o, retentionTtlMsFromEnv as s, table as c, text as l, timestamp as u } from "@voltro/database";
|
|
3
3
|
import { createHash as d, randomUUID as f } from "node:crypto";
|
|
4
|
-
import { ApprovalExpired as p, ApprovalForbidden as m, ApprovalNotFound as h, ApprovalNotPending as g, ApprovalRejected as _, ApprovalRequired as v, ApprovalSelfApproval as y, ApprovalUnavailable as b,
|
|
5
|
-
|
|
6
|
-
var
|
|
4
|
+
import { ApprovalExpired as p, ApprovalForbidden as m, ApprovalNotFound as h, ApprovalNotPending as g, ApprovalRejected as _, ApprovalRequired as v, ApprovalSelfApproval as y, ApprovalUnavailable as b, canonicalJson as x, checkGuardsEffect as S, isAuthenticatedGuard as C, isPolicyGuard as w, isUpgradedGuard as T, resolvePolicyAction as E, upgradedGuardShapeError as D } from "@voltro/protocol";
|
|
5
|
+
// src/approvals.ts
|
|
6
|
+
var O = "_voltro_approvals", k = 864e5, A = c(O, {
|
|
7
7
|
id: i({ prefix: "apv" }),
|
|
8
8
|
intentKey: l().maxLength(191),
|
|
9
9
|
procedure: l(),
|
|
@@ -22,24 +22,28 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
22
22
|
requestedAt: u().default("now"),
|
|
23
23
|
expiresAt: u(),
|
|
24
24
|
consumedAt: u().nullable()
|
|
25
|
-
}).index(["status", "expiresAt"]).index(["requestedBy"]),
|
|
25
|
+
}).index(["status", "expiresAt"]).index(["requestedBy"]), j = () => {
|
|
26
26
|
o({
|
|
27
27
|
source: "framework",
|
|
28
|
-
table:
|
|
28
|
+
table: O,
|
|
29
29
|
timeColumn: "requestedAt",
|
|
30
30
|
ttlMs: s(process.env.VOLTRO_APPROVALS_TTL_HOURS, 720)
|
|
31
31
|
});
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
32
|
+
}, M = (e, t) => e.map((e) => {
|
|
33
|
+
let n = D(e);
|
|
34
|
+
if (n) throw n;
|
|
35
|
+
return C(e) ? { kind: "authenticated" } : T(e) ? { kind: "upgraded" } : w(e) ? {
|
|
36
|
+
kind: "policy",
|
|
37
|
+
action: E(e, t),
|
|
38
|
+
resourceType: e.resourceType,
|
|
39
|
+
resource: e.resource(t) ?? null
|
|
40
|
+
} : {
|
|
41
|
+
kind: "scope",
|
|
42
|
+
scope: typeof e.scope == "string" ? [e.scope] : [...e.scope],
|
|
43
|
+
mode: e.mode ?? "all",
|
|
44
|
+
resource: e.resource?.(t) ?? null
|
|
45
|
+
};
|
|
46
|
+
}), N = (e) => e.map((e) => e.kind === "authenticated" ? { authenticated: !0 } : e.kind === "upgraded" ? { upgraded: !0 } : e.kind === "policy" ? {
|
|
43
47
|
action: e.action,
|
|
44
48
|
resourceType: e.resourceType,
|
|
45
49
|
resource: () => e.resource ?? void 0
|
|
@@ -47,18 +51,7 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
47
51
|
scope: e.scope,
|
|
48
52
|
mode: e.mode,
|
|
49
53
|
...e.resource === null ? {} : { resource: () => e.resource ?? void 0 }
|
|
50
|
-
}),
|
|
51
|
-
let t = (e) => {
|
|
52
|
-
if (Array.isArray(e)) return e.map(t);
|
|
53
|
-
if (typeof e == "object" && e) {
|
|
54
|
-
let n = e, r = Object.create(null);
|
|
55
|
-
for (let e of Object.keys(n).sort()) r[e] = t(n[e]);
|
|
56
|
-
return r;
|
|
57
|
-
}
|
|
58
|
-
return e;
|
|
59
|
-
};
|
|
60
|
-
return JSON.stringify(t(e) ?? null);
|
|
61
|
-
}, N = (e) => {
|
|
54
|
+
}), P = (e) => e.flatMap((e) => e.kind === "policy" ? [`${e.resourceType}:${e.action}`] : e.kind === "authenticated" ? ["authenticated"] : e.kind === "upgraded" ? ["upgraded"] : [...e.scope]), F = (e) => {
|
|
62
55
|
let t = [
|
|
63
56
|
e.procedure,
|
|
64
57
|
e.requestedBy ?? "",
|
|
@@ -67,48 +60,48 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
67
60
|
e.nonce ?? ""
|
|
68
61
|
].map((e) => `${e.length}:${e}`).join("");
|
|
69
62
|
return d("sha256").update(t, "utf8").digest("hex");
|
|
70
|
-
},
|
|
63
|
+
}, I = (e) => e instanceof Date ? e.toISOString() : typeof e == "string" ? e : (/* @__PURE__ */ new Date(0)).toISOString(), L = (e) => e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : 0, R = (e) => {
|
|
71
64
|
try {
|
|
72
65
|
let t = JSON.parse(String(e ?? "[]"));
|
|
73
66
|
return Array.isArray(t) ? t : [];
|
|
74
67
|
} catch {
|
|
75
68
|
return [];
|
|
76
69
|
}
|
|
77
|
-
},
|
|
70
|
+
}, z = async (e, t) => (await e.query({
|
|
78
71
|
table: "_voltro_approvals",
|
|
79
72
|
predicate: n("intentKey", t),
|
|
80
73
|
order: []
|
|
81
|
-
}))[0] ?? null,
|
|
74
|
+
}))[0] ?? null, B = async (e, t) => (await e.query({
|
|
82
75
|
table: "_voltro_approvals",
|
|
83
76
|
predicate: n("id", t),
|
|
84
77
|
order: []
|
|
85
|
-
}))[0] ?? null,
|
|
78
|
+
}))[0] ?? null, V = async (e, t, n) => {
|
|
86
79
|
let r = String(t.intentKey ?? ""), i = r.includes("#") ? r : `${r}#${String(t.id)}`;
|
|
87
|
-
await e.update(
|
|
80
|
+
await e.update(O, String(t.id), {
|
|
88
81
|
...n,
|
|
89
82
|
intentKey: i
|
|
90
83
|
});
|
|
91
|
-
},
|
|
84
|
+
}, H = (e) => {
|
|
92
85
|
let t = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)$/.exec(e.trim());
|
|
93
86
|
if (t === null) return null;
|
|
94
87
|
let n = Number(t[1]);
|
|
95
88
|
if (!(Number.isFinite(n) && n > 0)) return null;
|
|
96
89
|
let r = t[2];
|
|
97
90
|
return n * (r === "ms" ? 1 : r === "s" ? 1e3 : r === "m" ? 6e4 : r === "h" ? 36e5 : 864e5);
|
|
98
|
-
},
|
|
91
|
+
}, U = (e) => {
|
|
99
92
|
let i = e.store, a = e.now ?? Date.now, o = e.defaultExpiryMs ?? 864e5;
|
|
100
|
-
|
|
93
|
+
j();
|
|
101
94
|
let s = (e) => {
|
|
102
95
|
if (e.expiresIn === void 0) return o;
|
|
103
|
-
let t =
|
|
96
|
+
let t = H(e.expiresIn);
|
|
104
97
|
if (t === null) throw Error(`requiresApproval.expiresIn must be an interval like '4h' / '30m' (got ${JSON.stringify(e.expiresIn)})`);
|
|
105
98
|
return t;
|
|
106
99
|
}, c = async (e, t, n) => {
|
|
107
|
-
let o =
|
|
100
|
+
let o = M(e.policy.approvers, e.input), c = r({
|
|
108
101
|
kind: "typeid",
|
|
109
102
|
prefix: "apv"
|
|
110
|
-
},
|
|
111
|
-
await i.insertIgnore(
|
|
103
|
+
}, O), l = a();
|
|
104
|
+
await i.insertIgnore(O, {
|
|
112
105
|
id: c,
|
|
113
106
|
intentKey: t,
|
|
114
107
|
procedure: e.procedure,
|
|
@@ -117,7 +110,7 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
117
110
|
tenantId: e.subject?.tenantId ?? null,
|
|
118
111
|
payload: n,
|
|
119
112
|
approverGuards: JSON.stringify(o),
|
|
120
|
-
approverScopes: JSON.stringify(
|
|
113
|
+
approverScopes: JSON.stringify(P(o)),
|
|
121
114
|
reason: e.policy.reason ?? null,
|
|
122
115
|
status: "pending",
|
|
123
116
|
decidedBy: null,
|
|
@@ -128,7 +121,7 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
128
121
|
expiresAt: new Date(l + s(e.policy)),
|
|
129
122
|
consumedAt: null
|
|
130
123
|
}, { conflictColumns: ["intentKey"] });
|
|
131
|
-
let u = await
|
|
124
|
+
let u = await z(i, t);
|
|
132
125
|
if (u === null) throw new b({
|
|
133
126
|
procedure: e.procedure,
|
|
134
127
|
message: "the approval intent was written and could not be read back"
|
|
@@ -137,27 +130,27 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
137
130
|
}, l = (e, t) => new v({
|
|
138
131
|
approvalId: String(e.id),
|
|
139
132
|
procedure: String(e.procedure),
|
|
140
|
-
expiresAt:
|
|
141
|
-
requiredScopes:
|
|
133
|
+
expiresAt: I(e.expiresAt),
|
|
134
|
+
requiredScopes: P(R(e.approverGuards)),
|
|
142
135
|
reason: e.reason ?? null,
|
|
143
136
|
created: t
|
|
144
137
|
});
|
|
145
138
|
return { admit: async (e) => {
|
|
146
|
-
let r =
|
|
139
|
+
let r = x(e.input), o = F({
|
|
147
140
|
procedure: e.procedure,
|
|
148
141
|
requestedBy: e.subject?.id ?? null,
|
|
149
142
|
tenantId: e.subject?.tenantId ?? null,
|
|
150
143
|
payload: r,
|
|
151
144
|
nonce: e.nonce
|
|
152
|
-
}), s = await
|
|
145
|
+
}), s = await z(i, o);
|
|
153
146
|
if (s === null) throw l(await c(e, o, r), !0);
|
|
154
|
-
let u = String(s.status ?? "pending"), d =
|
|
155
|
-
if ((u === "pending" || u === "approved") && a() > d) throw await
|
|
147
|
+
let u = String(s.status ?? "pending"), d = L(s.expiresAt);
|
|
148
|
+
if ((u === "pending" || u === "approved") && a() > d) throw await V(i, s, { status: "expired" }), new p({
|
|
156
149
|
approvalId: String(s.id),
|
|
157
|
-
expiredAt:
|
|
150
|
+
expiredAt: I(s.expiresAt)
|
|
158
151
|
});
|
|
159
152
|
if (u === "pending") throw l(s, !1);
|
|
160
|
-
if (u === "rejected") throw await
|
|
153
|
+
if (u === "rejected") throw await V(i, s, {}), new _({
|
|
161
154
|
approvalId: String(s.id),
|
|
162
155
|
decidedBy: s.decidedBy ?? null,
|
|
163
156
|
note: s.note ?? null
|
|
@@ -168,17 +161,17 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
168
161
|
consumedAt: new Date(a()),
|
|
169
162
|
intentKey: `${o}#${String(s.id)}`
|
|
170
163
|
}, { where: t(n("id", String(s.id)), n("status", "approved")) }) === 1) return;
|
|
171
|
-
throw s = await
|
|
164
|
+
throw s = await z(i, o), s === null ? l(await c(e, o, r), !0) : l(s, !1);
|
|
172
165
|
}
|
|
173
|
-
throw await
|
|
166
|
+
throw await V(i, s, {}), l(await c(e, o, r), !0);
|
|
174
167
|
} };
|
|
175
|
-
},
|
|
176
|
-
|
|
177
|
-
},
|
|
178
|
-
|
|
179
|
-
},
|
|
168
|
+
}, W, G = (e) => {
|
|
169
|
+
W = e;
|
|
170
|
+
}, K = () => W, q = () => {
|
|
171
|
+
W = void 0;
|
|
172
|
+
}, J = async (e) => {
|
|
180
173
|
if (e.policy === void 0) return;
|
|
181
|
-
let t =
|
|
174
|
+
let t = K();
|
|
182
175
|
if (t === void 0) throw new b({
|
|
183
176
|
procedure: e.procedure,
|
|
184
177
|
message: `${e.procedure} declares \`requiresApproval\` and no approvals gate is installed on this boot path, so the framework cannot record the intent or verify a decision. Refusing the call rather than running it unapproved.`
|
|
@@ -191,17 +184,17 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
191
184
|
input: e.input,
|
|
192
185
|
...e.traceId === void 0 ? {} : { traceId: e.traceId }
|
|
193
186
|
});
|
|
194
|
-
},
|
|
195
|
-
let a = i.now ?? Date.now, o = await
|
|
187
|
+
}, Y = async (r, i) => {
|
|
188
|
+
let a = i.now ?? Date.now, o = await B(r, i.approvalId);
|
|
196
189
|
if (o === null) throw new h({ approvalId: i.approvalId });
|
|
197
190
|
let s = String(o.status ?? "pending");
|
|
198
191
|
if (s !== "pending") throw new g({
|
|
199
192
|
approvalId: i.approvalId,
|
|
200
193
|
status: s
|
|
201
194
|
});
|
|
202
|
-
if (a() >
|
|
195
|
+
if (a() > L(o.expiresAt)) throw await V(r, o, { status: "expired" }), new p({
|
|
203
196
|
approvalId: i.approvalId,
|
|
204
|
-
expiredAt:
|
|
197
|
+
expiredAt: I(o.expiresAt)
|
|
205
198
|
});
|
|
206
199
|
let c = i.approver?.id ?? null;
|
|
207
200
|
if (c === null) throw new m({
|
|
@@ -213,7 +206,7 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
213
206
|
approvalId: i.approvalId,
|
|
214
207
|
subjectId: c
|
|
215
208
|
});
|
|
216
|
-
let l =
|
|
209
|
+
let l = N(R(o.approverGuards)), u = await e.runPromise(S(i.approver, l, JSON.parse(String(o.payload ?? "null"))));
|
|
217
210
|
if (u) throw new m({
|
|
218
211
|
approvalId: i.approvalId,
|
|
219
212
|
required: "_tag" in u && u._tag === "ScopeError" ? u.required : null,
|
|
@@ -226,7 +219,7 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
226
219
|
decidedAt: new Date(a()),
|
|
227
220
|
note: i.note ?? null
|
|
228
221
|
}, { where: t(n("id", i.approvalId), n("status", "pending")) }) !== 1) {
|
|
229
|
-
let e = await
|
|
222
|
+
let e = await B(r, i.approvalId);
|
|
230
223
|
throw new g({
|
|
231
224
|
approvalId: i.approvalId,
|
|
232
225
|
status: String(e?.status ?? "unknown")
|
|
@@ -236,34 +229,33 @@ var T = "_voltro_approvals", E = 864e5, D = c(T, {
|
|
|
236
229
|
approvalId: i.approvalId,
|
|
237
230
|
status: d
|
|
238
231
|
};
|
|
239
|
-
},
|
|
232
|
+
}, X = async (t, n, r) => {
|
|
240
233
|
let i = n?.id ?? null;
|
|
241
234
|
if (i === null) return [];
|
|
242
235
|
let o = r?.now ?? Date.now, s = await t.query({
|
|
243
|
-
table:
|
|
236
|
+
table: O,
|
|
244
237
|
predicate: a("status", ["pending", "approved"]),
|
|
245
238
|
order: []
|
|
246
239
|
}), c = [];
|
|
247
240
|
for (let t of s) {
|
|
248
|
-
if (o() >
|
|
249
|
-
let r =
|
|
250
|
-
a || await e.runPromise(
|
|
241
|
+
if (o() > L(t.expiresAt)) continue;
|
|
242
|
+
let r = R(t.approverGuards), a = (t.requestedBy ?? null) === i, s = a ? "requested" : null;
|
|
243
|
+
a || await e.runPromise(S(n, N(r), JSON.parse(String(t.payload ?? "null")))) === null && String(t.status) === "pending" && (s = "to-decide"), s !== null && c.push({
|
|
251
244
|
id: String(t.id),
|
|
252
245
|
procedure: String(t.procedure),
|
|
253
246
|
kind: String(t.kind) === "action" ? "action" : "mutation",
|
|
254
247
|
requestedBy: t.requestedBy ?? null,
|
|
255
248
|
status: String(t.status ?? "pending"),
|
|
256
249
|
reason: t.reason ?? null,
|
|
257
|
-
requiredScopes:
|
|
258
|
-
requestedAt:
|
|
259
|
-
expiresAt:
|
|
250
|
+
requiredScopes: P(r),
|
|
251
|
+
requestedAt: I(t.requestedAt),
|
|
252
|
+
expiresAt: I(t.expiresAt),
|
|
260
253
|
decidedBy: t.decidedBy ?? null,
|
|
261
|
-
decidedAt: t.decidedAt == null ? null :
|
|
254
|
+
decidedAt: t.decidedAt == null ? null : I(t.decidedAt),
|
|
262
255
|
note: t.note ?? null,
|
|
263
256
|
relation: s
|
|
264
257
|
});
|
|
265
258
|
}
|
|
266
259
|
return c.sort((e, t) => t.requestedAt.localeCompare(e.requestedAt)).slice(0, r?.limit ?? 50);
|
|
267
|
-
},
|
|
268
|
-
|
|
269
|
-
export { T as APPROVALS_TABLE, E as DEFAULT_APPROVAL_EXPIRY_MS, D as _voltroApprovalsTable, N as approvalIntentKey, Y as approvalNonce, M as canonicalJson, G as clearApprovalGate, q as decideApproval, K as enforceApproval, W as getApprovalGate, U as installApprovalGate, V as makeApprovalGate, B as parseApprovalInterval, J as pendingApprovalsFor, A as rehydrateGuards, j as scopeStringsOf, k as serializeGuards };
|
|
260
|
+
}, Z = () => f();
|
|
261
|
+
export { O as APPROVALS_TABLE, k as DEFAULT_APPROVAL_EXPIRY_MS, A as _voltroApprovalsTable, F as approvalIntentKey, Z as approvalNonce, x as canonicalJson, q as clearApprovalGate, Y as decideApproval, J as enforceApproval, K as getApprovalGate, G as installApprovalGate, U as makeApprovalGate, H as parseApprovalInterval, X as pendingApprovalsFor, N as rehydrateGuards, P as scopeStringsOf, M as serializeGuards };
|
|
@@ -3,7 +3,7 @@ import { Context as r, Effect as i, Layer as a, Option as o, Schema as s } from
|
|
|
3
3
|
import { AuthMiddleware as c, ConnectionInfo as l, ConnectionInfoMiddleware as u, RequestedTenantRefused as d, SubjectService as f, Unauthenticated as p } from "@voltro/protocol";
|
|
4
4
|
import { Rpc as m } from "effect/rpc";
|
|
5
5
|
import { sessionExpiryFromHeaders as h } from "@voltro/protocol/session";
|
|
6
|
-
|
|
6
|
+
// src/authMiddlewareLayer.ts
|
|
7
7
|
var g = class extends r.Service()("@voltro/runtime/VerifiedCredentialLifetime") {}, _ = (e) => {
|
|
8
8
|
for (let t of e.requests.values()) if (m.isRpc(t) && [...t.middlewares].some((e) => e.key === c.key || e.key === u.key)) throw Error("withRpcAuthMiddleware requires a group without AuthMiddleware or ConnectionInfoMiddleware; apply the shared pair once");
|
|
9
9
|
return e.middleware(u).middleware(c);
|
|
@@ -33,15 +33,15 @@ var g = class extends r.Service()("@voltro/runtime/VerifiedCredentialLifetime")
|
|
|
33
33
|
return a.mergeAll(a.succeed(c, _), a.succeed(u, u.of((n, r) => i.gen(function* () {
|
|
34
34
|
let { headers: n, client: a, rpc: s } = r, l = yield* i.serviceOption(g), u = o.filter(l, (e) => e.request === r);
|
|
35
35
|
if (o.isNone(u) && m.has(r) && [...s.middlewares].some((e) => e.key === c.key)) throw Error("RPC authentication must run before ConnectionInfoMiddleware; compose the group with withRpcAuthMiddleware");
|
|
36
|
-
let d = o.isSome(u) ? u.value.credentialExpiresAt : t(a.id) ?? h(e(a.id, n)), f = n["idempotency-key"],
|
|
36
|
+
let d = o.isSome(u) ? u.value.credentialExpiresAt : t(a.id) ?? h(e(a.id, n)), f = e(a.id, n).cookie, p = n["idempotency-key"], _ = n["voltro-resume-from"], v = n["voltro-reconcile"], y = _ !== void 0 && /^\d+$/.test(_) ? Number(_) : void 0;
|
|
37
37
|
return {
|
|
38
38
|
clientId: a.id,
|
|
39
|
-
...f ? {
|
|
39
|
+
...f === void 0 ? {} : { cookieHeader: f },
|
|
40
|
+
...p ? { idempotencyKey: p } : {},
|
|
40
41
|
...d === void 0 ? {} : { credentialExpiresAt: d },
|
|
41
|
-
...
|
|
42
|
-
...
|
|
42
|
+
...y !== void 0 && Number.isSafeInteger(y) ? { resumeFrom: y } : {},
|
|
43
|
+
...v !== void 0 && /^[a-zA-Z0-9_-]{1,128}$/.test(v) ? { reconcile: v } : {}
|
|
43
44
|
};
|
|
44
45
|
}).pipe(i.flatMap((e) => i.provideService(n, l, e))))));
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export { v as makeAuthMiddlewareLayers, _ as withRpcAuthMiddleware };
|
|
46
|
+
}, y = (e) => a.succeed(u, u.of((t, { headers: n, client: r }) => i.sync(() => (e(n, r.id), { clientId: r.id })).pipe(i.flatMap((e) => i.provideService(t, l, e)))));
|
|
47
|
+
export { v as makeAuthMiddlewareLayers, y as observeConnectionHeaders, _ as withRpcAuthMiddleware };
|
package/dist/bindEvent.js
CHANGED
|
@@ -2,9 +2,9 @@ import { recordEventDelivered as e, recordEventDropped as t } from "./metrics.js
|
|
|
2
2
|
import { registerConnectionStream as n } from "./connectionCredentials.js";
|
|
3
3
|
import { boundByCredential as r } from "./credentialBound.js";
|
|
4
4
|
import { Effect as i, Queue as a, Stream as o } from "effect";
|
|
5
|
-
import { ConnectionInfo as s,
|
|
6
|
-
|
|
7
|
-
var
|
|
5
|
+
import { ConnectionInfo as s, ScopeError as c, SubjectService as l, checkGuardsEffect as u, isOpenAccess as d, recheckGuardsEffect as f } from "@voltro/protocol";
|
|
6
|
+
// src/bindEvent.ts
|
|
7
|
+
var p = 64, m = 1, h = (e) => e.kind === "gap" ? {
|
|
8
8
|
_tag: "gap",
|
|
9
9
|
missed: e.missed,
|
|
10
10
|
reason: e.reason
|
|
@@ -14,49 +14,69 @@ var f = 64, p = 1, m = (e) => e.kind === "gap" ? {
|
|
|
14
14
|
n: e.envelope.n,
|
|
15
15
|
emittedAt: e.envelope.emittedAt,
|
|
16
16
|
payload: e.envelope.payload
|
|
17
|
-
},
|
|
17
|
+
}, g = (e) => {
|
|
18
18
|
let t = new Map(e ?? []);
|
|
19
19
|
return (e, n = 0) => {
|
|
20
20
|
let r = t.get(e.origin) ?? 0;
|
|
21
21
|
return t.set(e.origin, Math.max(r, e.n)), r === 0 && n === 0 ? 0 : Math.max(0, e.n - r - 1);
|
|
22
22
|
};
|
|
23
|
-
},
|
|
24
|
-
let
|
|
25
|
-
if (
|
|
26
|
-
let e = yield*
|
|
23
|
+
}, _ = (p) => o.unwrap(i.gen(function* () {
|
|
24
|
+
let m = yield* l, _ = yield* s, v = m.tenantId ?? null, y = p.guards === void 0 ? void 0 : p.guards.filter((e) => !d(e));
|
|
25
|
+
if (y !== void 0 && y.length > 0 || m.type === "service") {
|
|
26
|
+
let e = yield* u(m, y ?? [], p.key);
|
|
27
27
|
if (e) return yield* i.fail(e);
|
|
28
28
|
}
|
|
29
|
-
let
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
let b = p.clientPolicy, x = () => new c({
|
|
30
|
+
required: p.requiredClientPolicy ?? "event:client-policy",
|
|
31
|
+
message: "event client access denied"
|
|
32
|
+
});
|
|
33
|
+
if (p.requiredClientPolicy !== void 0 && (!b || b.id !== p.requiredClientPolicy) || b !== void 0 && p.requiredClientPolicy === void 0) return yield* i.fail(x());
|
|
34
|
+
let S = () => ({
|
|
35
|
+
subject: structuredClone(m),
|
|
36
|
+
event: p.event,
|
|
37
|
+
key: structuredClone(p.key)
|
|
38
|
+
}), C = () => b === void 0 ? i.succeed(!0) : i.suspend(() => b.admit(S())).pipe(i.catch(() => i.succeed(!1)), i.catchDefect(() => i.succeed(!1)), i.map((e) => e === !0)), w = b?.monitor === void 0 ? void 0 : yield* i.suspend(() => b.monitor(S())).pipe(i.catch(() => i.fail(x())), i.catchDefect(() => i.fail(x())));
|
|
39
|
+
if (!(yield* C())) return yield* i.fail(x());
|
|
40
|
+
let T = p.bus.deliveryFor(p.event) === "latest", E = yield* a.sliding(p.queueSize ?? (T ? 1 : 64)), D = /* @__PURE__ */ new Map(), O = p.bus.subscribe({
|
|
41
|
+
tenantId: v,
|
|
42
|
+
event: p.event,
|
|
43
|
+
key: p.key,
|
|
44
|
+
options: p.options,
|
|
34
45
|
onAttach: (e) => {
|
|
35
|
-
|
|
46
|
+
D = e;
|
|
36
47
|
},
|
|
37
48
|
listener: (e) => {
|
|
38
|
-
i.runSync(a.offer(
|
|
49
|
+
i.runSync(a.offer(E, e));
|
|
39
50
|
}
|
|
40
51
|
});
|
|
41
52
|
if (yield* i.addFinalizer(() => i.sync(() => {
|
|
42
|
-
|
|
43
|
-
})),
|
|
44
|
-
let e = n(
|
|
45
|
-
i.runPromise(a.shutdown(
|
|
53
|
+
O();
|
|
54
|
+
})), _.clientId !== void 0) {
|
|
55
|
+
let e = n(_.clientId, () => {
|
|
56
|
+
i.runPromise(a.shutdown(E));
|
|
46
57
|
});
|
|
47
58
|
yield* i.addFinalizer(() => i.sync(() => {
|
|
48
59
|
e();
|
|
49
60
|
}));
|
|
50
61
|
}
|
|
51
|
-
let
|
|
52
|
-
function
|
|
62
|
+
let k = T ? () => 0 : g(D), A = () => f(m, y, p.key), j = o.fromQueue(E).pipe(o.flatMap((e) => o.unwrap(A().pipe(i.map((t) => t ? o.fail(t) : M(e))))), o.ensuring(a.shutdown(E)));
|
|
63
|
+
function M(e) {
|
|
64
|
+
if (b === void 0) return N(e);
|
|
65
|
+
let t = e.kind === "gap" ? C().pipe(i.map((e) => e ? "allow" : "deny")) : i.suspend(() => b.deliver({
|
|
66
|
+
...S(),
|
|
67
|
+
payload: structuredClone(e.envelope.payload),
|
|
68
|
+
emittedAt: e.envelope.emittedAt
|
|
69
|
+
})).pipe(i.catch(() => i.succeed("deny")), i.catchDefect(() => i.succeed("deny")));
|
|
70
|
+
return o.unwrap(t.pipe(i.map((t) => t === "allow" ? N(e) : t === "drop" && e.kind !== "gap" ? (k(e.envelope, e.prior), o.empty) : o.fail(x()))));
|
|
71
|
+
}
|
|
72
|
+
function N(n) {
|
|
53
73
|
return o.suspend(() => {
|
|
54
|
-
if (n.kind === "gap") return o.make(
|
|
55
|
-
let r =
|
|
56
|
-
e(
|
|
57
|
-
let i =
|
|
74
|
+
if (n.kind === "gap") return o.make(h(n));
|
|
75
|
+
let r = k(n.envelope, n.prior);
|
|
76
|
+
e(p.event);
|
|
77
|
+
let i = h(n);
|
|
58
78
|
if (r === 0) return o.make(i);
|
|
59
|
-
t(
|
|
79
|
+
t(p.event, "buffer", r);
|
|
60
80
|
let a = {
|
|
61
81
|
_tag: "gap",
|
|
62
82
|
missed: r,
|
|
@@ -65,8 +85,7 @@ var f = 64, p = 1, m = (e) => e.kind === "gap" ? {
|
|
|
65
85
|
return o.fromIterable([a, i]);
|
|
66
86
|
});
|
|
67
87
|
}
|
|
68
|
-
let
|
|
69
|
-
return r(
|
|
88
|
+
let P = { _tag: "attached" }, F = o.concat(o.fromIterable([P]), j), I = w === void 0 ? F : F.pipe(o.interruptWhen(w.pipe(i.catch(() => i.void), i.catchDefect(() => i.void), i.flatMap(() => i.fail(x())))));
|
|
89
|
+
return r(I, _.credentialExpiresAt, o.fromIterable([P]));
|
|
70
90
|
}));
|
|
71
|
-
|
|
72
|
-
export { f as EVENT_CLIENT_QUEUE_SIZE, p as EVENT_LATEST_QUEUE_SIZE, g as bindEvent, h as makeBufferGapDetector };
|
|
91
|
+
export { p as EVENT_CLIENT_QUEUE_SIZE, m as EVENT_LATEST_QUEUE_SIZE, _ as bindEvent, g as makeBufferGapDetector };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const BOOT_REFUSAL_NAME = "VoltroBootRefusal";
|
|
2
|
+
|
|
3
|
+
/** An error the boot path raised on purpose. The launcher prints its message
|
|
4
|
+
* once and exits 1 instead of degrading to a fallback path or printing a
|
|
5
|
+
* stack. */
|
|
6
|
+
export declare const bootRefusal: (message: string) => Error;
|
|
7
|
+
|
|
8
|
+
export declare const isBootRefusal: (error: unknown) => boolean;
|
|
9
|
+
|
|
10
|
+
export { }
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
// src/bootRefusal.ts
|
|
2
2
|
var e = "VoltroBootRefusal", t = (t) => {
|
|
3
3
|
let n = Error(t);
|
|
4
4
|
return n.name = e, n;
|
|
5
5
|
}, n = (e) => typeof e == "object" && !!e && e.name === "VoltroBootRefusal";
|
|
6
|
-
//#endregion
|
|
7
6
|
export { e as BOOT_REFUSAL_NAME, t as bootRefusal, n as isBootRefusal };
|