# Authorization Rules API Specification

This document defines the standardized API that all authorization rules must implement to ensure consistency, performance, and maintainability across the zanzibar-graph system.

## Overview

All authorization rules must extend the `BaseRule` class and implement the required abstract methods. This ensures:

- **Consistent Interface**: All rules have the same public API
- **Performance Tracking**: Built-in performance monitoring
- **Error Handling**: Standardized error responses
- **Batch Processing**: Optional but encouraged for performance
- **Early Exit**: Threshold-based optimization support
- **Input Validation**: Automatic parameter validation

## Core Interface

### Constructor

```javascript
constructor(arbiter)
```

**Parameters:**
- `arbiter` (Arbiter): The main Arbiter instance

**Requirements:**
- Must call `super(arbiter)` first
- Should initialize any rule-specific state
- Must not throw exceptions

### Primary Evaluation Method

```javascript
evaluate(userId, userKey, objectId, objectKey, rule, visited, currentRelation, options = {})
```

**Parameters:**
- `userId` (number): Internal user node ID
- `userKey` (string): User key (e.g., "user:alice")
- `objectId` (number): Internal object node ID  
- `objectKey` (string): Object key (e.g., "doc:secret")
- `rule` (Object): Rule configuration object
- `visited` (Set): Set of visited nodes for cycle detection
- `currentRelation` (string): Current relation being evaluated
- `options` (Object): Evaluation options

**Returns:** `RuleEvaluationResult` object

**Standard Options:**
```javascript
{
  // Performance options
  fastPath: false,                    // Enable early termination
  minAllowPossibility: null,          // Threshold for allow early exit (0-1)
  maxDenyPossibility: null,           // Threshold for deny early exit (0-1)
  
  // Inference options
  noInfer: false,                     // Disable inference
  allowInference: true,               // Allow inference (opposite of noInfer)
  
  // Binary mode
  binary: false,                      // Return binary allow/deny decisions
  
  // Evaluation tracking
  trackEvaluation: true,              // Include evaluation metadata
  
  // Rule-specific options (passed through)
  // ... additional options specific to rule type
}
```

### Batch Evaluation Method (Optional)

```javascript
batchEvaluate(queries, batchOptions = {})
```

**Parameters:**
- `queries` (Array): Array of query objects with same structure as `evaluate` parameters
- `batchOptions` (Object): Batch-specific options

**Returns:** Array of `RuleEvaluationResult` objects

**Query Object Structure:**
```javascript
{
  userId: number,
  userKey: string,
  objectId: number,
  objectKey: string,
  rule: Object,
  visited: Set,
  currentRelation: string,
  options: Object
}
```

### Batch Support Check

```javascript
canBatchProcess()
```

**Returns:** `boolean` - Whether this rule supports efficient batch processing

## Standard Result Structure

All evaluation methods must return a `RuleEvaluationResult` object:

```javascript
{
  // Core evaluation results (required)
  possibility_allow: number,          // 0-1, possibility of allowing access
  possibility_deny: number,           // 0-1, possibility of denying access
  reliability: number,                // 0-1, reliability of the evaluation
  
  // Metadata (required, can be null)
  meta_allow: Object | null,          // Metadata for allow decision
  meta_deny: Object | null,           // Metadata for deny decision
  
  // Optional fields
  reason: string,                     // Reason for the result
  error: boolean,                     // Whether this is an error result
  details: Object,                    // Additional details
  evaluation: Object                  // Evaluation tracking data
}
```

### Standard Metadata Structure

```javascript
// meta_allow / meta_deny structure
{
  ruleType: string,                   // Type of rule (e.g., 'direct', 'tuple_to_userset')
  reason: string,                     // Reason for decision
  rule: Object,                       // Original rule configuration
  
  // Performance metadata
  earlyExit: boolean,                 // Whether early exit was used
  earlyExitReason: string,            // Reason for early exit
  
  // Rule-specific metadata
  // ... additional fields specific to rule type
}
```

## Implementation Requirements

### Abstract Methods (Must Implement)

```javascript
// Core evaluation logic
_evaluateRule(userId, userKey, objectId, objectKey, rule, visited, currentRelation, options)

// Batch evaluation logic (optional, only if canBatchProcess() returns true)
_batchEvaluateRule(queries, batchOptions)
```

### Performance Tracking

All rules automatically track:
- Individual evaluation count and timing
- Batch evaluation count and timing
- Average evaluation times

Access via:
```javascript
rule.getPerformanceStats()
rule.resetPerformanceStats()
```

### Error Handling

Rules should handle errors gracefully:
- Input validation is automatic
- Exceptions are caught and converted to error results
- Batch operations fall back to individual evaluations on error

## Rule-Specific Configurations

### Common Rule Properties

```javascript
{
  type: string,                       // Rule type identifier
  ruleType: string,                   // 'defeasible', 'defeater', 'strict'
  priority: number,                   // Rule priority (higher = more important)
  weight: number,                     // Rule weight for aggregation
  
  // Performance options
  no_infer: boolean,                  // Disable inference for this rule
  allowInference: boolean,            // Allow inference
  
  // Aggregation options
  owaWeights: Array<number>,          // OWA aggregation weights
  aggregator: string,                 // Aggregation method ('max', 'min', 'avg', etc.)
  
  // Rule-specific properties
  // ... varies by rule type
}
```

### DirectRule Configuration

```javascript
{
  type: 'direct',
  relation: string,                   // Relation to check (optional, uses currentRelation)
  reverse: boolean                    // Check in reverse direction
}
```

### TupleToUsersetRule Configuration

```javascript
{
  type: 'tuple_to_userset',
  tuplesetRelation: string,           // Relation from object to intermediate
  computedRelation: string,           // Relation from user to intermediate
  reverse: boolean                    // Check in reverse direction
}
```

### ParentRule Configuration

```javascript
{
  type: 'parent',
  parentRelation: string,             // Relation defining parent-child
  relation: string,                   // Relation to check on parent
  reverse: boolean                    // Check in reverse direction
}
```

### SimilarityRule Configuration

```javascript
{
  type: 'similar_to',
  relation: string,                   // Relation to find similarities for
  k: number,                          // Number of similar entities to consider
  similarityThreshold: number,        // Minimum similarity threshold (0-1)
  reverse: boolean,                   // Check in reverse direction
  fallbackToBasicSimilarity: boolean  // Use basic similarity when embeddings unavailable
}
```

### MultiHopRule Configuration

```javascript
{
  type: 'multi_hop',
  relation: string,                   // Relation to traverse
  maxDepth: number,                   // Maximum path depth
  minReliability: number,             // Minimum path reliability
  decayFactor: number,                // Reliability decay per hop
  pathAggregation: string,            // How to aggregate multiple paths ('max', 'sum', 'owa')
  reverse: boolean,                   // Search in reverse direction
  allowInference: boolean,            // Allow inference for missing edges
  fallbackToBasicPaths: boolean       // Use basic path finding as fallback
}
```

### ComputedRule Configuration

```javascript
{
  type: 'computed',
  relation: string                    // Relation to recursively evaluate
}
```

## Logical Operators

### Union (OR) Configuration

```javascript
{
  union: Array<RuleConfig>,           // Array of rules to OR together
  aggregator: string,                 // Aggregation method
  owaWeights: Array<number>,          // OWA weights for fusion
  reliabilityWeighting: boolean       // Weight by reliability
}
```

### Intersection (AND) Configuration

```javascript
{
  intersection: Array<RuleConfig>,    // Array of rules to AND together
  aggregator: string,                 // Aggregation method (defaults to 'min')
  owaWeights: Array<number>           // OWA weights for fusion
}
```

### Exclusion (A AND NOT B) Configuration

```javascript
{
  exclusion: [RuleConfig, RuleConfig] // [base rule, exclusion rule]
}
```

## Performance Optimization Guidelines

### Early Exit Support

Rules should support early termination when:
- `options.fastPath` is true
- `options.minAllowPossibility` threshold is met
- `options.maxDenyPossibility` threshold is met

### Batch Processing

Rules that can benefit from batch processing should:
- Override `canBatchProcess()` to return `true`
- Implement `_batchEvaluateRule()` method
- Group similar operations for efficiency
- Use indexed lookups instead of linear scans

### Caching

Rules should leverage:
- Arbiter's built-in caching mechanisms
- Batch caches for intermediate results
- Embedding caches for similarity calculations

## Testing Requirements

All rules must include:
- Unit tests for individual evaluation
- Batch evaluation tests (if supported)
- Performance benchmarks
- Error handling tests
- Edge case coverage

## Migration Guide

To migrate existing rules to the new API:

1. **Extend BaseRule**: Change `export class MyRule` to `export class MyRule extends BaseRule`
2. **Rename evaluate**: Rename `evaluate()` to `_evaluateRule()`
3. **Update constructor**: Call `super(arbiter)` first
4. **Handle options**: Use normalized options parameter
5. **Update tests**: Test against new interface

## Example Implementation

```javascript
import { BaseRule } from './BaseRule.js';

export class ExampleRule extends BaseRule {
  constructor(arbiter) {
    super(arbiter);
    // Rule-specific initialization
  }

  canBatchProcess() {
    return true; // This rule supports batching
  }

  _evaluateRule(userId, userKey, objectId, objectKey, rule, visited, currentRelation, options) {
    // Implement rule-specific logic
    const result = {
      possibility_allow: 0.8,
      possibility_deny: 0.1,
      reliability: 0.9,
      meta_allow: {
        ruleType: 'example',
        reason: 'example_evaluation',
        rule
      },
      meta_deny: null,
      reason: 'example_result'
    };

    return result;
  }

  _batchEvaluateRule(queries, batchOptions) {
    // Implement efficient batch processing
    return queries.map(query => 
      this._evaluateRule(
        query.userId, 
        query.userKey, 
        query.objectId, 
        query.objectKey, 
        query.rule, 
        query.visited, 
        query.currentRelation, 
        query.options
      )
    );
  }
}
```

This standardized API ensures all rules work consistently while allowing for rule-specific optimizations and features. 