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
+89
View File
@@ -0,0 +1,89 @@
import assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import { Arbiter } from '../../src/core/Arbiter.js';
describe('Graph Structure and Queries', () => {
test('basic node and relation creation', () => {
const arbiter = new Arbiter();
arbiter.addNode('user:1', 'user');
arbiter.addNode('resource:1', 'resource');
const nodeId1 = arbiter.resolveNodeId('user:1');
const nodeId2 = arbiter.resolveNodeId('resource:1');
assert.ok(nodeId1 !== undefined, 'user node ID resolved');
assert.ok(nodeId2 !== undefined, 'resource node ID resolved');
assert.strictEqual(arbiter.resolveKey(nodeId1), 'user:1', 'reverse key lookup works');
});
test('direct relation authorization', () => {
const arbiter = new Arbiter();
arbiter.addNode('user:1', 'user');
arbiter.addNode('resource:1', 'resource');
arbiter.setRelationConfig('owner', { type: 'direct' });
arbiter.addRelation('user:1', 'owner', 'resource:1', 1.0);
const result = arbiter.check('user:1', 'owner', 'resource:1');
assert.strictEqual(result.possibility, 1.0, 'owner relation grants access');
assert.strictEqual(result.reason, 'direct_match', 'reason is direct_match');
});
test('absence of relation denies access', () => {
const arbiter = new Arbiter();
arbiter.addNode('user:1', 'user');
arbiter.addNode('resource:1', 'resource');
arbiter.addNode('user:2', 'user');
arbiter.setRelationConfig('owner', { type: 'direct' });
arbiter.addRelation('user:1', 'owner', 'resource:1', 1.0);
const result = arbiter.check('user:2', 'owner', 'resource:1');
assert.strictEqual(result.possibility, 0.0, 'non-owner denied');
assert.strictEqual(result.reason, 'no_relation', 'reason is no_relation');
});
test('node data storage and retrieval', () => {
const arbiter = new Arbiter();
arbiter.addNode('user:1', 'user', { tier: 'premium', level: 5 });
const data = arbiter.getNodeData('user:1');
assert.strictEqual(data.tier, 'premium');
assert.strictEqual(data.level, 5);
});
test('node data update', () => {
const arbiter = new Arbiter();
arbiter.addNode('user:1', 'user', { tier: 'premium' });
arbiter.updateNodeData('user:1', { tier: 'enterprise', level: 10 });
const data = arbiter.getNodeData('user:1');
assert.strictEqual(data.tier, 'enterprise');
assert.strictEqual(data.level, 10);
});
test('multiple relations between different node types', () => {
const arbiter = new Arbiter();
arbiter.addNode('user:1', 'user');
arbiter.addNode('group:1', 'group');
arbiter.addNode('resource:1', 'resource');
arbiter.setRelationConfig('member', { type: 'direct' });
arbiter.setRelationConfig('can_view', { type: 'direct' });
arbiter.addRelation('user:1', 'member', 'group:1', 1.0);
arbiter.addRelation('group:1', 'can_view', 'resource:1', 1.0);
const memberResult = arbiter.check('user:1', 'member', 'group:1');
const viewResult = arbiter.check('group:1', 'can_view', 'resource:1');
assert.strictEqual(memberResult.possibility, 1.0);
assert.strictEqual(viewResult.possibility, 1.0);
});
});