Commit graph

19 commits

Author SHA1 Message Date
Jonas Rabenstein
da1d36739f web: use Form and Query from axum_extra
Otherwise Vec can not be deserialized.
2026-08-13 05:07:38 +02:00
Claude
84f5f24b6a dedupe HTML escaping into a shared html module
web_escape (main.rs) and escape_html (auth.rs, web.rs) were three
byte-identical copies of the same & < > " ' replacement chain. Moved
into src/html.rs as html::escape and used from all three call sites.
2026-08-13 04:12:13 +02:00
Claude
1a0ee71e6b sessions: expire after 1 day
Sessions previously had no expiry at all: a county_session cookie
was valid forever until an explicit /logout. Both session lookups
now reject rows older than 1 day (created_at-based, not sliding),
and db::delete_expired_sessions prunes expired rows so the table
doesn't grow unbounded; it's called during the existing OAuth-start
housekeeping alongside the oauth_states cleanup.
2026-08-13 04:12:13 +02:00
Claude
1473e726f3 webhook: compare secret in constant time
payload.secret != expected_secret short-circuits on the first
differing byte, which leaks timing information about how many
leading bytes of a guess are correct. Use subtle::ConstantTimeEq
instead.
2026-08-13 04:12:13 +02:00
Claude
85369069c3 remove remaining dead code left over from /dev endpoints
db::ensure_dev_athlete was never called (main.rs had its own,
inferior copy, removed in the previous commit). Config::dev_sync_days
and Config::require_api_key were only used by the now-removed
/dev/sync handlers.
2026-08-13 04:12:13 +02:00
Claude
1c3fd3d20f remove /dev/sync debug endpoints
/dev/sync/{api_key} and /dev/sync/{api_key}/{athlete_id} took a
personal Intervals.icu API key as a URL path segment, which leaks
into server/proxy access logs (and tower_http's TraceLayer spans),
browser history, and Referer headers. There's no legitimate reason
to keep a credential-in-URL debug backdoor around outside local
development, so it's gone along with its handlers.

This also removes main.rs's local ensure_dev_athlete, which
duplicated db::ensure_dev_athlete but used a racy check-then-insert
instead of an upsert (TOCTOU on concurrent dev syncs for the same
athlete).
2026-08-13 04:12:13 +02:00
Claude
5a49624435 perf: batch county-crossing detection into one query per activity
geo::crossings_between issued one DB round trip per consecutive GPS
sample pair (tens of thousands per multi-hour activity), even though
almost every segment stays inside a single county and produces no
crossing at all.

geo::crossings_for_track batches all segments of a track into a
single query via UNNEST ... WITH ORDINALITY. The per-segment geometry
logic (endpoint county lookup via the GiST index, boundary
intersection, ST_LineLocatePoint for the fractional position) is
unchanged, it now just runs once per activity instead of once per
segment.
2026-08-13 04:12:13 +02:00
Jonas Rabenstein
2ab16a68b7 merge 2026-08-13 03:54:14 +02:00
Jonas Rabenstein
961d6665b5 fmt 2026-08-13 03:04:13 +02:00
Jonas Rabenstein
859603399a sync 2026-08-13 02:43:17 +02:00
Jonas Rabenstein
3cfd5bdd6c add map and clicks 2026-08-12 17:57:25 +02:00
Jonas Rabenstein
45bcc13788 state 2026-08-12 17:49:27 +02:00
Jonas Rabenstein
eda8e76a20 fixups 2026-08-12 14:24:50 +02:00
Jonas Rabenstein
89091a03d3 dev api key 2026-08-12 14:02:12 +02:00
Jonas Rabenstein
06c837b244 fixes 2026-08-12 13:48:51 +02:00
Jonas Rabenstein
189803d24d fixup! fixup! fix nix develop psql setup 2026-08-12 13:38:35 +02:00
Jonas Rabenstein
f4405db550 fixup! fix nix develop psql setup 2026-08-12 13:37:37 +02:00
Jonas Rabenstein
53329182bd fix nix develop psql setup 2026-08-12 13:31:44 +02:00
Jonas Rabenstein
a9d22e8312 chatgpt 2026-08-12 13:24:01 +02:00