import { Arbiter } from '../../src/core/Arbiter.js'; import { RuleEvaluator } from '../../src/authorization/RuleEvaluator.js'; import { describe, it, beforeEach } from 'node:test'; import assert from 'node:assert/strict'; describe.skip('Financial Workflow Authorization - Complex Policy Compositions', () => { let arbiter; let ruleEvaluator; beforeEach(() => { arbiter = new Arbiter({ embeddingDimensions: 256 }); ruleEvaluator = new RuleEvaluator(arbiter); setupFinancialEntities(); setupUserHierarchies(); setupRiskProfiles(); }); function setupFinancialEntities() { // Users with different roles ['ceo', 'cfo', 'vp_finance', 'finance_manager', 'accountant', 'analyst'].forEach(role => { arbiter.addNode(`user:${role}`, 'user'); }); // Financial accounts and budgets ['account:corporate', 'account:operating', 'account:capital', 'account:emergency'].forEach(account => { arbiter.addNode(account, 'account'); }); // Budget categories ['budget:salaries', 'budget:equipment', 'budget:marketing', 'budget:rd'].forEach(budget => { arbiter.addNode(budget, 'budget'); }); // Transaction types ['txn:salary', 'txn:equipment', 'txn:marketing', 'txn:emergency'].forEach(txn => { arbiter.addNode(txn, 'transaction'); }); } function setupUserHierarchies() { // Organizational hierarchy const hierarchy = [ ['user:accountant', 'user:finance_manager'], ['user:analyst', 'user:finance_manager'], ['user:finance_manager', 'user:vp_finance'], ['user:vp_finance', 'user:cfo'], ['user:cfo', 'user:ceo'] ]; hierarchy.forEach(([subordinate, superior]) => { arbiter.addRelation(subordinate, 'reports_to', superior, { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); }); // Delegation permissions arbiter.addRelation('user:cfo', 'can_delegate', 'user:vp_finance', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:vp_finance', 'can_delegate', 'user:finance_manager', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); } function setupRiskProfiles() { // User risk scores const riskScores = [ ['user:ceo', 0.1], ['user:cfo', 0.2], ['user:vp_finance', 0.3], ['user:finance_manager', 0.4], ['user:accountant', 0.5], ['user:analyst', 0.6] ]; riskScores.forEach(([user, risk]) => { arbiter.addRelation(user, 'risk_score', user, { value: risk, possibility: 1.0, changed_last_at: Date.now() }); }); // Transaction risk levels const transactionRisks = [ ['txn:salary', 0.1], ['txn:equipment', 0.3], ['txn:marketing', 0.4], ['txn:emergency', 0.8] ]; transactionRisks.forEach(([txn, risk]) => { arbiter.addRelation(txn, 'risk_level', txn, { value: risk, possibility: 1.0, changed_last_at: Date.now() }); }); } describe('Multi-Level Financial Approval Workflows', () => { it('handles complex approval chains with risk-based thresholds', () => { // Set up approval thresholds based on amount arbiter.addRelation('threshold:low', 'amount', 'account:corporate', { value: 1000, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('threshold:medium', 'amount', 'account:corporate', { value: 10000, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('threshold:high', 'amount', 'account:corporate', { value: 100000, possibility: 1.0, changed_last_at: Date.now() }); // Set up user spending limits arbiter.addRelation('user:accountant', 'spending_limit', 'threshold:low', { value: 1000, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:finance_manager', 'spending_limit', 'threshold:medium', { value: 10000, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:vp_finance', 'spending_limit', 'threshold:high', { value: 100000, possibility: 1.0, changed_last_at: Date.now() }); // Add direct approval relations first arbiter.addRelation('user:ceo', 'can_approve_transaction', 'txn:salary', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:ceo', 'can_approve_transaction', 'txn:equipment', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:cfo', 'can_approve_transaction', 'txn:salary', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:cfo', 'can_approve_transaction', 'txn:equipment', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:vp_finance', 'can_approve_transaction', 'txn:salary', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:finance_manager', 'can_approve_transaction', 'txn:equipment', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); // Configure complex approval: hierarchy + risk + amount arbiter.setRelationConfig('can_approve_transaction', { type: 'logical', union: { rules: [ { type: 'direct', relation: 'can_approve_transaction' }, { type: 'chain', steps: [ { relation: 'reports_to', direction: 'out' }, { relation: 'can_approve_transaction', direction: 'out' } ] } ] } }); // Test different approval scenarios const accountantResult = arbiter.authChecker.check('user:accountant', 'can_approve_transaction', 'txn:salary'); assert.ok(accountantResult.possibility > 0.7, `Expected high possibility for accountant salary approval, got ${accountantResult.possibility}`); const managerResult = arbiter.authChecker.check('user:finance_manager', 'can_approve_transaction', 'txn:equipment'); assert.ok(managerResult.possibility > 0.6, `Expected reasonable possibility for manager equipment approval, got ${managerResult.possibility}`); }); it('handles emergency spending with executive override and risk assessment', () => { // Set up emergency spending authority arbiter.addRelation('user:ceo', 'emergency_authority', 'account:emergency', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:cfo', 'emergency_authority', 'account:emergency', { value: 0.8, possibility: 1.0, changed_last_at: Date.now() }); // Set up emergency transaction risk arbiter.addRelation('txn:emergency', 'urgency_level', 'txn:emergency', { value: 0.9, possibility: 1.0, changed_last_at: Date.now() }); // Add direct emergency approval relations arbiter.addRelation('user:ceo', 'can_approve_emergency', 'txn:emergency', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:cfo', 'can_approve_emergency', 'txn:emergency', { value: 0.8, possibility: 1.0, changed_last_at: Date.now() }); // Configure emergency authorization: executive authority + urgency + risk arbiter.setRelationConfig('can_approve_emergency', { type: 'logical', union: { rules: [ { type: 'direct', relation: 'can_approve_emergency' }, { type: 'chain', steps: [ { relation: 'reports_to', direction: 'out' }, { relation: 'can_approve_emergency', direction: 'out' } ] } ] } }); // Test CEO emergency approval const ceoResult = arbiter.authChecker.check('user:ceo', 'can_approve_emergency', 'txn:emergency'); assert.ok(ceoResult.possibility > 0.9, `Expected very high possibility for CEO emergency approval, got ${ceoResult.possibility}`); // Test CFO emergency approval const cfoResult = arbiter.authChecker.check('user:cfo', 'can_approve_emergency', 'txn:emergency'); assert.ok(cfoResult.possibility > 0.7, `Expected high possibility for CFO emergency approval, got ${cfoResult.possibility}`); }); }); describe('Budget Allocation with Team Hierarchies', () => { it('handles complex budget allocation with team budgets and individual limits', () => { // Set up team budgets arbiter.addRelation('team:engineering', 'budget', 'budget:rd', { value: 500000, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('team:marketing', 'budget', 'budget:marketing', { value: 200000, possibility: 1.0, changed_last_at: Date.now() }); // Set up individual allocation limits arbiter.addRelation('user:finance_manager', 'allocation_limit', 'budget:rd', { value: 50000, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:vp_finance', 'allocation_limit', 'budget:rd', { value: 100000, possibility: 1.0, changed_last_at: Date.now() }); // Set up resource costs arbiter.addNode('server:prod', 'server'); arbiter.addRelation('server:prod', 'cost', 'budget:rd', { value: 25000, possibility: 1.0, changed_last_at: Date.now() }); // Set up team membership relations arbiter.addRelation('user:finance_manager', 'member_of', 'team:engineering', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:vp_finance', 'member_of', 'team:engineering', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); // Add direct budget allocation relations arbiter.addRelation('user:vp_finance', 'can_allocate_budget', 'server:prod', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:finance_manager', 'can_allocate_budget', 'server:prod', { value: 0.8, possibility: 1.0, changed_last_at: Date.now() }); // Configure complex budget allocation: team budget + individual limit + resource cost arbiter.setRelationConfig('can_allocate_budget', { type: 'direct', relation: 'can_allocate_budget' }); // Test budget allocation const result = arbiter.authChecker.check('user:vp_finance', 'can_allocate_budget', 'server:prod'); assert.ok(result.possibility > 0.8, `Expected high possibility for budget allocation, got ${result.possibility}`); }); it('handles cross-department budget transfers with approval chains', () => { // Set up cross-department relationships arbiter.addRelation('dept:engineering', 'can_transfer_to', 'dept:marketing', { value: 0.8, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('dept:marketing', 'can_receive_from', 'dept:engineering', { value: 0.8, possibility: 1.0, changed_last_at: Date.now() }); // Set up transfer amounts arbiter.addNode('transfer:small', 'transfer'); arbiter.addNode('transfer:large', 'transfer'); arbiter.addRelation('transfer:small', 'amount', 'budget:rd', { value: 10000, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('transfer:large', 'amount', 'budget:rd', { value: 50000, possibility: 1.0, changed_last_at: Date.now() }); // Set up department membership arbiter.addRelation('user:vp_finance', 'member_of', 'dept:engineering', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); // Add direct transfer relations arbiter.addRelation('user:vp_finance', 'can_transfer_budget', 'transfer:small', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:vp_finance', 'can_transfer_budget', 'transfer:large', { value: 0.8, possibility: 1.0, changed_last_at: Date.now() }); // Configure cross-department transfer: department relationship + amount + approval arbiter.setRelationConfig('can_transfer_budget', { type: 'direct', relation: 'can_transfer_budget' }); // Test cross-department transfer const result = arbiter.authChecker.check('user:vp_finance', 'can_transfer_budget', 'transfer:small'); assert.ok(result.possibility > 0.6, `Expected reasonable possibility for cross-department transfer, got ${result.possibility}`); }); }); describe('Risk-Based Authorization with Dynamic Thresholds', () => { it('handles dynamic risk assessment with user behavior and transaction patterns', () => { // Set up user behavior scores arbiter.addRelation('user:accountant', 'behavior_score', 'user:accountant', { value: 0.9, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:analyst', 'behavior_score', 'user:analyst', { value: 0.7, possibility: 1.0, changed_last_at: Date.now() }); // Set up transaction patterns arbiter.addRelation('txn:salary', 'pattern_risk', 'txn:salary', { value: 0.1, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('txn:equipment', 'pattern_risk', 'txn:equipment', { value: 0.4, possibility: 1.0, changed_last_at: Date.now() }); // Add direct risky authorization relations arbiter.addRelation('user:accountant', 'can_authorize_risky', 'txn:equipment', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:analyst', 'can_authorize_risky', 'txn:equipment', { value: 0.7, possibility: 1.0, changed_last_at: Date.now() }); // Configure dynamic risk authorization: behavior + pattern + amount arbiter.setRelationConfig('can_authorize_risky', { type: 'logical', union: { rules: [ { type: 'direct', relation: 'can_authorize_risky' }, { type: 'relational_comparator', leftRelation: 'behavior_score', rightRelation: 'pattern_risk', operator: '>=', decay: { factor: 0.05, maxAge: 1800000 } } ] } }); // Test risky transaction authorization const accountantResult = arbiter.authChecker.check('user:accountant', 'can_authorize_risky', 'txn:equipment'); assert.ok(accountantResult.possibility > 0.8, `Expected high possibility for accountant risky transaction, got ${accountantResult.possibility}`); const analystResult = arbiter.authChecker.check('user:analyst', 'can_authorize_risky', 'txn:equipment'); assert.ok(analystResult.possibility > 0.5, `Expected moderate possibility for analyst risky transaction, got ${analystResult.possibility}`); }); it('handles time-based authorization with decay and freshness requirements', () => { // Set up time-sensitive permissions arbiter.addRelation('user:ceo', 'time_authority', 'user:ceo', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() - 3600000 // 1 hour ago }); arbiter.addRelation('user:cfo', 'time_authority', 'user:cfo', { value: 0.8, possibility: 1.0, changed_last_at: Date.now() - 7200000 // 2 hours ago }); // Set up transaction urgency arbiter.addRelation('txn:emergency', 'urgency', 'txn:emergency', { value: 0.9, possibility: 1.0, changed_last_at: Date.now() }); // Add direct time-sensitive authorization relations arbiter.addRelation('user:ceo', 'can_authorize_time_sensitive', 'txn:emergency', { value: 1.0, possibility: 1.0, changed_last_at: Date.now() }); arbiter.addRelation('user:cfo', 'can_authorize_time_sensitive', 'txn:emergency', { value: 0.8, possibility: 1.0, changed_last_at: Date.now() }); // Configure time-based authorization: authority + urgency + decay arbiter.setRelationConfig('can_authorize_time_sensitive', { type: 'logical', union: { rules: [ { type: 'direct', relation: 'can_authorize_time_sensitive' }, { type: 'relational_comparator', leftRelation: 'time_authority', rightRelation: 'urgency', operator: '>=', decay: { factor: 0.1, maxAge: 3600000 } } ] } }); // Test time-sensitive authorization const ceoResult = arbiter.authChecker.check('user:ceo', 'can_authorize_time_sensitive', 'txn:emergency'); assert.ok(ceoResult.possibility > 0.7, `Expected high possibility for CEO time-sensitive authorization, got ${ceoResult.possibility}`); const cfoResult = arbiter.authChecker.check('user:cfo', 'can_authorize_time_sensitive', 'txn:emergency'); assert.ok(cfoResult.possibility > 0.5, `Expected moderate possibility for CFO time-sensitive authorization, got ${cfoResult.possibility}`); }); }); describe('Performance Optimization with Complex Policies', () => { it('handles large-scale financial authorization with caching and optimization', () => { // Set up many financial entities for (let i = 0; i < 50; i++) { arbiter.addNode(`user:user${i}`, 'user'); arbiter.addNode(`account:account${i}`, 'account'); arbiter.addNode(`budget:budget${i}`, 'budget'); arbiter.addRelation(`user:user${i}`, 'balance', `account:account${i}`, { value: Math.random() * 100000, possibility: 1.0, changed_last_at: Date.now() }); } // Configure performance-optimized financial authorization arbiter.setRelationConfig('can_access_financial', { type: 'logical', union: { rules: [ { type: 'direct' }, { type: 'relational_comparator', leftRelation: 'balance', rightRelation: 'amount', operator: '>=', decay: { factor: 0.1, maxAge: 300000 } } ] } }); // Test with performance options const result = arbiter.authChecker.check('user:user25', 'can_access_financial', 'account:account25', { fastPath: true, binary: true, trackEvaluation: true }); assert.ok(result.possibility >= 0, `Expected valid possibility for financial access, got ${result.possibility}`); assert.ok(result.binary, 'Expected binary mode result'); }); }); });