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,88 @@
|
||||
import { test, describe, it } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { setupChainRuleTestGraph } from './helpers.js';
|
||||
|
||||
describe('ChainRule Comprehensive Tests', () => {
|
||||
|
||||
describe('Value Extraction and Aggregation', () => {
|
||||
it('extracts and sums values from chain endpoints', () => {
|
||||
const arbiter = setupChainRuleTestGraph();
|
||||
|
||||
// Test: user → group → project → budget (extract budget values)
|
||||
arbiter.setRelationConfig('user_budget_access', {
|
||||
type: 'chain',
|
||||
steps: [
|
||||
{ relation: 'member_of', direction: 'out' }, // user → group
|
||||
{ relation: 'manages', direction: 'out' }, // group → project
|
||||
{ relation: 'has_budget', direction: 'out' } // project → budget
|
||||
],
|
||||
extractValues: true,
|
||||
extractFrom: 2, // Extract from step 2 (projects)
|
||||
extractRelation: 'has_budget', // Extract budget values
|
||||
valueAggregation: 'sum' // Sum all budgets
|
||||
});
|
||||
|
||||
// Alice should have access to engineering budgets
|
||||
const result1 = arbiter.check('user:alice', 'user_budget_access', 'budget:tech-2024');
|
||||
|
||||
// Authorization should succeed
|
||||
assert.equal(result1.possibility, 1);
|
||||
assert.equal(result1.reason, 'allow_rule_matched');
|
||||
|
||||
// Values should NOT be in the authorization result (they're internal only)
|
||||
assert.equal(result1.value, undefined);
|
||||
assert.equal(result1.hasValue, undefined);
|
||||
|
||||
// The ChainRule internally calculated values for potential use by other rules,
|
||||
// but authorization results only contain allow/deny possibilities
|
||||
});
|
||||
|
||||
it('aggregates values using max aggregation', () => {
|
||||
const arbiter = setupChainRuleTestGraph();
|
||||
|
||||
arbiter.setRelationConfig('max_project_budget', {
|
||||
type: 'chain',
|
||||
steps: [
|
||||
{ relation: 'member_of', direction: 'out' },
|
||||
{ relation: 'manages', direction: 'out' },
|
||||
{ relation: 'has_budget', direction: 'out' }
|
||||
],
|
||||
extractValues: true,
|
||||
extractFrom: 2,
|
||||
extractRelation: 'has_budget',
|
||||
valueAggregation: 'max' // Use maximum budget
|
||||
});
|
||||
|
||||
// Alice should have access to budgets
|
||||
const result = arbiter.check('user:alice', 'max_project_budget', 'budget:tech-2024');
|
||||
assert.equal(result.possibility, 1);
|
||||
|
||||
// Values are internal only, not exposed in authorization results
|
||||
assert.equal(result.value, undefined);
|
||||
});
|
||||
|
||||
it('aggregates values using min aggregation', () => {
|
||||
const arbiter = setupChainRuleTestGraph();
|
||||
|
||||
arbiter.setRelationConfig('min_project_cost', {
|
||||
type: 'chain',
|
||||
steps: [
|
||||
{ relation: 'member_of', direction: 'out' },
|
||||
{ relation: 'manages', direction: 'out' },
|
||||
{ relation: 'has_cost', direction: 'out' }
|
||||
],
|
||||
extractValues: true,
|
||||
extractFrom: 2,
|
||||
extractRelation: 'has_cost',
|
||||
valueAggregation: 'min' // Use minimum cost
|
||||
});
|
||||
|
||||
// Alice should have access to cost information
|
||||
const result = arbiter.check('user:alice', 'min_project_cost', 'budget:tech-2024');
|
||||
assert.equal(result.possibility, 1);
|
||||
|
||||
// Values are internal only, not exposed in authorization results
|
||||
assert.equal(result.value, undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user