initial commit: @arbiter/core authorization engine with js-rigor hardening

Zanzibar-style authorization graph engine (direct/chain/TTU/defeasible/
binary modes, condensed snapshots, value relations) with 39 rigor test
campaigns. Includes fixes for snapshot binary writer/reader format
mismatch (snapshot-of-snapshot corruption), possibility write-boundary
validation, empty-graph snapshot serialization, relation lookup cache
direction collision, config-redefinition cache invalidation, binary
threshold semantics, defeasible compiled routing, and comparator
reason whitelisting.
This commit is contained in:
John Dvorak
2026-07-31 13:44:06 -07:00
commit 717ae1031e
373 changed files with 654131 additions and 0 deletions
@@ -0,0 +1,282 @@
import assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import { CondensedGraph } from '../../src/core/CondensedGraph.js';
const runPerf = process.env.RUN_PERF_TESTS === '1';
const perfTest = runPerf ? test : test.skip;
describe('CondensedGraph - Reliable Memory & Performance', () => {
perfTest('memory efficiency - multiple sizes', () => {
const sizes = [1000, 10000, 50000];
sizes.forEach(size => {
if (global.gc) global.gc();
const baseline = process.memoryUsage();
const graph = new CondensedGraph();
const afterCreate = process.memoryUsage();
for (let i = 0; i < size; i++) {
graph.addEdge(
`user:${i % 100}`,
['owner', 'member', 'viewer', 'editor'][i % 4],
`doc:${i % 500}`
);
}
graph.finalizePerfectHash();
graph.finalizeWaveletAdjacency({ dropAdjacencyList: true });
const afterAdd = process.memoryUsage();
const stats = graph.getStats();
const typedArrayMem = stats.memoryUsage.typedArrays;
const nodeMapMem = stats.memoryUsage.nodeMap;
const totalMem = stats.memoryUsage.total;
console.log(`\nMemory (${size} edges):`);
console.log(` Nodes: ${stats.numNodes}`);
console.log(` Edges: ${stats.numEdges}`);
console.log(` Avg degree: ${stats.avgDegree.toFixed(2)}`);
console.log(` Typed arrays: ${(typedArrayMem / 1024 / 1024).toFixed(2)} MB`);
console.log(` Node map: ${(nodeMapMem / 1024 / 1024).toFixed(2)} MB`);
console.log(` Total: ${(totalMem / 1024 / 1024).toFixed(2)} MB`);
console.log(` Bytes/edge: ${stats.bytesPerEdge.toFixed(2)}`);
console.log(` Capacity: ${stats.capacity}, Utilization: ${(stats.utilization * 100).toFixed(1)}%`);
assert.ok(stats.numEdges === size, `Should have ${size} edges`);
assert.ok(totalMem < size * 1000, `Memory should be reasonable`);
});
});
perfTest('read performance - warm cache', () => {
const sizes = [1000, 10000, 50000];
sizes.forEach(size => {
const graph = new CondensedGraph();
for (let i = 0; i < size; i++) {
graph.addEdge(
`user:${i % 100}`,
['owner', 'member', 'viewer', 'editor'][i % 4],
`doc:${i % 500}`
);
}
graph.finalizePerfectHash();
graph.finalizeWaveletAdjacency({ dropAdjacencyList: true });
const operations = [
{ name: 'getOutEdgesByRel', fn: () => graph.getOutEdgesByRel('user:0', 'owner') },
{ name: 'findEdge', fn: () => graph.findEdge('user:0', 'owner') },
{ name: 'hasEdge', fn: () => graph.hasEdge('user:0', 'owner', 'doc:0') },
{ name: 'getDegree', fn: () => graph.getDegree('user:0') }
];
console.log(`\nRead performance (${size} edges):`);
operations.forEach(op => {
const iterations = 100000;
let count = 0;
const start = performance.now();
for (let i = 0; i < iterations; i++) {
const result = op.fn();
if (result) count++;
}
const duration = performance.now() - start;
const avgMicros = (duration / iterations) * 1000;
const opsPerSec = iterations / (duration / 1000);
console.log(` ${op.name}: ${avgMicros.toFixed(3)} µs (${opsPerSec.toFixed(0)} ops/sec)`);
assert.ok(duration < 5000, `${op.name} should be fast`);
});
});
});
perfTest('iteration performance', () => {
const sizes = [1000, 10000, 50000];
sizes.forEach(size => {
const graph = new CondensedGraph();
for (let i = 0; i < size; i++) {
graph.addEdge(
`user:${i % 100}`,
['owner', 'member', 'viewer', 'editor'][i % 4],
`doc:${i % 500}`
);
}
graph.finalizePerfectHash();
graph.finalizeWaveletAdjacency({ dropAdjacencyList: true });
console.log(`\nIteration performance (${size} edges):`);
let totalEdges = 0;
const iterations = 10000;
const start = performance.now();
for (let i = 0; i < iterations; i++) {
graph.forEachOutEdgeByRel(`user:${i % 100}`, 'owner', (edge) => {
totalEdges++;
});
}
const duration = performance.now() - start;
const avgMicros = (duration / iterations) * 1000;
console.log(` forEachOutEdgeByRel: ${avgMicros.toFixed(3)} µs/iteration`);
console.log(` Total edges processed: ${totalEdges}`);
console.log(` Avg edges/node: ${(totalEdges / iterations).toFixed(2)}`);
assert.ok(duration < 5000, 'Iteration should be fast');
});
});
perfTest('write performance', () => {
const sizes = [1000, 10000, 50000];
sizes.forEach(size => {
const graph = new CondensedGraph();
const start = performance.now();
for (let i = 0; i < size; i++) {
graph.addEdge(
`user:${i % 100}`,
['owner', 'member', 'viewer', 'editor'][i % 4],
`doc:${i % 500}`
);
}
const duration = performance.now() - start;
const avgMicros = (duration / size) * 1000;
const edgesPerSec = size / (duration / 1000);
console.log(`\nWrite performance (${size} edges):`);
console.log(` Total time: ${duration.toFixed(2)} ms`);
console.log(` Avg time/edge: ${avgMicros.toFixed(3)} µs`);
console.log(` Edges/sec: ${edgesPerSec.toFixed(0)}`);
assert.ok(avgMicros < 100, `addEdge should be fast`);
});
});
perfTest('comparison with plain array - memory', () => {
const size = 50000;
// CondensedGraph
const cg = new CondensedGraph();
for (let i = 0; i < size; i++) {
cg.addEdge(`user:${i % 100}`, ['owner', 'member', 'viewer', 'editor'][i % 4], `doc:${i % 500}`);
}
cg.finalizePerfectHash();
cg.finalizeWaveletAdjacency({ dropAdjacencyList: true });
const cgStats = cg.getStats();
const cgMem = cgStats.memoryUsage.total;
// Plain array
const plainEdges = [];
for (let i = 0; i < size; i++) {
plainEdges.push({
src: `user:${i % 100}`,
rel: ['owner', 'member', 'viewer', 'editor'][i % 4],
dst: `doc:${i % 500}`,
possibility: 1.0,
reliability: 1.0
});
}
// Estimate plain array memory (rough estimate)
const plainMem = size * 120; // ~120 bytes per object + overhead
console.log('\nMemory comparison (50K edges):');
console.log(` CondensedGraph: ${(cgMem / 1024 / 1024).toFixed(2)} MB`);
console.log(` Plain array (est): ${(plainMem / 1024 / 1024).toFixed(2)} MB`);
console.log(` Savings: ${((plainMem - cgMem) / plainMem * 100).toFixed(1)}%`);
console.log(` CondensedGraph bytes/edge: ${cgStats.bytesPerEdge.toFixed(2)}`);
console.log(` Plain array bytes/edge (est): ${(plainMem / size).toFixed(2)}`);
assert.ok(cgMem < plainMem, 'CondensedGraph should use less memory');
});
perfTest('comparison with plain array - performance', () => {
const size = 50000;
// CondensedGraph
const cg = new CondensedGraph();
for (let i = 0; i < size; i++) {
cg.addEdge(`user:${i % 100}`, ['owner', 'member', 'viewer', 'editor'][i % 4], `doc:${i % 500}`);
}
cg.finalizePerfectHash();
cg.finalizeWaveletAdjacency({ dropAdjacencyList: true });
// Plain array
const plainEdges = [];
for (let i = 0; i < size; i++) {
plainEdges.push({
src: `user:${i % 100}`,
rel: ['owner', 'member', 'viewer', 'editor'][i % 4],
dst: `doc:${i % 500}`,
possibility: 1.0,
reliability: 1.0
});
}
const iterations = 1000;
// CondensedGraph: getOutEdges
const cgStart = performance.now();
for (let i = 0; i < iterations; i++) {
cg.getOutEdgesByRel(`user:${i % 100}`, 'owner');
}
const cgTime = performance.now() - cgStart;
// Plain array: filter
const plainStart = performance.now();
for (let i = 0; i < iterations; i++) {
plainEdges.filter(e => e.src === `user:${i % 100}`);
}
const plainTime = performance.now() - plainStart;
console.log('\nPerformance comparison (50K edges, 1K lookups):');
console.log(` CondensedGraph: ${cgTime.toFixed(2)} ms (${(cgTime / iterations).toFixed(3)} µs/lookup)`);
console.log(` Plain array filter: ${plainTime.toFixed(2)} ms (${(plainTime / iterations).toFixed(3)} µs/lookup)`);
console.log(` Speedup: ${(plainTime / cgTime).toFixed(2)}x`);
assert.ok(cgTime < plainTime, 'CondensedGraph should be faster');
});
perfTest('scalability trends', () => {
console.log('\n\n=== Scalability Analysis ===\n');
const sizes = [1000, 10000, 50000];
console.log('Size | Nodes | Edges | Avg Deg | Memory (MB) | Bytes/Edge');
console.log('------|-------|-------|---------|-------------|-------------');
sizes.forEach(size => {
const graph = new CondensedGraph();
for (let i = 0; i < size; i++) {
graph.addEdge(`user:${i % 100}`, ['owner', 'member', 'viewer', 'editor'][i % 4], `doc:${i % 500}`);
}
graph.finalizePerfectHash();
graph.finalizeWaveletAdjacency({ dropAdjacencyList: true });
const stats = graph.getStats();
console.log(
`${size.toString().padStart(5)} | ` +
`${stats.numNodes.toString().padStart(5)} | ` +
`${stats.numEdges.toString().padStart(5)} | ` +
`${stats.avgDegree.toFixed(2).padStart(7)} | ` +
`${(stats.memoryUsage.total / 1024 / 1024).toFixed(2).padStart(11)} | ` +
`${stats.bytesPerEdge.toFixed(2).padStart(11)}`
);
});
});
});