maybe_start_location_tracking/2 matched %{track_location: true} in the
track_settings argument. No caller passes that key -- all five call sites
send %{map_id: _, track: true | false} -- so the clause never matched and
the function could not turn location tracking on. maybe_start_ship_tracking/2
had the identical defect.
Match on the state's active_maps instead: a character on at least one map
should be polling their location.
Without this, a character is stranded by an event they never initiated. When
a browser's presence lapses past the grace period the character is untracked
server-side, active_maps empties, and maybe_stop_tracking/2 clears
track_location. The character is still online in EVE throughout, and the only
other writer -- update_online/1 -- is gated on an online-status transition
that a character who stays logged in never produces. So the browser
reconnecting cannot restore it. update_location/1 then falls through to its
catch-all on every tick, and the character stops moving on the map while
every liveness signal keeps reporting healthy.
This is why #620 reports that toggling tracking off and on does not help but
relogging in EVE does: toggling routes through the dead clause, while
relogging produces the online transition that restores the flag as a side
effect.
Fixes#620
Review of the previous commit found that Ash returns NotFound wrapped
inside Ash.Error.Invalid, not as a bare struct. Verified against a live
query: `Api.Map.by_id(<missing uuid>)` returns
{:error, %Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{}]}}
so the bare-NotFound clause never matched. A genuinely missing map would
have propagated as a generic error and logged a spurious error line.
Match the wrapped shape as well. Confirmed `MapRepo.get/2` now returns
{:error, :not_found} for a missing map with no error log. No caller
depends on the :not_found atom specifically (all use wildcard or
with/else), so propagation of real faults is unaffected.
Also make track_character_on_map/2 clear stale per-map location caches,
mirroring TrackingUtils.track_character/4, which the helper claimed to
mirror but did not.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
MapRepo.get/2 flattened every error from Api.Map.by_id/1 into
{:error, :not_found}. That turned infrastructure faults into a
"map does not exist" signal: a DBConnection.OwnershipError in test
surfaced as "Failed to load map state" -> "map not loaded" ->
"Timeout waiting for map ... Check Map.Manager is running", pointing
at Map.Manager (which was running fine) instead of the real cause.
Keep the :not_found translation for a genuine Ash NotFound, and
propagate + log anything else.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
LiveView event handlers were trusting client-supplied record IDs without
verifying they belong to the user's current map/user scope. A logged-in
user could push another map's record UUID over the LV socket and act on
it. Affected handlers:
- cancel-subscription / edit-subscription / update_subscription
(cancel or upgrade any map's paid subscription by ID)
- characters_live.ex "delete"
(soft-delete any user's character and null their user_id)
- cancel_ping
(cross-map rally-ping cancellation broadcast)
- deleteSystemComment
(cross-map comment deletion)
- update_passage_mass
(cross-map wormhole passage mass corruption)
- updateCharacterTracking
(untrack another user's character on a shared map)
Also fixes a related numeric-trust bug in subscribe/update_subscription
where `period`, `characters_limit`, and `hubs_limit` were parsed without
bounds, allowing `period: "-1"` to produce a back-dated subscription
with a negative price.
Adds WandererAppWeb.HandlerAuth with focused helpers each handler now
routes through, plus 26 regression tests covering both the IDOR auth
checks and the bounded-int parsers.
- fix(mapper): Update `whClassName` values for C1 and C4 destination types
- refactor(mapper): Consolidate K162 and multi-destination checks in bookmark formatting helper
- fix(map): Remove `c4_to_ns?` check and small ship size constraint from connection operations
- feat(bookmarks): Add settings to ignore return holes and use a custom symbol for auto-indexing
- feat(settings): Add a `dependsOn` property to conditionally render settings
- fix(systems): Correctly apply chained index formats for auto-tag and custom label
- refactor(bookmarks): Pass target system info to `handleAutoBookmark` for return hole detection
- feat(mapper): Add UI for advanced customization of bookmark format variables
- feat(mapper): Implement custom string mapping and `{dest_class_index}` logic for bookmark names
- feat(settings): Add `bookmark_custom_mapping` to user settings
- fix(mapper): Treat linked signatures as wormholes for auto-bookmarking
- feat(mapper): Implement auto-tagging and auto-labeling logic for destination systems
- feat(settings): Add UI options to configure system auto-tag and auto-label formats
- feat(backend): Add new system auto-tag and auto-label settings to user preferences
- refactor(settings): Extract shared auto-format options into a constant
- feat(bookmarks): Add a dedicated 'Bookmarks' settings tab with advanced formatting options.
- feat(bookmarks): Implement auto-filling of a wormhole's temporary name based on its index.
- feat(bookmarks): Add setting to start wormhole bookmark indices from 0.
- feat(bookmarks): Add setting to enable or disable automatic copying of bookmark names.
- fix(bookmarks): Handle bookmark index 0 correctly in auto-naming calculations.
- refactor(settings): Move bookmark format setting to the new 'Bookmarks' tab.
- chore(api): Add new bookmark settings to the backend allowlist.
- feat(signatures): Automatically copy formatted bookmark name to clipboard on WH link or update
- feat(settings): Add support for text input fields in the settings UI for bookmark format
- feat(signatures): Add `k162Type` to custom info to specify K162 destination type
- refactor(map): Extract system class group logic into a `getSystemClassGroup` helper
- fix(signatures): Add error handling for malformed `custom_info` JSON
- fix(ui): Correct typo in `LINK_SIGNATURE_SETTINGS` constant
- feat(backend): Add `bookmark_name_format` field to user settings