Skip to content

Retire the area dual-writer once setAreas accepts a trusted flag #838

Description

@hokiepokedad2

Blocked on jfberry/PoracleNG#217.

Every user-geofence area mutation bypasses SetAreasAsync and writes humans.area and profiles.area directly through IUserAreaDualWriter. The reason: PoracleNG's HandleSetAreas intersects the submitted list against fences with userSelectable == true for non-admins, and PoracleWeb serves user-drawn geofences with userSelectable: false on purpose — to keep their names out of the bot's !area picker and out of DM text. So the names were silently stripped, the UI showed optimistic success, and a refresh revealed the geofence gone.

#217 adds an opt-in trusted flag to POST /v2/humans/{id}/areas that lifts the userSelectable filter only — unknown fence names are still rejected, so a typo can't become a stored area matching nothing. It also returns what was stored and what was rejected, so a partly-ignored request stops looking like a fully-applied one.

Delete

grep -rn "HACK: trusted-set-areas" --include="*.cs" lists every site. UserGeofenceService holds eleven of them; AreaController one; the rest are the interface and DI.

AreaController.UpdateAreas gets simpler in two ways: PreserveOwnedAreasInHumanAsync after SetAreasAsync becomes unnecessary, and the new rejected array means we can surface a genuinely partial save instead of guessing.

Does NOT cover the override path

UserOwnedOverrideAreaProxy stays, and gets more load-bearing, not less.

override_areas on a tracking write is validated against the same fence set, and #217's tracking.go:298 builds it with settableAreaNames(deps, human, admin, false)trusted hardcoded false. There is no equivalent escape hatch on that path. Worse, #217 revives that check: validateOverrideFields gated on oc.permitted != nil, permitted came from AreaLogic, and main.go never set AreaLogic, so it was dead code on every tracking write. It now runs.

Raised on the #217 review; if it isn't taken there it needs its own upstream issue before this one can close completely.

Watch for

The dual writer is one atomic SaveChangesAsync spanning both tables. SetAreasAsync is one HTTP call. Sequencing several of them where there used to be one transaction is a new failure mode — a create that adds the area but leaves no user_geofences row, or the reverse. Work out the ordering deliberately rather than translating call-for-call.

RenameAreaInAllProfilesAsync is the subtle one (#408). On approval the old name is userSelectable: false and the promoted name isn't in PoracleNG's fence list yet, because the reload happens afterwards. trusted fixes the first half; the second half is an ordering problem that survives it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions