Skip to content

Issue #608 API deprecation lifecycle gap analysis

Baseline

The versioned v1 API already had one authoritative policy in docs/api/versioning.md. It required a replacement, OpenAPI deprecation metadata, public migration guidance, a retirement condition, and a documented migration period before removal. The backend already added API-Version: v1 to all v1 responses, and docs/api/openapi.yaml already described the public and consumer fixture-event JSON exports.

The remaining gap was demonstrable lifecycle behaviour: no implemented operation produced a standards-aligned deprecation signal, identified a concrete successor in the response, or showed the complete consumer path in the policy and OpenAPI.

Smallest safe mechanism

The implementation deprecates only:

GET /api/v1/fixtures/{fixtureId}/events/export.json

It remains fully available and returns the unchanged JSON export. The existing consumer-key equivalent is its successor:

GET /api/v1/consumer/fixtures/{fixtureId}/events/export.json

Both use the same controller, response representation and filtering model. The successor therefore provides a real, already-implemented migration target, without duplicating a route or fabricating a removal.

The route-specific middleware emits Deprecation: ?1 (RFC 9745) and an RFC 8288 Link header using rel="successor-version". It substitutes the fixture identifier and preserves the request query string, allowing a client to follow the exact replacement URL. It validates the mapping on application startup, rejecting missing/non-absolute replacement paths, duplicate entries, or replacement templates that lose path parameters. Browser clients can read the lifecycle headers through CORS.

No retirement date has been approved. Sunset is omitted rather than inventing a production promise; the policy specifies the coordinated update required if a date is later approved.

Acceptance-criteria traceability

Issue #608 criterion Evidence
One policy and a concrete lifecycle example docs/api/versioning.md remains the policy and now contains the complete response example.
OpenAPI marks the deprecated surface deprecated: true, successor guidance and documented response headers on the public JSON export.
Response metadata and replacement information Middleware emits Deprecation and a concrete successor-version Link. No Sunset is applicable without an approved retirement date.
Compatibility and no fake removal The existing public route/controller remains unchanged; health and other v1 routes receive no lifecycle metadata.
Automated verification deprecation-lifecycle.contract.test.ts covers compatibility, headers, query preservation, unaffected v1 behaviour, OpenAPI, and invalid replacement configuration.
Advanced API user-feedback Completed. P13 successfully completed API-03 on the deployed build under #612. #612 subsequently closed with an Accepted with documented limitations final gate result.

Scope and privacy review

The change is HTTP middleware and documentation only. It adds no database behaviour, credentials, secrets, internal data, new route, or retirement date.

AI Declaration

The preceding document was generated and edited with the assistance of Codex[GPT-5], and later reviewed, reconciled and edited for final-state accuracy with the assistance of ChatGPT-Web[GPT-5.6 Sol].