@voltro/plugin-audit 0.83.1 → 0.85.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 +1191 -0
- package/THIRD-PARTY-NOTICES.md +1 -57
- package/dist/index.d.ts +1 -1
- package/dist/index.js +229 -198
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { audit as e } from "./mixin.js";
|
|
2
|
-
import {
|
|
3
|
-
import { anonymousSubject as
|
|
4
|
-
import { createLogger as
|
|
5
|
-
import { and as
|
|
6
|
-
import { createHash as
|
|
2
|
+
import { Cause as t, Effect as n } from "effect";
|
|
3
|
+
import { anonymousSubject as r, definePlugin as i, pluginInstanceName as a, rawImpersonationMark as o } from "@voltro/protocol";
|
|
4
|
+
import { createLogger as s } from "@voltro/logger";
|
|
5
|
+
import { and as c, column as l, eq as u, gt as d, id as f, integer as p, isNotNull as m, isNull as h, json as g, lte as _, or as v, registerRetention as ee, resolveActorSnapshot as y, retentionTtlMsFromEnv as b, scopeKeyOf as x, table as S, text as C, timestamp as w } from "@voltro/database";
|
|
6
|
+
import { createHash as T, createHmac as E, randomBytes as D } from "node:crypto";
|
|
7
7
|
//#region src/redactionShape.ts
|
|
8
|
-
var
|
|
8
|
+
var O = 4, k = 32, A = 64, te = /^[A-Za-z_$][A-Za-z0-9_$]*$/, j = (e, t) => e === 0 || t <= 0 || e >= t ? `string(${e})` : `string(<${t})`, M = (e, t) => e.length <= A && te.test(e) ? e : `<key:${j(e.length, t)}>`, N = (e, t = 0, n = 16) => {
|
|
9
9
|
if (e === null) return "null";
|
|
10
10
|
if (e === void 0) return "undefined";
|
|
11
11
|
let r = typeof e;
|
|
12
|
-
if (r === "string") return
|
|
12
|
+
if (r === "string") return j(e.length, n);
|
|
13
13
|
if (r === "number" || r === "boolean" || r === "bigint" || r === "symbol" || r === "function") return r;
|
|
14
14
|
if (e instanceof Date) return "date";
|
|
15
|
-
if (t >=
|
|
15
|
+
if (t >= O) return Array.isArray(e) ? "array(…)" : "object(…)";
|
|
16
16
|
if (Array.isArray(e)) {
|
|
17
|
-
let r = e.slice(0,
|
|
18
|
-
return e.length >
|
|
17
|
+
let r = e.slice(0, k).map((e) => N(e, t + 1, n));
|
|
18
|
+
return e.length > k ? [...r, `…${e.length - k} more`] : r;
|
|
19
19
|
}
|
|
20
20
|
if (r === "object") {
|
|
21
21
|
let r = Object.entries(e), i = {};
|
|
22
|
-
for (let [e, a] of r.slice(0,
|
|
23
|
-
return r.length >
|
|
22
|
+
for (let [e, a] of r.slice(0, k)) i[M(e, n)] = N(a, t + 1, n);
|
|
23
|
+
return r.length > k && (i["…"] = `${r.length - k} more key(s)`), i;
|
|
24
24
|
}
|
|
25
25
|
return r;
|
|
26
|
-
},
|
|
26
|
+
}, P = (e, t = 16) => ({ __redacted: N(e, 0, t) }), F = "_voltro_audit_log", I = [
|
|
27
27
|
"tag",
|
|
28
28
|
"at",
|
|
29
29
|
"subjectId",
|
|
@@ -38,26 +38,26 @@ var x = 4, S = 32, C = 64, w = /^[A-Za-z_$][A-Za-z0-9_$]*$/, T = (e, t) => e ===
|
|
|
38
38
|
"input",
|
|
39
39
|
"outcome",
|
|
40
40
|
"errorTag"
|
|
41
|
-
],
|
|
41
|
+
], L = (e) => {
|
|
42
42
|
if (e == null) return "null";
|
|
43
43
|
if (e instanceof Date) return JSON.stringify(e.toISOString());
|
|
44
44
|
let t = typeof e;
|
|
45
|
-
return t === "number" || t === "boolean" || t === "string" ? JSON.stringify(e) : t === "bigint" ? JSON.stringify(String(e)) : Array.isArray(e) ? `[${e.map(
|
|
46
|
-
},
|
|
45
|
+
return t === "number" || t === "boolean" || t === "string" ? JSON.stringify(e) : t === "bigint" ? JSON.stringify(String(e)) : Array.isArray(e) ? `[${e.map(L).join(",")}]` : t === "object" ? `{${Object.entries(e).filter(([, e]) => e !== void 0).sort(([e], [t]) => e < t ? -1 : +(e > t)).map(([e, t]) => `${JSON.stringify(e)}:${L(t)}`).join(",")}}` : JSON.stringify(String(e));
|
|
46
|
+
}, ne = (e) => e instanceof Date ? e.toISOString() : e, re = (e) => L(Object.fromEntries(I.map((t) => [t, ne(e[t] ?? null)]))), ie = (e) => {
|
|
47
47
|
let t = process.env.VOLTRO_AUDIT_CHAIN_SECRET;
|
|
48
|
-
return t ?
|
|
49
|
-
},
|
|
48
|
+
return t ? E("sha256", t).update(e, "utf8").digest("hex") : T("sha256").update(e, "utf8").digest("hex");
|
|
49
|
+
}, R = (e, t) => ie(JSON.stringify([
|
|
50
50
|
t.chainId,
|
|
51
51
|
t.seq,
|
|
52
52
|
t.prevHash,
|
|
53
|
-
|
|
54
|
-
])),
|
|
53
|
+
re(e)
|
|
54
|
+
])), z = (e = D(12).toString("base64url")) => {
|
|
55
55
|
let t = 0, n = null;
|
|
56
56
|
return {
|
|
57
57
|
chainId: e,
|
|
58
58
|
link: (r) => {
|
|
59
59
|
t += 1;
|
|
60
|
-
let i =
|
|
60
|
+
let i = R(r, {
|
|
61
61
|
chainId: e,
|
|
62
62
|
seq: t,
|
|
63
63
|
prevHash: n
|
|
@@ -71,92 +71,144 @@ var x = 4, S = 32, C = 64, w = /^[A-Za-z_$][A-Za-z0-9_$]*$/, T = (e, t) => e ===
|
|
|
71
71
|
return n = i, a;
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
};
|
|
75
|
+
async function* B(e, t) {
|
|
76
|
+
let n = t.chainId === void 0 ? void 0 : u("chainId", t.chainId), r = (e, t, n) => ({
|
|
77
|
+
table: F,
|
|
78
|
+
predicate: e,
|
|
79
|
+
order: n,
|
|
80
|
+
take: t,
|
|
81
|
+
skip: void 0,
|
|
82
|
+
projection: void 0
|
|
83
|
+
});
|
|
84
|
+
if (t.limit !== void 0) {
|
|
85
|
+
yield* await e.query(r(n, t.limit, [{
|
|
79
86
|
column: "chainId",
|
|
80
87
|
direction: "asc"
|
|
81
88
|
}, {
|
|
82
89
|
column: "seq",
|
|
83
90
|
direction: "asc"
|
|
84
|
-
}]
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
}]));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
let i = [...await e.query({
|
|
95
|
+
...r(n, void 0, [{
|
|
96
|
+
column: "chainId",
|
|
97
|
+
direction: "asc"
|
|
98
|
+
}]),
|
|
99
|
+
groupBy: ["chainId"],
|
|
100
|
+
aggregations: [
|
|
101
|
+
l("chainId"),
|
|
102
|
+
{
|
|
103
|
+
op: "max",
|
|
104
|
+
column: "seq",
|
|
105
|
+
alias: "lastSeq"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
op: "max",
|
|
109
|
+
column: "id",
|
|
110
|
+
alias: "lastId"
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
})].sort((e, t) => String(e.chainId) < String(t.chainId) ? -1 : +(String(e.chainId) > String(t.chainId)));
|
|
114
|
+
for (let t of i) {
|
|
115
|
+
let n = t.chainId, i = n == null ? h("chainId") : u("chainId", n), a = n == null ? [!1] : [!1, !0];
|
|
116
|
+
for (let o of a) {
|
|
117
|
+
if (o && t.lastSeq == null) continue;
|
|
118
|
+
let a = [i, _("id", t.lastId)];
|
|
119
|
+
n != null && a.push(o ? c(m("seq"), _("seq", t.lastSeq)) : h("seq"));
|
|
120
|
+
let s;
|
|
121
|
+
for (;;) {
|
|
122
|
+
let t = s === void 0 ? void 0 : o ? v(d("seq", s.seq), c(u("seq", s.seq), d("id", s.id))) : d("id", s.id), n = await e.query(r(c(...a, ...t ? [t] : []), 1e3, [...o ? [{
|
|
123
|
+
column: "seq",
|
|
124
|
+
direction: "asc"
|
|
125
|
+
}] : [], {
|
|
126
|
+
column: "id",
|
|
127
|
+
direction: "asc"
|
|
128
|
+
}]));
|
|
129
|
+
if (yield* n, n.length < 1e3) break;
|
|
130
|
+
let i = n[n.length - 1];
|
|
131
|
+
if (i.id === void 0 || i.id === s?.id) throw Error("audit verification cursor did not advance");
|
|
132
|
+
s = i;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
var V = async (e, t = {}) => {
|
|
138
|
+
let n = [], r = [], i = 0, a = 0, o = null, s = () => {
|
|
139
|
+
o &&= (r.push({
|
|
140
|
+
chainId: o.chainId,
|
|
141
|
+
from: o.from,
|
|
142
|
+
to: o.last,
|
|
143
|
+
tip: o.tip,
|
|
144
|
+
prunedPrefix: o.from > 1
|
|
93
145
|
}), null);
|
|
94
146
|
};
|
|
95
|
-
for (let
|
|
96
|
-
let
|
|
97
|
-
if (typeof
|
|
98
|
-
|
|
147
|
+
for await (let r of B(e, t)) {
|
|
148
|
+
let e = r.chainId, t = r.hash, c = r.seq;
|
|
149
|
+
if (typeof e != "string" || typeof t != "string" || c == null) {
|
|
150
|
+
i += 1;
|
|
99
151
|
continue;
|
|
100
152
|
}
|
|
101
|
-
let
|
|
102
|
-
|
|
103
|
-
chainId:
|
|
104
|
-
from:
|
|
105
|
-
last:
|
|
106
|
-
tip:
|
|
107
|
-
}) : (
|
|
153
|
+
let l = Number(c), u = typeof r.prevHash == "string" ? r.prevHash : null, d = typeof r.id == "string" ? r.id : void 0;
|
|
154
|
+
a += 1, !o || o.chainId !== e ? (s(), o = {
|
|
155
|
+
chainId: e,
|
|
156
|
+
from: l,
|
|
157
|
+
last: l,
|
|
158
|
+
tip: t
|
|
159
|
+
}) : (l === o.last + 1 ? u !== o.tip && n.push({
|
|
108
160
|
kind: "broken-link",
|
|
109
|
-
chainId:
|
|
110
|
-
seq:
|
|
161
|
+
chainId: e,
|
|
162
|
+
seq: l,
|
|
111
163
|
...d ? { rowId: d } : {},
|
|
112
|
-
detail: `prevHash does not match the hash of seq ${
|
|
113
|
-
}) :
|
|
164
|
+
detail: `prevHash does not match the hash of seq ${o.last}`
|
|
165
|
+
}) : n.push({
|
|
114
166
|
kind: "gap",
|
|
115
|
-
chainId:
|
|
116
|
-
seq:
|
|
117
|
-
detail: `chain jumps from seq ${
|
|
118
|
-
}),
|
|
119
|
-
chainId:
|
|
120
|
-
seq:
|
|
121
|
-
prevHash:
|
|
122
|
-
}) !==
|
|
167
|
+
chainId: e,
|
|
168
|
+
seq: o.last + 1,
|
|
169
|
+
detail: `chain jumps from seq ${o.last} to ${l} — ${l - o.last - 1} row(s) missing`
|
|
170
|
+
}), o.last = l, o.tip = t), R(r, {
|
|
171
|
+
chainId: e,
|
|
172
|
+
seq: l,
|
|
173
|
+
prevHash: u
|
|
174
|
+
}) !== t && n.push({
|
|
123
175
|
kind: "tampered",
|
|
124
|
-
chainId:
|
|
125
|
-
seq:
|
|
176
|
+
chainId: e,
|
|
177
|
+
seq: l,
|
|
126
178
|
...d ? { rowId: d } : {},
|
|
127
179
|
detail: "the row content does not hash to its stored hash — a column was altered"
|
|
128
180
|
});
|
|
129
181
|
}
|
|
130
|
-
return
|
|
131
|
-
ok:
|
|
132
|
-
rowsChecked:
|
|
133
|
-
unchainedRows:
|
|
134
|
-
chains:
|
|
135
|
-
issues:
|
|
182
|
+
return s(), {
|
|
183
|
+
ok: n.length === 0,
|
|
184
|
+
rowsChecked: a,
|
|
185
|
+
unchainedRows: i,
|
|
186
|
+
chains: r,
|
|
187
|
+
issues: n,
|
|
136
188
|
keyed: !!process.env.VOLTRO_AUDIT_CHAIN_SECRET
|
|
137
189
|
};
|
|
138
|
-
},
|
|
139
|
-
id:
|
|
140
|
-
tag:
|
|
141
|
-
at:
|
|
142
|
-
subjectId:
|
|
143
|
-
tenantId:
|
|
144
|
-
traceId:
|
|
145
|
-
status:
|
|
146
|
-
durationMs:
|
|
147
|
-
subject:
|
|
148
|
-
actor:
|
|
149
|
-
scope:
|
|
150
|
-
scopeKey:
|
|
151
|
-
metadata:
|
|
152
|
-
impersonation:
|
|
153
|
-
input:
|
|
154
|
-
outcome:
|
|
155
|
-
errorTag:
|
|
156
|
-
chainId:
|
|
157
|
-
seq:
|
|
158
|
-
prevHash:
|
|
159
|
-
hash:
|
|
190
|
+
}, H = S(F, {
|
|
191
|
+
id: f({ prefix: "audit" }),
|
|
192
|
+
tag: C(),
|
|
193
|
+
at: w(),
|
|
194
|
+
subjectId: C().nullable(),
|
|
195
|
+
tenantId: C().nullable(),
|
|
196
|
+
traceId: C(),
|
|
197
|
+
status: C(),
|
|
198
|
+
durationMs: C(),
|
|
199
|
+
subject: g(),
|
|
200
|
+
actor: g().nullable(),
|
|
201
|
+
scope: g().nullable(),
|
|
202
|
+
scopeKey: C().nullable(),
|
|
203
|
+
metadata: g().nullable(),
|
|
204
|
+
impersonation: g().nullable(),
|
|
205
|
+
input: g(),
|
|
206
|
+
outcome: g(),
|
|
207
|
+
errorTag: C().nullable(),
|
|
208
|
+
chainId: C().nullable(),
|
|
209
|
+
seq: p().nullable(),
|
|
210
|
+
prevHash: C().nullable(),
|
|
211
|
+
hash: C().nullable()
|
|
160
212
|
}).index("byAuditTag", ["tag"]).index("byAuditTrace", ["traceId"]).index("byAuditSubjectStatus", [
|
|
161
213
|
"subjectId",
|
|
162
214
|
"status",
|
|
@@ -165,7 +217,7 @@ var x = 4, S = 32, C = 64, w = /^[A-Za-z_$][A-Za-z0-9_$]*$/, T = (e, t) => e ===
|
|
|
165
217
|
"tenantId",
|
|
166
218
|
"status",
|
|
167
219
|
"at"
|
|
168
|
-
]).index("byAuditScope", ["scopeKey", "at"]).index("byAuditChain", ["chainId", "seq"]),
|
|
220
|
+
]).index("byAuditScope", ["scopeKey", "at"]).index("byAuditChain", ["chainId", "seq"]), U = [H], W = (e) => ({
|
|
169
221
|
tag: e.tag,
|
|
170
222
|
at: new Date(e.ts),
|
|
171
223
|
subjectId: e.subject.id ?? null,
|
|
@@ -176,61 +228,61 @@ var x = 4, S = 32, C = 64, w = /^[A-Za-z_$][A-Za-z0-9_$]*$/, T = (e, t) => e ===
|
|
|
176
228
|
subject: e.subject,
|
|
177
229
|
actor: e.actor ?? null,
|
|
178
230
|
scope: e.scope ?? null,
|
|
179
|
-
scopeKey:
|
|
231
|
+
scopeKey: x(e.scope),
|
|
180
232
|
metadata: e.metadata ?? null,
|
|
181
233
|
impersonation: e.impersonation ?? null,
|
|
182
234
|
input: e.input,
|
|
183
235
|
outcome: e.outcome,
|
|
184
|
-
errorTag: e.outcome.kind === "error" ?
|
|
185
|
-
}),
|
|
236
|
+
errorTag: e.outcome.kind === "error" ? G(e.outcome.error) : null
|
|
237
|
+
}), G = (e) => {
|
|
186
238
|
if (typeof e != "object" || !e) return null;
|
|
187
239
|
let t = e._tag;
|
|
188
240
|
return typeof t == "string" && t !== "" ? t : null;
|
|
189
|
-
},
|
|
190
|
-
table:
|
|
191
|
-
predicate:
|
|
241
|
+
}, K = async (e, t) => e.query({
|
|
242
|
+
table: F,
|
|
243
|
+
predicate: u("traceId", t),
|
|
192
244
|
order: [{
|
|
193
245
|
column: "at",
|
|
194
246
|
direction: "asc"
|
|
195
247
|
}]
|
|
196
|
-
}),
|
|
197
|
-
let r =
|
|
248
|
+
}), q = async (e, t, n = {}) => {
|
|
249
|
+
let r = x(t);
|
|
198
250
|
if (r === null) return [];
|
|
199
|
-
let i =
|
|
251
|
+
let i = u("scopeKey", r);
|
|
200
252
|
return e.query({
|
|
201
|
-
table:
|
|
202
|
-
predicate: n.status === void 0 ? i :
|
|
253
|
+
table: F,
|
|
254
|
+
predicate: n.status === void 0 ? i : c(i, u("status", n.status)),
|
|
203
255
|
order: [{
|
|
204
256
|
column: "at",
|
|
205
257
|
direction: "desc"
|
|
206
258
|
}],
|
|
207
259
|
take: n.limit ?? 100
|
|
208
260
|
});
|
|
209
|
-
},
|
|
210
|
-
let r =
|
|
261
|
+
}, J = async (e, t, n = {}) => {
|
|
262
|
+
let r = u("subjectId", t);
|
|
211
263
|
return e.query({
|
|
212
|
-
table:
|
|
213
|
-
predicate: n.status === void 0 ? r :
|
|
264
|
+
table: F,
|
|
265
|
+
predicate: n.status === void 0 ? r : c(r, u("status", n.status)),
|
|
214
266
|
order: [{
|
|
215
267
|
column: "at",
|
|
216
268
|
direction: "desc"
|
|
217
269
|
}],
|
|
218
270
|
take: n.limit ?? 100
|
|
219
271
|
});
|
|
220
|
-
},
|
|
221
|
-
let t =
|
|
272
|
+
}, Y = (e) => {
|
|
273
|
+
let t = z();
|
|
222
274
|
return async (n) => {
|
|
223
275
|
let r = n.actor !== void 0 || typeof e.query != "function" ? n : {
|
|
224
276
|
...n,
|
|
225
|
-
actor: await
|
|
277
|
+
actor: await y(e, n.subject.id ?? null, n.subject.type)
|
|
226
278
|
};
|
|
227
|
-
await e.insert(
|
|
279
|
+
await e.insert(F, t.link(W(r)));
|
|
228
280
|
};
|
|
229
|
-
},
|
|
230
|
-
|
|
231
|
-
},
|
|
232
|
-
|
|
233
|
-
},
|
|
281
|
+
}, X = s({ scope: "@voltro/plugin-audit" }), Z = 1e3, Q = [], ae = () => [...Q], oe = () => {
|
|
282
|
+
Q.length = 0;
|
|
283
|
+
}, se = (e) => {
|
|
284
|
+
Q.push(e), Q.length > Z && Q.splice(0, Q.length - Z);
|
|
285
|
+
}, ce = (e) => {
|
|
234
286
|
let t = e.subject.id ? `${e.subject.type}:${e.subject.id}` : e.subject.type, n = e.outcome.kind === "ok" ? "ok" : "error", r = {
|
|
235
287
|
subject: t,
|
|
236
288
|
tenant: e.subject.tenantId ?? null,
|
|
@@ -238,70 +290,49 @@ var x = 4, S = 32, C = 64, w = /^[A-Za-z_$][A-Za-z0-9_$]*$/, T = (e, t) => e ===
|
|
|
238
290
|
durationMs: e.outcome.durationMs,
|
|
239
291
|
traceId: e.traceId
|
|
240
292
|
};
|
|
241
|
-
n === "error" ?
|
|
242
|
-
},
|
|
243
|
-
let r = e(
|
|
244
|
-
return r === void 0 ?
|
|
293
|
+
n === "error" ? X.warn(e.tag, r) : X.info(e.tag, r);
|
|
294
|
+
}, le = (e, t) => typeof e == "function" ? (t) => n.suspend(() => {
|
|
295
|
+
let r = e(t);
|
|
296
|
+
return r === void 0 ? n.void : n.isEffect(r) ? r : n.tryPromise({
|
|
245
297
|
try: () => Promise.resolve(r),
|
|
246
298
|
catch: (e) => e
|
|
247
299
|
});
|
|
248
|
-
}) : e === "datastore" ? (e) =>
|
|
249
|
-
let r =
|
|
250
|
-
return r ?
|
|
300
|
+
}) : e === "datastore" ? (e) => n.suspend(() => {
|
|
301
|
+
let r = t();
|
|
302
|
+
return r ? n.tryPromise({
|
|
251
303
|
try: () => r(e),
|
|
252
304
|
catch: (e) => e
|
|
253
|
-
}) :
|
|
254
|
-
}) : e === "memory" ? (e) =>
|
|
255
|
-
let
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
if (e._tag === "Die") {
|
|
262
|
-
n.push(e.defect);
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
if (e._tag !== "Interrupt") {
|
|
266
|
-
if (e._tag === "Sequential") {
|
|
267
|
-
r(e.left), r(e.right);
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
if (e._tag === "Parallel") {
|
|
271
|
-
r(e.left), r(e.right);
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
return r(e), t[0] ?? n[0] ?? e;
|
|
278
|
-
}, $ = "@voltro/plugin-audit", re = (e = {}) => {
|
|
279
|
-
let o = e.sink === "datastore";
|
|
280
|
-
o && ee({
|
|
305
|
+
}) : n.void;
|
|
306
|
+
}) : e === "memory" ? (e) => n.sync(() => se(e)) : (e) => n.sync(() => ce(e)), ue = (e) => {
|
|
307
|
+
let n = e.reasons.filter(t.isFailReason).map((e) => e.error), r = e.reasons.filter(t.isDieReason).map((e) => e.defect);
|
|
308
|
+
return n[0] ?? r[0] ?? e;
|
|
309
|
+
}, $ = "@voltro/plugin-audit", de = (e = {}) => {
|
|
310
|
+
let t = e.sink === "datastore";
|
|
311
|
+
t && ee({
|
|
281
312
|
source: "plugin",
|
|
282
|
-
table:
|
|
313
|
+
table: F,
|
|
283
314
|
timeColumn: "at",
|
|
284
|
-
ttlMs:
|
|
315
|
+
ttlMs: b(process.env.VOLTRO_AUDIT_LOG_TTL_HOURS, 8760)
|
|
285
316
|
});
|
|
286
|
-
let s, c =
|
|
317
|
+
let s, c = le(e.sink, () => s), l = (e) => e === void 0 || !e.global && !e.sticky ? e : new RegExp(e.source, e.flags.replace(/[gy]/g, "")), u = l(e.exclude), d = l(e.include), f = (e) => !(u?.test(e) || d && !d.test(e)), p = (t) => {
|
|
287
318
|
let n = e.record ?? "all";
|
|
288
319
|
return n === "all" ? !0 : n === "errors" ? t.outcome.kind === "error" : n(t);
|
|
289
|
-
},
|
|
320
|
+
}, m = { __redacted: "all" }, h = e.redactionLengthFloor ?? 16, g = (t) => {
|
|
290
321
|
let n = e.redactInput ?? "all";
|
|
291
322
|
return n === "none" ? t : n === "all" ? {
|
|
292
323
|
...t,
|
|
293
|
-
input:
|
|
324
|
+
input: m
|
|
294
325
|
} : n === "shape" ? {
|
|
295
326
|
...t,
|
|
296
|
-
input:
|
|
327
|
+
input: P(t.input, h)
|
|
297
328
|
} : {
|
|
298
329
|
...t,
|
|
299
330
|
input: n(t)
|
|
300
331
|
};
|
|
301
|
-
},
|
|
332
|
+
}, _ = (t) => {
|
|
302
333
|
let n = e.redactOutcome ?? "all";
|
|
303
334
|
if (n === "none") return t;
|
|
304
|
-
let r = t.outcome, i = n === "all" ?
|
|
335
|
+
let r = t.outcome, i = n === "all" ? m : n === "shape" ? ((e) => P(e, h))(r.kind === "ok" ? r.value : r.error) : n(t);
|
|
305
336
|
if (r.kind === "ok") return {
|
|
306
337
|
...t,
|
|
307
338
|
outcome: {
|
|
@@ -320,7 +351,7 @@ var x = 4, S = 32, C = 64, w = /^[A-Za-z_$][A-Za-z0-9_$]*$/, T = (e, t) => e ===
|
|
|
320
351
|
}
|
|
321
352
|
}
|
|
322
353
|
};
|
|
323
|
-
},
|
|
354
|
+
}, v = (t) => {
|
|
324
355
|
let n = e.redactSubject ?? "metadata";
|
|
325
356
|
if (n === "none") return t;
|
|
326
357
|
if (typeof n == "function") return {
|
|
@@ -329,7 +360,7 @@ var x = 4, S = 32, C = 64, w = /^[A-Za-z_$][A-Za-z0-9_$]*$/, T = (e, t) => e ===
|
|
|
329
360
|
};
|
|
330
361
|
let r = t.subject;
|
|
331
362
|
if (r.metadata === void 0) return t;
|
|
332
|
-
let { metadata: i, ...a } = r, o = n === "metadata-shape" ?
|
|
363
|
+
let { metadata: i, ...a } = r, o = n === "metadata-shape" ? P(i, h) : m;
|
|
333
364
|
return {
|
|
334
365
|
...t,
|
|
335
366
|
subject: {
|
|
@@ -337,67 +368,67 @@ var x = 4, S = 32, C = 64, w = /^[A-Za-z_$][A-Za-z0-9_$]*$/, T = (e, t) => e ===
|
|
|
337
368
|
metadata: o
|
|
338
369
|
}
|
|
339
370
|
};
|
|
340
|
-
},
|
|
341
|
-
let t =
|
|
371
|
+
}, y = (e) => {
|
|
372
|
+
let t = o(e.subject);
|
|
342
373
|
return t === null ? e : {
|
|
343
374
|
...e,
|
|
344
375
|
impersonation: t
|
|
345
376
|
};
|
|
346
|
-
}, x = (e) =>
|
|
377
|
+
}, x = (e) => p(e) ? c(_(v(g(y(e))))) : n.void, S = (t) => {
|
|
347
378
|
if (e.resolveScope !== void 0) try {
|
|
348
379
|
return e.resolveScope(t);
|
|
349
380
|
} catch {
|
|
350
381
|
return;
|
|
351
382
|
}
|
|
352
|
-
}, C = (
|
|
353
|
-
tag:
|
|
354
|
-
subject:
|
|
355
|
-
input:
|
|
383
|
+
}, C = (t, r) => e.metadata === void 0 ? n.succeed(void 0) : n.tryPromise(async () => e.metadata({
|
|
384
|
+
tag: t.tag,
|
|
385
|
+
subject: t.subject,
|
|
386
|
+
input: t.input,
|
|
356
387
|
outcome: r
|
|
357
|
-
})).pipe(
|
|
358
|
-
let r = Date.now(), i = S(
|
|
359
|
-
return e.pipe(
|
|
388
|
+
})).pipe(n.catchCause(() => n.succeed(void 0))), w = (e, t) => f(t.tag) ? n.suspend(() => {
|
|
389
|
+
let r = Date.now(), i = S(t);
|
|
390
|
+
return e.pipe(n.tap((e) => C(t, {
|
|
360
391
|
kind: "ok",
|
|
361
392
|
value: e
|
|
362
|
-
}).pipe(
|
|
393
|
+
}).pipe(n.flatMap((n) => x({
|
|
363
394
|
ts: r,
|
|
364
|
-
tag:
|
|
365
|
-
subject:
|
|
395
|
+
tag: t.tag,
|
|
396
|
+
subject: t.subject,
|
|
366
397
|
...i === void 0 ? {} : { scope: i },
|
|
367
|
-
...
|
|
368
|
-
traceId:
|
|
369
|
-
input:
|
|
398
|
+
...n === void 0 ? {} : { metadata: n },
|
|
399
|
+
traceId: t.traceId,
|
|
400
|
+
input: t.input,
|
|
370
401
|
outcome: {
|
|
371
402
|
kind: "ok",
|
|
372
403
|
value: e,
|
|
373
404
|
durationMs: Date.now() - r
|
|
374
405
|
}
|
|
375
|
-
}))).pipe(
|
|
376
|
-
let a =
|
|
377
|
-
return C(
|
|
406
|
+
}))).pipe(n.catchCause(() => n.void))), n.tapCause((e) => {
|
|
407
|
+
let a = ue(e);
|
|
408
|
+
return C(t, {
|
|
378
409
|
kind: "error",
|
|
379
410
|
error: a
|
|
380
|
-
}).pipe(
|
|
411
|
+
}).pipe(n.flatMap((e) => x({
|
|
381
412
|
ts: r,
|
|
382
|
-
tag:
|
|
383
|
-
subject:
|
|
413
|
+
tag: t.tag,
|
|
414
|
+
subject: t.subject,
|
|
384
415
|
...i === void 0 ? {} : { scope: i },
|
|
385
416
|
...e === void 0 ? {} : { metadata: e },
|
|
386
|
-
traceId:
|
|
387
|
-
input:
|
|
417
|
+
traceId: t.traceId,
|
|
418
|
+
input: t.input,
|
|
388
419
|
outcome: {
|
|
389
420
|
kind: "error",
|
|
390
421
|
error: a,
|
|
391
422
|
durationMs: Date.now() - r
|
|
392
423
|
}
|
|
393
|
-
}))).pipe(
|
|
424
|
+
}))).pipe(n.catchCause(() => n.void));
|
|
394
425
|
}));
|
|
395
426
|
}) : e, T = (e) => {
|
|
396
|
-
let
|
|
397
|
-
f(
|
|
427
|
+
let t = `http.${e.method.toUpperCase()} ${e.path}`;
|
|
428
|
+
f(t) && n.runPromise(x({
|
|
398
429
|
ts: Date.now() - e.durationMs,
|
|
399
|
-
tag:
|
|
400
|
-
subject:
|
|
430
|
+
tag: t,
|
|
431
|
+
subject: r(null),
|
|
401
432
|
traceId: e.traceId,
|
|
402
433
|
input: {
|
|
403
434
|
method: e.method,
|
|
@@ -420,10 +451,10 @@ var x = 4, S = 32, C = 64, w = /^[A-Za-z_$][A-Za-z0-9_$]*$/, T = (e, t) => e ===
|
|
|
420
451
|
value: { status: e.status },
|
|
421
452
|
durationMs: e.durationMs
|
|
422
453
|
}
|
|
423
|
-
}).pipe(
|
|
424
|
-
}, E = w, D = w,
|
|
425
|
-
return
|
|
426
|
-
name:
|
|
454
|
+
}).pipe(n.catchCause(() => n.void)));
|
|
455
|
+
}, E = w, D = w, O = w, k = w;
|
|
456
|
+
return i({
|
|
457
|
+
name: a({
|
|
427
458
|
base: $,
|
|
428
459
|
alias: e.alias
|
|
429
460
|
}),
|
|
@@ -434,21 +465,21 @@ var x = 4, S = 32, C = 64, w = /^[A-Za-z_$][A-Za-z0-9_$]*$/, T = (e, t) => e ===
|
|
|
434
465
|
"rpc:intercept:action",
|
|
435
466
|
"rpc:intercept:workflow",
|
|
436
467
|
"http:intercept",
|
|
437
|
-
...
|
|
468
|
+
...t ? ["store:write"] : [],
|
|
438
469
|
...e.recordQueries === !0 ? ["rpc:intercept:query"] : []
|
|
439
470
|
],
|
|
440
|
-
...
|
|
441
|
-
...e.tables === !1 ? {} : { extendSchema: { tables:
|
|
471
|
+
...t ? {
|
|
472
|
+
...e.tables === !1 ? {} : { extendSchema: { tables: U } },
|
|
442
473
|
bindDataStore: (e) => {
|
|
443
|
-
s =
|
|
474
|
+
s = Y(e);
|
|
444
475
|
}
|
|
445
476
|
} : {},
|
|
446
477
|
interceptMutation: E,
|
|
447
478
|
interceptAction: D,
|
|
448
|
-
interceptWorkflow:
|
|
479
|
+
interceptWorkflow: O,
|
|
449
480
|
onHttpRoute: T,
|
|
450
|
-
...e.recordQueries === !0 ? { interceptQuery:
|
|
481
|
+
...e.recordQueries === !0 ? { interceptQuery: k } : {}
|
|
451
482
|
});
|
|
452
483
|
};
|
|
453
484
|
//#endregion
|
|
454
|
-
export {
|
|
485
|
+
export { F as AUDIT_LOG_TABLE, e as audit, q as auditByScope, J as auditBySubject, K as auditByTrace, W as auditEventToRow, H as auditLogTable, U as auditLogTables, de as auditPlugin, R as auditRowHash, oe as clearAuditBuffer, Y as dataStoreAuditSink, z as makeAuditChain, ae as readAuditBuffer, V as verifyAuditChain };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/plugin-audit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.85.0",
|
|
4
4
|
"description": "Audit plugin — ships the `audit()` schema mixin (createdAt/updatedAt/createdBy/updatedBy → Actor) plus an optional interceptor that records every mutation and action (queries on request) to a configurable sink (console / memory / datastore / custom function).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"node": ">=24.0.0"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@voltro/database": "0.
|
|
42
|
-
"@voltro/logger": "0.
|
|
43
|
-
"@voltro/protocol": "0.
|
|
41
|
+
"@voltro/database": "0.85.0",
|
|
42
|
+
"@voltro/logger": "0.85.0",
|
|
43
|
+
"@voltro/protocol": "0.85.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"effect": "
|
|
46
|
+
"effect": "4.0.1"
|
|
47
47
|
},
|
|
48
48
|
"publishConfig": {
|
|
49
49
|
"access": "public"
|