Skip to content

fix(api): return 422 for an unknown concelho on v2 incident endpoints (#27) - #49

Merged
tomahock merged 1 commit into
mainfrom
fix/v2-invalid-concelho-422
Oct 26, 2026
Merged

tomahock merged 1 commit into
mainfrom
fix/v2-invalid-concelho-422

Conversation

@tomahock

Copy link
Copy Markdown
Member

Closes #27

Problem

?concelho= on the v2 incident endpoints returned 200 {"success": true, "data": []} for any value, even ???, so clients cannot tell a typo from "no fires".

Change

  • App\Support\Concelho: known municipalities = Location level 2 names (plus Espanha), lower-cased and cached for 24h. If the locations collection is empty, validation is skipped (fail open).
  • IncidentController::concelhoFilter() used by GET /v2/incidents/active, /v2/incidents/active/kml and /v2/incidents/search:
    • absent or empty → no filter (unchanged);
    • unknown or non-string (concelho[]=…) → 422 {"success": false, "error": "invalid_concelho", "message": "Unknown concelho: ???"};
    • known → matches the value as sent or the casing the ingestion jobs store (Vila Nova De Gaia), so Vila Nova de Gaia / vila nova de gaia now find fires and existing exact values keep working (whereIn, still uses the index).
  • Known concelho with no fires still returns 200 with an empty list.
  • v1/legacy endpoints are unchanged.
  • OpenAPI: new concelho-v2.yaml parameter (optional, case-insensitive, 422 on unknown) and 422 response on the three paths. v2-search previously documented concelho as required, which it isn't.

Tests

  • New tests/Feature/Controllers/IncidentController/ConcelhoFilterTest.php (5 tests): 422 on ??? (active + search), 422 on array, case-insensitive match, empty list for known concelho, no filter when absent/empty. 3 of them fail on main.
  • Full suite against a throwaway MongoDB 7: 80 tests pass.

Deploy

Deploy as usual. No env changes, no migrations. The concelho list is cached for 24h under locations.concelhos.v1 (php artisan cache:forget locations.concelhos.v1 after changing locations).

⚠️ Behaviour change for API clients: requests with an unknown concelho now get 422 instead of an empty 200.

🤖 Generated with Claude Code

…#27)

/v2/incidents/active, /v2/incidents/active/kml and /v2/incidents/search
returned 200 with an empty list for any concelho, even "???". The value
is now checked (case-insensitively) against the known municipalities
(Location level 2, cached for a day) and an unknown or non-string value
returns 422 {"success": false, "error": "invalid_concelho"}.

Matching also accepts the casing the ingestion jobs store
("Vila Nova De Gaia"), so "Vila Nova de Gaia" now finds fires too while
exact values keep working.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-26T15:17:58.897042Z c27a5c2 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@tomahock
tomahock merged commit 5520aff into main Oct 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

V2 api - Add 4xx error handling on invalid query string parameter

1 participant