Problem
Today, the area_manager role is scoped by a flat list of numeric area IDs in the user.geofence column (e.g., [364, 935, 53, ...]). This has two limitations:
- No nesting — granting "UK area admin" requires listing every UK community (
country + 40+ community areas). If a new community is created inside the UK, it must be manually added to the geofence list.
- Static lists — an admin must maintain geofence lists manually, running DB queries to discover new areas within the permitted region.
Example: ollie has geofence = [364, 53, 79, 93, 98, 100, ...] (43 IDs for UK country + all communities). A cleaner model would be geofence = [364] and the API resolves "all areas nested within area 364."
Proposed solution
Allow a single parent area ID in the geofence to imply access to all child areas dynamically. The check changes from:
geofence.contains(&area_id)
to something like:
geofence.contains(&area_id) || is_nested_within_any(area_id, &geofence)
Where is_nested_within_any does a spatial containment check: the child area's centroid (or bounding box) falls within the geofenced parent area's polygon. This would also enable automatic access to newly created areas within the permitted region — no geofence list syncing required.
Implementation considerations:
- Spatial containment: the API already stores area polygons as GeoJSON in
area.tags.geo_json. A centroid or bbox containment check against the parent area's geometry is sufficient. The area.bbox_west/south/east/north columns make this efficient (a quick index scan before the full polygon check).
- Fallback behavior: if the geofence contains a non-country area (e.g., a community), only that specific area is accessible — no implicit children because communities don't nest.
- Backward compatibility: existing flat-list geofences should continue working. The containment check is additive.
- Performance: for
add_area, the user can't create new top-level areas when geofenced — but they could create communities inside their permitted region. The containment check for one area is cheap; for listing, a bbox pre-filter avoids full-polygon checks.
Alternative considered
A geofence_mode column (flat vs nested) to opt in, but that adds schema complexity. Simpler to make the behavioral change transparent: if a geofenced parent area contains the target area, access is granted.
Related
area_manager role introduced in recent schema migrations (geofence column on user)
check_geofence() in api/src/service/area.rs is the central enforcement point
- Ref:
set_user_geofence RPC, add_area handler (blocks area managers with non-empty geofence from creating new areas)
Problem
Today, the
area_managerrole is scoped by a flat list of numeric area IDs in theuser.geofencecolumn (e.g.,[364, 935, 53, ...]). This has two limitations:country+ 40+communityareas). If a new community is created inside the UK, it must be manually added to the geofence list.Example:
olliehasgeofence = [364, 53, 79, 93, 98, 100, ...](43 IDs for UK country + all communities). A cleaner model would begeofence = [364]and the API resolves "all areas nested within area 364."Proposed solution
Allow a single parent area ID in the geofence to imply access to all child areas dynamically. The check changes from:
to something like:
Where
is_nested_within_anydoes a spatial containment check: the child area's centroid (or bounding box) falls within the geofenced parent area's polygon. This would also enable automatic access to newly created areas within the permitted region — no geofence list syncing required.Implementation considerations:
area.tags.geo_json. A centroid or bbox containment check against the parent area's geometry is sufficient. Thearea.bbox_west/south/east/northcolumns make this efficient (a quick index scan before the full polygon check).add_area, the user can't create new top-level areas when geofenced — but they could create communities inside their permitted region. The containment check for one area is cheap; for listing, a bbox pre-filter avoids full-polygon checks.Alternative considered
A
geofence_modecolumn (flatvsnested) to opt in, but that adds schema complexity. Simpler to make the behavioral change transparent: if a geofenced parent area contains the target area, access is granted.Related
area_managerrole introduced in recent schema migrations (geofence column onuser)check_geofence()inapi/src/service/area.rsis the central enforcement pointset_user_geofenceRPC,add_areahandler (blocks area managers with non-empty geofence from creating new areas)