All writing

Enforce budgets at the level the human approved them

Aggregate usage counters up to the granularity the approver actually saw, so wildcard expansion can't silently multiply an approved ceiling by the number of rows it fanned out into.

Here’s a bug that type systems, tests-per-function, and code review all tend to miss, because every individual piece is correct: an owner approves an app for “1,000 requests per day.” The app’s grant asks for llm:* — any installed LLM provider — and the gateway expands that wildcard into permission rows: one per connector, per action. Seven connectors, two actions each: fourteen rows. Each row dutifully carries the limit from the approval: 1,000/day. Each row’s counter is enforced correctly. The app can now make 14,000 requests per day, and every log line looks fine.

The ceiling the human approved got multiplied by an implementation detail — the fan-out factor of the storage schema. Nothing lied; the enforcement just happened at a different granularity than the approval.

The boundary

The rule Cookey lands on: limits are enforced at the granularity at which they were approved, regardless of the granularity at which they’re stored. The owner approves budgets on a grant (the contract with one app). Storage denormalizes those budgets onto every permission row for fast lookup — that’s fine. But the enforcement check must aggregate usage across all of a grant’s permissions before comparing to the cap.

The design pointedly does not go the other way — splitting the approved budget across rows (1,000 ÷ 14 per row). That preserves the total but invents per-provider sub-limits the owner never chose, and breaks the moment a connector is added or removed. Denormalized limit, aggregated usage: the approved number stays exactly the number the human saw.

Implementation

The budget module (apps/proxy/src/server/limits/budget.ts) states the invariant in its header comment, which I’d argue is the most load-bearing comment in the codebase:

// Budgets come from the GRANT (decisions.budget) and are denormalized
// onto every permission row, so enforcement aggregates usage across ALL
// of a grant's permissions — otherwise a wildcard bound to N connectors
// × M actions would multiply the owner-approved ceiling by N×M.

Counters are written per-permission (that granularity is useful — the admin UI shows per-provider usage bars), but the enforcement read sums over the grant:

/** Sum usage counters for a period across every permission of a grant. */
async function grantPeriodUsage(
  grantId: string,
  periodType: UsagePeriodType,
  periodStart: Date,
): Promise<{ requests: number; tokens: number; costUsd: number }> {
  const totals = await prisma.permissionUsage.aggregate({
    where: { permission: { grantId }, periodType, periodStart },
    _sum: { requestCount: true, tokenCount: true, costUsd: true },
  });
  return {
    requests: totals._sum.requestCount ?? 0,
    tokens: totals._sum.tokenCount ?? 0,
    costUsd: totals._sum.costUsd ?? 0,
  };
}

export async function checkAndIncrementRequestUsage(
  permissionId: string,
  grantId: string,
  quotas: { dailyQuota?: number | null; monthlyQuota?: number | null },
): Promise<BudgetResult & { period: UsagePeriodType }> {
  const now = new Date();

  // Write at the storage granularity (this permission)…
  await Promise.all([
    incrementUsage(permissionId, "DAILY", dailyPeriodStart(now), { requests: 1 }),
    incrementUsage(permissionId, "MONTHLY", monthlyPeriodStart(now), { requests: 1 }),
  ]);

  // …but check at the approval granularity (the whole grant).
  const [daily, monthly] = await Promise.all([
    grantPeriodUsage(grantId, "DAILY", dailyPeriodStart(now)),
    grantPeriodUsage(grantId, "MONTHLY", monthlyPeriodStart(now)),
  ]);

  if (quotas.dailyQuota && daily.requests > quotas.dailyQuota) {
    return { allowed: false, used: daily.requests, limit: quotas.dailyQuota, /* … */ };
  }
  // …monthly check, then allow
}

If you’re adapting this, the shape to copy is the signature: the check function takes both the row-level ID (where to write) and the contract-level ID (what to sum and compare). The moment your enforcement function only receives the row ID, the aggregation is impossible and the N×M bug is structural. This function sits in the request pipeline after permission lookup and before the upstream call, so it already has both IDs in hand.

The same principle propagates to reporting: the endpoint that tells an app its remaining budget (/v1/grant) must aggregate identically — getGrantUsageSnapshot(grantId) in the same file — or apps will be told they have budget left that enforcement will deny. Any place that answers “how much is used?” at a different granularity than enforcement is a bug in waiting.

Failure behavior

Two degradations are worth knowing. Under concurrent requests there’s a small admission race: two requests can both increment, both read the aggregate before the other’s increment lands in their read, and both pass at exactly the boundary. The window is one round-trip wide and the overshoot is bounded by concurrency, not by fan-out — an owner might see 1,002/1,000 on a burst, never 14,000/1,000. Request counts also increment at admission even when the request is subsequently denied over-quota, a deliberately preserved semantic: a denied request consumed its slot, which makes hammering the gate itself cost quota.

The subtler failure is schema drift. If someone adds a new usage dimension (say, per-model counters) and enforces it per-row because that’s where the numbers are, the multiplication bug returns on the new axis. The defense is the comment quoted above sitting directly on the aggregation function — the invariant lives next to the only code that can violate it.

What changes operationally

Once enforcement matches approval granularity, the approval screen becomes trustworthy in a strong sense: the number the owner types is the number the system holds, under wildcard expansion, connector installs, and future refactors of the permission schema. That changes what you can safely build on top — Cookey’s approval UI projects worst-case daily spend from those caps, and the projection is only honest because the cap can’t be silently multiplied downstream. The general audit question this leaves you with is portable to any system with wildcards or role expansion: for every limit a human sets, find the row the enforcement reads — and count how many of those rows one approval can create.