docs(openapi): Declare API lifecycle status

Summary

Update operations in api/openapi/v1.yaml to declare x-gitlab-lifecycle: experiment. The extension is how a consumer of https://api.gitlab.com/rest/ learns the management API is not generally available; the document carried that claim nowhere else. Vocabulary and placement follow the API style guide: operation-level, experiment or beta, and a generally available operation drops the key rather than declaring a third value.

Two gates keep the sweep complete as operations are added. rule/operation-lifecycle in api/openapi/redocly.yaml fails lint:openapi on a missing value or one outside the vocabulary; it sits under the management@v1 entry rather than the root rules block, so it does not reach gitlab-v1.yaml. TestContract_EveryOperationDeclaresLifecycle pins the value to experiment, which the lint rule deliberately leaves open.

gitlab-v1.yaml is untouched: it authenticates the calling service, not an end user, so it has no consumer to signal maturity to. The pages job renders both documents, so the asymmetry is deliberate rather than an omission. This is feature maturity, unrelated to the soft-delete lifecycle that artifact-registry::lifecycle and ADR-009's lifecycle policies mean by the word. No Bruno or e2e catalog change: no operation, URL, method, body, or response code moves.

Governing ADRs

ADR-009: API Design relates; this conforms, and no amendment is needed. It governs the API surfaces, endpoint structure, and versioning prefixes, none of which move here — no route added, removed, or renamed, no prefix, auth mode, or pagination rule changed.

ADR-009's two OpenAPI clauses ("payloads live in the corresponding OpenAPI specifications", and "payload changes do not require ADR updates") are about payloads and schemas, so they do not cover operation metadata directly; they establish the sufficient weaker point that the documents' contents are the codebase's business. No ADR addresses vendor extensions or maturity markers — grep -ri openapi docs/adr/ returns only those two clauses. Mirror freshness checked per docs/adr/README.md: no upstream decision commits since the last local change.

Testing

TestContract_EveryOperationDeclaresLifecycle walks every declared operation and requires the extension, modeled on TestContract_EveryResponseDeclaresXRequestID beside it; loadContractDoc runs doc.Validate, so a malformed extension fails there too.

Related to https://gitlab.com/gitlab-com/gl-infra/api-docs/-/work_items/42

Edited by Chance Feick

Merge request reports

Loading
Loading