feat(api): generate and commit the API deployment OpenAPI spec - #2237
Draft
chandrasekharan-zipstack wants to merge 4 commits into
Draft
feat(api): generate and commit the API deployment OpenAPI spec#2237chandrasekharan-zipstack wants to merge 4 commits into
chandrasekharan-zipstack wants to merge 4 commits into
Conversation
The published Python clients and their generated SDKs are built from a spec of the deployment execute/status endpoints, which until now was produced by a script living outside this repo — so a route or serializer change here could silently invalidate it. The schema annotation for DeploymentExecution now lives next to the view, and `manage.py generate_docstudio_spec` writes specs/docstudio-oss.json. A unit test regenerates and compares, so drift fails in this repo's existing CI tier rather than in a client repo, with no database or extra CI job needed. The generated spec is unchanged from what the external script produced, apart from a root `tags` array — clients had nowhere to read group descriptions from. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014f9oEEYspPH4fmPULTnLkJ
The committed spec is what published clients are generated from, so the places where it disagreed with the server are places every SDK inherits. - Declare the bearer scheme the endpoints enforce. DRF's unset authentication default was being introspected as a decision and published session and basic auth, which these endpoints do not accept. - Declare the failures a caller has to handle (400/401/403/404/409/429) and describe the 406, so a generated client can branch on them. - Derive the response model from the serializer that builds the response, which drops `workflow_id` -- a field no code path produces. - Stop shadowing `files`: the real field carries the binary annotation, so a change to it now moves the spec. - Drop the MCP operations. MCP speaks JSON-RPC over one POST, so it had no REST shape to describe and was published with guessed responses, no security, and an internal docstring as its description. - Say in the shipped text that a status read is one-shot, and that documents may be supplied as files or presigned URLs. The gate had the same blind spots. It now resolves the real mount instead of comparing against a hand-written copy of it, fails when the generator reports a diagnostic instead of certifying its guess, and asserts the auth scheme and error statuses. Verified by mutation: moving the mount, adding a response field, changing the `files` constraint and dropping the auth annotation each redden the suite, and none of them did before. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014f9oEEYspPH4fmPULTnLkJ
The deployment endpoints are the public API surface, and the generated clients carry this title into their own documentation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014f9oEEYspPH4fmPULTnLkJ
The spec describes one endpoint today, and five of these tests read it by unpacking a single item or by indexing get and post directly. The first endpoint added turns all five red for no reason, and a GET-only one raises KeyError. They now walk whatever the spec documents. The drift and diagnostics gates are unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014f9oEEYspPH4fmPULTnLkJ
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Why
The published Python clients (
unstract-client) and the SDKs generated for them are built from an OpenAPI description of the API deploymentexecute/statusendpoints. That description was being produced by a script living outside this repository, so a route, serializer or response change here could silently invalidate it — the breakage would surface later, in a client repo, against a spec nobody in this PR could see.This moves generation in-repo and makes drift a test failure.
What
drf-spectacularadded as a backend dependency;DEFAULT_SCHEMA_CLASSandSPECTACULAR_SETTINGSset insettings/base.py. Both are read only during schema generation — no request-time behaviour changes.DeploymentExecutionnow sits above the view inapi_deployment_views.py. It exists because the introspected schema is wrong in ways that matter to a generated client: a bareFileFieldmaps toformat: uri(correct for output, wrong for a multipart upload),result: nullwhile an execution is pending crashes a generated deserialiser withoutallow_null, andoperation_id/tagsdecide the command names and module paths clients expose.api_v2/deployment_spec_urls.py— a urlconf that mirrors the real mount. Generating against the included sub-urlconf drops the prefix and produces paths the server does not serve.manage.py generate_docstudio_specwritesspecs/docstudio-oss.json(sorted keys, so the committed file is a usable drift signal).--checkfails instead of writing.api_v2/tests/test_docstudio_spec.pyregenerates and compares. It runs in the existingunit-backendgroup — no database, no new CI job, and no second copy of the env block.Regenerating
Change a route, a serializer or the annotation, then in
backend/:and commit the result. The test tells you this in its failure message.
Testing
658 passed, 1 skippedin the backend unit suite (the tier this lands in), including the two new spec tests. Verified the generated spec is byte-identical to what the external script produced, apart from the roottagsarray — clients had nowhere to read group descriptions from, which is the one deliberate addition.🤖 Generated with Claude Code
https://claude.ai/code/session_014f9oEEYspPH4fmPULTnLkJ