Dead code with zero callers (deprecation notes promised removal): - RelationCSR index: always-off option (useRelationCsrIndex), never enabled in production, wired through RelationManager/RelationUpdates/ RelationLookup. Removed the module and all wiring. - getAggregatedBlurredValue (RelationManager) and aggregateBlurredValues (ValueManager): @deprecated shims, zero callers. - QualitativeRelationalComparatorRule._aggregateBlurredValues: @deprecated shim, zero callers. Kept compareRelationValues: non-deprecated public API, coherent and clock-threaded, just currently callerless. Stale scaffolding shipping in the published artifact (files: src/): - src/ast/tests/* and src/ast/examples/*: orphaned duplicates of tests/ast/, zero references anywhere, 11 files in the tarball. Removed; the live copies live in tests/ast/. Internal docs moved out of the shipped surface (1266 lines) to docs/internal/: VALUE_OPTIMIZATION_SUMMARY, rules API_SPECIFICATION, ast README, qualitative README — repo-kept, not packaged. Tarball .md count: 11 -> 1. Rigor 251/251, full suite 853/791/0.
8.1 KiB
AST Module - DSL Compiler for Zanzibar-Graph
This module provides a complete Abstract Syntax Tree (AST) system for parsing and compiling the Evidence DSL into rule configurations that interface with the zanzibar-graph authorization system.
Overview
The AST module consists of three main components:
- Parser - Converts DSL text into AST nodes
- Generator - Converts AST nodes into rule configurations
- Compiler - Orchestrates the parsing and generation process
Architecture
DSL Text → Parser → AST Nodes → Generator → Rule Configs → setRelationConfig()
Features
- Complete DSL Support - Supports all DSL constructs from the specification
- Modular Design - Clean separation of concerns with pluggable components
- Error Handling - Comprehensive error reporting and validation
- Program Management - Support for multiple compiled programs
- Rule Generation - Automatic conversion to existing rule system
- Extensible - Easy to add new node types and generators
Quick Start
import { DSLCompiler } from './src/ast/index.js';
// Create compiler with arbiter instance
const compiler = new DSLCompiler(arbiter);
// Compile DSL text
const result = compiler.compile(dslText, 'my-program');
if (result.success) {
console.log(`Generated ${result.generatedCount} rules`);
} else {
console.error('Compilation errors:', result.errors);
}
Core Components
1. AST Nodes (/nodes/)
The AST nodes represent the parsed structure of the DSL:
- BaseNode - Base class for all AST nodes
- ProgramNode - Root node containing all definitions
- DefinitionNode - Type definitions with fields and behaviors
- FactNode - Fact definitions with parameters and properties
- EvidenceNode - Evidence definitions with bodies
- MeasureNode - Measure definitions for value collection
- ExpressionNode - Expressions, variables, and literals
- And many more...
2. Parser (/parser/)
The DSL parser converts text into AST nodes:
import { DSLParser } from './parser/DSLParser.js';
const parser = new DSLParser();
const program = parser.parse(dslText);
3. Generator (/generator/)
The rule generator converts AST nodes into rule configurations:
import { RuleGenerator } from './generator/RuleGenerator.js';
const generator = new RuleGenerator(arbiter);
const result = generator.generateRules(program);
4. Compiler (DSLCompiler.js)
The main compiler orchestrates the entire process:
import { DSLCompiler } from './DSLCompiler.js';
const compiler = new DSLCompiler(arbiter);
const result = compiler.compile(dslText, 'program-name');
Usage Examples
Basic Compilation
const dsl = `
definition User {
role: string
isActive: boolean
}
fact hasRole(user: User, role: string) CACHE eager
evidence canRead(user: User, doc: Document) {
hasRole(user, 'admin')
}
`;
const result = compiler.compile(dsl, 'auth');
Complex DSL with Defeasible Logic
const complexDSL = `
evidence canAccessCritical(user: User, resource: Resource) {
// Strict requirement
ALWAYS user.isActive
// Defeasible access
WHEN hasRole(user, 'admin') UNLESS isSuspended(user)
// Requirements
REQUIRES hasClearance(user, resource.level)
// Fusion evidence
fusion majority {
user.isTrusted
user.hasRecentActivity
}
}
`;
const result = compiler.compile(complexDSL, 'critical-access');
Multiple Programs
const programs = {
'auth': `
fact hasRole(user: User, role: string)
evidence canRead(user: User, doc: Document) {
hasRole(user, 'admin')
}
`,
'finance': `
fact hasBalance(user: User, amount: number)
evidence canWithdraw(user: User, amount: number) {
hasBalance(user, amount)
}
`
};
const result = compiler.compileMultiple(programs);
API Reference
DSLCompiler
Methods
compile(dslText, programName)- Compile DSL text into rulescompileMultiple(programs)- Compile multiple programsvalidate(dslText)- Validate DSL without compilationgetCompiledProgram(name)- Get compiled program by namegetAllCompiledPrograms()- Get all compiled programsremoveCompiledProgram(name)- Remove compiled programclearCompiledPrograms()- Clear all programsgetCompilationStats()- Get compilation statistics
Properties
arbiter- The arbiter instanceparser- The DSL parsergenerator- The rule generator
DSLParser
Methods
parse(dslText)- Parse DSL text into ASTgetErrors()- Get parser errors
RuleGenerator
Methods
generateRules(program)- Generate rules from ASTgetErrors()- Get generator errorsgetGeneratedRules()- Get generated rules
Supported DSL Constructs
Type Definitions
definition User {
role: string
isActive: boolean
lastActive: timestamp BEHAVES {
decaying down hourly
} CACHE lazy
}
Facts
fact hasRole(user: User, role: string) CACHE eager
fact isMember(user: User, group: Group) transitive CACHE lazy
Evidence
evidence canRead(user: User, doc: Document) {
// Direct evidence
owns(user, doc)
// Pattern matching
isMember(user, *group) {
canRead(group, doc)
} limit 5
// Defeasible logic
WHEN hasRole(user, 'admin') UNLESS isSuspended(user)
}
Measures
measure userBalance(user: User) {
user.balance
} PROVIDES number
measure userPermissions(user: User) {
fusion max {
user.role.permissions
user.group.permissions
}
} PROVIDES Permission[]
Error Handling
The compiler provides comprehensive error handling:
const result = compiler.compile(dslText);
if (!result.success) {
console.error('Compilation failed:');
result.errors.forEach(error => console.error(` - ${error}`));
}
if (result.warnings.length > 0) {
console.warn('Warnings:');
result.warnings.forEach(warning => console.warn(` - ${warning}`));
}
Testing
Run the test suite:
import { runDSLCompilerTests } from './tests/DSLCompiler.test.js';
const testResults = runDSLCompilerTests(arbiter);
console.log('Test Results:', testResults);
Examples
See the examples directory for comprehensive usage examples:
examples/DSLExample.js- Complete usage examplestests/DSLCompiler.test.js- Test suite
Integration with Existing System
The AST module integrates seamlessly with the existing zanzibar-graph system:
- Parser converts DSL text to AST nodes
- Generator converts AST nodes to rule configurations
- Compiler applies rules via
arbiter.setRelationConfig()
The generated rules are compatible with all existing rule types:
- Direct rules
- Computed rules
- Parent rules
- Tuple-to-userset rules
- Similarity rules
- Multi-hop rules
- Logical operators
- Defeasible logic
Extensibility
The AST system is designed to be extensible:
- Add new node types by extending
BaseNode - Add new parsers by extending
DSLParser - Add new generators by extending
RuleGenerator - Add new compilers by extending
DSLCompiler
Performance Considerations
- Lazy evaluation - AST nodes are created on demand
- Efficient parsing - Token-based parsing with minimal memory usage
- Rule caching - Generated rules are cached for reuse
- Batch processing - Support for compiling multiple programs at once
Future Enhancements
- Incremental compilation - Only recompile changed parts
- Parallel processing - Compile multiple programs in parallel
- Advanced optimizations - Rule optimization and simplification
- IDE support - Language server protocol support
- Visualization - AST visualization tools
Contributing
When contributing to the AST module:
- Follow the existing code structure
- Add comprehensive tests for new features
- Update documentation
- Ensure backward compatibility
- Follow the established patterns
License
This module is part of the zanzibar-graph project and follows the same license terms.