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,352 @@
|
||||
import { DSLCompiler } from '../DSLCompiler.js';
|
||||
import { Arbiter } from '../../core/Arbiter.js';
|
||||
|
||||
/**
|
||||
* Progressive Test Suite - Tests each language feature incrementally
|
||||
*/
|
||||
export function runProgressiveTestSuite() {
|
||||
console.log('=== Progressive DSL Test Suite ===\n');
|
||||
|
||||
const arbiter = new Arbiter();
|
||||
const compiler = new DSLCompiler(arbiter);
|
||||
|
||||
const tests = [
|
||||
{
|
||||
name: '1. Basic Definitions',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
age: number
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '2. Definitions with Arrays',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
roles: string[]
|
||||
permissions: Permission[]
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '3. Definitions with Behaviors',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
lastActive: timestamp BEHAVES {
|
||||
decaying down hourly
|
||||
}
|
||||
score: number BEHAVES {
|
||||
blurring adaptive confidence_95
|
||||
}
|
||||
session: string BEHAVES {
|
||||
ttl 24h
|
||||
}
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '4. Definitions with Cache Directives',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
lastActive: timestamp BEHAVES {
|
||||
decaying down hourly
|
||||
} CACHE lazy
|
||||
score: number BEHAVES {
|
||||
blurring adaptive confidence_95
|
||||
} CACHE eager
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '5. Basic Facts',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact hasRole(user: User, role: string)
|
||||
fact isActive(user: User)`,
|
||||
expected: { definitions: 1, facts: 2, evidence: 0, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '6. Facts with Properties',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact hasRole(user: User, role: string) CACHE eager
|
||||
fact isMember(user: User, group: Group) transitive CACHE lazy
|
||||
fact isFriend(user: User, friend: User) symmetrical`,
|
||||
expected: { definitions: 1, facts: 3, evidence: 0, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '7. Facts with Limits',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact isMember(user: User, group: Group) transitive limit 10
|
||||
fact isFriend(user: User, friend: User) symmetrical limit 100`,
|
||||
expected: { definitions: 1, facts: 2, evidence: 0, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '8. Simple Evidence',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact hasRole(user: User, role: string)
|
||||
|
||||
evidence canRead(user: User, doc: Document) {
|
||||
hasRole(user, 'admin')
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '9. Evidence with Multiple Statements',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact hasRole(user: User, role: string)
|
||||
fact owns(user: User, doc: Document)
|
||||
|
||||
evidence canRead(user: User, doc: Document) {
|
||||
owns(user, doc)
|
||||
hasRole(user, 'admin')
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 2, evidence: 1, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '10. Evidence with ALWAYS',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact isActive(user: User)
|
||||
|
||||
evidence canRead(user: User, doc: Document) {
|
||||
ALWAYS isActive(user)
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '11. Evidence with REQUIRES',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact hasClearance(user: User, level: string)
|
||||
|
||||
evidence canRead(user: User, doc: Document) {
|
||||
REQUIRES hasClearance(user, doc.level)
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '12. Evidence with WHEN',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact hasRole(user: User, role: string)
|
||||
|
||||
evidence canRead(user: User, doc: Document) {
|
||||
WHEN hasRole(user, 'admin')
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '13. Evidence with WHEN UNLESS',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact hasRole(user: User, role: string)
|
||||
fact isSuspended(user: User)
|
||||
|
||||
evidence canRead(user: User, doc: Document) {
|
||||
WHEN hasRole(user, 'admin') UNLESS isSuspended(user)
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 2, evidence: 1, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '14. Evidence with Pattern Matching',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact isMember(user: User, group: Group)
|
||||
|
||||
evidence canRead(user: User, doc: Document) {
|
||||
isMember(user, *group) {
|
||||
canRead(group, doc)
|
||||
}
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '15. Evidence with Pattern Matching and Limits',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact isMember(user: User, group: Group)
|
||||
|
||||
evidence canRead(user: User, doc: Document) {
|
||||
isMember(user, *group) {
|
||||
canRead(group, doc)
|
||||
} limit 5
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '16. Evidence with Fusion',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
}
|
||||
|
||||
fact hasRole(user: User, role: string)
|
||||
fact isMember(user: User, group: Group)
|
||||
|
||||
evidence canRead(user: User, doc: Document) {
|
||||
fusion max {
|
||||
hasRole(user, 'admin')
|
||||
isMember(user, *group) {
|
||||
canRead(group, doc)
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expected: { definitions: 1, facts: 2, evidence: 1, measures: 0 }
|
||||
},
|
||||
{
|
||||
name: '17. Basic Measures',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
role: string
|
||||
}
|
||||
|
||||
measure userRole(user: User) {
|
||||
user.role
|
||||
} PROVIDES string`,
|
||||
expected: { definitions: 1, facts: 0, evidence: 0, measures: 1 }
|
||||
},
|
||||
{
|
||||
name: '18. Measures with Fusion',
|
||||
dsl: `
|
||||
definition User {
|
||||
name: string
|
||||
role: string
|
||||
}
|
||||
|
||||
fact hasRole(user: User, role: string)
|
||||
|
||||
measure userPermissions(user: User) {
|
||||
fusion max {
|
||||
user.role.permissions
|
||||
hasRole(user, 'admin')
|
||||
}
|
||||
} PROVIDES Permission[]`,
|
||||
expected: { definitions: 1, facts: 1, evidence: 0, measures: 1 }
|
||||
},
|
||||
{
|
||||
name: '19. Complete Example',
|
||||
dsl: `
|
||||
definition User {
|
||||
role: string
|
||||
isActive: boolean
|
||||
lastActive: timestamp BEHAVES {
|
||||
decaying down hourly
|
||||
} CACHE lazy
|
||||
}
|
||||
|
||||
definition Document {
|
||||
level: string
|
||||
owner: User
|
||||
}
|
||||
|
||||
fact hasRole(user: User, role: string) CACHE eager
|
||||
fact owns(user: User, doc: Document) CACHE eager
|
||||
|
||||
evidence canRead(user: User, doc: Document) {
|
||||
owns(user, doc)
|
||||
|
||||
WHEN hasRole(user, 'admin') UNLESS isSuspended(user)
|
||||
}
|
||||
|
||||
measure userRole(user: User) {
|
||||
user.role
|
||||
} PROVIDES string`,
|
||||
expected: { definitions: 2, facts: 2, evidence: 1, measures: 1 }
|
||||
}
|
||||
];
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
for (const test of tests) {
|
||||
console.log(`\n--- ${test.name} ---`);
|
||||
|
||||
try {
|
||||
const result = compiler.compile(test.dsl, `test-${passed + failed + 1}`);
|
||||
|
||||
const actual = {
|
||||
definitions: result.program.definitions.length,
|
||||
facts: result.program.facts.length,
|
||||
evidence: result.program.evidence.length,
|
||||
measures: result.program.measures.length
|
||||
};
|
||||
|
||||
const success = result.success &&
|
||||
actual.definitions === test.expected.definitions &&
|
||||
actual.facts === test.expected.facts &&
|
||||
actual.evidence === test.expected.evidence &&
|
||||
actual.measures === test.expected.measures;
|
||||
|
||||
if (success) {
|
||||
console.log('✅ PASSED');
|
||||
console.log(` Definitions: ${actual.definitions}, Facts: ${actual.facts}, Evidence: ${actual.evidence}, Measures: ${actual.measures}`);
|
||||
passed++;
|
||||
} else {
|
||||
console.log('❌ FAILED');
|
||||
console.log(` Expected: ${JSON.stringify(test.expected)}`);
|
||||
console.log(` Actual: ${JSON.stringify(actual)}`);
|
||||
if (result.errors.length > 0) {
|
||||
console.log(` Errors: ${result.errors.join(', ')}`);
|
||||
}
|
||||
failed++;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('❌ FAILED');
|
||||
console.log(` Error: ${error.message}`);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n=== Test Suite Results ===`);
|
||||
console.log(`Total Tests: ${passed + failed}`);
|
||||
console.log(`Passed: ${passed}`);
|
||||
console.log(`Failed: ${failed}`);
|
||||
console.log(`Success Rate: ${((passed / (passed + failed)) * 100).toFixed(1)}%`);
|
||||
|
||||
return { passed, failed, total: passed + failed };
|
||||
}
|
||||
|
||||
// Run the test suite
|
||||
runProgressiveTestSuite();
|
||||
Reference in New Issue
Block a user