feat/one-api
needs attentionviewing older commite8ffa5e · incrementalPR #326reviewed 2026-07-21 01:33 UTC4H · 7M · 5L · 4I- Purpose
- Establish an unambiguous, machine-readable wire contract for the One-API program so W3 implementors can implement converged API shapes without re-reading the actual handlers.
- Goal
- Add prescriptive resource nesting rules and shipped-accurate wire examples to one-api.md
- Sub-goals
- SG-1: one-api.md rule (decision, wire grammar, operation grammar, parity classes, wave plan)
- SG-2: Route classifier → route-inventory.json (250 routes)
- SG-3: shared-kernel PublicIdPrefix registry merge; CFE_JOB_PREFIX cjb→cfj
- SG-4: ADRs 016/018/020 distilled into owning rules; docs/ADRs/ retired
- SG-N: untrack .branch/ working files
- What
- Added 'Resource shape & nesting' section (4 nesting signatures, 2 flat/nest smells each, open-map pattern) and 'Canonical wire examples' section (bill list, energy-summary aggregate, async job lifecycle, failure shapes) to .claude/rules/one-api.md — 252 lines, docs only.
- Why
- W3 DUAL convergence needs concrete reference shapes. Without shipped-accurate examples, implementors must read multiple handler files to understand the wire contract; the rule file is the SSOT so examples belong here.
- Areas
- .claude/rules/+252−0
- Blast
- Docs/rules only — 252 lines added to .claude/rules/one-api.md. No production code changed on this incremental diff. Full branch: 90 files, +6620/−13652 (dominated by docs/ADRs/ removal and scripts/one-api/route-inventory.json).
Findings · 21
correctness6
concept_meaning uses `unit` — shipped schema requires `units` (plural)
.claude/rules/one-api.md
ConceptMeaning interface and its Zod schema both define the field as `units` (plural). An implementor following this example emits the wrong field name — clients silently get undefined for every unit.
Job phase 'created' not in PublicJobPhaseSchema enum
.claude/rules/one-api.md
Shipped enum: queued|collecting|processing|persisting|finalizing|completed|failed. 'created' does not exist. Correct value is 'queued'.
Job phase 'persisted' not in PublicJobPhaseSchema enum
.claude/rules/one-api.md
Completed-job example shows phase: 'persisted'. Shipped enum has 'persisting' (in-progress), not 'persisted'. Terminal completed phase is 'finalizing' or 'completed'.
Failure shapes omit 429 — a status code the API actively emits
.claude/rules/one-api.md
Section titled 'the complete set' enumerates 400/401/404/409/500. ts-rest-auth.ts emits HTTP 429 RATE_LIMIT_EXCEEDED and PublicApiErrorCode includes 'rate_limited'. False completeness claim will mislead SDK authors.
concept_meaning position differs between list and detail endpoints
.claude/rules/one-api.md
On list, concept_meaning is at envelope root. On GET /v1/bills/:id, it lives inside data. Rule shows only the list shape.
`items` as integer count (not array) is consistent with shipped schema
.claude/rules/one-api.md
PublicBillListResponseSchema confirms items: z.number().int().nonnegative(). Array lives under `data`. No bug — unusual naming worth a note in the grammar.
security3
Failure shapes omit 403 (insufficient scope) — completeness claim is false
.claude/rules/one-api.md
403 needed when a valid credential lacks the required scope (W2 scope enforcement). Without a canonical 403 shape, implementors will conflate it with 401.
409 OCC leaks version counters to public callers
.claude/rules/one-api.md
expectedVersion/actualVersion enable a timing oracle for public routes. Should note that version numbers are withheld from public 409 bodies (W3 ratification item).
401 uniform response adequately prevents credential oracle attacks
.claude/rules/one-api.md
Single uniform 401 body for all credential failure paths. Correct design — no action needed.
conventions4
`object` rule says 'registry entity name' — shipped literals are lowercase shorthand
.claude/rules/one-api.md
PublicIdPrefix registry uses PascalCase (CfeJob). Shipped schemas use lowercase shorthand (z.literal('job')). 'Registry entity name' is ambiguous.
`concept_meaning` at envelope root not explained by nesting rule or JSend definition
.claude/rules/one-api.md
Rule defines envelope as {status, data}; concept_meaning lives at root. Real JSend departure not named as an exception.
Job flat nullable scalars violate the rule's own 'correlated nullable' smell without annotation
.claude/rules/one-api.md
Rule says correlated nullable scalars should be one optional block. Queued-job shows result:null, error:null, started_at:null, completed_at:null — no ⚠ explaining the intentional flat shape.
`items` as count vs array — unusual convention worth noting
.claude/rules/one-api.md
Most REST APIs use `items` as the array field name. Here it is a count. No inconsistency with code, but not self-documenting.
improvement8
Missing PATCH/OCC example leaves Update mechanics unspecified
.claude/rules/one-api.md
No example showing request body with version, 200 response with version:N+1, or the 409/200 relationship. Implementors will omit version on first attempt.
Cursor inbound param name not shown — client will silently get wrong results
.claude/rules/one-api.md
parseBillsListQuery reads q.cursor — inbound param is 'cursor', not 'next_cursor'. A client passing ?next_cursor=<token> silently gets the full list via passthrough.
`object: 'job'` and `object: 'energy_summary'` have no registry entry
.claude/rules/one-api.md
Rule states object MUST equal the registry entity name. PublicIdPrefix has no 'job' or 'energy_summary' entry. Allocation rule for non-entity resources is unspecified.
`progress/result/error` mis-classified as optional block
.claude/rules/one-api.md
`progress` is always present; `result`/`error` are mutually exclusive non-null. Three fields do NOT appear/disappear together — closer to a discriminated union over lifecycle stages.
`completed_at` populated on failed jobs — misleading name not annotated
.claude/rules/one-api.md
Failed job example shows completed_at set even though status is 'failed'. Semantics are 'terminal state reached at'. Should be annotated as a ⚠ wart.
`hired_demand`/`connected_charge` as strings contradicts floats-for-measurements rule
.claude/rules/one-api.md
These are kW values (not money) yet appear as strings due to Drizzle numeric() coercion. Rule says measurements are floats (energy_summary). Exception not annotated.
GET single, DELETE, webhook event shapes have no examples
.claude/rules/one-api.md
Operation grammar lists 7 op types; examples cover List + Async-job create/poll. Single-resource GET, Delete response body, and signed webhook envelope are absent.
`partial_success` job status has no example
.claude/rules/one-api.md
PublicJobStatusSchema includes partial_success. An implementor may collapse it into 'completed' when deriving from examples rather than the schema.
History · 47 commits
- 82bb5b9blockedincremental5H · 5M · 4L2026-08-12 01:48
- 90aa3d5needs attentionincremental1H · 5M · 3L2026-08-11 19:37
- 29d19a0needs attentionincremental1H · 5M · 9L2026-08-11 17:41
- 9bd8a0cneeds attentionfull0H · 5M · 9L2026-08-11 02:14
- 62ec3f7needs attentionincremental2H · 5M · 6L2026-08-10 22:51
- f93bca9needs attentionincremental2H · 5M · 8L2026-08-10 17:51
- 052db6fneeds attentionincremental1H · 3M · 4L2026-08-09 21:13
- 45699caneeds attentionincremental0H · 7M · 11L2026-08-09 17:44
- b843d8aneeds attentionincremental1H · 7M · 9L2026-08-09 04:05
- e1757b8needs attentionincremental0H · 3M · 6L2026-08-05 02:11
- 7a762faneeds attentionincremental2H · 5M · 5L2026-08-05 01:25
- 3300a60needs attentionincremental2H · 4M · 7L2026-08-04 19:06
- 0c8a7f5needs attentionincremental0H · 4M · 9L2026-08-04 18:15
- 345f42eneeds attentionincremental2H · 6M · 9L2026-08-04 17:28
- 8338a9aneeds attentionincremental5H · 14M · 14L2026-08-04 00:33
- 41be4c3needs attentionincremental0H · 5M · 7L2026-08-03 23:49
- 5ed593dneeds attentionincremental1H · 6M · 6L2026-08-03 21:32
- b333e25needs attentionincremental4H · 9M · 8L2026-08-03 21:00
- 5642cccneeds attentionincremental2H · 3M · 2L2026-08-03 20:17
- 73b0b39needs attentionincremental3H · 10M · 13L2026-07-31 18:29
- b19852eneeds attentionincremental0H · 1M · 5L2026-07-29 05:04
- 3845205needs attentionincremental3H · 6M · 4L2026-07-29 04:47
- eb8eb50needs attentionincremental0H · 1M · 2L2026-07-29 03:03
- f4720a3needs attentionincremental6H · 8M · 7L2026-07-29 02:54
- f8d341ablockedincremental2H · 2M · 5L2026-07-29 00:00
- a7f1a64needs attentionincremental2H · 8M · 8L2026-07-28 18:41
- 738b60bblockedincremental3H · 6M · 5L2026-07-28 00:46
- 2c248b6needs attentionincremental8H · 12M · 8L2026-07-27 23:23
- 1346cc0needs attentionincremental2H · 8M · 6L2026-07-27 20:15
- 0716018needs attentionincremental2H · 11M · 12L2026-07-27 19:22
- 215cd2dneeds attentionincremental3H · 6M · 5L2026-07-27 17:04
- ec46958needs attentionincremental0H · 3M · 5L2026-07-27 16:51
- de7b337blockedincremental4H · 9M · 14L2026-07-27 06:36
- b1bb9c0needs attentionincremental1H · 2M · 4L2026-07-27 05:09
- 4701d11needs attentionincremental0H · 4M · 3L2026-07-27 04:44
- e1626c4needs attentionincremental3H · 9M · 10L2026-07-27 03:21
- 195f198needs attentionincremental3H · 3M · 3L2026-07-25 01:22
- 42c7358safeincremental0H · 0M · 0L2026-07-22 20:46
- 85b9018needs attentionincremental0H · 1M · 6L2026-07-21 23:51
- a7b2a9aneeds attentionincremental0H · 9M · 12L2026-07-21 18:49
- c2ee0daneeds attentionincremental4H · 7M · 7L2026-07-21 02:17
- e8ffa5eneeds attentionincremental4H · 7M · 5L2026-07-21 01:33current
- a2d2a54needs attentionincremental2H · 7M · 3L2026-07-21 00:51
- 576fbd6needs attentionfull1H · 6M · 7L2026-07-21 00:35
- d3465e8needs attentionincremental1H · 7M · 10L2026-07-21 00:23
- dc794a7needs attentionincremental0H · 5M · 5L2026-07-20 23:46
- 9082773needs attentionfull1H · 3M · 3L2026-07-20 23:13