Skip to content

Releases: ernestdefoe/recruiting

3.1.1 — audit hardening

Choose a tag to compare

@github-actions github-actions released this 08 Jun 20:19

Floxum audit hardening (→ ≥95). Cold-lock window 30→60s (headroom for CFBD + On3 timeouts), assertRegistered() guard on the API, native fetchapp.request, and admin settings wired through the translator.

3.1.0

Choose a tag to compare

@ernestdefoe ernestdefoe released this 31 May 03:47

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 /recruiting page is fully TypeScript-type-checked (the prior @ts-nocheck escape hatch is gone), and the API URL is derived correctly for subdirectory installs.

3.0.0

Choose a tag to compare

@github-actions github-actions released this 26 May 02:56

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

Choose a tag to compare

@ernestdefoe ernestdefoe released this 20 May 03:18

No changes made.

2.0.14

Choose a tag to compare

@ernestdefoe ernestdefoe released this 20 May 03:13
fix: address audit findings — drop dead widget, move enrichment off r…

v2.0.13

Choose a tag to compare

@github-actions github-actions released this 20 May 03:17

What's Changed

  • No changes

Full Changelog: 2.0.12...v2.0.13

2.0.12

Choose a tag to compare

@ernestdefoe ernestdefoe released this 19 May 16:41
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

Choose a tag to compare

@ernestdefoe ernestdefoe released this 16 May 18:33
Flarum 2 audit: FA7 icons, auth guard, constructor injection, and min…

2.0.10

Choose a tag to compare

@ernestdefoe ernestdefoe released this 16 May 18:20
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

Choose a tag to compare

@ernestdefoe ernestdefoe released this 16 May 17:56
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>