Skip to content

Wire evaluateTenantQuota into job-dispatch's real admission path (currently only feeds a dashboard number) #7647

Description

@JSONbored

Problem

evaluateTenantQuota() (packages/loopover-engine/src/tenant-quota.ts) is a complete, tested, pure quota-decision function (compute/time/concurrency dimensions) — but its only caller anywhere in src/**/packages/** is customer-loop-view.ts, which uses it purely to render a read-only dashboard number and explicitly discards the concurrency dimension. src/queue/job-dispatch.ts — the actual dispatch path — has zero tenant/quota references. A tenant that exceeds its compute/time/concurrency allocation is not stopped anywhere in the runtime today. The issue that produced this function (#4796, closed) had explicit deliverables/acceptance-criteria calling for a tenant to be "stopped cleanly" when over quota; what shipped didn't meet that bar.

Area

Platform / cost-control. Directly addresses the maintainer's own standing top concern: an unbounded tenant burning real compute/API spend with nothing stopping it.

Proposal

Wire evaluateTenantQuota() into job-dispatch.ts's real admission path: before dispatching a job for a tenant, evaluate its quota and refuse dispatch (with a clear, actionable rejection) when exceeded — mirroring the concurrency dimension customer-loop-view.ts currently discards, not just compute/time.

This does not need to wait on #4920 (the persisted plan/quota/subscription data model, still fully undone) to provide real protection now — scope the quota SOURCE as config/env-injectable defaults for this pass (a real but interim input), so the actual numbers are trivially swappable for #4920's persisted model later without touching the enforcement wiring itself. Don't invent plan-tier business logic here — that's #4920/#4804's job; this issue is the mechanism, not the numbers.

Deliverables

  • Real admission-time enforcement in job-dispatch.ts calling evaluateTenantQuota() (all dimensions, including concurrency) before dispatching a tenant's job.
  • A config/env-sourced interim quota input, structured so it can be swapped for a persisted-data-model source later without changing the enforcement call site.
  • A clear, tenant-facing rejection reason when blocked (not a silent drop).

Resources

  • packages/loopover-engine/src/tenant-quota.ts (the existing pure decision function)
  • packages/loopover-engine/src/customer-loop-view.ts (the only current, non-enforcing consumer)
  • src/queue/job-dispatch.ts (the real dispatch path, currently tenant-unaware)
  • Per-tenant rate limits & quotas #4796 (closed — shipped the decision function, not the enforcement)
  • Design a quota/plan/subscription/invoice data model #4920 (persisted plan/quota data model — this issue's later, proper quota source)

Boundaries

No plan-tier business logic, no real pricing/limit numbers invented here — mechanism only, using config/env-injectable interim values. No reward/pricing figures in this issue.

maintainer-only — this is the admission-control path for the whole dispatch queue; a mistake here fails either open (quota does nothing, the exact gap this closes) or closed (blocks legitimate work fleet-wide). First pass needs maintainer review, matching this repo's own treatment of the gate's own merge/close authority.

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.roadmapOn the Wave-2 agent-layer roadmap board (project 9)

Projects

Status
Todo

Relationships

None yet

Development

No branches or pull requests

Issue actions