Start free

Pinned floors

Some lanes are dangerous enough that a policy must never be able to wave them through. HESO pins a floor on those lanes: you can tighten them, but you cannot allow-without-approval.

A policy file is an ordered list of rules, and the first rule that matches a subject, verb, scope, and conditions decides the action. That gives you a lot of room to make a mistake. Pinned floors are the part of the engine that stops a policy author from waving through something dangerous, by accident or on purpose.

What a floor is

A floor is a built-in minimum decision the engine enforces at load time, no matter what your rules say. A normal rule is something you write; a floor is something the engine already knows. Certain action lanes carry a built-in promise: they can never resolve weaker than require_approval.

The check runs when the policy is parsed, not when an action arrives. So a policy that breaks a floor never loads — it is rejected before it can gate a single action. There is no window where a bad policy is live and quietly allowing things it should not.

Floors are enforced, not advisory

A floor is not a lint warning you can ignore. A policy that contradicts one is rejected at load — the engine refuses to run it. The safe default for any unmatched dangerous lane is also require_approval, so a gap in your rules fails closed, not open.

The dangerous lanes

Four lanes are floored. Each maps to an action verb, and each carries the same floor: it cannot be allowed without human approval.

LaneVerbFloor
Paymentspaymentrequire_approval
Deletesdeleterequire_approval
Account changesaccount_changerequire_approval
Large data exportsdata_exportrequire_approval

These are the actions where a wrong move is expensive and hard to undo: money leaves, records vanish, credentials change, data walks out the door. The floor says a human with their own key has to stand behind each one. That human approval is what lifts a receipt from L0 to L1.

Tighten, never bypass

A floor sets a minimum, not a maximum. You are free to make a dangerous lane stricter — you just cannot make it looser than the floor. Tightening is exactly what most real policies do:

  • Require more than one approver — a finance lead and a CFO must both co-sign, not just one person.
  • Lower a threshold so approval kicks in earlier — route every payment over $1,000 instead of over $5,000.
  • Block outright — a block decision is stricter than approval, so blocking a lane is always allowed.
  • Add a tighter sla_minutes so the approval cannot sit unanswered.

Here is a rule that tightens the payment floor. It keeps require_approval and adds two named approvers and a shorter SLA — the engine accepts it because it asks for more, not less:

heso.toml
# Allowed: the floor for payments is require_approval.# This rule TIGHTENS it — two approvers, a faster SLA.[[rule]]id = "pay-large"order = 10enabled = truesubject = { kind = "any" }verb = "payment"scope = "*"conditions = [  { field = "amount_usd", op = "gt", value = 5000, display = "amount over $5,000" },]decision = "require_approval"approvers = ["finance-lead", "cfo"]sla_minutes = 30

The one thing you can never write is a rule that resolves a floored lane to allow with no human in the loop. That is the single move a floor forbids.

The [FLOOR_BYPASS] error

When a rule would allow-without-approval a dangerous lane, the engine rejects the whole policy at load with a [FLOOR_BYPASS] error that names the offending rule id and verb. The policy below tries to auto-allow every payment:

heso.toml
# Rejected at LOAD time. You cannot allow a payment# without human approval — payment is a floored lane.[[rule]]id = "pay-auto"order = 10enabled = truesubject = { kind = "any" }verb = "payment"scope = "*"conditions = []decision = "allow"

Loading it fails. The error identifies precisely which rule broke the floor and on which verb, so the fix is unambiguous:

bash
[FLOOR_BYPASS] rule "pay-auto" cannot allow verb "payment" without approval

Two error families guard the load path. A [FLOOR_BYPASS] means the file parsed fine but a rule contradicts a pinned floor. A [PARSE] means the file is malformed — bad TOML, a missing field, or a value the engine cannot read — and never reaches the floor check at all. Both stop the policy from loading.

A rejected policy does not deploy

Either error aborts the load, which means the policy is never activated. The control plane re-runs the same checks, so a policy that fails locally also fails on the server — there is no path where a floor-bypassing file slips into production.

Checked before you deploy

You do not have to push a policy to find out it breaks a floor. The exact same engine logic runs in the browser, so the editor catches it the moment you write it. Two functions back this:

  • parsePolicy — reads the TOML and surfaces a [PARSE] error if the file is malformed.
  • validateNoFloorBypass — runs the floor check and surfaces the [FLOOR_BYPASS] error, with the same rule id and verb you would see on the server.

The browser, Node, and Python all call the one Rust core — nothing is reimplemented — so the reason string you read in the editor is byte-identical to the one the engine would produce at deploy. You see the real verdict, not a guess, before anything ships. See Test & deploy for the full simulate-then-deploy loop, and the browser verifier for how the WASM surface runs these checks locally.

What a floor guarantees — and what it doesn't

A floor guarantees that a loaded policy can never auto-allow a dangerous lane: the structure is sound and a person must co-sign before it can proceed. It constrains authorization — no dangerous action runs unsigned — not the outcome; it does not say whether the co-signer approved wisely.

Next steps