Skip to content

Serving OpenAPI Specs - #38093

Draft
kaapstorm wants to merge 5 commits into
nh/api-openapi-generatorfrom
nh/api-openapi-serving
Draft

Serving OpenAPI Specs#38093
kaapstorm wants to merge 5 commits into
nh/api-openapi-generatorfrom
nh/api-openapi-serving

Conversation

@kaapstorm

Copy link
Copy Markdown
Contributor

Technical Summary

Serves the OpenAPI specs generated by PR #38092

Feature Flag

Safety Assurance

Safety story

Automated test coverage

QA Plan

Migrations

  • The migrations in this code can be safely applied first independently of the code. Pay particular attention to backward incompatible operations like RemoveField, RenameField, RemoveConstraint, and others described here that can cause errors when migrations are applied to a live database.

Rollback instructions

  • This PR can be reverted after deploy with no further considerations

Labels & Review

  • Risk label is set correctly
  • The set of people pinged as reviewers is appropriate for the level of risk of the change

yarn build now produces one Redoc page per generated spec into docs/api/dist/,
which is gitignored: deployed environments build static assets as a required
step, so committing roughly 3MB of generated HTML would buy nothing that the
committed specs do not already give us.

Chaining it onto yarn build rather than adding a separate CI step is what makes
that true everywhere the assets are built -- the Build Static Files job and a
production deploy alike -- instead of only where a workflow remembers to ask
for it. build-static.yml says so in its progress line.

DEV_SETUP explains that a local checkout needs the build before those pages
work, since yarn dev does not run it.
The views that publish the specs and the command that writes them need the same
notion of where the artifacts live. Defining it once means they cannot disagree.

Also computes description coverage per spec, so the reference index can show
which APIs are fully documented and which are only structurally generated.
Coverage resolves $ref and descends anyOf/oneOf/allOf branches rather than
reading schema['properties'] directly: case-v2's detail response is an anyOf
whose first branch carries 14 fields, and a direct read would count none of
them, publishing a denominator that understated the API's real surface.
/api/openapi.json serves the bundle and /api/docs/<slug>/openapi.json serves
one API's spec, with /.well-known/openapi.json as a discovery alias. The
well-known path is a de facto convention, not an IANA-registered URI.

Each response carries the requesting host as the servers default, so a client
that follows it reaches the deployment it fetched the spec from rather than
www.commcarehq.org. The ETag covers the host as well as the file contents,
because the served bytes differ per host.
Rendered from the catalogue at request time rather than generated, so it cannot
drift from what is actually documented, and a new API appears with no build
step.

It also shows how completely each API is described, which makes the remaining
documentation work visible instead of something a reader has to be told.
An unknown slug is rejected against the catalogue rather than the filesystem. A
missing artifact names the build command under DEBUG and logs a warning
otherwise, because in a deployed environment it means the asset build did not
run.
@dimagimon dimagimon added dependencies Pull requests that update a dependency file Risk: High Change affects files that have been flagged as high risk. labels Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file Risk: High Change affects files that have been flagged as high risk.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants