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:
@@ -0,0 +1,175 @@
|
||||
import { describe, test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { CondensedGraph } from '../../src/core/CondensedGraph.js';
|
||||
import { ShardedSnapshotBuilder } from '../../src/core/shards/ShardedSnapshotBuilder.js';
|
||||
import { ShardedSnapshot } from '../../src/core/shards/ShardedSnapshot.js';
|
||||
import { FileShardStorage } from '../../src/core/shards/FileShardStorage.js';
|
||||
import { DeltaShardBinary } from '../../src/core/shards/DeltaShardBinary.js';
|
||||
|
||||
function buildSnapshot(bucketSize = 4) {
|
||||
const graph = new CondensedGraph();
|
||||
|
||||
const user0 = graph._ensureNode('user:0');
|
||||
const user1 = graph._ensureNode('user:1');
|
||||
const doc0 = graph._ensureNode('doc:0');
|
||||
const doc1 = graph._ensureNode('doc:1');
|
||||
|
||||
graph.addEdge(user0, 'owner', doc0);
|
||||
graph.addEdge(user1, 'owner', doc0);
|
||||
|
||||
graph.finalizePerfectHash();
|
||||
graph.finalizeWaveletAdjacency({ dropAdjacencyList: true });
|
||||
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'sharded-delta-'));
|
||||
const builder = new ShardedSnapshotBuilder({ bucketSize, includeDirections: ['out', 'in'] });
|
||||
const manifest = builder.build(graph, dir);
|
||||
const storage = new FileShardStorage(dir);
|
||||
const snapshot = new ShardedSnapshot(manifest, storage, { cacheLimit: 8 });
|
||||
snapshot.initializeSync();
|
||||
|
||||
return { graph, snapshot, dir, ids: { user0, user1, doc0, doc1 } };
|
||||
}
|
||||
|
||||
function writeDeltaLayer(snapshot, dir, name, entries) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
const merged = new Map();
|
||||
|
||||
for (const entry of entries) {
|
||||
const shardMeta = snapshot._selectShardMeta(entry.relationId, entry.direction, entry.srcId);
|
||||
assert.ok(shardMeta, 'Missing shard meta for delta entry');
|
||||
const localSource = snapshot._localSource(entry.srcId, shardMeta);
|
||||
const key = shardMeta.cacheKey;
|
||||
let bucket = merged.get(key);
|
||||
if (!bucket) {
|
||||
bucket = { shardMeta, additions: [], removals: [] };
|
||||
merged.set(key, bucket);
|
||||
}
|
||||
for (const add of entry.additions) {
|
||||
bucket.additions.push({
|
||||
srcLocal: localSource,
|
||||
otherId: add.dstId,
|
||||
possBits: add.possBits,
|
||||
relBits: add.relBits
|
||||
});
|
||||
}
|
||||
for (const rem of entry.removals) {
|
||||
bucket.removals.push({
|
||||
srcLocal: localSource,
|
||||
otherId: rem.dstId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const shards = [];
|
||||
for (const bucket of merged.values()) {
|
||||
const shardMeta = bucket.shardMeta;
|
||||
const buffer = DeltaShardBinary.serialize({
|
||||
relationId: shardMeta.relationId,
|
||||
direction: shardMeta.direction,
|
||||
rangeStart: shardMeta.rangeStart,
|
||||
rangeEnd: shardMeta.rangeEnd,
|
||||
nodeCount: snapshot.nodeCount,
|
||||
additions: bucket.additions,
|
||||
removals: bucket.removals
|
||||
});
|
||||
|
||||
const shardKey = `delta-${name}-${shardMeta.key}`;
|
||||
fs.writeFileSync(path.join(dir, shardKey), new Uint8Array(buffer));
|
||||
shards.push({
|
||||
key: shardKey,
|
||||
relationId: shardMeta.relationId,
|
||||
direction: shardMeta.direction,
|
||||
rangeStart: shardMeta.rangeStart,
|
||||
rangeEnd: shardMeta.rangeEnd,
|
||||
cacheKey: shardMeta.cacheKey
|
||||
});
|
||||
}
|
||||
|
||||
return { shards };
|
||||
}
|
||||
|
||||
// ADR-003: sharded snapshots are stubs in src/core/shards/ — tests are the spec for when the subsystem is implemented.
|
||||
describe.skip('Sharded snapshot delta overlay', () => {
|
||||
test('adds and removes edges in overlay reads', () => {
|
||||
const { graph, snapshot, dir, ids } = buildSnapshot(4);
|
||||
const relId = graph.getRelationId('owner');
|
||||
|
||||
const baseEdge = snapshot.findEdgeSync(ids.user0, relId, ids.doc0);
|
||||
assert.ok(baseEdge, 'Expected base edge');
|
||||
|
||||
const deltaDir = path.join(dir, 'delta');
|
||||
const deltaManifest = writeDeltaLayer(snapshot, deltaDir, 'l1', [
|
||||
{
|
||||
relationId: relId,
|
||||
direction: 'out',
|
||||
srcId: ids.user0,
|
||||
additions: [],
|
||||
removals: [{ dstId: ids.doc0 }]
|
||||
},
|
||||
{
|
||||
relationId: relId,
|
||||
direction: 'out',
|
||||
srcId: ids.user1,
|
||||
additions: [{ dstId: ids.doc1, possBits: 65535, relBits: 65535 }],
|
||||
removals: []
|
||||
}
|
||||
]);
|
||||
|
||||
snapshot.setDeltaLayers([{ shards: deltaManifest.shards, storage: new FileShardStorage(deltaDir) }]);
|
||||
|
||||
const removedEdge = snapshot.findEdgeSync(ids.user0, relId, ids.doc0);
|
||||
assert.equal(removedEdge, null);
|
||||
|
||||
const addedEdge = snapshot.findEdgeSync(ids.user1, relId, ids.doc1);
|
||||
assert.ok(addedEdge, 'Expected added edge');
|
||||
|
||||
const user0Edges = snapshot.getOutEdgesSync(ids.user0, relId);
|
||||
assert.equal(user0Edges.length, 0);
|
||||
|
||||
const user1Edges = snapshot.getOutEdgesSync(ids.user1, relId);
|
||||
assert.equal(user1Edges.length, 2);
|
||||
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
test('later delta layers override earlier ones', () => {
|
||||
const { graph, snapshot, dir, ids } = buildSnapshot(4);
|
||||
const relId = graph.getRelationId('owner');
|
||||
|
||||
const layer1Dir = path.join(dir, 'delta-1');
|
||||
const layer2Dir = path.join(dir, 'delta-2');
|
||||
|
||||
const layer1 = writeDeltaLayer(snapshot, layer1Dir, 'l1', [
|
||||
{
|
||||
relationId: relId,
|
||||
direction: 'out',
|
||||
srcId: ids.user0,
|
||||
additions: [{ dstId: ids.doc1, possBits: 65535, relBits: 65535 }],
|
||||
removals: []
|
||||
}
|
||||
]);
|
||||
|
||||
const layer2 = writeDeltaLayer(snapshot, layer2Dir, 'l2', [
|
||||
{
|
||||
relationId: relId,
|
||||
direction: 'out',
|
||||
srcId: ids.user0,
|
||||
additions: [],
|
||||
removals: [{ dstId: ids.doc1 }]
|
||||
}
|
||||
]);
|
||||
|
||||
snapshot.setDeltaLayers([
|
||||
{ shards: layer1.shards, storage: new FileShardStorage(layer1Dir) },
|
||||
{ shards: layer2.shards, storage: new FileShardStorage(layer2Dir) }
|
||||
]);
|
||||
|
||||
const edge = snapshot.findEdgeSync(ids.user0, relId, ids.doc1);
|
||||
assert.equal(edge, null);
|
||||
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user