Secure use of Assemblic for Rules as Code with OpenFisca

Secure use of Assemblic for Rules as Code with OpenFisca

10 May 2026


Rules as Code systems make policy executable. When something goes wrong in one of these systems, the failure is rarely just technical; it can mean a citizen receives an incorrect entitlement, an agency makes an unappealable compliance decision, or sensitive information is disclosed without authority. That is a different kind of risk from a broken shopping cart, and it calls for a different level of discipline.

This article is written for developers building and operating OpenFisca applications on Assemblic. It covers some basic tips and tricks to remember when managing your own OpenFisca systems. This basic guidance is not a definitive guide and doesn’t replace your own good security hygiene practices, formal security reviews or penetration tests.



What Assemblic handles, and what you still own

Assemblic manages a significant portion of the security boundary: infrastructure, automated deployments, WAF and CDN protection, MFA, and audit logging. That is genuinely useful, and it removes a class of problems you would otherwise have to solve yourself.

What it does not cover is everything that happens inside your application: the rule logic you write, the data you send into the system, how you manage access, the quality of your tests, and the integrity of the Python packages your application depends on. Understanding that boundary clearly is the first step to building something secure.

A useful way to think about it: Assemblic secures the pipes; you are responsible for what flows through them and what happens at the other end.



Validate inputs like you mean it

OpenFisca variables are deterministic functions over typed inputs. That structure is one of the platform’s real strengths for auditability, but it does not protect you from bad data arriving at your service layer. In a government context, the inputs to your rules often determine someone’s eligibility, payment amount, or compliance status. You need to treat input validation as a core control, not an afterthought.

Validation must happen at the server, on every request, regardless of what the client claims to have already checked. In practice, that means:

  • Reject any field that is not in your expected schema
  • Use positive allowlists for enumerations, not blocklists
  • Constrain numeric ranges and dates to values that are actually meaningful for the rule
  • Validate combinations of fields that carry policy meaning, not just individual values in isolation

Here is a minimal but complete example Python pattern:

from decimal import Decimal, InvalidOperation
from datetime import date
from enum import StrEnum

class Residency(StrEnum):
    AUSTRALIAN_RESIDENT = "australian_resident"
    TEMPORARY_RESIDENT = "temporary_resident"
    NON_RESIDENT = "non_resident"

ALLOWED_KEYS = {"age", "annual_income", "residency", "claim_date"}

def validate_payload(payload: dict) -> dict:
    unknown = set(payload) - ALLOWED_KEYS
    if unknown:
        raise ValueError(f"Unexpected fields: {sorted(unknown)}")

    age = int(payload["age"])
    if age < 0 or age > 130:
        raise ValueError("age out of range")

    try:
        income = Decimal(str(payload["annual_income"]))
    except InvalidOperation as exc:
        raise ValueError("annual_income must be numeric") from exc
    if income < 0 or income > Decimal("10000000"):
        raise ValueError("annual_income out of range")

    residency = Residency(payload["residency"])  # raises ValueError on unknown value
    claim_date = date.fromisoformat(payload["claim_date"])

    return {
        "age": age,
        "annual_income": income,
        "residency": residency.value,
        "claim_date": claim_date.isoformat(),
    }

The pattern is deliberately boring. Do not build rule paths on raw dictionaries, implicit type coercions, or dynamic execution. Avoid `eval` entirely. Treat any outbound URL fetch as a privileged operation and restrict it to an explicit allowlist.



Write tests that actually prove something

In an OpenFisca application, a wrong rule is a security failure. A missed threshold, an unhandled boundary condition, or an untested interaction between parameters and reforms can produce incorrect outcomes at scale, silently, with no visible error.

OpenFisca’s YAML test format is well-suited for documenting and verifying rule behaviour. The key is to be explicit about the cases that actually matter: boundary values, null paths, conflicting inputs, and the conditions under which eligibility or compliance status changes.

A threshold test should look something like this:

- name: "Eligibility threshold — qualifies at boundary"
  period: 2026-07
  input:
    age: 55
    annual_income: 49999
  output:
    eligible: true

- name: "Eligibility threshold — fails above boundary"
  period: 2026-07
  input:
    age: 55
    annual_income: 50000
  output:
    eligible: false

 

These are not just quality checks. They are the mechanism by which you can demonstrate that a rule behaves as intended, that a change did not break something downstream, and that the system produces consistent outcomes under the same inputs. They also make your CI pipeline meaningful: if every change must pass the full test suite before promotion, you have a real gate, not a formality.

A sound test strategy covers four areas:

  1. Deterministic rule validation. Every formula should have at least one named test that binds specific inputs to expected outputs and notes the policy basis for that expectation.
  2. Boundary conditions. If eligibility changes at age 55, income of $50,000, or a specific commencement date, those thresholds need dedicated tests.
  3. Negative cases. Test the conditions under which someone does not qualify, as carefully as those under which they do.
  4. Regression protection. Run the full suite in CI before every promotion. A test that only runs locally is not a control.

One point that often gets missed: technical correctness does not prove policy correctness. A policy owner should review rule changes against the legislative intent, not just approve a green CI run. Codification done without that collaboration is one of the most common sources of silent error in Rules as Code systems.



Manage access properly

Assemblic provides MFA through Auth0. These are baseline requirements, not optional extras. The minimum expected configuration is:

  • Enforce MFA for everyone with access to production environments or policy repositories
  • No shared accounts, ever
  • Separate the role of owner/admin from the role of policy modeller and developer (member); these should not be the same person with the same access level
  • Review access periodically and revoke promptly when someone leaves or changes role

The environment model matters here too. Assemblic provisions separate production and development environments and supports a three-branch deployment strategy (develop, stage, main). The discipline that makes this useful is procedural: no direct changes in production, no shared secrets between environments, no production data in development or test, and no promotion without review and a passing test suite.



Handle data with the assumption that it is sensitive

Any fact submitted to an OpenFisca application may be sensitive. In a government context, that is almost always true. Some practical defaults:

  • Do not put sensitive values in URLs; use POST bodies
  • Minimise the data collected to what the rule actually requires; do not collect fields you do not use
  • Keep production data out of development and test environments; use synthetic data instead
  • If your application processes personal information, document those data flows formally before go-live

Assemblic’s infrastructure provides TLS, WAF, and CDN protection. Your application layer still needs to handle sensitive data carefully in how it logs, stores, and passes values between components. Be deliberate about what ends up in logs; structured logging with explicit field allowlists is a safer pattern than logging raw request payloads.



Keep your dependencies under control

This is the area most development teams underweight until something goes wrong. If you are running OpenFisca on Assemblic and pulling in Python packages, the integrity of those packages is part of your security posture.

Practical steps that make a real difference:

Pin and hash your dependencies. Use pip’s hash-checking mode and a pinned requirements.txt or lock file. A constraints file for shared or transitive dependencies gives you predictable builds and makes supply chain tampering detectable.

Run pip-audit regularly. It scans your installed packages and requirements files against known vulnerability databases. Integrate it into your CI pipeline so you find out about new vulnerabilities before they reach production.

Assess upstream health before adopting a dependency. Is the project actively maintained? Does it have a published security policy? Is it widely used in comparable contexts? These are not bureaucratic questions; they are risk questions.

Do not install packages you do not need. Every additional dependency is an additional attack surface. Review your requirements periodically and remove things that are no longer used.

Protect your CI pipeline. The pipeline that builds and deploys your application is a privileged system. Use short-lived credentials, restrict workflow permissions, and audit the actions and tooling you pull in through CI.

A note on OpenFisca itself: it is a well-regarded open source project, but upstream popularity is not the same as mature security governance. Treat it as you would any open source dependency: monitor for vulnerabilities, maintain your own patching process, and do not assume that someone else is watching.



Set up meaningful logging

Assemblic provides audit logging at the platform level. Your application needs to complement that with logging at the application level. The goal is to produce an evidence trail that lets you answer two questions after the fact: what happened, and why did the system produce that result?

At a minimum, your application should log:

  • Authentication events (successful and failed)
  • Authorisation decisions, especially failures and denials
  • Rule changes and environment promotions
  • API usage patterns that deviate significantly from the norm
  • Any security control failure or unexpected exception

Be deliberate about what you do not log. Raw request payloads, personally identifiable information, and secrets should not appear in logs. Use structured logging with explicit field selection, and send logs to a system that is logically separate from the application so they cannot be tampered with or lost if the application is compromised.



Pre-launch checklist

Before you go live with an OpenFisca application on Assemblic, work through this list. Each item is a concrete action, not a policy statement.

ActionWhy it matters
Classify all data sent to the service; document whether personal data is necessaryYou cannot protect data you have not thought about
Enforce MFA for all privileged users; no shared accountsCredential compromise is the most common initial access vector
Define roles for admin, policy modeller, developer and reviewer; apply least privilegeSeparation of duty prevents a single mistake becoming a major incident
Separate dev, test/stage, and production environments; separate secrets between themEnvironment bleed is a common source of data exposure and rule error
Pin and hash Python dependencies; maintain a constraints fileUnpinned dependencies are a supply chain risk
Run pip-audit in CI; define remediation timeframes for discovered vulnerabilitiesVulnerability discovery without a remediation process is not a control
Write YAML tests for every formula and boundary condition; run them in CI before promotionTests that do not gate promotion do not prevent regression
Get policy owner sign-off on every material rule changeTechnical correctness is necessary but not sufficient
Decide which API endpoints are public, authenticated, or internal-only; rate-limit external endpointsOpenFisca’s /calculate endpoint can be expensive; unauthenticated access is a DoS risk
Define your application logs; mask sensitive fields; send logs off-hostLogs that live on the same host as the application are not trustworthy after an incident
Document how you will handle vulnerabilities discovered in the platform or your applicationA vulnerability response process that exists only in someone’s head is not a process
Document decommission steps: accounts, secrets, logs, data retentionApplications get turned off; the steps for doing that safely should be written down first


Where to go from here

The controls above are not optional extras for high-security deployments. They are the baseline for building software where decisions affect people’s rights and entitlements. Assemblic removes a substantial infrastructure burden; the application discipline described in this article is what you add on top.

If you are unsure where to start, begin with input validation and tests. Those two controls, done properly, prevent the largest class of silent errors in Rules as Code systems. Everything else builds from there.