Operator limits: operator API to read usage
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 18/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- typescript
Research direction
This depends on the operator API from #275 and the usage table from #272, so check whether both are merged before starting. Read the operator routes and the usage repository functions they expose, then add the feed, per-workspace, and summary endpoints, plus the cursor encoding and the settled-at safety lag. Extend contracts/operator-api.v1.json and make the test table T01 to T10 pass. Done means those integration tests pass and the real responses validate against the contract.
Written by the indexing model from the issue text.
Description
Part of #268. Depends on #272 and #275.
Problem
An external service that sets limits also has to read what was consumed: to keep its own accounts, to decide a period's outcome, to answer a support question. The operator API of #275 has no usage endpoint, and the usage table of #272 is only reachable from inside the app.
Behavior
GET /api/operator/v1/usage?after=<cursor>&limit=— a page of settled records of every workspace, ordered by(settled_at, id). Each item:id,workspaceId,jobId,reviewKind,keyMode,modelTier(the tier name or null; never a model name),costMicroUsd(integer or null),promptTokens,completionTokens,settledAt,reason(null or a short code such asno_result). The response has an opaquenextCursor.GET /api/operator/v1/workspaces/{id}/usage— the same for one workspace, plusfrom/tofilters onsettledAt.GET /api/operator/v1/workspaces/{id}/usage/summary?from=&to=— per kind and key mode: record count, settled count, sum of known cost, number of records with unknown cost.- Out-of-order commits. A record becomes visible to the feed only when its
settled_atis older than a safety lag (default 60 seconds, a validated instance constant), so a record committed late can never be skipped by a reader that already moved past its position. Readers must still treatidas the idempotency key; the contract says so. - Records are immutable once served.
voidandreservedrecords are not served. - No pull request, repository, branch, title or user data in any item.
- The contract file
contracts/operator-api.v1.jsongrows with these shapes and examples.
Scope
Routes, cursor encoding (opaque, validated, bounded), repository read functions use those of #272, contract additions, docs, tests.
Out of scope
Pushing events to a URL, deleting or correcting records, exports to files.
Test cases
| ID | kind | level | case | expected |
|---|---|---|---|---|
| T01 | behavior | integration | three settled records | served in (settled_at, id) order with a cursor that continues without gaps or repeats |
| T02 | behavior | integration | a record settled 10 seconds ago | not served yet; served after the lag |
| T03 | behavior | integration | reserved and void records |
never served |
| T04 | security | integration | items and logs | contain no model name, repository, pull request, email or key |
| T05 | behavior | integration | summary for a period | counts and sums match the records; unknown costs counted separately |
| T06 | negative | integration | malformed or oversized cursor, limit out of range | 400 with a stable code |
| T07 | security | integration | no token | 404 with the token unset, 401 with a wrong one (as #275) |
| T08 | behavior | integration | a workspace filter | only that workspace's records |
| T09 | contract | integration | real answers | valid against operator-api.v1.json |
| T10 | regression | integration | a new record for a job with a repeated completion | the feed shows one item |
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 1
- Avg merge
- 1h 15m
- Merged PRs (30d)
- 217
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ExpidetGames/code-reviewer
-
area: app type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
ExpidetGames/code-reviewer#308 ·
Maintainers usually reply within 1 day
-
type: docs
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
ExpidetGames/code-reviewer#94 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 25/100
ExpidetGames/code-reviewer#401 ·
Maintainers usually reply within 1 day
-
area: app type: chore
Difficulty 3/5 1-2 days Newbie friendliness 45/100
ExpidetGames/code-reviewer#393 ·
Maintainers usually reply within 1 day
-
area: runner type: bug
Difficulty 4/5 3-5 days Newbie friendliness 42/100
ExpidetGames/code-reviewer#390 ·
Maintainers usually reply within 1 day
All issues in ExpidetGames/code-reviewer
Similar issues
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 70/100
lingdojo/kana-dojo#32590 · 1 comment · 5 reactions ·
Maintainers usually reply within 1 day
-
bug p2
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
bastani-inc/atomic#3703 ·
Maintainers usually reply within 1 day
-
backend bug difficulty: medium priority: medium reliability
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
trustflow-protocol/trustflow-backend#730 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
firecrawl/firecrawl-mcp-server#548 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 90/100
Maintainers usually reply within 1 day