@prooflog/node 0.1.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/README.md +77 -0
- package/dist/index.d.mts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +598 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +592 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +33 -0
- package/src/client.ts +146 -0
- package/src/index.ts +10 -0
- package/src/types.ts +22 -0
- package/tsconfig.json +7 -0
- package/tsup.config.ts +13 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc2) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc2 = __getOwnPropDesc(from, key)) || desc2.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
|
+
|
|
33
|
+
// ../../node_modules/.pnpm/fast-json-stable-stringify@2.1.0/node_modules/fast-json-stable-stringify/index.js
|
|
34
|
+
var require_fast_json_stable_stringify = __commonJS({
|
|
35
|
+
"../../node_modules/.pnpm/fast-json-stable-stringify@2.1.0/node_modules/fast-json-stable-stringify/index.js"(exports2, module2) {
|
|
36
|
+
"use strict";
|
|
37
|
+
module2.exports = function(data, opts) {
|
|
38
|
+
if (!opts) opts = {};
|
|
39
|
+
if (typeof opts === "function") opts = { cmp: opts };
|
|
40
|
+
var cycles = typeof opts.cycles === "boolean" ? opts.cycles : false;
|
|
41
|
+
var cmp = opts.cmp && /* @__PURE__ */ (function(f) {
|
|
42
|
+
return function(node) {
|
|
43
|
+
return function(a, b) {
|
|
44
|
+
var aobj = { key: a, value: node[a] };
|
|
45
|
+
var bobj = { key: b, value: node[b] };
|
|
46
|
+
return f(aobj, bobj);
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
})(opts.cmp);
|
|
50
|
+
var seen = [];
|
|
51
|
+
return (function stringify2(node) {
|
|
52
|
+
if (node && node.toJSON && typeof node.toJSON === "function") {
|
|
53
|
+
node = node.toJSON();
|
|
54
|
+
}
|
|
55
|
+
if (node === void 0) return;
|
|
56
|
+
if (typeof node == "number") return isFinite(node) ? "" + node : "null";
|
|
57
|
+
if (typeof node !== "object") return JSON.stringify(node);
|
|
58
|
+
var i, out;
|
|
59
|
+
if (Array.isArray(node)) {
|
|
60
|
+
out = "[";
|
|
61
|
+
for (i = 0; i < node.length; i++) {
|
|
62
|
+
if (i) out += ",";
|
|
63
|
+
out += stringify2(node[i]) || "null";
|
|
64
|
+
}
|
|
65
|
+
return out + "]";
|
|
66
|
+
}
|
|
67
|
+
if (node === null) return "null";
|
|
68
|
+
if (seen.indexOf(node) !== -1) {
|
|
69
|
+
if (cycles) return JSON.stringify("__cycle__");
|
|
70
|
+
throw new TypeError("Converting circular structure to JSON");
|
|
71
|
+
}
|
|
72
|
+
var seenIndex = seen.push(node) - 1;
|
|
73
|
+
var keys = Object.keys(node).sort(cmp && cmp(node));
|
|
74
|
+
out = "";
|
|
75
|
+
for (i = 0; i < keys.length; i++) {
|
|
76
|
+
var key = keys[i];
|
|
77
|
+
var value = stringify2(node[key]);
|
|
78
|
+
if (!value) continue;
|
|
79
|
+
if (out) out += ",";
|
|
80
|
+
out += JSON.stringify(key) + ":" + value;
|
|
81
|
+
}
|
|
82
|
+
seen.splice(seenIndex, 1);
|
|
83
|
+
return "{" + out + "}";
|
|
84
|
+
})(data);
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// src/index.ts
|
|
90
|
+
var index_exports = {};
|
|
91
|
+
__export(index_exports, {
|
|
92
|
+
ProofLog: () => ProofLog
|
|
93
|
+
});
|
|
94
|
+
module.exports = __toCommonJS(index_exports);
|
|
95
|
+
|
|
96
|
+
// src/client.ts
|
|
97
|
+
var import_neon_http = require("drizzle-orm/neon-http");
|
|
98
|
+
var import_serverless = require("@neondatabase/serverless");
|
|
99
|
+
var import_drizzle_orm = require("drizzle-orm");
|
|
100
|
+
|
|
101
|
+
// ../db/src/schema.ts
|
|
102
|
+
var import_pg_core = require("drizzle-orm/pg-core");
|
|
103
|
+
var organisations = (0, import_pg_core.pgTable)("organisations", {
|
|
104
|
+
id: (0, import_pg_core.uuid)("id").primaryKey().defaultRandom(),
|
|
105
|
+
name: (0, import_pg_core.text)("name").notNull(),
|
|
106
|
+
plan: (0, import_pg_core.text)("plan").notNull().default("free"),
|
|
107
|
+
createdAt: (0, import_pg_core.timestamp)("created_at").notNull().defaultNow()
|
|
108
|
+
});
|
|
109
|
+
var auditLogs = (0, import_pg_core.pgTable)(
|
|
110
|
+
"audit_logs",
|
|
111
|
+
{
|
|
112
|
+
id: (0, import_pg_core.uuid)("id").primaryKey().defaultRandom(),
|
|
113
|
+
organisationId: (0, import_pg_core.uuid)("organisation_id").notNull().references(() => organisations.id),
|
|
114
|
+
sequence: (0, import_pg_core.bigint)("sequence", { mode: "number" }).notNull(),
|
|
115
|
+
action: (0, import_pg_core.text)("action").notNull(),
|
|
116
|
+
actor: (0, import_pg_core.jsonb)("actor").notNull(),
|
|
117
|
+
target: (0, import_pg_core.jsonb)("target"),
|
|
118
|
+
metadata: (0, import_pg_core.jsonb)("metadata"),
|
|
119
|
+
hash: (0, import_pg_core.text)("hash").notNull(),
|
|
120
|
+
previousHash: (0, import_pg_core.text)("previous_hash").notNull(),
|
|
121
|
+
createdAt: (0, import_pg_core.timestamp)("created_at").notNull().defaultNow()
|
|
122
|
+
},
|
|
123
|
+
(t) => [
|
|
124
|
+
(0, import_pg_core.unique)("audit_logs_org_sequence_idx").on(t.organisationId, t.sequence)
|
|
125
|
+
]
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// ../../node_modules/.pnpm/@noble+hashes@2.2.0/node_modules/@noble/hashes/utils.js
|
|
129
|
+
function isBytes(a) {
|
|
130
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
|
|
131
|
+
}
|
|
132
|
+
function abytes(value, length, title = "") {
|
|
133
|
+
const bytes = isBytes(value);
|
|
134
|
+
const len = value?.length;
|
|
135
|
+
const needsLen = length !== void 0;
|
|
136
|
+
if (!bytes || needsLen && len !== length) {
|
|
137
|
+
const prefix = title && `"${title}" `;
|
|
138
|
+
const ofLen = needsLen ? ` of length ${length}` : "";
|
|
139
|
+
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
140
|
+
const message = prefix + "expected Uint8Array" + ofLen + ", got " + got;
|
|
141
|
+
if (!bytes)
|
|
142
|
+
throw new TypeError(message);
|
|
143
|
+
throw new RangeError(message);
|
|
144
|
+
}
|
|
145
|
+
return value;
|
|
146
|
+
}
|
|
147
|
+
function aexists(instance, checkFinished = true) {
|
|
148
|
+
if (instance.destroyed)
|
|
149
|
+
throw new Error("Hash instance has been destroyed");
|
|
150
|
+
if (checkFinished && instance.finished)
|
|
151
|
+
throw new Error("Hash#digest() has already been called");
|
|
152
|
+
}
|
|
153
|
+
function aoutput(out, instance) {
|
|
154
|
+
abytes(out, void 0, "digestInto() output");
|
|
155
|
+
const min = instance.outputLen;
|
|
156
|
+
if (out.length < min) {
|
|
157
|
+
throw new RangeError('"digestInto() output" expected to be of length >=' + min);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function clean(...arrays) {
|
|
161
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
162
|
+
arrays[i].fill(0);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function createView(arr) {
|
|
166
|
+
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
167
|
+
}
|
|
168
|
+
function rotr(word, shift) {
|
|
169
|
+
return word << 32 - shift | word >>> shift;
|
|
170
|
+
}
|
|
171
|
+
var hasHexBuiltin = /* @__PURE__ */ (() => (
|
|
172
|
+
// @ts-ignore
|
|
173
|
+
typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
|
|
174
|
+
))();
|
|
175
|
+
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
176
|
+
function bytesToHex(bytes) {
|
|
177
|
+
abytes(bytes);
|
|
178
|
+
if (hasHexBuiltin)
|
|
179
|
+
return bytes.toHex();
|
|
180
|
+
let hex = "";
|
|
181
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
182
|
+
hex += hexes[bytes[i]];
|
|
183
|
+
}
|
|
184
|
+
return hex;
|
|
185
|
+
}
|
|
186
|
+
function createHasher(hashCons, info = {}) {
|
|
187
|
+
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
188
|
+
const tmp = hashCons(void 0);
|
|
189
|
+
hashC.outputLen = tmp.outputLen;
|
|
190
|
+
hashC.blockLen = tmp.blockLen;
|
|
191
|
+
hashC.canXOF = tmp.canXOF;
|
|
192
|
+
hashC.create = (opts) => hashCons(opts);
|
|
193
|
+
Object.assign(hashC, info);
|
|
194
|
+
return Object.freeze(hashC);
|
|
195
|
+
}
|
|
196
|
+
var oidNist = (suffix) => ({
|
|
197
|
+
// Current NIST hashAlgs suffixes used here fit in one DER subidentifier octet.
|
|
198
|
+
// Larger suffix values would need base-128 OID encoding and a different length byte.
|
|
199
|
+
oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// ../../node_modules/.pnpm/@noble+hashes@2.2.0/node_modules/@noble/hashes/_md.js
|
|
203
|
+
function Chi(a, b, c) {
|
|
204
|
+
return a & b ^ ~a & c;
|
|
205
|
+
}
|
|
206
|
+
function Maj(a, b, c) {
|
|
207
|
+
return a & b ^ a & c ^ b & c;
|
|
208
|
+
}
|
|
209
|
+
var HashMD = class {
|
|
210
|
+
blockLen;
|
|
211
|
+
outputLen;
|
|
212
|
+
canXOF = false;
|
|
213
|
+
padOffset;
|
|
214
|
+
isLE;
|
|
215
|
+
// For partial updates less than block size
|
|
216
|
+
buffer;
|
|
217
|
+
view;
|
|
218
|
+
finished = false;
|
|
219
|
+
length = 0;
|
|
220
|
+
pos = 0;
|
|
221
|
+
destroyed = false;
|
|
222
|
+
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
223
|
+
this.blockLen = blockLen;
|
|
224
|
+
this.outputLen = outputLen;
|
|
225
|
+
this.padOffset = padOffset;
|
|
226
|
+
this.isLE = isLE;
|
|
227
|
+
this.buffer = new Uint8Array(blockLen);
|
|
228
|
+
this.view = createView(this.buffer);
|
|
229
|
+
}
|
|
230
|
+
update(data) {
|
|
231
|
+
aexists(this);
|
|
232
|
+
abytes(data);
|
|
233
|
+
const { view, buffer, blockLen } = this;
|
|
234
|
+
const len = data.length;
|
|
235
|
+
for (let pos = 0; pos < len; ) {
|
|
236
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
237
|
+
if (take === blockLen) {
|
|
238
|
+
const dataView = createView(data);
|
|
239
|
+
for (; blockLen <= len - pos; pos += blockLen)
|
|
240
|
+
this.process(dataView, pos);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
244
|
+
this.pos += take;
|
|
245
|
+
pos += take;
|
|
246
|
+
if (this.pos === blockLen) {
|
|
247
|
+
this.process(view, 0);
|
|
248
|
+
this.pos = 0;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
this.length += data.length;
|
|
252
|
+
this.roundClean();
|
|
253
|
+
return this;
|
|
254
|
+
}
|
|
255
|
+
digestInto(out) {
|
|
256
|
+
aexists(this);
|
|
257
|
+
aoutput(out, this);
|
|
258
|
+
this.finished = true;
|
|
259
|
+
const { buffer, view, blockLen, isLE } = this;
|
|
260
|
+
let { pos } = this;
|
|
261
|
+
buffer[pos++] = 128;
|
|
262
|
+
clean(this.buffer.subarray(pos));
|
|
263
|
+
if (this.padOffset > blockLen - pos) {
|
|
264
|
+
this.process(view, 0);
|
|
265
|
+
pos = 0;
|
|
266
|
+
}
|
|
267
|
+
for (let i = pos; i < blockLen; i++)
|
|
268
|
+
buffer[i] = 0;
|
|
269
|
+
view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);
|
|
270
|
+
this.process(view, 0);
|
|
271
|
+
const oview = createView(out);
|
|
272
|
+
const len = this.outputLen;
|
|
273
|
+
if (len % 4)
|
|
274
|
+
throw new Error("_sha2: outputLen must be aligned to 32bit");
|
|
275
|
+
const outLen = len / 4;
|
|
276
|
+
const state = this.get();
|
|
277
|
+
if (outLen > state.length)
|
|
278
|
+
throw new Error("_sha2: outputLen bigger than state");
|
|
279
|
+
for (let i = 0; i < outLen; i++)
|
|
280
|
+
oview.setUint32(4 * i, state[i], isLE);
|
|
281
|
+
}
|
|
282
|
+
digest() {
|
|
283
|
+
const { buffer, outputLen } = this;
|
|
284
|
+
this.digestInto(buffer);
|
|
285
|
+
const res = buffer.slice(0, outputLen);
|
|
286
|
+
this.destroy();
|
|
287
|
+
return res;
|
|
288
|
+
}
|
|
289
|
+
_cloneInto(to) {
|
|
290
|
+
to ||= new this.constructor();
|
|
291
|
+
to.set(...this.get());
|
|
292
|
+
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
293
|
+
to.destroyed = destroyed;
|
|
294
|
+
to.finished = finished;
|
|
295
|
+
to.length = length;
|
|
296
|
+
to.pos = pos;
|
|
297
|
+
if (length % blockLen)
|
|
298
|
+
to.buffer.set(buffer);
|
|
299
|
+
return to;
|
|
300
|
+
}
|
|
301
|
+
clone() {
|
|
302
|
+
return this._cloneInto();
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
var SHA256_IV = /* @__PURE__ */ Uint32Array.from([
|
|
306
|
+
1779033703,
|
|
307
|
+
3144134277,
|
|
308
|
+
1013904242,
|
|
309
|
+
2773480762,
|
|
310
|
+
1359893119,
|
|
311
|
+
2600822924,
|
|
312
|
+
528734635,
|
|
313
|
+
1541459225
|
|
314
|
+
]);
|
|
315
|
+
|
|
316
|
+
// ../../node_modules/.pnpm/@noble+hashes@2.2.0/node_modules/@noble/hashes/sha2.js
|
|
317
|
+
var SHA256_K = /* @__PURE__ */ Uint32Array.from([
|
|
318
|
+
1116352408,
|
|
319
|
+
1899447441,
|
|
320
|
+
3049323471,
|
|
321
|
+
3921009573,
|
|
322
|
+
961987163,
|
|
323
|
+
1508970993,
|
|
324
|
+
2453635748,
|
|
325
|
+
2870763221,
|
|
326
|
+
3624381080,
|
|
327
|
+
310598401,
|
|
328
|
+
607225278,
|
|
329
|
+
1426881987,
|
|
330
|
+
1925078388,
|
|
331
|
+
2162078206,
|
|
332
|
+
2614888103,
|
|
333
|
+
3248222580,
|
|
334
|
+
3835390401,
|
|
335
|
+
4022224774,
|
|
336
|
+
264347078,
|
|
337
|
+
604807628,
|
|
338
|
+
770255983,
|
|
339
|
+
1249150122,
|
|
340
|
+
1555081692,
|
|
341
|
+
1996064986,
|
|
342
|
+
2554220882,
|
|
343
|
+
2821834349,
|
|
344
|
+
2952996808,
|
|
345
|
+
3210313671,
|
|
346
|
+
3336571891,
|
|
347
|
+
3584528711,
|
|
348
|
+
113926993,
|
|
349
|
+
338241895,
|
|
350
|
+
666307205,
|
|
351
|
+
773529912,
|
|
352
|
+
1294757372,
|
|
353
|
+
1396182291,
|
|
354
|
+
1695183700,
|
|
355
|
+
1986661051,
|
|
356
|
+
2177026350,
|
|
357
|
+
2456956037,
|
|
358
|
+
2730485921,
|
|
359
|
+
2820302411,
|
|
360
|
+
3259730800,
|
|
361
|
+
3345764771,
|
|
362
|
+
3516065817,
|
|
363
|
+
3600352804,
|
|
364
|
+
4094571909,
|
|
365
|
+
275423344,
|
|
366
|
+
430227734,
|
|
367
|
+
506948616,
|
|
368
|
+
659060556,
|
|
369
|
+
883997877,
|
|
370
|
+
958139571,
|
|
371
|
+
1322822218,
|
|
372
|
+
1537002063,
|
|
373
|
+
1747873779,
|
|
374
|
+
1955562222,
|
|
375
|
+
2024104815,
|
|
376
|
+
2227730452,
|
|
377
|
+
2361852424,
|
|
378
|
+
2428436474,
|
|
379
|
+
2756734187,
|
|
380
|
+
3204031479,
|
|
381
|
+
3329325298
|
|
382
|
+
]);
|
|
383
|
+
var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
|
|
384
|
+
var SHA2_32B = class extends HashMD {
|
|
385
|
+
constructor(outputLen) {
|
|
386
|
+
super(64, outputLen, 8, false);
|
|
387
|
+
}
|
|
388
|
+
get() {
|
|
389
|
+
const { A, B, C, D, E, F, G, H } = this;
|
|
390
|
+
return [A, B, C, D, E, F, G, H];
|
|
391
|
+
}
|
|
392
|
+
// prettier-ignore
|
|
393
|
+
set(A, B, C, D, E, F, G, H) {
|
|
394
|
+
this.A = A | 0;
|
|
395
|
+
this.B = B | 0;
|
|
396
|
+
this.C = C | 0;
|
|
397
|
+
this.D = D | 0;
|
|
398
|
+
this.E = E | 0;
|
|
399
|
+
this.F = F | 0;
|
|
400
|
+
this.G = G | 0;
|
|
401
|
+
this.H = H | 0;
|
|
402
|
+
}
|
|
403
|
+
process(view, offset) {
|
|
404
|
+
for (let i = 0; i < 16; i++, offset += 4)
|
|
405
|
+
SHA256_W[i] = view.getUint32(offset, false);
|
|
406
|
+
for (let i = 16; i < 64; i++) {
|
|
407
|
+
const W15 = SHA256_W[i - 15];
|
|
408
|
+
const W2 = SHA256_W[i - 2];
|
|
409
|
+
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
410
|
+
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
411
|
+
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
|
|
412
|
+
}
|
|
413
|
+
let { A, B, C, D, E, F, G, H } = this;
|
|
414
|
+
for (let i = 0; i < 64; i++) {
|
|
415
|
+
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
416
|
+
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
|
|
417
|
+
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
418
|
+
const T2 = sigma0 + Maj(A, B, C) | 0;
|
|
419
|
+
H = G;
|
|
420
|
+
G = F;
|
|
421
|
+
F = E;
|
|
422
|
+
E = D + T1 | 0;
|
|
423
|
+
D = C;
|
|
424
|
+
C = B;
|
|
425
|
+
B = A;
|
|
426
|
+
A = T1 + T2 | 0;
|
|
427
|
+
}
|
|
428
|
+
A = A + this.A | 0;
|
|
429
|
+
B = B + this.B | 0;
|
|
430
|
+
C = C + this.C | 0;
|
|
431
|
+
D = D + this.D | 0;
|
|
432
|
+
E = E + this.E | 0;
|
|
433
|
+
F = F + this.F | 0;
|
|
434
|
+
G = G + this.G | 0;
|
|
435
|
+
H = H + this.H | 0;
|
|
436
|
+
this.set(A, B, C, D, E, F, G, H);
|
|
437
|
+
}
|
|
438
|
+
roundClean() {
|
|
439
|
+
clean(SHA256_W);
|
|
440
|
+
}
|
|
441
|
+
destroy() {
|
|
442
|
+
this.destroyed = true;
|
|
443
|
+
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
444
|
+
clean(this.buffer);
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
var _SHA256 = class extends SHA2_32B {
|
|
448
|
+
// We cannot use array here since array allows indexing by variable
|
|
449
|
+
// which means optimizer/compiler cannot use registers.
|
|
450
|
+
A = SHA256_IV[0] | 0;
|
|
451
|
+
B = SHA256_IV[1] | 0;
|
|
452
|
+
C = SHA256_IV[2] | 0;
|
|
453
|
+
D = SHA256_IV[3] | 0;
|
|
454
|
+
E = SHA256_IV[4] | 0;
|
|
455
|
+
F = SHA256_IV[5] | 0;
|
|
456
|
+
G = SHA256_IV[6] | 0;
|
|
457
|
+
H = SHA256_IV[7] | 0;
|
|
458
|
+
constructor() {
|
|
459
|
+
super(32);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
var sha256 = /* @__PURE__ */ createHasher(
|
|
463
|
+
() => new _SHA256(),
|
|
464
|
+
/* @__PURE__ */ oidNist(1)
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
// ../crypto/src/hash.ts
|
|
468
|
+
var import_fast_json_stable_stringify = __toESM(require_fast_json_stable_stringify());
|
|
469
|
+
var GENESIS_HASH = "0".repeat(64);
|
|
470
|
+
function computeHash(event, previousHash) {
|
|
471
|
+
const payload = (0, import_fast_json_stable_stringify.default)({
|
|
472
|
+
organisationId: event.organisationId,
|
|
473
|
+
sequence: event.sequence,
|
|
474
|
+
action: event.action,
|
|
475
|
+
actor: event.actor,
|
|
476
|
+
target: event.target ?? null,
|
|
477
|
+
metadata: event.metadata ?? null,
|
|
478
|
+
createdAt: event.createdAt,
|
|
479
|
+
previousHash
|
|
480
|
+
});
|
|
481
|
+
return bytesToHex(sha256(new TextEncoder().encode(payload)));
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// src/client.ts
|
|
485
|
+
var ProofLog = class {
|
|
486
|
+
db;
|
|
487
|
+
constructor(config) {
|
|
488
|
+
if (!config.databaseUrl) throw new Error("databaseUrl is required");
|
|
489
|
+
const sql = (0, import_serverless.neon)(config.databaseUrl);
|
|
490
|
+
this.db = (0, import_neon_http.drizzle)(sql);
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Pushes a new audit log event directly to the database.
|
|
494
|
+
* Handles concurrency retries internally.
|
|
495
|
+
*/
|
|
496
|
+
async ingest(organisationId, options) {
|
|
497
|
+
const maxRetries = 3;
|
|
498
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
499
|
+
try {
|
|
500
|
+
const lastEntry = await this.db.select().from(auditLogs).where((0, import_drizzle_orm.eq)(auditLogs.organisationId, organisationId)).orderBy((0, import_drizzle_orm.desc)(auditLogs.sequence)).limit(1);
|
|
501
|
+
const previousHash = lastEntry.length ? lastEntry[0].hash : GENESIS_HASH;
|
|
502
|
+
const sequence = lastEntry.length ? lastEntry[0].sequence + 1 : 1;
|
|
503
|
+
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
504
|
+
const hash = computeHash(
|
|
505
|
+
{
|
|
506
|
+
organisationId,
|
|
507
|
+
sequence,
|
|
508
|
+
action: options.action,
|
|
509
|
+
actor: options.actor,
|
|
510
|
+
target: options.target ?? null,
|
|
511
|
+
metadata: options.metadata ?? null,
|
|
512
|
+
createdAt
|
|
513
|
+
},
|
|
514
|
+
previousHash
|
|
515
|
+
);
|
|
516
|
+
await this.db.insert(auditLogs).values({
|
|
517
|
+
organisationId,
|
|
518
|
+
sequence,
|
|
519
|
+
action: options.action,
|
|
520
|
+
actor: options.actor,
|
|
521
|
+
target: options.target ?? null,
|
|
522
|
+
metadata: options.metadata ?? null,
|
|
523
|
+
hash,
|
|
524
|
+
previousHash,
|
|
525
|
+
createdAt: new Date(createdAt)
|
|
526
|
+
});
|
|
527
|
+
return { sequence, hash };
|
|
528
|
+
} catch (error) {
|
|
529
|
+
if (error.code === "23505" || error.message?.includes("23505") || error.message?.includes("unique constraint")) {
|
|
530
|
+
if (attempt === maxRetries - 1) {
|
|
531
|
+
throw new Error("Failed to ingest audit log due to high concurrency. Please try again.");
|
|
532
|
+
}
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
throw error;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
throw new Error("Unreachable");
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Triggers a cryptographic verification of the audit log chain for the organisation in batches.
|
|
542
|
+
*/
|
|
543
|
+
async verify(organisationId) {
|
|
544
|
+
const batchSize = 1e3;
|
|
545
|
+
let hasMore = true;
|
|
546
|
+
let currentSequence = 0;
|
|
547
|
+
let totalEntries = 0;
|
|
548
|
+
let expectedPreviousHash = GENESIS_HASH;
|
|
549
|
+
while (hasMore) {
|
|
550
|
+
const batch = await this.db.select().from(auditLogs).where(
|
|
551
|
+
(0, import_drizzle_orm.and)(
|
|
552
|
+
(0, import_drizzle_orm.eq)(auditLogs.organisationId, organisationId),
|
|
553
|
+
(0, import_drizzle_orm.gt)(auditLogs.sequence, currentSequence)
|
|
554
|
+
)
|
|
555
|
+
).orderBy((0, import_drizzle_orm.asc)(auditLogs.sequence)).limit(batchSize);
|
|
556
|
+
if (batch.length === 0) {
|
|
557
|
+
hasMore = false;
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
for (const entry of batch) {
|
|
561
|
+
if (entry.previousHash !== expectedPreviousHash) {
|
|
562
|
+
return {
|
|
563
|
+
valid: false,
|
|
564
|
+
totalEntries,
|
|
565
|
+
tamperedAt: entry.sequence,
|
|
566
|
+
reason: `Chain broken at sequence ${entry.sequence}`
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
const recomputed = computeHash({
|
|
570
|
+
organisationId: entry.organisationId,
|
|
571
|
+
sequence: entry.sequence,
|
|
572
|
+
action: entry.action,
|
|
573
|
+
actor: entry.actor,
|
|
574
|
+
target: entry.target,
|
|
575
|
+
metadata: entry.metadata,
|
|
576
|
+
createdAt: entry.createdAt.toISOString()
|
|
577
|
+
}, entry.previousHash);
|
|
578
|
+
if (recomputed !== entry.hash) {
|
|
579
|
+
return {
|
|
580
|
+
valid: false,
|
|
581
|
+
totalEntries,
|
|
582
|
+
tamperedAt: entry.sequence,
|
|
583
|
+
reason: `Hash mismatch at sequence ${entry.sequence} \u2014 data tampered`
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
expectedPreviousHash = entry.hash;
|
|
587
|
+
currentSequence = entry.sequence;
|
|
588
|
+
totalEntries++;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return { valid: true, totalEntries };
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
595
|
+
0 && (module.exports = {
|
|
596
|
+
ProofLog
|
|
597
|
+
});
|
|
598
|
+
//# sourceMappingURL=index.js.map
|