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,176 @@
|
||||
/**
|
||||
* Analysis of which rules use reachability optimization
|
||||
*/
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { BigGraphGenerator } from '../helpers/big-graph-generator.js';
|
||||
|
||||
test('analyzes which rules use reachability optimization', async () => {
|
||||
if (process.env.TEST_DEBUG === '1') console.log('🔍 Analyzing which rules use reachability optimization...');
|
||||
|
||||
const generator = new BigGraphGenerator();
|
||||
const graphData = generator.generateGraph('enterprise');
|
||||
const arbiter = generator.loadIntoArbiter(graphData);
|
||||
|
||||
// Initialize reachability checker
|
||||
await arbiter.initializeReachabilityChecker({
|
||||
strategy: 'auto',
|
||||
twoHopOptions: {},
|
||||
treeCoverOptions: {}
|
||||
});
|
||||
|
||||
// Get initial reachability stats
|
||||
const initialStats = arbiter.getReachabilityStats();
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`Initial reachability stats: ${initialStats.totalQueries} queries`);
|
||||
|
||||
// Test different rule types
|
||||
const testCases = [
|
||||
{
|
||||
name: 'DirectRule',
|
||||
relation: 'can_read',
|
||||
description: 'Direct relations (should use fast path)'
|
||||
},
|
||||
{
|
||||
name: 'ChainRule',
|
||||
relation: 'can_read_via_role',
|
||||
description: 'Chain relations (should use reachability)'
|
||||
},
|
||||
{
|
||||
name: 'MultiHopRule',
|
||||
relation: 'can_access_multi_hop',
|
||||
description: 'Multi-hop relations (should use reachability)'
|
||||
},
|
||||
{
|
||||
name: 'ParentRule',
|
||||
relation: 'can_read', // Parent rule uses direct relations
|
||||
description: 'Parent relations (might use reachability)'
|
||||
},
|
||||
{
|
||||
name: 'TupleToUsersetRule',
|
||||
relation: 'can_read',
|
||||
description: 'Tuple-to-userset relations (might use reachability)'
|
||||
}
|
||||
];
|
||||
|
||||
const results = {};
|
||||
|
||||
for (const testCase of testCases) {
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`\\n=== TESTING ${testCase.name} ===`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`Description: ${testCase.description}`);
|
||||
|
||||
// Reset reachability stats
|
||||
const beforeStats = arbiter.getReachabilityStats();
|
||||
|
||||
// Test the rule
|
||||
const testRelations = graphData.relations.filter(r =>
|
||||
r.src.startsWith('user:') && r.dst.startsWith('doc:') &&
|
||||
r.relation === 'can_read'
|
||||
).slice(0, 3);
|
||||
|
||||
const startTime = Date.now();
|
||||
let queryCount = 0;
|
||||
const latencies = [];
|
||||
|
||||
for (const relation of testRelations) {
|
||||
const queryStart = process.hrtime.bigint();
|
||||
try {
|
||||
const result = arbiter.check(relation.src, testCase.relation, relation.dst);
|
||||
const queryEnd = process.hrtime.bigint();
|
||||
const latency = Number(queryEnd - queryStart) / 1000000;
|
||||
latencies.push(latency);
|
||||
queryCount++;
|
||||
} catch (error) {
|
||||
queryCount++;
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
const qps = (queryCount / duration) * 1000;
|
||||
const avgLatency = latencies.length > 0 ?
|
||||
latencies.reduce((a, b) => a + b, 0) / latencies.length : 0;
|
||||
|
||||
// Get reachability stats after
|
||||
const afterStats = arbiter.getReachabilityStats();
|
||||
const reachabilityQueries = afterStats.totalQueries - beforeStats.totalQueries;
|
||||
const twoHopHits = afterStats.twoHopHits - beforeStats.twoHopHits;
|
||||
const treeCoverHits = afterStats.treeCoverHits - beforeStats.treeCoverHits;
|
||||
const fallbackQueries = afterStats.fallbackQueries - beforeStats.fallbackQueries;
|
||||
|
||||
results[testCase.name] = {
|
||||
qps,
|
||||
avgLatency,
|
||||
reachabilityQueries,
|
||||
twoHopHits,
|
||||
treeCoverHits,
|
||||
fallbackQueries,
|
||||
usesReachability: reachabilityQueries > 0
|
||||
};
|
||||
|
||||
if (process.env.TEST_DEBUG === '1') console.log(` QPS: ${qps.toFixed(2)}`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(` Avg Latency: ${avgLatency.toFixed(3)}ms`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(` Reachability Queries: ${reachabilityQueries}`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(` TwoHop Hits: ${twoHopHits}`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(` TreeCover Hits: ${treeCoverHits}`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(` Fallback Queries: ${fallbackQueries}`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(` Uses Reachability: ${reachabilityQueries > 0 ? '✅ YES' : '❌ NO'}`);
|
||||
}
|
||||
|
||||
// Analysis
|
||||
if (process.env.TEST_DEBUG === '1') console.log('\\n=== REACHABILITY OPTIMIZATION ANALYSIS ===');
|
||||
|
||||
const rulesUsingReachability = Object.entries(results)
|
||||
.filter(([name, result]) => result.usesReachability)
|
||||
.map(([name, result]) => name);
|
||||
|
||||
const rulesNotUsingReachability = Object.entries(results)
|
||||
.filter(([name, result]) => !result.usesReachability)
|
||||
.map(([name, result]) => name);
|
||||
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`\\n✅ Rules USING reachability optimization:`);
|
||||
rulesUsingReachability.forEach(rule => {
|
||||
const result = results[rule];
|
||||
if (process.env.TEST_DEBUG === '1') console.log(` - ${rule}: ${result.reachabilityQueries} queries, ${result.treeCoverHits} tree-cover hits`);
|
||||
});
|
||||
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`\\n❌ Rules NOT using reachability optimization:`);
|
||||
rulesNotUsingReachability.forEach(rule => {
|
||||
const result = results[rule];
|
||||
if (process.env.TEST_DEBUG === '1') console.log(` - ${rule}: ${result.qps.toFixed(2)} QPS, ${result.avgLatency.toFixed(3)}ms avg`);
|
||||
});
|
||||
|
||||
// Performance comparison
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`\\n=== PERFORMANCE COMPARISON ===`);
|
||||
const reachabilityRules = rulesUsingReachability.map(rule => ({ name: rule, ...results[rule] }));
|
||||
const nonReachabilityRules = rulesNotUsingReachability.map(rule => ({ name: rule, ...results[rule] }));
|
||||
|
||||
if (reachabilityRules.length > 0) {
|
||||
const avgReachabilityQPS = reachabilityRules.reduce((sum, rule) => sum + rule.qps, 0) / reachabilityRules.length;
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`Average QPS for rules WITH reachability: ${avgReachabilityQPS.toFixed(2)}`);
|
||||
}
|
||||
|
||||
if (nonReachabilityRules.length > 0) {
|
||||
const avgNonReachabilityQPS = nonReachabilityRules.reduce((sum, rule) => sum + rule.qps, 0) / nonReachabilityRules.length;
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`Average QPS for rules WITHOUT reachability: ${avgNonReachabilityQPS.toFixed(2)}`);
|
||||
}
|
||||
|
||||
// Recommendations
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`\\n=== RECOMMENDATIONS ===`);
|
||||
if (rulesNotUsingReachability.length > 0) {
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`Consider optimizing these rules with reachability indexes:`);
|
||||
rulesNotUsingReachability.forEach(rule => {
|
||||
if (process.env.TEST_DEBUG === '1') console.log(` - ${rule}: Could benefit from reachability optimization`);
|
||||
});
|
||||
} else {
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`All tested rules are using reachability optimization! 🎉`);
|
||||
}
|
||||
|
||||
// Final stats
|
||||
const finalStats = arbiter.getReachabilityStats();
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`\\n=== FINAL REACHABILITY STATS ===`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`Total queries: ${finalStats.totalQueries}`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`TwoHop hits: ${finalStats.twoHopHits}`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`TreeCover hits: ${finalStats.treeCoverHits}`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`Fallback queries: ${finalStats.fallbackQueries}`);
|
||||
if (process.env.TEST_DEBUG === '1') console.log(`Strategy: ${finalStats.strategy}`);
|
||||
});
|
||||
Reference in New Issue
Block a user