Banked from Code4rena /audits enumeration (2026-06-10). Reusable across ALL Next.js/RSC
contest scanners (Code4rena, Sherlock EYE 11, Cantina EYE 12, any future fresh-lead source).
A platform badge or eyeballed count like "Live x99" can be a pure substring artifact of an
internal schema discriminator, NOT a real status. On C4, /audits had 99-100 hits of live
- every one from "schema":"live_judging", a per-record JSON field present on EVERY contest
regardless of state. Real status lived in the "status" key (Judging/Reporting/Completed),
and ZERO contests were actually live.
- DO: bind status to the JSON key (record.status), then independently confirm with
startTime <= now <= endTime. Two sources must agree.
- DON'T: grep -c live / trust a page badge count / trust a small-model WebFetch summary for
structured status.
C4 RSC exposes "codeAccess":"public"|"top_secret". top_secret = repo-gated (mitigation
reviews, private comps) and unclonable. Filter codeAccess=="public" BEFORE attempting a
clone or a GitHub-API 200 check. Saves wasted 404s and false "no repo" flags. Look for the
analogous field on each platform (Sherlock private flag, Cantina visibility).
"Is this source still launching new work?" belongs in the scanner-onboarding checklist ABOVE LOC/primitive-fit. C4 is in announced wind-down (closing; existing comps/bounties seen to completion) -> new-contest flow is ending -> it is a DECAYING lead source. Action: poll at LOW priority / alert-on-appearance only; do not reprioritize fresh-lead budget toward it. Keep Sherlock + Cantina + Immunefi as primary fresh lanes.
For contest enumeration, pull RAW HTML and parse deterministically:
1. curl the App-Router page (no auth/JS needed; RSC is server-rendered inline).
2. Unescape RSC quotes: u = raw.replace('\\"','"').replace('\\\\','\\').
3. Brace-scan objects anchored on a stable key ("slug":"): back to nearest {, forward to
the depth-0 }, json.loads.
4. Keep records containing endTime; read status/repo/formattedAmount/start/end/codeAccess.
Use WebFetch (small-model summarizer) ONLY for prose, never for status/field extraction - it
collapsed C4 to "no live audits, Page 1 of 10" and would have hidden the schema-literal trap.
Endpoint: GET code4rena.com/audits. Per-record fields: title, slug, status, formattedAmount
("$$X in USDC"), startTime, endTime (ISO-Z), repo (github.com/code-423n4//audits/<slug> -> grep github.com/... for repo when RSC repo absent.
Backend api.code4rena.com exists but no discoverable public /contests route - use SSR.