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,249 @@
import { Arbiter } from '../src/core/Arbiter.js';
import { OWAFusion } from '../src/utils/OWAFusion.js';
function parseArgNumber(args, name, fallback) {
const idx = args.indexOf(name);
if (idx === -1 || idx + 1 >= args.length) return fallback;
const value = Number(args[idx + 1]);
return Number.isFinite(value) ? value : fallback;
}
function hasArg(args, name) {
return args.includes(name);
}
class Profiler {
constructor() {
this.stats = new Map();
}
_record(label, deltaMs) {
let entry = this.stats.get(label);
if (!entry) {
entry = { calls: 0, totalMs: 0 };
this.stats.set(label, entry);
}
entry.calls += 1;
entry.totalMs += deltaMs;
}
wrap(obj, methodName, label) {
if (!obj || typeof obj[methodName] !== 'function') return;
const original = obj[methodName];
if (original.__profiled) return;
const profiler = this;
const wrapped = function(...args) {
const start = process.hrtime.bigint();
try {
return original.apply(this, args);
} finally {
const deltaMs = Number(process.hrtime.bigint() - start) / 1e6;
profiler._record(label, deltaMs);
}
};
wrapped.__profiled = true;
obj[methodName] = wrapped;
}
report() {
const entries = Array.from(this.stats.entries()).map(([label, data]) => ({
label,
calls: data.calls,
totalMs: data.totalMs,
avgMs: data.calls ? data.totalMs / data.calls : 0
}));
entries.sort((a, b) => b.totalMs - a.totalMs);
console.log('profile:function_ms');
for (const entry of entries) {
console.log(` ${entry.label} calls=${entry.calls} total_ms=${entry.totalMs.toFixed(3)} avg_ms=${entry.avgMs.toFixed(6)}`);
}
}
}
function buildOwaComparatorScenario(arbiter, size) {
for (let i = 0; i < size; i++) {
arbiter.addNode(`user:${i}`, 'user');
arbiter.addNode(`resource:${i}`, 'resource');
arbiter.addRelation(`user:${i}`, 'risk_score', `resource:${i}`, 1.0, { value: i % 2 === 0 ? 20 : 80 });
arbiter.addRelation(`user:${i}`, 'risk_bonus', `resource:${i}`, 1.0, { value: i % 2 === 0 ? 5 : 15 });
arbiter.addRelation(`user:${i}`, 'risk_noise', `resource:${i}`, 1.0, { value: i % 2 === 0 ? 0 : 10 });
arbiter.addRelation(`resource:${i}`, 'risk_limit', `resource:${i}`, 1.0, { value: 40 });
arbiter.addRelation(`resource:${i}`, 'risk_cap', `resource:${i}`, 1.0, { value: 45 });
}
arbiter.setRelationConfig('risk_score', { type: 'direct' });
arbiter.setRelationConfig('risk_bonus', { type: 'direct' });
arbiter.setRelationConfig('risk_noise', { type: 'direct' });
arbiter.setRelationConfig('risk_limit', { type: 'direct' });
arbiter.setRelationConfig('risk_cap', { type: 'direct' });
arbiter.setRelationConfig('risk_union_left', {
union: {
rules: [
{ type: 'direct', relation: 'risk_score' },
{ type: 'direct', relation: 'risk_bonus' },
{ type: 'direct', relation: 'risk_noise' }
],
aggregator: 'owa',
owaWeights: [0.5, 0.3, 0.2]
}
});
arbiter.setRelationConfig('risk_union_right', {
union: {
rules: [
{ type: 'direct', relation: 'risk_limit' },
{ type: 'direct', relation: 'risk_cap' }
],
aggregator: 'owa',
owaWeights: [0.6, 0.4]
}
});
arbiter.setRelationConfig('risk_ok_owa', {
type: 'relational_comparator',
comparator: '<=',
fallbackBehavior: 'deny',
left: {
rule: {
union: {
rules: [
{ type: 'direct', relation: 'risk_score' },
{ type: 'direct', relation: 'risk_bonus' },
{ type: 'direct', relation: 'risk_noise' }
],
aggregator: 'owa',
owaWeights: [0.5, 0.3, 0.2]
}
},
extractValue: true,
valueRelation: 'risk_score',
aggregator: 'owa',
owaWeights: [0.5, 0.3, 0.2]
},
right: {
rule: {
union: {
rules: [
{ type: 'direct', relation: 'risk_limit' },
{ type: 'direct', relation: 'risk_cap' }
],
aggregator: 'owa',
owaWeights: [0.6, 0.4]
}
},
extractValue: true,
valueRelation: 'risk_limit',
evaluateFrom: 'object',
aggregator: 'owa',
owaWeights: [0.6, 0.4]
}
});
}
function resetSortCounter() {
OWAFusion.sortCounter = { total: 0, byMode: {}, byMethod: {} };
return OWAFusion.sortCounter;
}
function snapshotSortCounter() {
const counter = OWAFusion.sortCounter || { total: 0, byMode: {}, byMethod: {} };
return {
total: counter.total || 0,
byMode: { ...counter.byMode },
byMethod: { ...counter.byMethod }
};
}
function runTrace(arbiter, relation, userKey, objectKey, label) {
resetSortCounter();
const start = process.hrtime.bigint();
const result = arbiter.check(userKey, relation, objectKey, {
fastPath: true,
includeMeta: true,
cacheRuleResult: false
});
const durationMs = Number(process.hrtime.bigint() - start) / 1e6;
const counts = snapshotSortCounter();
console.log(`trace:${label}`);
console.log(` result=${result.possibility.toFixed(3)} duration_ms=${durationMs.toFixed(3)}`);
console.log(` sorts_total=${counts.total}`);
console.log(` sorts_by_method=${JSON.stringify(counts.byMethod)}`);
console.log(` sorts_by_mode=${JSON.stringify(counts.byMode)}`);
}
function runBench(arbiter, relation, size, runs, label, useResourceKey = false) {
const userKey = `user:${Math.floor(size / 2)}`;
const objectKey = `resource:${Math.floor(size / 2)}`;
const subjectKey = useResourceKey ? objectKey : userKey;
const targetKey = useResourceKey ? objectKey : objectKey;
resetSortCounter();
for (let i = 0; i < 200; i++) {
arbiter.check(subjectKey, relation, targetKey, { fastPath: true, cacheRuleResult: false });
}
const start = process.hrtime.bigint();
for (let i = 0; i < runs; i++) {
arbiter.check(subjectKey, relation, targetKey, { fastPath: true, cacheRuleResult: false });
}
const durationMs = Number(process.hrtime.bigint() - start) / 1e6;
const counts = snapshotSortCounter();
const perQuery = durationMs / runs;
const sortsPerQuery = runs > 0 ? counts.total / runs : 0;
console.log(`bench:${label}`);
console.log(` runs=${runs} total_ms=${durationMs.toFixed(2)} per_query_ms=${perQuery.toFixed(4)}`);
console.log(` sorts_total=${counts.total} sorts_per_query=${sortsPerQuery.toFixed(3)}`);
console.log(` sorts_by_method=${JSON.stringify(counts.byMethod)}`);
console.log(` sorts_by_mode=${JSON.stringify(counts.byMode)}`);
}
const args = process.argv.slice(2);
const size = parseArgNumber(args, '--size', 10000);
const runs = parseArgNumber(args, '--runs', 20000);
const traceOne = hasArg(args, '--trace-one');
const profile = hasArg(args, '--profile');
const arbiter = new Arbiter({
enableRuleResultCache: false,
disableCaching: true
});
buildOwaComparatorScenario(arbiter, size);
let profiler = null;
if (profile) {
profiler = new Profiler();
profiler.wrap(arbiter, 'check', 'Arbiter.check');
profiler.wrap(arbiter.authChecker, 'check', 'AuthorizationChecker.check');
profiler.wrap(arbiter.authChecker.ruleEvaluator, 'evaluateRule', 'RuleEvaluator.evaluateRule');
profiler.wrap(arbiter.authChecker.ruleEvaluator.logicalOperators, 'evaluateUnion', 'LogicalOperators.evaluateUnion');
profiler.wrap(arbiter.authChecker.ruleEvaluator.ruleHandlers.direct, 'evaluate', 'DirectRule.evaluate');
const comparator = arbiter.authChecker.ruleEvaluator.ruleHandlers.relational_comparator?.rule;
if (comparator) {
profiler.wrap(comparator, '_evaluateOperand', 'RelationalComparatorRule._evaluateOperand');
profiler.wrap(comparator, '_extractValues', 'RelationalComparatorRule._extractValues');
profiler.wrap(comparator, '_aggregateCrispValues', 'RelationalComparatorRule._aggregateCrispValues');
profiler.wrap(comparator, '_compareBlurredValues', 'RelationalComparatorRule._compareBlurredValues');
}
profiler.wrap(OWAFusion, 'fuseWithMeta', 'OWAFusion.fuseWithMeta');
profiler.wrap(OWAFusion, 'fuseTriplesWithMeta', 'OWAFusion.fuseTriplesWithMeta');
}
if (traceOne) {
const userKey = `user:${Math.floor(size / 2)}`;
const objectKey = `resource:${Math.floor(size / 2)}`;
const resourceKey = objectKey;
runTrace(arbiter, 'risk_union_left', userKey, objectKey, 'union_left');
runTrace(arbiter, 'risk_union_right', resourceKey, resourceKey, 'union_right');
runTrace(arbiter, 'risk_ok_owa', userKey, objectKey, 'comparator_nested');
} else {
runBench(arbiter, 'risk_union_left', size, Math.max(1000, Math.floor(runs / 2)), 'union_left');
runBench(arbiter, 'risk_union_right', size, Math.max(1000, Math.floor(runs / 2)), 'union_right', true);
runBench(arbiter, 'risk_ok_owa', size, runs, 'comparator_nested');
}
if (profiler) {
profiler.report();
}