Skip to content

feat: deprecate-and-observe PR #984's audited apiv2 endpoints (registry)#1025

Merged
edwh merged 3 commits into
masterfrom
feat/deprecate-apiv2-audited-endpoints
Jul 9, 2026
Merged

feat: deprecate-and-observe PR #984's audited apiv2 endpoints (registry)#1025
edwh merged 3 commits into
masterfrom
feat/deprecate-apiv2-audited-endpoints

Conversation

@edwh

@edwh edwh commented Jul 9, 2026

Copy link
Copy Markdown
Member

Summary

Applies the deprecate-and-observe mechanism (PR #1021) to the 17 audited apiv2 endpoints that PR #984 would hard-delete — so they're retired safely (mark → watch real traffic → delete once confirmed silent) instead of deleted on the strength of a static audit.

Each endpoint is wrapped in deprecation.Marker("METHOD /path", "2026-08-01"), which:

  • logs one Loki hit per call (with caller identity for chase-down),
  • sets Deprecation + Sunset response headers,
  • registers itself so the nightly monitor:deprecated-endpoints report can observe it.

Relationship to #984

This is the deprecate-and-observe alternative to #984's apiv2 hard-deletes. #984 should drop its apiv2 route/handler/test/swagger deletions (its routing/spatial deletions + OpenAPI doc audit can stand). Once the nightly report shows an endpoint silent past its sunset, a follow-up deletes it — the same end state, reached with evidence. (#984 is also 149 commits behind master, so it needs a rebase regardless; this PR is cut fresh from master.)

Why a registry, not the spec or a config map

The monitor:deprecated-endpoints command needs, per endpoint, a sunset date. Two things ruled out the obvious homes:

  • Not the OpenAPI spec. swagger.json is go-swagger-generated at build (Dockerfile). Empirically: // Deprecated: true survives generation, but an x-sunset vendor extension breaks generation entirely (swagger:route has no slot for it). So the date can't live in the spec.
  • Not a config map. A batch-side map of {endpoint: sunset} can drift from the actual Marker() calls. A config entry without a matching Marker() → zero logs → the command falsely reports "safe to retire" and a live endpoint gets deleted. That's the exact failure the feat: safe endpoint deprecation-and-observe (deprecate → watch Loki → retire/chase) #1021 hardening pass guarded against.

The registry (the Marker() calls are the source of truth, served at GET /apiv2/deprecated) makes the observed set and the hit-logging the same act, so they can't drift. The batch command reads that endpoint — which is also simpler than parsing the spec (no {id}:id mapping; Go emits the Fiber form directly).

Endpoints deprecated (sunset 2026-08-01)

GET /activity, GET /messages, GET/PUT/PATCH/DELETE /isochrone, DELETE /message/:id, GET /modtools/admin/:id, GET /modtools/alert/:id, PATCH /config/admin, DELETE /noticeboard/:id, POST /story, DELETE /story/:id, POST /team, DELETE /team, PATCH /microvolunteering, GET /simulation.

(routing + spatial endpoints in #984 stay hard-deleted — they're internal service-to-service, deploy-atomic, not reachable by the web/app/external populations.)

Test plan

  • Go — full suite 3453 passed / 0 failed (the 17-call-site Marker(endpoint, sunset) change compiles across the tree; new deprecation tests cover headers, the logged pattern, List(), and GET /deprecated).
  • Laravel — full suite 4788 passed / 0 failed (DeprecatedEndpointService now reads /deprecated; command retire/still-in-use/could-not-check split; fail-loud on unreachable).
  • Vitest / Playwright — backend-only change; Vitest run locally, Playwright via CI (fresh containers).
  • In-container end-to-end — rebuilt apiv2 serves GET /apiv2/deprecated with all 17 entries; the batch container fetches it and the command runs correctly ("No deprecated endpoints past their sunset date", since all sunset 2026-08-01). This caught a real bug pre-merge: the endpoint is under the /apiv2 group prefix, so apiv2_deprecated_url needed /apiv2/deprecated.

edwh and others added 2 commits July 9, 2026 15:58
…istry approach)

Instead of #984's hard-deletes, wrap the 17 audited apiv2 endpoints in
deprecation.Marker(endpoint, sunset) so they log a Loki hit per call and carry
Deprecation/Sunset headers, and let monitor:deprecated-endpoints observe them.

Design: the Marker() calls are the single source of truth (registry), exposed via
GET /deprecated, because the served OpenAPI spec is go-swagger-GENERATED and its
swagger:route form can't carry an x-sunset extension (empirically: x-sunset breaks
generation; Deprecated:true survives). A registry (vs a config map) makes the
observed set and the hit-logging the same act, so they can't drift into a false
'safe to retire'.

- Go: Marker(endpoint,sunset)+registry+List()+GET /deprecated; 17 routes wrapped; tests.
- PHP: DeprecatedEndpointService reads GET /deprecated (not swagger.json); config
  apiv2_swagger_url -> apiv2_deprecated_url; command + tests updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CWbC1th5ZKGQswSoW1X2eg
In-container e2e caught it: GET http://apiv2:8192/deprecated 404s; the route is
registered under the /api and /apiv2 groups, so the reachable URL is
/apiv2/deprecated. Verified batch->apiv2 fetch returns all 17 registered endpoints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CWbC1th5ZKGQswSoW1X2eg
@netlify

netlify Bot commented Jul 9, 2026

Copy link
Copy Markdown

Deploy Preview for golden-caramel-d2c3a7 canceled.

Name Link
🔨 Latest commit 260a379
🔍 Latest deploy log https://app.netlify.com/projects/golden-caramel-d2c3a7/deploys/6a4fc1d83c51b8000849be0a

swagger.json is go-swagger-generated at build and x-sunset breaks generation, so
the sunset date moved into deprecation.Marker() (served at GET /apiv2/deprecated).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CWbC1th5ZKGQswSoW1X2eg
@FreegleGeeks FreegleGeeks added CI: Running CI build is currently running CI: Passed CI build passed and removed CI: Running CI build is currently running labels Jul 9, 2026
@edwh edwh merged commit 214b7c7 into master Jul 9, 2026
9 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI: Passed CI build passed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants