Make the API usable by an agent, and stop the contract going stale
Someone writing a script against ShopDB had two options: read a 705 KB spec, or guess. The spec is the reference, not an index, and handing an agent the whole thing means either truncating it or spending a context window on 479 operations nobody asked about. Three additions, each feeding the next. /api/docs/operations.txt is the index: every operation on one line with its method, path, tag, auth and summary, at around 70 KB for all 486. A caller can hold the entire API at once, find the four operations it needs, and only then fetch their schemas. /api/docs/openapi.json?tag=... narrows the spec to one of the 41 tag groups. Components are kept intact deliberately: pruning the schema graph to match would leave references resolving to nothing, and a generator that fails confusingly is worse than a file that is larger than strictly necessary. tools/mcp/ is an MCP server built on both. Five tools rather than 483, because a tool per operation is unusable - clients degrade past a few dozen and models start picking the wrong one. It reads everything from the live instance at call time, so enabling a plugin adds operations it can already reach with no change here. The token is the security boundary and the README says so plainly: every operation the credential permits is reachable, so exploratory work wants a read-scoped token. The rest of this is about the contract not drifting, which is what makes any of the above trustworthy. Two CI jobs: - api-contract runs the parity gates and then regenerates the spec and fails if anything changed. Those gates already existed and already worked - they caught both routes added here, unprompted - but nothing ran them except by hand, and the committed spec had silently drifted by three operations, including two setup endpoints added the day before. - migrations-mysql is the job the header comment has been claiming for some time while not existing. It described "the REAL multi-site deploy path" and "what catches an Alembic regression on MySQL before it ships", and there was no such job. That is worse than no comment: it is the false confidence that let a migration ship which could not build a schema on a fresh MySQL database. The suite runs on SQLite, and SQLite accepts a foreign key onto a table that does not exist. CONTRIBUTING.md now says to run gen_openapi.py --refresh after changing a route, and that a route the sweep cannot classify belongs in PUBLIC_ENDPOINTS with a reason rather than hand-edited into the inventory, which the next refresh would overwrite. The new index route is declared there alongside the spec it indexes.
This commit is contained in:
@@ -2445,7 +2445,22 @@
|
||||
"auth": "none (reviewed: named in the public-read or mutation sweep)",
|
||||
"params": "not documented",
|
||||
"purpose": "The generated OpenAPI 3.1 spec (machine + LLM readable).",
|
||||
"example": "curl http://localhost:5001/api/docs/openapi.json"
|
||||
"example": "curl http://localhost:5001/api/docs/openapi.json",
|
||||
"queryparams": [
|
||||
{
|
||||
"name": "tag",
|
||||
"type": "string",
|
||||
"required": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/docs/operations.txt",
|
||||
"auth": "none (reviewed: named in the public-read or mutation sweep)",
|
||||
"params": "not documented",
|
||||
"purpose": "Every operation, one line each: method, path, tag, auth, summary.",
|
||||
"example": "curl http://localhost:5001/api/docs/operations.txt"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
@@ -4780,6 +4795,14 @@
|
||||
{
|
||||
"surface": "core-setup",
|
||||
"endpoints": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/setup/checklist",
|
||||
"auth": "jwt + role:admin",
|
||||
"params": "not documented",
|
||||
"purpose": "What is configured and what is not, with a link to each fix.",
|
||||
"example": "curl http://localhost:5001/api/setup/checklist -H \"Authorization: Bearer $TOK\""
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/setup/complete",
|
||||
@@ -4797,6 +4820,14 @@
|
||||
"example": "curl -X POST http://localhost:5001/api/setup/create-admin -H 'Content-Type: application/json' -d '{}'",
|
||||
"readsbody": true
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/setup/health",
|
||||
"auth": "jwt + role:admin",
|
||||
"params": "not documented",
|
||||
"purpose": "Post-setup reality check, including whether a restart is outstanding.",
|
||||
"example": "curl http://localhost:5001/api/setup/health -H \"Authorization: Bearer $TOK\""
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/setup/needs-admin",
|
||||
|
||||
Reference in New Issue
Block a user