Note: Cache busting commit - please ignore
This is a proof-of-concept demonstrating how to encode complex Belgian social/legal business logic into maintainable, executable code. The POC addresses the core challenge: converting legal text to common language and calculating benefit eligibility for the Plateforme d'Aide Administrative.
The platform aims to:
- Convert Belgian legal/administrative text to plain language
- Optimize social benefits for precarious populations
- Provide conversational assistance (WhatsApp bot)
- Calculate eligibility and benefit amounts
Key Challenge: Legal rules are complex, change frequently, and must be understandable by:
- Social workers
- Beneficiaries (often with limited literacy)
- Automated systems (optimization algorithms)
Interactive documentation for all workflows is available at:
https://vanmarkic.github.io/PAA/
Features:
- Browse 131+ Belgian administrative workflows
- Filter by category (e.g.,
/PAA/workflows?category=propriete-intellectuelle) - Interactive workflow visualization
- Search and comparison tools
After analyzing the requirements, we chose a hybrid architecture combining:
Why:
- ✅ Human-readable by non-technical stakeholders (legal experts, social workers)
- ✅ Living documentation that stays in sync with code
- ✅ Executable specifications that can be validated
- ✅ Testable - scenarios become automated tests
- ✅ Versioned - track rule changes over time
Example:
Scénario: Travailleur à temps partiel avec maintien des droits éligible
Étant donné que je suis un travailleur à temps partiel
Et que j'ai le maintien des droits
Et que mon salaire brut mensuel est de 1200€
Quand je vérifie mon éligibilité à l'AGR
Alors je devrais être éligible
Et le montant de l'allocation devrait être 360€Why:
- ✅ Visual representation of complex workflows
- ✅ Predictable state transitions (no hidden states)
- ✅ Built-in retry logic and error handling
- ✅ Auditable - track exactly where in the process something failed
- ✅ Type-safe with TypeScript
Example: Legal text conversion pipeline
idle → extractingStructure → identifyingConcepts → mappingVocabulary
→ generatingVersions → validating → completed
↓ (if validation fails)
regeneratingWithConstraints ⟲
Why:
- ✅ Declarative rules that can be stored in database
- ✅ Dynamic updates without code deployment
- ✅ Priority-based evaluation
- ✅ Composable conditions (AND, OR, NOT)
- ✅ Auditable - know exactly which rules fired
Why:
- ✅ Compile-time safety for critical calculations (money, dates)
- ✅ Self-documenting with strong types
- ✅ Refactoring confidence
- ✅ IDE support for developers
PAA/
├── features/ # Gherkin business rules (human-readable)
│ ├── benefits/
│ │ └── income-guarantee.feature # AGR eligibility rules
│ └── conversion/
│ └── legal-text-conversion.feature
│
├── src/
│ ├── domain/ # Core business entities
│ │ └── types.ts # User, Benefit, LegalText, etc.
│ │
│ ├── workflows/ # XState state machines
│ │ └── conversionMachine.ts # Legal text conversion workflow
│ │
│ ├── rules/ # Business rules implementation
│ │ └── agrRules.ts # AGR eligibility rules engine
│ │
│ ├── services/ # Business logic services
│ │ └── conversionService.ts # Legal text conversion service
│ │
│ └── examples/ # Runnable examples
│ ├── agrExample.ts # AGR eligibility examples
│ └── conversionExample.ts # Conversion workflow examples
│
├── package.json
├── tsconfig.json
└── README.md
cd ../PAA
npm installAGR Eligibility Check:
npm run example:agrThis demonstrates:
- ✓ Eligible case (part-time, rights maintenance, salary < 1650€)
- ✗ Ineligible cases (salary too high, no rights maintenance, etc.)
- Optimization hints based on working hours
Legal Text Conversion Workflow:
npm run example:conversionThis demonstrates:
- State machine progression through conversion pipeline
- Retry logic when validation fails
- Context tracking at each step
npm run buildThe PAA project includes a modern React-based frontend application with a comprehensive UI for interacting with the system.
- React 18 with TypeScript for type-safe development
- Vite for lightning-fast development and optimized builds
- Radix UI components for accessibility
- Tailwind CSS for styling
- Dark mode support
- Responsive design for mobile, tablet, and desktop
- Multi-language support (FR, NL, DE)
- Node.js 18+ and npm 9+
- Docker and Docker Compose (for PostgreSQL and Redis)
# Start database and cache services
npm run docker:up
# In a separate terminal, start the API server
npm run dev:api
# The API will be available at http://localhost:3000
# API documentation at http://localhost:3000/docs# Navigate to frontend directory
cd frontend
# Install dependencies (first time only)
npm install
# Copy environment configuration
cp .env.example .env.local
# Start development server
npm run dev
# The frontend will be available at http://localhost:5173- Frontend UI: http://localhost:5173
- API Documentation: http://localhost:3000/docs
- Database Admin: http://localhost:5050 (pgAdmin)
- Redis Admin: http://localhost:8081 (Redis Commander)
cd frontend
# Build for production
npm run build
# Preview production build locally
npm run preview
# Build outputs to frontend/dist/- Bundle size: ~73 KB gzipped total
- Code splitting for optimal loading
- Lazy loading of components
- Source maps for debugging
- Environment-specific configuration
- Backend Development: The main PAA backend provides APIs and business logic
- Frontend Development: The React frontend provides the user interface
- Integration: Frontend proxies API calls to the backend during development
For detailed frontend documentation, see frontend/README.md.
See features/benefits/income-guarantee.feature
Benefits:
- Legal experts can validate rules without reading code
- Rules serve as automated tests
- Changes are tracked in git with clear history
- Scenarios cover edge cases explicitly
See src/workflows/conversionMachine.ts
The conversion pipeline implements the architecture from the documentation:
1. Extract legal structure (NLP)
2. Identify key concepts
3. Map to common vocabulary
4. Generate multiple versions (simple, detailed, examples)
5. Validate semantic accuracy
6. Retry if validation fails (max 3 attempts)Visualization available via XState tools.
See src/rules/agrRules.ts
Rules are defined as JSON objects:
{
conditions: {
all: [
{ fact: 'employmentStatus', operator: 'equal', value: 'part-time' },
{ fact: 'hasRightsMaintenance', operator: 'equal', value: true },
{ fact: 'monthlySalaryGross', operator: 'lessThan', value: 1650 }
]
},
event: { type: 'agr-eligible' }
}Can be:
- Stored in database
- Updated without deployment
- Versioned for legal compliance
- Audited (which rules fired when)
See src/domain/types.ts
Strong typing prevents errors:
interface EligibilityCheck {
benefitType: BenefitType; // Enum, not string
isEligible: boolean;
calculatedAmount?: number; // Optional, only if eligible
reason?: string; // Required if not eligible
}- Clear domain models (
User,Benefit,LegalText) - Ubiquitous language from business domain
- Bounded contexts (rules, workflows, services)
- Explicit state machines
- No hidden states or race conditions
- Predictable behavior
- Rules are strategies for eligibility determination
- Can swap/add rules dynamically
- Composition over inheritance
- Conversion is a pipeline of transformations
- Each stage has clear input/output
- Stages can be tested independently
- ❌ Cucumber alone doesn't execute business logic
- ❌ Step definitions still need implementation
- ❌ Doesn't handle complex workflows well
- ❌ State machines for business rules = verbose
- ❌ Hard for non-developers to validate
- ❌ No natural representation of eligibility conditions
- ❌ Doesn't handle workflows/pipelines well
- ❌ No visual representation
- ❌ State transitions are awkward
- ✅ Gherkin for what the rules are (readable specs)
- ✅ XState for how processes flow (visual workflows)
- ✅ Rules Engine for when conditions apply (runtime evaluation)
- ✅ TypeScript for implementation (type safety)
| Concern | Tool | Why |
|---|---|---|
| Business rule specification | Gherkin | Human-readable by legal experts |
| Workflow orchestration | XState | Visual, predictable state management |
| Runtime rule evaluation | json-rules-engine | Dynamic, database-driven rules |
| Type safety & implementation | TypeScript | Compile-time guarantees |
| Data validation | Zod (planned) | Runtime schema validation |
- ✅ Basic AGR rules
- ✅ Conversion workflow
- ✅ Type definitions
- Integrate actual LLM API (Claude/GPT)
- Add Zod schemas for validation
- Implement Cucumber step definitions
- Add more benefit types (RIS, unemployment, etc.)
- Create visual state machine diagrams
- Store rules in PostgreSQL
- Version rules with effective dates
- Audit trail for all eligibility checks
- Multi-language support (FR/NL/DE)
- Human-in-the-loop validation workflow
# features/benefits/new-benefit.feature
Fonctionnalité: Nouveau Bénéfice
Scénario: Cas d'éligibilité
Étant donné que [conditions]
Quand [action]
Alors [résultat attendu]// src/rules/newBenefitRules.ts
const rule: Rule = {
conditions: { /* ... */ },
event: { type: 'new-benefit-eligible' }
};// src/domain/types.ts
export type BenefitType = 'agr' | 'ris' | 'new-benefit';npm run example:new-benefit- One scenario per edge case - Don't combine multiple cases
- Use scenario outlines for parametric testing
- Write in French for Belgian context (stakeholder language)
- Include "why" in scenario descriptions
- Keep states focused - One responsibility per state
- Use meta descriptions - Document what each state does
- Handle all transitions - No undefined behavior
- Implement timeouts for async operations
- Prioritize rules - Explicit order when overlap exists
- Document facts - What each fact represents
- Test rule combinations - Ensure no conflicts
- Version rules - Track changes over time
This is a POC demonstrating architectural patterns. To extend:
- Add new
.featurefiles for new business rules - Implement corresponding rule engines
- Create examples demonstrating the functionality
- Update this README with new patterns
ISC
- No single tool solves everything - Complex business logic needs a hybrid approach
- Readability matters - Legal rules must be validated by domain experts
- Type safety prevents errors - Especially critical for money/date calculations
- Workflows need visualization - State machines make complex processes understandable
- Flexibility is key - Rules stored in DB can change without deployment
This POC proves the architecture is feasible and maintainable.