api: document the twenty-two routes that were serving traffic in silence
The inventory is hand-maintained, and should stay that way - its value is the prose, and what an endpoint is FOR cannot be derived from the code. An audit of all 372 documented operations found zero phantom routes and zero wrong parameter names, so the maintenance is in good order. What hand-maintenance cannot do is notice a route somebody added. Twenty-two were undocumented: the entire backups plugin surface, every one of the dashboard card endpoints added with contract 0.19.0, the GE-Enforce publish preflight, the employee SSO resolver, the protocol update verbs, and the four /api/docs routes - so the spec did not describe how to fetch the spec. Coverage is now a test. It walks the live url_map and fails when a served route has no entry, which means adding an endpoint includes describing it, in the same commit, while the author still knows what it is for. The reverse direction is checked too: a documented route that no longer exists sends a reader to a 404. Writing that test found one more thing. The inventory writes multi-verb routes as "PUT|PATCH", and neither the parity check nor the generator split on the pipe - so those operations were absent from the published spec entirely, with nothing reporting it. The spec now carries all 394 operations the code serves, which is the first time the two numbers have matched. The generator's own docstring claimed the inventory could be regenerated. It cannot; nothing generates it. That sentence is why nobody noticed it was falling behind.
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
"""Generate docs/openapi.json from docs/api-inventory.json.
|
||||
|
||||
The inventory is a list of {surface, endpoints:[{method,path,auth,params,purpose,
|
||||
example}]} objects (one per API surface). Re-run after adding/changing endpoints
|
||||
(update api-inventory.json first, or regenerate it). Served interactively at
|
||||
/api/docs (see shopdb/core/api/docs.py).
|
||||
example}]} objects (one per API surface). It is HAND-MAINTAINED - nothing
|
||||
generates it, and the docstring here used to imply otherwise. That is deliberate:
|
||||
its value is the prose, and what an endpoint is FOR cannot be derived from the
|
||||
code. Coverage is enforced instead, by tests/test_api_inventory_parity.py, which
|
||||
fails when a served route has no entry.
|
||||
|
||||
So: describe the endpoint in api-inventory.json, then re-run this. Served
|
||||
interactively at /api/docs (see shopdb/core/api/docs.py).
|
||||
|
||||
venv/bin/python scripts/gen_openapi.py
|
||||
"""
|
||||
@@ -179,7 +184,10 @@ def build(surfaces):
|
||||
for s in surfaces:
|
||||
tags.append({'name': s['surface']})
|
||||
for e in s.get('endpoints', []):
|
||||
for verb in re.split(r'[\/,]', (e.get('method') or 'GET')):
|
||||
# 'PUT|PATCH' is how the inventory writes a multi-verb route.
|
||||
# Without the pipe here, neither verb matched VERBS and the
|
||||
# operation vanished from the spec without a word.
|
||||
for verb in re.split(r'[\/,|]', (e.get('method') or 'GET')):
|
||||
verb = verb.strip().lower()
|
||||
if verb not in VERBS:
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user