Governance Rules

Budgets, rate ceilings, and model and provider access -- the half of a guardrail DevZero enforces on every request.

Governance Rules

The governance half of a guardrail is DevZero's end to end, and it binds every request, whoever's credential pays.

The control plane decides; the gateway does the arithmetic. The gate runs on the decided model, before any cache is consulted.

Governance ships in shadow mode. The enforcement mode is set per gateway deployment (off, shadow or enforce) -- not per guardrail and not per team -- and a hosted gateway defaults to shadow: every rule on this page is evaluated and recorded, and nothing is denied. A self-hosted gateway defaults to off, where the gate does not run at all. Confirm which mode your gateway is in before relying on a rule to refuse traffic.

Budgets

SettingMeaning
LimitA hard ceiling in USD. Unset or zero means no budget, not "no spending allowed".
Resetdaily, weekly, monthly, or unset for a lifetime budget anchored at the guardrail's creation. Windows are calendar UTC.
Counter scopeprincipal (the default) or team.

A budget's ceiling is per cadence. A daily ceiling read against a month of spend looks like a team wildly over budget when it is not, which is why every surface that shows a budget also shows its reset cadence. Only a monthly ceiling is directly comparable to a month of spend.

A pooled budget -- counter scope team -- is counted against every principal bound to the guardrail together, so one bucket exhausts for everyone it governs. The guardrail's rate ceilings pool into the same bucket.

Money is carried as integer micro-USD everywhere -- on the wire and in every counter -- so there is no floating-point drift.

Validation on the amount: USD only, no finer than 0.0001,andbelow0.0001, and below 100,000,000.

Soft-warn thresholds

Fractions of the budget at which a crossing is announced rather than refused. Each is crossed once per window.

Crossing a threshold changes no verdict. Enforcement never reads them -- they exist to tell you something before the ceiling does.

Each threshold is a fraction greater than zero and at most one. They are stored as a whole set, so if you drive the API yourself you must round-trip them or they are erased.

Rate ceilings

SettingMeaning
Requests per minute0 means unlimited.
Tokens per minute0 means unlimited.

The control plane owns what these mean; the gateway owns the counting. Both pool into the same bucket as the budget when the counter scope is team.

Avoid calling an upstream provider's own throttling a "rate limit" in the same breath as these. A provider throttle is the upstream refusing you; these are your own ceilings, and they are reported differently in the failure taxonomy.

Model and provider access

Four lists, and all of them take wildcard patterns: * matches any run of characters, and everything without a * is byte-exact.

ListEffect
Allowed modelsOnly these may be served. Empty means unrestricted.
Ignored modelsA match denies, even when the allow list would permit it.
Allowed providersOnly these may serve. Empty means unrestricted.
Ignored providersA match denies.

Two rules govern how they combine:

  • An exclusion beats a permission.
  • An empty permit list means unrestricted, not "permit nothing".

A non-empty provider allow list fails closed on a provider the gate cannot recognise. That is deliberate: a request whose provider is unknown cannot be proved to satisfy a restriction, so it is refused rather than admitted.

A byte-exact entry must match what the gateway actually sends. One mismatch is a silent false deny, cached for a short window. Introduce access rules in shadow mode and read the would-deny decisions before enforcing.

On the keyed connector route

On that route the gate is handed a connector id rather than a catalog provider slug, because the serving endpoint is chosen upstream afterwards. So the decision defers: the control plane expands your wildcard patterns into literal provider slugs and hands the rules back, and the gateway enforces them.

If the catalog is unreadable while your rules contain a wildcard, the control plane refuses the decision rather than shipping a pattern that would never match anything. A wildcard that expands to no known provider is not a refusal: an allow list that matches nothing still denies everything, and a deny list that matches nothing denies nothing. That makes the model catalog a hard dependency of the governance decision on this route.

Auto mode

Auto splits the guarantee, because a delegated request has no decided model for an allowlist to bind. See Auto mode.

Deny reasons

A denial names one of a fixed set of sixteen:

ReasonMeaning
model_not_allowedThe decided model failed the model rules.
provider_not_allowedThe provider failed the provider rules.
policy_disabledThe guardrail is switched off.
policy_expiredThe guardrail's expiry has passed.
unattributed_deniedTraffic with no resolvable identity, under a guardrail that denies it.
budget_exhaustedAccrued spend reached the budget ceiling for the window.
rate_limitedThe requests-per-minute ceiling was exceeded.
tpm_exceededThe tokens-per-minute ceiling was exceeded.
budget_unavailableThe spend counter could not be read and the fail mode is closed.
policy_unavailableThe control plane could not be reached and the fail mode is closed.
credential_unavailableNo forwardable credential resolved for a team-funded request.
custody_unsupported_upstreamThe requested custody arm does not exist on the decided upstream.
key_invalidThe key is unknown, revoked, expired or disabled.
key_policy_not_meteredA key's guardrail is seat-sourced or absent, so it has no team-funded credential.
user_policy_not_meteredThe same, for a signed-in DevZero account.
token_invalidThe DevZero access token did not verify.

Deny reasons have two authors that do not overlap: the control plane's verdict about the principal and the guardrail, and the gateway's own outcomes at forward time. Do not read the set as one enumeration owned by one side.

A refusal is collapsed into one shape where distinguishing it would tell a probing caller something they should not learn, and distinguished where the two cases name different remedies.

Unattributed traffic

Traffic with no resolvable identity is a real category, and a team-default guardrail decides what happens to it: govern it as the default does, drop the access rules for it, or deny it.

That setting is read only when the guardrail is resolved as the team default. And dropping the access rules is not a bare allow -- the guardrail still has to be active and unexpired, and the rate ceilings and budget still apply.

Reading spend against a guardrail

Two reads exist and they are not interchangeable:

ReadQuestion it answers
Principal usageWhat enforcement sees: spend inside the guardrail's own window, filtered the way enforcement filters.
Key spendWhat has this key cost over the last N days, with no policy filter at all.

Never sum key spend against a budget limit -- it would overstate consumption, because it counts traffic the budget does not. It also counts traffic on your own credentials, so it answers "what did this key's traffic cost", not "what does the team owe DevZero".

Two more honesty rules on the enforcement read:

  • For a seat credential class, all the monetary and window fields are absent. Seat telemetry cost is an API-equivalent estimate, not money spent, and must never be presented as spend.
  • A partial sum is disclosed rather than presented as complete. Historical rows can predate a column the figure depends on.

What "true allow" means for your credential

No request is ever forwarded on a DevZero-funded credential without a governance verdict that actually allowed it, produced fresh -- because a verdict replayed during an outage cannot see a key revoked since.

Failing that check strips the credential and forwards the request anyway, where the upstream rejects it. That is deliberate: it is not a DevZero denial, and it costs $0 rather than billing an account nobody authorised.

On this page