feat: complete published registry contracts and gated SRO ingestion
All checks were successful
Mostovik Backend CI/CD / Tests and lint (push) Successful in 3m55s
Mostovik Backend CI/CD / Build linux/amd64 release images (push) Successful in 3m43s
Mostovik Backend CI/CD / Deploy and verify internal main (push) Has been skipped
Mostovik Backend CI/CD / Deploy customer main (push) Has been skipped
Mostovik Backend CI/CD / Deploy dev (push) Successful in 1m45s
All checks were successful
Mostovik Backend CI/CD / Tests and lint (push) Successful in 3m55s
Mostovik Backend CI/CD / Build linux/amd64 release images (push) Successful in 3m43s
Mostovik Backend CI/CD / Deploy and verify internal main (push) Has been skipped
Mostovik Backend CI/CD / Deploy customer main (push) Has been skipped
Mostovik Backend CI/CD / Deploy dev (push) Successful in 1m45s
This commit is contained in:
67
tools/openapi/README.md
Normal file
67
tools/openapi/README.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Canonical OpenAPI
|
||||
|
||||
`GET /openapi.json` serves the OpenAPI 3 document bundled with the backend release.
|
||||
The Swagger UI and its Swagger 2 export remain available at `/`.
|
||||
|
||||
The source is the actual DRF serializers and view annotations. `build.mjs` converts
|
||||
Swagger 2 to OpenAPI 3, adds the source-record discriminated variants and the named
|
||||
ordering enum with comma-separated ordering, then validates the resulting document.
|
||||
Do not edit `src/core/openapi.json` or generated TypeScript by hand.
|
||||
|
||||
From the backend root (Python dependencies installed with uv):
|
||||
|
||||
```sh
|
||||
PYTHONPATH=src uv run python src/manage.py generate_swagger tools/openapi/swagger.json --overwrite --format=json --settings=settings.test
|
||||
cd tools/openapi
|
||||
bun install --frozen-lockfile --ignore-scripts
|
||||
bun build.mjs
|
||||
bun run apigen
|
||||
bun run type-check
|
||||
```
|
||||
|
||||
The runtime gate also validates rendered responses from the real DRF list/detail
|
||||
views against Orval's generated Zod schemas, including every documented HTTP
|
||||
status. Generate its synthetic fixtures in the isolated test database, then run:
|
||||
|
||||
```sh
|
||||
# From the backend root. The parent directory of this explicit path must exist.
|
||||
OPENAPI_RUNTIME_FIXTURES=/tmp/mostovik-openapi-runtime.json PYTHONPATH=src uv run pytest tests/apps/organizations/test_openapi_runtime_fixtures.py -q
|
||||
cd tools/openapi
|
||||
bun run apigen
|
||||
bun run contract-check /tmp/mostovik-openapi-runtime.json
|
||||
```
|
||||
|
||||
Zod is pinned to 4.3.6. The gate covers a full Budget payload with unknown raw
|
||||
fields, all five SME size units, nullable SRO admission dates, mixed/filtered lists,
|
||||
empty arrays and zero counts, and 400/404 errors. Parsed responses must equal the
|
||||
original JSON so that an apparently successful parser cannot silently discard
|
||||
raw keys. Ordinary pytest runs write no fixture file; writing is enabled only by
|
||||
`OPENAPI_RUNTIME_FIXTURES`. No live upstream requests or business databases are
|
||||
used. The generated validators are disposable build output, never handwritten.
|
||||
|
||||
Bun is pinned to 1.3.9 in CI; the tool dependencies are locked in `bun.lock`.
|
||||
CI regenerates the source Swagger document, runs `bun build.mjs --check`, generates
|
||||
a client and compiles a strict TypeScript fixture. It fails if the bundled contract
|
||||
is stale, invalid, loses discrimination, or removes the named ordering enum.
|
||||
|
||||
For the frontend, copy the bundled document to its `openapi.json`, then run its own
|
||||
`bun run apigen` and `bun run type-check`. Keep source-group checks before reading
|
||||
source-specific payloads. Multipart upload operations now have one accurately
|
||||
documented content type, so Orval generates `...Mutation` rather than the former
|
||||
multi-content-type `...MutationWithFormData` name. The generated function still
|
||||
constructs FormData and sends multipart data.
|
||||
|
||||
Before accepting an upgraded live dataset:
|
||||
|
||||
```sh
|
||||
python src/manage.py migrate --noinput
|
||||
python src/manage.py normalize_published_registry_payloads
|
||||
python src/manage.py normalize_published_registry_payloads --apply
|
||||
python src/manage.py build_source_record_exports
|
||||
```
|
||||
|
||||
The first normalization command is a dry run. Applying it preserves record UIDs,
|
||||
publication timestamps and artifact IDs, but atomically increments the affected
|
||||
artifact content revisions. New export tickets return 503 until a matching export
|
||||
generation is built; already issued tickets keep their pinned generation.
|
||||
SRO access remains gated as described in `docs/sro-membership-source.md`.
|
||||
Reference in New Issue
Block a user