⚖️ Machine-Readable Legislation & Rules API

Transforming laws and policies into executable, queryable, automated compliance infrastructure

What It Is

Machine-Readable Legislation transforms laws, regulations, and policies from unstructured text (PDFs, legal documents) into structured, semantic, executable formats that software systems can understand, query, and automatically enforce. Rules as Code (RaC) takes this further: legislation is drafted using controlled vocabularies linked to OWL ontologies, then exposed as queryable APIs.

Core Vision: Instead of humans reading 200-page laws to determine eligibility for a benefit or permit, AI agents query a Rules API: POST /rules/check-eligibility {"citizen": {...}, "benefit": "housing_allowance"} → Response: {"eligible": true, "reason": "Income < €30k AND resident_of_municipality"}

This is the missing link in digital government: We have APIs for data, but not for the rules that govern how data should be used. Machine-readable legislation enables:

Technical Architecture

Legislation Drafting Stack

Layer Technology Purpose
Controlled Vocabularies SKOS (sanastot.suomi.fi) Standardized terms with URIs (e.g., "housing_allowance" → unique ID)
Ontologies OWL (tietomallit.suomi.fi) Semantic relationships (e.g., "Citizen subClassOf Person", "hasIncome range xsd:decimal")
Rule Language SWRL, RIF, DMN (Decision Model Notation), or custom DSL Express legal logic in machine-executable format
Rule Engine Drools, OpenFisca, Blawx, or custom (Rete algorithm) Execute rules against input data → infer conclusions
Legislative Markup Akoma Ntoso XML, LegalDocML Structure legal documents (sections, articles, amendments)
Version Control Git (for rules), Finlex API (for Finnish laws) Track amendments, temporal validity ("rule valid 2024-01-01 to 2025-12-31")
Rules API Gateway REST/GraphQL + OpenAPI spec Expose rules as queryable endpoints

Rules as Code Workflow

┌──────────────────────────────────────────────────────────────────────┐ │ Legislation Lifecycle │ └──────────────────────────────────────────────────────────────────────┘ 1. DRAFTING (Legislative Authors) ┌────────────────────────────────┐ │ Legal Text (Natural Language) │ │ + Controlled Vocabulary Tags │ │ + Semantic Annotations (OWL) │ └────────────┬───────────────────┘ │ 2. FORMALIZATION (Legal Engineers + AI) ┌────────────▼───────────────────┐ │ Extract Rules: │ │ IF income < €30,000 │ │ AND resident_of_municipality │ │ THEN eligible(housing_allow) │ └────────────┬───────────────────┘ │ 3. ENCODING (Rules as Code) ┌────────────▼───────────────────┐ │ SWRL / DMN / DSL: │ │ Citizen(?c) ^ │ │ hasIncome(?c, ?i) ^ │ │ lessThan(?i, 30000) ^ │ │ residesIn(?c, ?m) -> │ │ eligible(?c, HousingAllowance)│ └────────────┬───────────────────┘ │ 4. VALIDATION (Automated Testing) ┌────────────▼───────────────────┐ │ Test Cases: │ │ Input: {income: 25000, ...} │ │ Expected: eligible = true │ │ Result: ✓ Pass │ └────────────┬───────────────────┘ │ 5. PUBLICATION (Rules API) ┌────────────▼───────────────────┐ │ POST /api/rules/check │ │ {"citizen": {...}} │ │ Response: {"eligible": true} │ └────────────┬───────────────────┘ │ 6. CONSUMPTION (Systems + AI Agents) ┌────────────▼───────────────────────────┐ │ Kela System: Queries rules API │ │ AI Agent: "Is person X eligible?" │ │ Mobile App: Real-time eligibility │ └────────────────────────────────────────┘ Amendment Flow: Parliament passes amendment → Rules updated in Git → CI/CD → API updated → All systems get new rules automatically

Controlled Vocabularies & Ontologies

Why Controlled Vocabularies?

Legal text is ambiguous. "Resident" could mean: domicile, registered address, physical presence, or tax residence. Controlled vocabularies assign unique URIs to each concept, linked to OWL ontologies that define precise semantics.

Example: Housing Allowance Ontology

# OWL Ontology (Turtle syntax) @prefix ex: . @prefix owl: . @prefix xsd: . # Classes ex:Citizen a owl:Class ; rdfs:label "Citizen"@en, "Kansalainen"@fi ; rdfs:comment "Person with Finnish residency status" . ex:HousingAllowance a owl:Class ; rdfs:label "Housing Allowance"@en, "Asumistuki"@fi ; rdfs:comment "Social benefit for low-income residents" . ex:Municipality a owl:Class ; rdfs:label "Municipality"@en, "Kunta"@fi . # Properties ex:hasIncome a owl:DatatypeProperty ; rdfs:domain ex:Citizen ; rdfs:range xsd:decimal ; rdfs:label "annual income in euros" . ex:residesIn a owl:ObjectProperty ; rdfs:domain ex:Citizen ; rdfs:range ex:Municipality ; rdfs:label "has registered address in" . ex:hasHousingCost a owl:DatatypeProperty ; rdfs:domain ex:Citizen ; rdfs:range xsd:decimal ; rdfs:label "monthly housing costs in euros" . # Rules (SWRL - Semantic Web Rule Language) [HousingAllowanceEligibility: (?c rdf:type ex:Citizen) (?c ex:hasIncome ?income) lessThan(?income, 30000) (?c ex:residesIn ?m) (?m rdf:type ex:Municipality) -> (?c ex:eligibleFor ex:HousingAllowance) ]

Integration with Finnish Interoperability Platform

Platform Component Rules as Code Use
sanastot.suomi.fi (SKOS vocabularies) Provides standardized URIs for legal terms used in rules
tietomallit.suomi.fi (OWL models) Defines semantic structure referenced by rules (classes, properties, constraints)
koodistot.suomi.fi (Code lists) Enumerations used in rules (e.g., benefit types, permit categories)

Key Insight: By drafting legislation using terms from these registries, rules automatically inherit semantic definitions. When a term's definition updates in tietomallit.suomi.fi, all rules referencing it can be validated for consistency.

Rules API Design

Two Types of Rules

Type Source Authority Examples
Legislative Rules Acts of Parliament, Government decrees Legal force (binding) Benefit eligibility, tax rates, permit requirements
Organizational Policy Rules Agency policies, internal guidelines Administrative (discretionary) Priority scoring, risk assessment, service standards

API Endpoints

# OpenAPI Specification (excerpt) paths: /rules/check-eligibility: post: summary: Check eligibility for a benefit or service operationId: checkEligibility requestBody: required: true content: application/json: schema: type: object properties: ruleId: type: string description: URI of rule (e.g., "housing-allowance-2024") context: type: object description: Input data (citizen attributes, application data) properties: income: type: number residency: type: string housingCost: type: number responses: '200': description: Eligibility determination content: application/json: schema: type: object properties: eligible: type: boolean reason: type: string description: Human-readable explanation citations: type: array items: type: object properties: law: type: string description: "Law identifier (e.g., 'Social Security Act §15')" url: type: string description: "Finlex URL to law section" /rules/query: post: summary: Query rules by criteria (e.g., "all rules affecting companies in industry X") # ... (similar structure) /rules/validate-compliance: post: summary: Check if an action complies with applicable rules # ... (e.g., "Can company X export product Y to country Z?") /rules/calculate: post: summary: Calculate amounts (taxes, benefits, fees) based on rules # ... (e.g., "Calculate child benefit for family with 3 children, income €45k")

Example API Call: Housing Allowance Eligibility

# Request POST /api/rules/check-eligibility Content-Type: application/json { "ruleId": "https://tietomallit.suomi.fi/housing-allowance/eligibility-2024", "context": { "citizen": { "id": "010190-900C", "income": 25000, "residency": "Helsinki", "housingCost": 800 } } } # Response { "eligible": true, "confidence": 1.0, "reason": "Income (€25,000) is below threshold (€30,000) AND registered resident of Helsinki", "citations": [ { "law": "Asumistukilaki 408/2015 §3", "section": "Income limits", "url": "https://finlex.fi/fi/laki/ajantasa/2015/20150408#L1P3" } ], "calculatedAmount": 450.50, "unit": "EUR/month", "validFrom": "2024-01-01", "validTo": "2024-12-31" }

Real-World Use Cases

1. Automated Benefit Eligibility (Kela)

Scenario: Citizen applies for housing allowance via mobile app.

Traditional Process:
  1. Kela officer reads 200-page Act (Asumistukilaki)
  2. Manually checks income, residency, family size against tables
  3. Calculates benefit amount using formula (error-prone)
  4. Decision in 2-4 weeks
With Rules API:
  1. App queries: POST /rules/check-eligibility {"ruleId": "housing-allowance", "context": {...}}
  2. Rules API evaluates → returns: {"eligible": true, "amount": 450.50, "reason": "..."}
  3. Instant decision (no human review needed for simple cases)
  4. Officer reviews only edge cases flagged by AI
Benefit: 95% of applications auto-processed, decision time: 1 hour → 5 minutes

2. Permit Pre-Validation (Construction)

Scenario: Company designs building, wants to know if it complies before applying for permit.

Traditional: Submit permit application → wait 6 weeks → get rejection ("violates zoning rule §12")

With Rules API:
  1. BIM software queries: POST /rules/validate-compliance {"ruleId": "building-code-2024", "context": {"buildingHeight": 25, "zone": "residential", ...}}
  2. Rules API: {"compliant": false, "violations": ["Height exceeds 20m limit for residential zones (§12)"]}
  3. Architect adjusts design → re-queries → {"compliant": true}
  4. Submits permit application with pre-validated design
Benefit: 80% fewer rejections, 50% faster permit processing

3. Export Control Automation (Tulli)

Scenario: Company exports electronics to Russia (hypothetical, complex sanctions).

Traditional: Read 500 pages of EU/UN sanctions lists, dual-use goods regulations → manual determination

With Rules API:
  1. ERP queries: POST /rules/validate-compliance {"ruleId": "export-control-2024", "context": {"product": "HS-8542.31", "destination": "RU", "endUser": "..."}}
  2. Rules API checks: Product classification, sanctions lists, dual-use regulations, license requirements
  3. Response: {"allowed": false, "reason": "Product on EU dual-use list, license required for Russia"}
  4. System prevents shipment, suggests alternative markets or license application
Benefit: Zero violations, automatic compliance in real-time

4. Tax Calculation (Vero)

Scenario: Freelancer calculates quarterly VAT.

Traditional: Read tax law → fill 20-field form → hope calculation is correct

With Rules API:
  1. Accounting software: POST /rules/calculate {"ruleId": "vat-2024", "context": {"revenue": 50000, "expenses": 10000, "vatRate": "standard"}}
  2. Rules API: {"vatOwed": 9600, "calculation": "...", "dueDate": "2024-04-15"}
  3. Auto-generates pre-filled tax return
Benefit: 99% accuracy, zero manual calculation errors

5. Proactive Compliance (AI Agent)

Scenario: AI agent monitors company operations for regulatory compliance.

Process:
  1. AI subscribes to event stream: "EmployeeHired", "ProductShipped", "ContractSigned"
  2. For each event, queries Rules API: POST /rules/validate-compliance {...}
  3. If violation detected: {"compliant": false, "violation": "Employee count >50 requires works council (§25)"}
  4. AI alerts management: "Action required: Form works council within 30 days"
Benefit: Proactive compliance (violations prevented before they occur)

Implementation Considerations

Legal Engineering Challenges

Challenge Solution Approach
Ambiguity in Legal Text Use controlled vocabularies from drafting stage, disambiguate with ontologies
Discretionary Rules Express as probability scores or flag for human review (e.g., "case officer may grant exception")
Temporal Validity Version rules in Git, tag with effective dates, API returns rule valid for query timestamp
Conflicting Rules Ontology reasoning detects conflicts, flag for legislative review
Privacy Rules API doesn't store input data (stateless), audit log tracks queries only
Explainability API returns reasoning trace + law citations (GDPR "right to explanation")

Technology Stack Recommendation

Component Options Rationale
Rule Engine OpenFisca, Drools, or custom (Rete algorithm) OpenFisca: Tax/benefit focus, Python-based, used by France
Drools: Enterprise Java, complex rule management
Ontology Store Apache Jena, Ontotext GraphDB, Stardog SPARQL query support, reasoning capabilities, scalable
Legislative Markup Akoma Ntoso XML, LegalDocML International standard for parliamentary documents
Version Control Git (rules as code), semantic versioning Track amendments, branching for draft legislation
API Framework FastAPI (Python), Spring Boot (Java) REST + GraphQL support, OpenAPI auto-generation
Critical Constraint: Rules as Code is not the law itself—it's an interpretation. In case of conflict, legal text prevails. Best practice: Treat RaC as "reference implementation" with legal text as authoritative source. Courts may review rule logic for correctness.

Real-World Implementations

International Leaders

Country/Initiative Approach Status
New Zealand - Better Rules Draft legislation in decision tables → automated eligibility tools Production (rates rebates, student allowances)
France - OpenFisca Tax & benefit rules as Python code, public API Production (used by gov services + startups)
Australia - Digital Service Standard Machine-consumable legislation (pilot), API-first mandates Pilot programs
Canada - Rules as Code CRA (tax agency) experimenting with rule formalization Research phase
EU - ELI (European Legislation Identifier) URIs for all EU laws, machine-readable metadata Adopted (not full RaC, but foundation)

Deployment Roadmap (Finland)

Phase Timeframe Deliverables
Foundation 2025-2026 Pilot: 5 high-volume benefit rules (housing allow, child benefit, etc.) formalized + API
Expansion 2026-2027 20+ rules online, legislative drafting tools with controlled vocab support
Integration 2027-2028 Rules API standard for all new legislation, AI agents consume rules
Maturity 2028+ 100+ rules, proactive compliance agents, cross-border rule interop (EU)

Technical References

Back to Overview