import assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import { Arbiter } from '../../src/core/Arbiter.js'; describe('Graph Structure and Queries', () => { test('basic node and relation creation', () => { const arbiter = new Arbiter(); arbiter.addNode('user:1', 'user'); arbiter.addNode('resource:1', 'resource'); const nodeId1 = arbiter.resolveNodeId('user:1'); const nodeId2 = arbiter.resolveNodeId('resource:1'); assert.ok(nodeId1 !== undefined, 'user node ID resolved'); assert.ok(nodeId2 !== undefined, 'resource node ID resolved'); assert.strictEqual(arbiter.resolveKey(nodeId1), 'user:1', 'reverse key lookup works'); }); test('direct relation authorization', () => { const arbiter = new Arbiter(); arbiter.addNode('user:1', 'user'); arbiter.addNode('resource:1', 'resource'); arbiter.setRelationConfig('owner', { type: 'direct' }); arbiter.addRelation('user:1', 'owner', 'resource:1', 1.0); const result = arbiter.check('user:1', 'owner', 'resource:1'); assert.strictEqual(result.possibility, 1.0, 'owner relation grants access'); assert.strictEqual(result.reason, 'direct_match', 'reason is direct_match'); }); test('absence of relation denies access', () => { const arbiter = new Arbiter(); arbiter.addNode('user:1', 'user'); arbiter.addNode('resource:1', 'resource'); arbiter.addNode('user:2', 'user'); arbiter.setRelationConfig('owner', { type: 'direct' }); arbiter.addRelation('user:1', 'owner', 'resource:1', 1.0); const result = arbiter.check('user:2', 'owner', 'resource:1'); assert.strictEqual(result.possibility, 0.0, 'non-owner denied'); assert.strictEqual(result.reason, 'no_relation', 'reason is no_relation'); }); test('node data storage and retrieval', () => { const arbiter = new Arbiter(); arbiter.addNode('user:1', 'user', { tier: 'premium', level: 5 }); const data = arbiter.getNodeData('user:1'); assert.strictEqual(data.tier, 'premium'); assert.strictEqual(data.level, 5); }); test('node data update', () => { const arbiter = new Arbiter(); arbiter.addNode('user:1', 'user', { tier: 'premium' }); arbiter.updateNodeData('user:1', { tier: 'enterprise', level: 10 }); const data = arbiter.getNodeData('user:1'); assert.strictEqual(data.tier, 'enterprise'); assert.strictEqual(data.level, 10); }); test('multiple relations between different node types', () => { const arbiter = new Arbiter(); arbiter.addNode('user:1', 'user'); arbiter.addNode('group:1', 'group'); arbiter.addNode('resource:1', 'resource'); arbiter.setRelationConfig('member', { type: 'direct' }); arbiter.setRelationConfig('can_view', { type: 'direct' }); arbiter.addRelation('user:1', 'member', 'group:1', 1.0); arbiter.addRelation('group:1', 'can_view', 'resource:1', 1.0); const memberResult = arbiter.check('user:1', 'member', 'group:1'); const viewResult = arbiter.check('group:1', 'can_view', 'resource:1'); assert.strictEqual(memberResult.possibility, 1.0); assert.strictEqual(viewResult.possibility, 1.0); }); });