Releases: ernestdefoe/recruiting
Releases · ernestdefoe/recruiting
Release list
3.1.1 — audit hardening
Floxum audit hardening (→ ≥95). Cold-lock window 30→60s (headroom for CFBD + On3 timeouts), assertRegistered() guard on the API, native fetch → app.request, and admin settings wired through the translator.
3.1.0
What's Changed
A full internal code audit — one new admin setting, plus reliability, ethics, and type-safety fixes under the hood.
New
- Disable On3 headshots. A new admin toggle (Enable On3 player headshots) lets you stop all outbound traffic to On3 entirely — recruits then show star-tier initials avatars. The setting's help text documents exactly what the scrape does, and the admin panel now shows when headshots were last successfully refreshed.
Fixed
- No more request stampede on a cold cache. The first request for a recruiting class used to make two blocking outbound calls (~22 s) with no lock, so a burst of visitors each launched their own pair of fetches. A single-flight lock now guarantees at most one cold fetch; everyone else serves the warmed cache or retries automatically.
- Honest scraping. Removed the spoofed Chrome browser User-Agent used to bypass On3's bot detection (a ToS/identity-spoofing risk that could get the forum's IP blocked). The fetch now identifies itself truthfully.
- Layout-change detection. If On3 returns a page but almost no players parse out, the extension now logs a warning instead of silently dropping all headshots.
Internal
- The outbound HTTP client is now container-managed and injected, so operators can layer forum-wide middleware (logging, retry, proxy).
- The
/recruitingpage is fully TypeScript-type-checked (the prior@ts-nocheckescape hatch is gone), and the API URL is derived correctly for subdirectory installs.
3.0.0
What's Changed
- Build changelog from commits when release body is a placeholder
- Replace release-drafter with commit-based draft-release workflow
- Add workflow_dispatch trigger to publish-to-flarum.yml
- Convert to TypeScript (audit fix)
- docs: add Floxum marketplace badges to README
Full Changelog: 2.0.15...3.0.0
2.0.15
2.0.14
fix: address audit findings — drop dead widget, move enrichment off r…
v2.0.13
2.0.12
docs(README): document caching strategy + queue-worker recommendation The architectural changes around stale-while-revalidate caching + RefreshRecruitsJob earn no benefit on Flarum's default `sync` queue driver — operators have to configure database/redis/sqs and run a worker to get truly out-of-band refresh. Documenting that contract so the deployment guidance is visible without spelunking through commit messages. Also: - Mention the new "Page / Widget Title" admin setting in the config table (registered in the previous commit). - Reframe "Cache Duration" as a SOFT TTL with a link to the new caching section so admins understand stale data is intentional. - Expand "How it works" step 3 to describe the dispatch-and-serve flow rather than the old block-and-fetch flow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.0.11
Flarum 2 audit: FA7 icons, auth guard, constructor injection, and min…
2.0.10
Switch to On3 rankings page for headshots (one request per year)
The per-player search approach was broken because On3's search page
returns featured/popular players regardless of the query — actual
results require client-side JavaScript.
New approach: fetch /rivals/rankings/player/football/{year}/ once.
This page is fully server-rendered, contains 150+ players with both
profile hrefs (/rivals/{slug}-{id}/) and on3static.com image URLs
in the same HTML. One HTTP request per year, cached 24 hours.
buildOn3ImageMap() fetches the rankings page.
parseOn3Rankings() extracts a nameSlug → imageUrl map by finding
the on3static image closest (≤5000 chars) to each profile href.
enrichWithPhotos() looks up each CFBD recruit by normalised name slug.
Also removes all Guzzle Pool / concurrent per-player scraping code —
no longer needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.0.9
Rewrite On3 image extraction to use closest-image-to-slug approach
The previous impl required a quote character before /rivals/ which
didn't match Next.js JSON data attributes or other encoding variants,
causing extractOn3Image() to always return null.
New strategy:
1. preg_match_all to collect ALL on3static image positions
2. preg_match_all to collect ALL /rivals/ and /db/ profile paths
3. Find the path whose slug matches the player name (full slug first,
then first-two-parts fallback for Jr./suffix differences)
4. Return the on3static image with the smallest positional distance
to the matched path (threshold 8 000 chars)
No quote-character requirement — matches hrefs, JSON strings, Next.js
__NEXT_DATA__ and any other encoding On3 uses.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>