August was the month Edge Model grew a memory. In July the tool learned to ingest results and push real-time updates. In August it learned to persist your preferences across sessions, track how its predictions compare to market odds over time, and let groups of people compete against each other — and against the model — on the same fixtures. Here is what we shipped across the month, from 0.6.0 through 0.6.29.
The tool got an identity layer
The most consequential structural change of the month was free user accounts. You can now register with an email and password, and every preference you set — your last loaded league, favourite teams, the tab you had open — is synced to the server. Sign in on a second device and the app hydrates immediately from your stored prefs: no re-selecting a competition, no reconfiguring your view. Cross-device continuity went from zero to automatic.
The account system is built on HMAC-signed stateless session tokens. There is no session store to manage; the server signs each token with a stable secret and verifies the signature on every request. Sessions survive server restarts and deployments. A 30-day sliding expiry means you stay logged in indefinitely as long as you use the app at least monthly. Password reset via email was the follow-on: a signed time-limited reset link lands in your inbox within seconds and expires after an hour whether used or not.
The model's predictions got held accountable
A Bayesian model that cannot be evaluated is a black box you are being asked to trust. That started changing in August. We added edge accuracy tracking: every league result that the model had pre-match odds data for now records a triple of (model probability, market probability, actual outcome) to a private log. The model evaluation protocol — Brier score, calibration across ten probability deciles, prior sensitivity — was formalised into a reusable script and then wired into a public-facing performance page at /metrics.
The metrics page updates live as results are recorded. It shows the model's cumulative Brier score for the loaded league, a per-match trend chart so you can see whether accuracy is improving or degrading mid-season, a calibration table, and — for leagues where enough edge log data exists — a comparison against market Brier scores. The question "is the model actually any good?" now has a real answer you can inspect rather than a claim you have to take on faith.
The fixture experience got sharper
Two things that sound small made a material difference to the daily experience of using the Fixtures tab. The first was the edge pill shimmer. Previously, fixture cards would appear with an empty pill slot that might stay empty or might fill in — there was no visual distinction between "odds are loading" and "odds are not available for this match." We replaced the blank state with a shimmer animation that plays while the odds fetch is in flight and resolves either to a real edge pill or to nothing, cleanly, with no intermediate flicker.
The second was the last-ingestion timestamp. When you open the Fixtures tab on a Sunday morning, you might be looking at data that was ingested at 06:00 UTC, or you might be looking at data from three days ago if the scheduler had a quiet week. A "Last updated X ago" label in the standings header now tells you exactly when the model state last changed. No more guessing whether the standings reflect the most recent matches.
Security and reliability got serious attention
Adding user accounts meant there was now something genuinely worth protecting. August included a security hardening pass: Content Security Policy and HSTS headers, a CORS lockdown to the production domain, a blocklist that returns 429 for known exploit probe paths without logging them as real errors, and a fix to the rate-limiting logic that had been keying on a proxy IP instead of the actual client IP. The net result is a server that handles abuse patterns gracefully rather than noisily.
Operational visibility got a similar upgrade. Structured logging now gives every server message a severity prefix — [ERROR], [WARN], [INFO] — so production logs are scannable without reading prose. Slack error alerts fire for all 5xx responses and selected 4xx events, so a production problem surfaces in a notification rather than waiting to be discovered. The combination of structured logs and real-time alerts means the difference between knowing about a problem and finding out about it three hours later when a user mentions it.
The social layer became a real competition
The biggest feature of the month was Group Picks. The old picks tab was a single-device log — one person submitting predictions, the model as the only benchmark, no stakes. Group Picks replaces that with a genuine multi-account competition. Create a group for a specific league, copy the invite link, and send it to anyone you want to include. Each member submits their own H/D/A predictions for upcoming fixtures from their own account. Picks are hidden from other members until each fixture kicks off, then revealed and scored.
The leaderboard ranks all members by correct picks and lists the Edge Model itself as a synthetic player — its own pre-kickoff probability estimates translated into H/D/A form. Beating the model consistently over a full season is the implicit benchmark of the whole feature. All group state updates propagate via Server-Sent Events so the leaderboard and submitted-pick indicators refresh in real time across everyone's open tabs. Someone submits a pick, and within a second the "submitted" indicator appears for every other member without a page refresh.
The join flow handles the guest case cleanly. If you receive an invite link and are not signed in, the invite code is saved to sessionStorage. The auth modal opens. Once you register or log in, the join completes automatically — you arrive directly in the group view without ever needing to click the link again.
The things that did not make headlines
August also included a data integrity panel for detecting mismatches between recorded results and external data, a delete-specific-result endpoint for correcting history without a full replay, a custom preset upload feature for authenticated users who want to load competitions we do not cover, and a period-over-period analytics dashboard so we can see whether engagement is trending up or down week by week. Seven bug fixes closed edge cases that had been accumulating since July — ingestion preset isolation, odds querying the wrong sport in league mode, fixture card names wrapping on mobile, a second-order error in the request logger that was flooding logs with noise.
None of those individually feels like a release. Collectively they represent the difference between a tool that handles the expected case and one that handles the unexpected case without breaking. The model is now running on 29 versions of polish it did not have at the start of August, and the five major European leagues are three weeks into their seasons with every result ingested automatically. The September agenda is shorter; the August agenda was the infrastructure that makes September possible.