- configs/tunnel.yaml: replace hardcoded address with wildcard
*.projectshitpost.fun:8443 (covers both edge nodes)
- internal/tunnel/tunnel_test.go: use TEST-NET-1 (RFC 5737) IP
192.0.2.10 instead of a real one
- docs/AUTH.md: token issue command now runs on stats host
- Skip rows with null/malformed timestamps instead of silently
re-stamping with time.Now() (data corruption hidden behind a
fallback). Drops the time import.
- Replace ad-hoc parentDir() with stdlib filepath.Dir().
- Add t.Fatal error checks to TestExtractRows_SkipsBadExtra
(CREATE TABLE / INSERT) and switch sql.Open to checked form.
- New TestExtractRows_SkipsBadTimestamp covers the null-ts path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a Store-method API for the RecordSpeedTest RPC (Task 8) and the
retention sweep (Task 14):
- SaveSpeedTest / ListRecentSpeedTests / DeleteSpeedTestsBefore
- SpeedTest struct (no json tags; that decision deferred to Task 10)
Schema lives in migrations/002_speedtests.sql to match the existing
embed.FS pattern (rather than inline in Go). The migrate() loop now
iterates every *.sql in lexical order, so future migrations drop in
without code changes. Both files use CREATE ... IF NOT EXISTS so the
existing 001 migration remains idempotent on already-initialised DBs.
CHECK constraints enforce node IN ('fl','pl1') and non-negative metric
values at the DB level. country has no DB CHECK — validation belongs
to the gRPC handler in Task 8.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Source-of-truth gitea repo lives at bergamot/stats-gateway, not
bergabruh/stats-gateway (404). Fixes user-facing dashboard footer
+ about page links.
Note: Go module path 'gitea.projectshitpost.fun/bergabruh/...' is
still wrong but rename touches every import + protobuf — separate
refactor PR.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>