Governance & trust
Governance is the dispose half of Fibric: the deterministic machinery that stands between what a model wants and what actually happens. The model proposes; a deterministic executor disposes, under a fail-closed policy, with single-flight and idempotency making each action safe, tenancy keeping it walled off, and a receipt making it accountable. This is the part you can read, write, and audit.
Propose and dispose
This is the single most important idea in the platform, and governance is built directly on top of it. The model never acts. It produces a validated ExecutionPlan, a list of proposed actions stated as capabilities and arguments. A deterministic executor then disposes of that plan: it validates the shape, checks every action against your policy, enforces single-flight and idempotency, runs what survives in order, and writes a receipt for each step.
Proposes
Reasons over what was sensed and emits a validated plan of capabilities and arguments. Suggestive, never authoritative. The model is allowed to want things.
Disposes
Deterministic. Validates the plan, applies policy, enforces single-flight and idempotency, runs what is allowed, writes a receipt. The executor is the only thing allowed to do things.
Because the dispose half is deterministic and the model cannot reach a system except through it, the boundary between what the model wants and what actually happens is a hard line, not a hope. Everything else on this page is what that line is made of.
Fail-closed trust policies
A trust policy is the rulebook the executor enforces while disposing. It is fail-closed: anything the policy does not explicitly allow is refused. A policy can veto any action before it ever happens, no matter how confidently the model proposed it. You write the allow list, the per-run limits, and the conditions; the executor decides nothing on its own.
The capability is on the allow list, its arguments pass, and any conditions and limits are satisfied. The action runs, and a receipt records which rule allowed it.
Not on the allow list, a limit exceeded, a condition unmet, or simply unrecognized. The action is refused. The default answer is no.
Fail-closed is the default for a reason. An open-by-default system fails toward action; a fail-closed system fails toward inaction. When you are acting on the physical world, the safe failure is to do nothing. Here is a policy that allows a ship-risk operator to hold orders, but caps how many it can hold per run and requires a receipt on every hold.
# fail-closed: nothing runs unless a rule below allows it.
default: deny
allow:
- capability: orders.read # reads are unconditional here
- capability: orders.hold
where:
reason: ship-risk-review # only this hold reason
limits:
per_run: 25 # at most 25 holds in one run
per_entity: 1 # never hold the same order twice
require:
- receipt # a hold is not complete without one
- capability: notify.send
where:
to: ops-queue # may only message the ops queue
limits:
per_run: 50
An operator that proposes access.unlock when the policy only allows orders.* does not error out in the world. The executor refuses the action and records the refusal. A proposal can be declined, but it can never edit the rulebook that declined it.
Real data is a policy too
Fibric refuses to act on data it cannot verify is real. A fallback or placeholder value is tagged at the source as source: "fallback", and a tagged value can never be treated as a governed metric. This means a placeholder can never trigger a real action, the same fail-closed instinct, applied to the inputs rather than the outputs.
# refuse to act on anything not verified as real data
require:
- data.source: governed # never "fallback", never "seed"
# a value tagged source:"fallback" is visible to a human,
# but it can never satisfy this rule, so it can never act.
The data layer tags any fallback so a placeholder cannot pass as a real number. A real tenant renders only governed real data, and an action gated on data.source: governed simply will not fire on a value that was filled in to keep a chart from being empty.
Single-flight and idempotency
Two kernel primitives keep action safe under load, and the executor enforces both while disposing. Single-flight per entity means at most one action is in flight for a given entity at a time, so two runs cannot both hold the same order or unlock the same door at once. Idempotency keys mean the same logical action applied twice has the effect of applying it once: retries are safe, duplicates collapse.
ship-risk:SO-10884:hold
└── operator ──┘ └─ entity ─┘ └ action ┘
same key twice → applied once. retries collapse.
The key is built from the operator, the entity, and the action. Run the operator again a minute later and it proposes the same hold with the same key; the executor recognizes the key and makes the second attempt a no-op. Single-flight serializes by entity so two concurrent runs queue rather than collide. Together they make a runaway structurally impossible rather than merely unlikely.
The 657-flood
The reason these are primitives and not nice-to-haves is a specific failure mode. A loop reasons, proposes a notification, and reasons again before the first one settles, proposing it once more, over and over, until it has sent the same message six hundred and fifty-seven times. Without governance, an agentic system on the physical world does exactly this. With it, the second send is a no-op and the loop is serialized.
The same notification fired again and again. No key to collapse the repeats, no single-flight to serialize the entity. The loop floods.
The idempotency key makes every repeat a no-op, and single-flight serializes the entity. The same loop sends exactly once.
Nobody has to remember to add a guard. Single-flight and idempotency are properties of the executor, so the 657-flood cannot occur whether the loop is yours, the model's, or a bug. The repeats collapse before they ever reach a connector.
Walled-off tenancy
Tenancy is provable isolation, and it is part of governance because an action that touches the wrong tenant is the worst action of all. Every envelope and every row carries reseller_id and tenant_id, and the data layer enforces that a query scoped to one tenant can only ever see that tenant's rows. Isolation is not a convention the application remembers to follow; it is a property the storage layer guarantees.
-- every query runs under the caller's tenant, set per request.
-- the row-level policy makes cross-tenant reads return nothing.
CREATE POLICY tenant_isolation ON events
USING (tenant_id = current_setting('app.tenant_id'));
-- a placeholder or seed row for one tenant cannot surface in
-- another, and a real tenant sees only governed real data.
The same wall that keeps tenants apart keeps seed and mock data out of a tenant that is supposed to see live numbers. The boundary is the spine of the whole system, and the executor never disposes of an action without a tenant on the envelope, so an unscoped action cannot exist.
Receipts
Every action leaves a receipt: the immutable record of what was proposed, which policy rule decided it, the idempotency key, and the outcome. Receipts are what make Fibric explainable. You can always answer what it did and why, after the fact, for any action, in any tenant. A receipt is not a log line you hope was written, the executor writes it as it disposes, and a policy can require a receipt before an action is considered complete.
{
"receipt_id": "rc_5b21",
"tenant_id": "t_8f2a…c901",
"capability": "orders.hold",
"proposed_by": "model",
"policy": { "decision": "allow", "rule": "orders.hold" },
"idempotency_key": "ship-risk:SO-10884:hold",
"outcome": "applied"
}
A refused action leaves a receipt too. When the policy denies a proposal, the receipt records the decision as deny and the rule that produced it, so a refusal is as accountable as an action. If you cannot account for something, it did not happen, and governance is precisely the guarantee that everything can be accounted for.
The model proposes; a deterministic executor disposes under a fail-closed policy, with single-flight and idempotency making each action safe, tenancy keeping it walled off, and a receipt making it accountable.
Keep going
- Operators, the propose half: what produces the plans this page disposes of.
- Connectors & capabilities, the systems actions reach, only after policy allows them.
- Core concepts, all nine ideas behind the kernel, in one place.
- API reference, plans, policies, and receipts on the wire.