Initial import of verae-archive-worm from zapier monorepo

This commit is contained in:
George Lambert 2026-09-11 13:37:35 -04:00
commit 4c7fe00ff4
6 changed files with 145 additions and 0 deletions

40
src/archive.js Normal file
View file

@ -0,0 +1,40 @@
/**
* In-process WORM archive: append-only records + bloom.
* @module archive
*/
import { Bloom } from './bloom.js';
export class WormArchive {
/**
* @param {string} archiveId
*/
constructor(archiveId) {
this.archiveId = archiveId;
this.bloom = new Bloom();
/** @type {Map<string, object[]>} */
this.byHash = new Map();
}
/**
* @param {{ sha256: string, kind: string, record: object }} put
*/
put(put) {
const key = String(put.sha256).toLowerCase();
const list = this.byHash.get(key) ?? [];
list.push({ kind: put.kind, record: put.record, archiveId: this.archiveId, storedAt: new Date().toISOString() });
this.byHash.set(key, list);
this.bloom.add(key);
}
/**
* Bloom miss null (caller must stay silent). Hit records (may be empty if false positive).
* @param {string} sha256
* @returns {object[]|null}
*/
query(sha256) {
const key = String(sha256).toLowerCase();
if (!this.bloom.mightHave(key)) return null;
return this.byHash.get(key) ?? [];
}
}

46
src/bloom.js Normal file
View file

@ -0,0 +1,46 @@
/**
* Tiny Bloom filter for SHA256 membership (false positives ok).
* @module bloom
*/
import { createHash } from 'node:crypto';
export class Bloom {
/**
* @param {number} [m=16384] bit count
* @param {number} [k=4] hash rounds
*/
constructor(m = 16384, k = 4) {
this.m = m;
this.k = k;
this.bits = Buffer.alloc(Math.ceil(m / 8));
}
/**
* @param {string} s
* @returns {number[]}
*/
hashes(s) {
const digest = createHash('sha256').update(String(s)).digest();
const out = [];
for (let i = 0; i < this.k; i += 1) {
const n = digest.readUInt32BE((i * 4) % 28);
out.push(n % this.m);
}
return out;
}
add(s) {
for (const i of this.hashes(s)) {
this.bits[i >> 3] |= 1 << (i & 7);
}
}
/**
* @param {string} s
* @returns {boolean} maybe (never a guaranteed yes)
*/
mightHave(s) {
return this.hashes(s).every((i) => (this.bits[i >> 3] & (1 << (i & 7))) !== 0);
}
}