Files
Aleksandr Meshchryakov 18971d33ec
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
feat: complete published registry contracts and gated SRO ingestion
2026-09-14 17:01:02 +02:00
..

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):

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:

# 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:

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.