fix(graphql): set no-store on GraphQL error envelopes#2199
Conversation
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2199 +/- ##
=======================================
Coverage 93.21% 93.21%
=======================================
Files 52 52
Lines 8225 8226 +1
Branches 3018 3019 +1
=======================================
+ Hits 7667 7668 +1
Misses 96 96
Partials 462 462
🚀 New features to boost your workflow:
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review — safe to merge
✅ Approved — safe to merge Review summary
Nits — 3 non-blocking
Review context
Contributor next steps
Signal definitions
Review detailsGenerated from public PR metadata and the diff. Advisory only; deterministic signals remain authoritative. Minimal, correct fix for a real bug: GraphQL error envelopes were being sent with `public, max-age=60, stale-while-revalidate=300` because the cache-control path didn't distinguish a GraphQL-level error (a 200 with a populated `errors` array) from a clean success. The conditional `result.errors?.length ? 'no-store' : ...` is exactly right — undefined and empty-array both coerce falsy, matching the spec guarantee that a non-empty `errors` array is the only error signal. The two new tests cover both branches, the errored case fails on the prior code and passes on the fix, and the pattern is consistent with how `no-store` is applied in `rpc-proxy.mjs`. Nits (3)
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Summary
POSTthat populatedresult.errors(a resolver hitting a failed KV/D1/R2 read) still returned the success cache directivepublic, max-age=60, stale-while-revalidate=300, so a transient backend error advertised itself as cacheable for 60s and served while stale for a further 300s.200envelope with a populatederrorsarray, so it slips past the existing norm that only clean200s are cached. Emittingno-storeon that envelope keeps a fronting cache, or a directive-respecting client, from pinning a backend error for the success window.What Changed
handleGraphQLRequestnow setscache-control: no-storewhenresult.errorsis populated and keeps the success directive only for a clean result. The status and body stay byte-identical, and the SDL/GETresponse plus the pre-execution400/405/413paths are untouched.tests/graphql.test.mjs: a cleanPOSTkeeps the success directive, and an erroredPOST(a resolver read that throws, the realistic corrupt-artifact trigger) switches tono-store. The errored case fails on the prior code and passes with the fix, and the pair covers both branches of the new conditional.validate:contract-driftstays clean.Closes #2084
Registry Safety
validator-local state.
Validation
npm run checknpm run validatenpm run validate:schemasnpm run validate:apinpm run validate:openapinpm run validate:typesnpm run validate:artifact-budgetsnpm run validate:docsnpm run validate:intakenpm run validate:workflowsnpm run worker:testnpm run test:coveragenpm run scan:public-safetygit diff --check