feat: implement spatial boundary checks for Bari municipal area in GeoJSON handling

This commit is contained in:
gabdevele
2026-06-15 14:45:38 +02:00 Unverified
parent 088a2ed866
commit aab7420706
13 changed files with 310 additions and 15 deletions
+5
View File
@@ -51,6 +51,7 @@ Authorization: Bearer <token>
public external-team summary link
- `GET /open-data/reports`
anonymized reports in `RESOLVED` or `CLOSED`
filtered to Bari municipal boundary
## User Reference / Personal
- `GET /report-categories`
@@ -63,6 +64,7 @@ Authorization: Bearer <token>
## Report Endpoints
- `POST /reports`
create citizen report, optional inline `media`, area inferred by GeoJSON
coordinates must stay inside allowed Bari municipal boundary
- `GET /reports`
citizen sees own reports; operator/admin see all
- `GET /reports/{id}`
@@ -111,6 +113,7 @@ Authorization: Bearer <token>
- `PATCH /admin/categories/{id}`
- `POST /admin/areas`
- `PATCH /admin/areas/{id}`
area polygon must stay inside allowed Bari municipal boundary
- `POST /admin/teams`
- `PATCH /admin/teams/{id}`
- `GET /admin/users`
@@ -153,3 +156,5 @@ Authorization: Bearer <token>
- `assignments` is historical external team linkage only.
- Feedback does not auto-close report.
- Public intervention summary exposes citizen phone by design, but not email or full surname.
- Report coordinates are constrained to Bari municipal boundary.
- Admin-created area polygons must stay inside Bari municipal boundary.
+4
View File
@@ -47,6 +47,8 @@ Effective permission helpers:
- `take` exists for `OPEN -> UNDER_REVIEW` without team assignment.
- External team link is public, revocable, tied to current assignment, hashed in
`intervention_access_links`.
- Spatial scope is constrained to Bari municipal boundary from
`allowed_boundaries.code = 'BARI'`.
## Status Machine
- Allowed statuses: `OPEN`, `UNDER_REVIEW`, `ASSIGNED`, `IN_PROGRESS`,
@@ -68,6 +70,7 @@ Effective permission helpers:
- `moderation_flags`
- `report_category_team_categories`
- `intervention_access_links`
- `allowed_boundaries`
## HTTP/Error Conventions
- `401`: missing/invalid auth
@@ -94,4 +97,5 @@ Output path:
hardcoded allowlist, not user input.
- Public intervention summary currently excludes email and full surname, but
still exposes citizen phone by design.
- Allowed-area containment for admin areas is vertex-based, simple not strict GIS-hard.
- No frontend doc set here beyond API/OpenAPI docs.
+3
View File
@@ -36,6 +36,8 @@ Schema truth is `migrations/*.sql`. This file is compact human map of current DB
- `report_category_team_categories`
explicit compatibility mapping:
report category -> team category
- `allowed_boundaries`
active allowed municipal containment geometry, currently seeded with `BARI`
## Report Domain
- `reports`
@@ -101,3 +103,4 @@ Schema truth is `migrations/*.sql`. This file is compact human map of current DB
- No dedicated table for external team personnel
- No route-optimization/routing tables
- No audit table for intervention link access beyond `last_accessed_at`
- Containment check for admin area polygons is simple vertex-inside check
+12 -3
View File
@@ -40,9 +40,10 @@ public revocable link generated by operator/admin.
### Citizen flow
1. Register/login.
2. `POST /reports` with category, coordinates, address, description, optional media array.
3. Backend infers `area_id` by GeoJSON polygon match when possible.
4. Report starts `OPEN`, status history row inserted.
5. Citizen can:
3. Backend first rejects coordinates outside Bari municipal boundary.
4. Backend infers `area_id` by GeoJSON polygon match when possible.
5. Report starts `OPEN`, status history row inserted.
6. Citizen can:
- list own reports
- read detail/history/media
- chat on own report
@@ -72,6 +73,7 @@ public revocable link generated by operator/admin.
### Admin flow
- Create/update categories, areas, teams
- Area GeoJSON must stay inside Bari municipal boundary
- List users, edit roles, ban/unban
- Read stats
- Review moderation queue and resolve/dismiss flags
@@ -89,6 +91,13 @@ public revocable link generated by operator/admin.
- `GET /interventions/{token}` returns public summary for field team:
report data, location, media, assigned team, masked citizen identity, phone.
## Spatial Boundary Rule
- `allowed_boundaries` stores active municipal allowed area.
- Current seed uses `BARI`.
- Report coordinates outside boundary are rejected.
- Admin area polygons outside boundary are rejected.
- Open data output is filtered again by same boundary.
## Current Notifications / Rewards / Moderation
- Notifications: local in-app only.
- Reward points: awarded once per `(report_id, reason)`.
+3
View File
@@ -38,6 +38,7 @@ moderate abuse, and inspect operational stats.
- create report with category, coordinates, address, description
- optional inline media on creation
- later media upload up to total 5 files
- coordinates must stay inside Bari municipal boundary
- area inferred by GeoJSON polygon match
- citizen report list/detail/history/media
- operator queues:
@@ -79,6 +80,7 @@ moderate abuse, and inspect operational stats.
### Admin
- create/update categories
- create/update areas
area polygons must stay inside Bari municipal boundary
- create/update teams
- list users, update roles, ban/unban
- global stats including area/category/team resolution aggregates
@@ -87,6 +89,7 @@ moderate abuse, and inspect operational stats.
- active area list
- anonymized resolved/closed open-data export
- public intervention token endpoint
- open-data output filtered to Bari municipal boundary
## Current Workflow Summary
### Citizen