raster: fall back to GraphQL slug lookup when the artwork page is bot-challenged - #12
Merged
Conversation
…-challenged raster.art now serves a Vercel bot-protection checkpoint (HTTP 429 challenge page) to non-browser fetchers, so the serialized page payload stopped being a reliable source for the numeric artwork id and the kit API path died before it started — the nightly live fixture has failed since 2026-07-20. The public keyless GraphQL API (api.raster.art) is not behind the checkpoint and models not-found as a null query field. When page HTML is unavailable or carries no artworkId, resolve the id (and title) via artworkBySlug and continue through the kit tokens API as before. The page-payload path still wins when HTML is available (e.g. from the headless renderer), and the page fetch is now non-fatal.
… challenges Two failure modes were masked by the live-fixture step failing first (fail-fast) since 2026-07-17: - OpenSea and Verse fixtures pinned the exact first-listed token id, which tracks the marketplace's live listing order, not resolver behavior (OpenSea drifted #63 -> #190, Verse #178 -> #236 with resolution working correctly). Fixtures now assert collection identity (chain + contract) and a well-formed numeric token id. - The raster headless fixture cannot render from datacenter IPs while raster.art's Vercel checkpoint challenges them (it renders fine from residential networks). When rendering finds nothing and the page is provably bot-challenged, the fixture now skips with a diagnostic instead of failing.
moskovich
added a commit
that referenced
this pull request
Jul 25, 2026
npm cannot configure a trusted publisher for a package that does not exist yet (npm/cli#8544), so the first publish authenticates with an NPM_TOKEN repo secret when present — the same token-era ff-cli used before its OIDC switch (ff-cli #61). Once the package exists and the trusted publisher is wired, delete the secret; the workflow then publishes via OIDC with no further change. Also merges main (raster GraphQL fallback + fixture fixes, #12) so this branch's CI reflects the healed live suite.
This was referenced Jul 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Restores the nightly live CI signal, red since 2026-07-17. Two commits, three masked failure modes:
1. Raster live fixture (the original nightly red): raster.art now fronts its pages with a Vercel Security Checkpoint — non-browser fetchers get an HTTP 429 challenge document. The resolver's kit-API path started by reading the numeric
artworkIdfrom the page's serialized payload, so resolution died before reaching the (unaffected) kit API. Fix: when page HTML is unavailable or has noartworkId, resolve id + title via the public keyless GraphQL API (artworkBySlug), then page throughkit.raster.artas before. Page-payload path still wins when HTML is available (headless renderer), preserving resolver order; the page fetch is now non-fatal; GraphQL title ridesTokenFindingsResult.title.2. OpenSea + Verse headless fixtures (masked by fail-fast): they pinned the exact first-listed token id, which tracks the marketplace's live listing order, not resolver behavior (OpenSea drifted #63→#190, Verse #178→#236 with resolution working correctly). Fixtures now assert collection identity (chain + contract) and a well-formed numeric token id.
3. Raster headless fixture (masked, CI-only): real Chromium can't get past the checkpoint from datacenter IPs (renders fine from residential networks). When rendering finds nothing and the page is provably bot-challenged, the fixture skips with a diagnostic instead of failing.
Testing
npm run verify: 175/175, including new unit tests simulating the challenged site (429 page + live GraphQL/kit mocks; fallback resolves tokens + title, GraphQL miss reports not-found).