Epic 11 — Rate Limiting & Quota Visibility

Covers read-only visibility into the user's sliding-window run quota, per-repository concurrency limit, and the pr_lock advisory lock wait queue. This epic is purely observational; submit-time rate-limit rejection rendering lives in Epic 3, and pr_lock live status during a run lives in Epic 7.

Personas: BU (primary consumer) OP (full visibility including system-wide limits)

Shared modules: CorrelationChip EnvProvenance

Non-goals: Configuring quota thresholds or rate-limit policies (those are server-side OP admin actions, not a UI concern in this epic).

Story 11.1 — Sliding-Window Run Quota Gauge

As a
BU
I want
to see my current run quota usage and the remaining capacity in the sliding window
So that
I can plan when to trigger runs without hitting a 429 rejection
Scenario: Quota gauge renders on the quota page
Giventhe user navigates to /quota WhenGET /quota/runs resolves Thena gauge is rendered showing: used runs in the current window, maximum allowed runs per window, time until the window resets (relative countdown), and a visual fill indicator using the design-token colour scale
Scenario: Quota at capacity — visual warning state
GivenGET /quota/runs returns remaining: 0 Thenthe fill indicator reaches 100% and switches to an amber/red warning colour; copy reads Quota exhausted — next window opens in <countdown>
Endpoint / DBPurpose
GET /quota/runsCurrent usage, maximum, window expiry
DB Valkey amtp:rl:user:{userId}:runsSliding-window counter (3600 s)

Story 11.2 — Per-Repository Concurrency Gauge

As a
BU
I want
to see the number of concurrently active runs for each repository
So that
I know whether adding another run trigger will queue behind existing work
Scenario: Concurrency gauge renders per project
Giventhe user is on the quota page or project detail page WhenGET /quota/concurrency?project_id={project_id} resolves Thenthe concurrency gauge shows: active run count for the project, maximum concurrent runs allowed, and a visual fill indicator
Scenario: At maximum concurrency — non-blocking advisory
GivenGET /quota/concurrency returns active: N, max: N (at capacity) Thena non-blocking advisory reads: This repository is at maximum concurrency. A new run will queue until an active run completes.; the run-trigger form in Epic 3 remains submittable
Endpoint / DBPurpose
GET /quota/concurrency?project_id={project_id}Active run count and maximum for repository
DB Valkey amtp:rl:repo:{repo}:concurrencyConcurrency counter (3600 s)

Story 11.3 — pr_lock Wait Queue Visibility

As a
BU
I want
to see whether the advisory PR lock is currently held for a repository
So that
I can anticipate a delay in PR delivery for any run I trigger
Scenario: pr_lock is free — neutral indicator
GivenGET /quota/pr_lock?project_id={project_id} returns locked: false Thenno pr_lock indicator is shown (or a PR lock: free indicator in a neutral style)
Scenario: pr_lock is held — queue depth shown
GivenGET /quota/pr_lock?project_id={project_id} returns locked: true, queue_depth: 2, held_since: "<ISO>" Thena PR lock held indicator is shown with: how long the lock has been held (held_since) and the number of runs waiting (queue_depth: 2); a tooltip explains: The repository advisory lock is held during PR delivery to prevent concurrent writes. Runs queued: N.
Endpoint / DBPurpose
GET /quota/pr_lock?project_id={project_id}Lock status, held_since, queue_depth
DB Valkey amtp:rl:repo:{repo}:pr_lockAdvisory lock key (120 s per acquisition)