Skip to content
Merged
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
281 commits
Select commit Hold shift + click to select a range
7465528
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 26, 2026
bbc5e9f
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 26, 2026
91cfdfc
linear, fireflies: the broken-escape refusal's docstring records the …
nuriyoo Oct 26, 2026
8ca5d6e
Merge branch 'main' into graphql-a-request-error-is-apollos
nuriyoo Oct 26, 2026
15ebfdd
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 26, 2026
bbbd780
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 26, 2026
524369d
linear, fireflies: rows for PUT and PATCH at Linear's root, a PROPFIN…
nuriyoo Oct 26, 2026
e0abba0
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 26, 2026
47ef3b9
fireflies: the method set Fastify reads a body for holds the measurem…
nuriyoo Oct 26, 2026
ae7c3d3
linear: each answer carries the headers Linear sends, and the JSON Ap…
nuriyoo Oct 26, 2026
99deef1
linear, fireflies: rows for Cloudflare's CONNECT and TRACE at the roo…
nuriyoo Oct 26, 2026
c7af760
linear: Origin's copies are joined as Linear joined them, an empty co…
nuriyoo Oct 26, 2026
98429dc
tests: Linear's header and budget tables point at the code's record o…
nuriyoo Oct 26, 2026
4afd507
fireflies: each answer carries the headers Fireflies sends, and a key…
nuriyoo Oct 26, 2026
19a5215
fireflies: a refused field's own error is left out, and rows for whic…
nuriyoo Oct 26, 2026
142ed5d
fireflies: a root field's directive reads the variables as the run co…
nuriyoo Oct 26, 2026
33ab350
tests: a served field's error stays beside the refused fields' in the…
nuriyoo Oct 26, 2026
1b9f72a
tests: the budget test points at Budget's record of the run
nuriyoo Oct 26, 2026
90b4f40
graphql: execute_payload loses the parameters no router passes, and t…
nuriyoo Oct 26, 2026
777a712
fireflies: Budget's docstring is the one record of its run, and the d…
nuriyoo Oct 26, 2026
402bcb0
linear: a non-null root field's refused argument is answered ahead of…
nuriyoo Oct 26, 2026
c0165b6
graphql: the root-argument check reads non-null root fields alone, an…
nuriyoo Oct 26, 2026
5bd03c6
graphql: Fireflies' 500 is graphql-depth-limit's, and each location c…
nuriyoo Oct 26, 2026
69b8809
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 26, 2026
53187d7
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 26, 2026
6d3b419
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 26, 2026
7a925f9
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 26, 2026
6583c21
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 26, 2026
2517eb8
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 26, 2026
8917910
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 26, 2026
2798146
fireflies: rows for a named operation, two operations' errors, a type…
nuriyoo Oct 26, 2026
ac90a8f
fireflies: the crawl holds no more than the errors it stops at, and t…
nuriyoo Oct 26, 2026
758720b
graphql: the run comment, the depth rule's docstring and a test docst…
nuriyoo Oct 26, 2026
689d0a1
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 26, 2026
48b4dbb
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 26, 2026
4262065
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 26, 2026
34c9310
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 26, 2026
1c431cc
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 26, 2026
ef033ad
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 26, 2026
79ec35e
linear: the not-found rows sit in the body table, and the router's do…
nuriyoo Oct 26, 2026
637846b
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 26, 2026
c0a27ec
linear, fireflies: an empty Origin is no preflight, Fastify's plain t…
nuriyoo Oct 26, 2026
b240ac1
fireflies: a row for plain text past the limit holding a byte that is…
nuriyoo Oct 26, 2026
3ac023e
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 26, 2026
a933bf3
linear, fireflies: a path is routed once its dot segments are resolve…
nuriyoo Oct 26, 2026
19cb771
linear, fireflies: control rows for a broken escape in the query besi…
nuriyoo Oct 26, 2026
f66b361
linear, fireflies: the broken escape's docstring points at the middle…
nuriyoo Oct 26, 2026
edb4a8c
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 26, 2026
0a9e4bf
docs: Linear's endpoint is each path Express hands Apollo Server once…
nuriyoo Oct 26, 2026
9327b89
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 26, 2026
8e79af0
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 26, 2026
bc8c0fa
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 26, 2026
75a1537
linear: the body table's comment wraps at 100
nuriyoo Oct 26, 2026
52d07fc
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 26, 2026
7f939e3
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 26, 2026
4177a17
linear: Express's 304 for a fresh GET, the budget's reset an hour on,…
nuriyoo Oct 26, 2026
aa97d81
linear: a row for Cloudflare's CONNECT at a path the front reads as /
nuriyoo Oct 26, 2026
8cd8e62
linear: the 304's measurement sits in _fresh's docstring
nuriyoo Oct 26, 2026
381ed77
fireflies: graphql-depth-limit's 500 carries no Cache-Control, and a …
nuriyoo Oct 26, 2026
e1faabc
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 26, 2026
a9f4909
fireflies: the budget's constants count root fields, and the docstrin…
nuriyoo Oct 26, 2026
f433004
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 26, 2026
188eac5
linear: a refused argument at __type or another nullable root field c…
nuriyoo Oct 26, 2026
fddbce1
fireflies: a refused key is held a minute from its first refusal, the…
nuriyoo Oct 26, 2026
f7c0e2f
fireflies: graphql-js's argument refusals come ahead of the budget's,…
nuriyoo Oct 26, 2026
fd1b6e7
fireflies: every resolver error comes after the budget's refusals, as…
nuriyoo Oct 26, 2026
6c8d11c
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 26, 2026
26c610e
fireflies: the hold's test table points at the docstring that dates t…
nuriyoo Oct 26, 2026
47d10a2
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 26, 2026
6451cda
linear: HEAD's 304 carries the ETag its 200 leaves off, and fresh rea…
nuriyoo Oct 26, 2026
cf451e2
linear: rows for fresh's whitespace past ASCII, and no guard the ETag…
nuriyoo Oct 26, 2026
ae434e0
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 26, 2026
2d47662
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 26, 2026
b0bedec
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 27, 2026
5c16437
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 27, 2026
91b6bf3
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 27, 2026
fb387cd
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
315f4f2
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
ed59299
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 27, 2026
30eb880
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 27, 2026
14fea25
linear tests: a request `_LINEAR_HTTP` sends carries its headers in t…
nuriyoo Oct 27, 2026
8c66405
fireflies tests: a request `_FIREFLIES_HTTP` sends carries its header…
nuriyoo Oct 27, 2026
18230d5
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
6be0935
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
cc47ac0
fireflies: Spent.refuse's docstring gives the six samples of the race
nuriyoo Oct 27, 2026
4aacdf0
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
5237085
linear: a 405 and OPTIONS / with If-None-Match: * are answered as wit…
nuriyoo Oct 27, 2026
f5d6896
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
f668fb6
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
a0a81b5
linear: an If-None-Match tag is stripped of spaces alone, as fresh re…
nuriyoo Oct 27, 2026
56cf79a
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
92b8d32
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
61a14b8
fireflies: the race's sentence names its two fields, and the order te…
nuriyoo Oct 27, 2026
2b1b800
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
74a4fc1
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 27, 2026
852daf8
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 27, 2026
0e6a5f5
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
f395a93
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
58ffa2d
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 27, 2026
30e8a84
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 27, 2026
542c550
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 27, 2026
40633d1
linear: past the limit the request bucket's level stops at 0, as Line…
nuriyoo Oct 27, 2026
98ee09e
fireflies: the review's notes on the telemetry row, HSTS, a body refu…
nuriyoo Oct 27, 2026
ea23334
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
f6f371f
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
e177aa4
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 27, 2026
b5c76e7
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 27, 2026
f7df1d5
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 27, 2026
d999ea3
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 27, 2026
a3048df
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 27, 2026
75170e8
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
714444a
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
b225c74
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 27, 2026
f45e9d4
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 27, 2026
b9fd3dd
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 27, 2026
f2ebdfe
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
a682c17
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
21c1af2
linear tests: _linear_status's docstring points at the table that rea…
nuriyoo Oct 27, 2026
78c3be0
tests: each measured table of the HTTP layer runs as one test
nuriyoo Oct 27, 2026
ac95809
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 27, 2026
fc6c41f
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 27, 2026
fc72d46
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
54d520c
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
3193fc4
linear tests: the rows whose answer without a key turns on what the d…
nuriyoo Oct 27, 2026
257efc8
linear tests: each stage of Apollo Server's that refuses ahead of the…
nuriyoo Oct 27, 2026
a973fbd
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 27, 2026
d2ad248
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 27, 2026
8b774e8
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 27, 2026
ec8c95f
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 27, 2026
b8553f4
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 27, 2026
a0b1789
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
929567f
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
73ef323
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 27, 2026
08a2510
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 27, 2026
90f44f4
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 27, 2026
a85ce77
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 27, 2026
2a18028
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 27, 2026
644cd85
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
b498175
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
8dc2705
fireflies tests: _sent's docstring wraps at the line length
nuriyoo Oct 27, 2026
0f8a9f7
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 27, 2026
b255180
linear tests: the headers test's docstring points at the comment over…
nuriyoo Oct 27, 2026
dd02e64
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
52c9992
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
dc1fc78
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 27, 2026
139245c
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 27, 2026
b347ab1
fireflies: _envelope names every code _FRIENDLY holds
nuriyoo Oct 27, 2026
86b2a47
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 27, 2026
7fe4dda
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 27, 2026
4624cbd
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 27, 2026
9dcffc2
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 27, 2026
be29416
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 27, 2026
5cae426
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
dcbf71c
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 27, 2026
9320a05
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 27, 2026
9d4bd6b
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
1afd5aa
fireflies tests: an unknown id's answer ends with the newline each Fi…
nuriyoo Oct 27, 2026
f245bf3
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
560831b
linear: If-None-Match is read without the whitespace around it, and C…
nuriyoo Oct 27, 2026
0cbee48
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
e3f40ac
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
e5f3c7c
express_http: the fresh versions are named once, on NO_CACHE
nuriyoo Oct 27, 2026
7d0163d
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 27, 2026
903cd0d
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 27, 2026
b5b27d0
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 28, 2026
326fc66
graphql: a query a persisted query's hash matches is parsed however e…
nuriyoo Oct 28, 2026
5b3917b
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 28, 2026
6aa5d5e
tests: a hidden by-id root's answer equals an absent one's, body for …
nuriyoo Oct 28, 2026
e5d1ac8
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 28, 2026
b11dda5
tests: Cloudflare's answers ahead of Linear and Fireflies are one tab…
nuriyoo Oct 28, 2026
8052b14
main, tests, NOTICE.md: the table comment points at the middlewares, …
nuriyoo Oct 28, 2026
ce5cc22
graphql: the module docstring names a Refusal's code and message, and…
nuriyoo Oct 28, 2026
8b7d08a
graphql: js_words names the five refusals graphql-js 17 words otherwise
nuriyoo Oct 28, 2026
22e386e
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 28, 2026
722d3ce
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 28, 2026
7c8e02f
Merge branch 'graphql-a-request-error-is-apollos' into linear-introsp…
nuriyoo Oct 28, 2026
270eaf3
Merge branch 'linear-introspection-and-401-are-linears' into graphql-…
nuriyoo Oct 28, 2026
4576a71
Merge branch 'graphql-the-http-layer-is-apollos-and-expresss' into gr…
nuriyoo Oct 28, 2026
a364056
linear, tests: the route docstring describes one route, and the Cloud…
nuriyoo Oct 28, 2026
c6c2d1c
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 28, 2026
fe01b35
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 28, 2026
3e60d59
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 28, 2026
cf7a758
Merge branch 'main' into graphql-a-request-error-is-apollos
nuriyoo Oct 28, 2026
4a69884
linear, docs, tests: Cloudflare's CONNECT carries nosniff at slashes …
nuriyoo Oct 28, 2026
527dc3c
tests: the headers each Linear answer carries are columns of _LINEAR_…
nuriyoo Oct 28, 2026
5f0f5ec
linear, tests: an If-None-Match keeps what follows it but spaces and …
nuriyoo Oct 28, 2026
19a5436
linear: a preflight's header names lose the U+00A0s around them, and …
nuriyoo Oct 28, 2026
c3a1193
linear: the fresh cases _fresh's docstring listed are rows of _LINEAR…
nuriyoo Oct 28, 2026
d4232e4
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 28, 2026
b333970
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 28, 2026
7aac439
linear: CONNECT at a path climbing past the root carries no nosniff, …
nuriyoo Oct 28, 2026
c317ec6
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 28, 2026
07e301c
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 28, 2026
62f6351
graphql: js_words names each kind of refusal graphql-js 17 answers ot…
nuriyoo Oct 28, 2026
fbb2247
linear: introspection is answered without a credential, the 401 is Li…
nuriyoo Oct 28, 2026
919b6c8
Merge commit 'fbb2247e' into graphql-the-http-layer-is-apollos-and-ex…
nuriyoo Oct 28, 2026
8aa5790
linear, fireflies: each method, content type and Accept is answered b…
nuriyoo Oct 28, 2026
1bad7ec
Merge remote-tracking branch 'origin/main' into graphql-a-request-err…
nuriyoo Oct 28, 2026
f4d2fd9
Merge commit '919b6c8' into graphql-each-path-is-routed-as-the-vendor…
nuriyoo Oct 28, 2026
e7efff6
Merge remote-tracking branch 'origin/graphql-a-request-error-is-apoll…
nuriyoo Oct 28, 2026
3d4d8de
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 28, 2026
ed56506
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 28, 2026
82a0a76
tests: the headers each Fireflies answer carries are columns of _FIRE…
nuriyoo Oct 28, 2026
381c57e
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 28, 2026
9aa7464
fireflies: an alias or a fragment named __proto__ spends the budget a…
nuriyoo Oct 28, 2026
5c91435
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 28, 2026
ea30e3f
Merge remote-tracking branch 'origin/main' into graphql-each-path-is-…
nuriyoo Oct 28, 2026
be7d6df
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 28, 2026
b2c34a7
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 28, 2026
5c37c4c
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 28, 2026
467a033
Merge branch 'main' into graphql-each-path-is-routed-as-the-vendor-ro…
nuriyoo Oct 28, 2026
54f6520
Merge remote-tracking branch 'origin/main' into graphql-each-path-is-…
nuriyoo Oct 29, 2026
57041cc
linear, fireflies: a cut escape, a `..` past the root and each dot se…
nuriyoo Oct 29, 2026
15bd499
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 29, 2026
457f667
linear, docs: the header notes cover 2026-10-25 to 2026-10-28, the CO…
nuriyoo Oct 29, 2026
69c10ff
linear, tests: nosniff goes on each answer at a path Linear's load ba…
nuriyoo Oct 29, 2026
6a3677c
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 29, 2026
eaa59d0
fireflies, docs: the refusal switch has its own Fireflies section in …
nuriyoo Oct 29, 2026
cd892e2
fireflies, tests: the minute's and the day's budget are settings defa…
nuriyoo Oct 29, 2026
d0dbb95
fireflies, docs: the budget's root fields are those a resolver runs f…
nuriyoo Oct 29, 2026
b883a2b
Merge remote-tracking branch 'origin/fireflies-each-answer-carries-fi…
nuriyoo Oct 29, 2026
ec6d8ce
linear, graphql: a nullable root field's refused argument is answered…
nuriyoo Oct 29, 2026
4fe3fed
linear: the row of __type's refused argument alone, where the run rea…
nuriyoo Oct 29, 2026
e4c6e40
graphql: run's docstring keeps the run's errors at the other root fie…
nuriyoo Oct 29, 2026
e6deb0c
Merge branch 'main' into graphql-each-path-is-routed-as-the-vendor-ro…
nuriyoo Oct 29, 2026
d4e3150
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 29, 2026
88c6fc8
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 29, 2026
f16b2df
Merge remote-tracking branch 'origin/main' into graphql-each-path-is-…
nuriyoo Oct 29, 2026
e7846e7
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 29, 2026
abf6def
test_linear: rows for what follows no-cache in Cache-Control, which f…
nuriyoo Oct 29, 2026
998147e
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 29, 2026
f39a131
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 29, 2026
aaa69ab
tests: each raw request is built by one helper beside raw_exchange
nuriyoo Oct 30, 2026
86a22aa
Merge remote-tracking branch 'origin/main' into graphql-each-path-is-…
nuriyoo Oct 30, 2026
97f4a21
Merge remote-tracking branch 'origin/graphql-each-path-is-routed-as-t…
nuriyoo Oct 30, 2026
fd3d787
Merge remote-tracking branch 'origin/linear-each-answer-carries-linea…
nuriyoo Oct 30, 2026
810b2cf
Merge remote-tracking branch 'origin/fireflies-each-answer-carries-fi…
nuriyoo Oct 30, 2026
1ca0082
Merge remote-tracking branch 'origin/main' into graphql-each-path-is-…
nuriyoo Oct 30, 2026
dc88aad
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 30, 2026
12e4771
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 30, 2026
4a01294
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 30, 2026
90ecce4
Merge remote-tracking branch 'origin/main' into graphql-each-path-is-…
nuriyoo Oct 30, 2026
6a0e4f3
Merge branch 'graphql-each-path-is-routed-as-the-vendor-routes-it' in…
nuriyoo Oct 30, 2026
ab421ed
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 30, 2026
88a35cb
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 30, 2026
becd462
Merge branch 'main' into graphql-each-path-is-routed-as-the-vendor-ro…
nuriyoo Oct 30, 2026
68827e6
Merge remote-tracking branch 'origin/graphql-each-path-is-routed-as-t…
nuriyoo Oct 30, 2026
93d711c
Merge branch 'linear-each-answer-carries-linears-headers' into firefl…
nuriyoo Oct 30, 2026
9c0ba59
Merge branch 'fireflies-each-answer-carries-fireflies-headers-and-bud…
nuriyoo Oct 30, 2026
b2d98b6
Merge branch 'main' into linear-a-refused-root-argument-is-answered-f…
nuriyoo Oct 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions backlot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ def _resolve_path_defaults(cls, values):
# has what the switch does and when to flip it.
github_enforce_rate_limits: bool = True

# --- fireflies ---
# On by default: a mock more permissive than the vendor hides the refusal a client meets in
# production (see ``backlot.routers.fireflies.Budget``). docs/configuration.md's Fireflies
# section has what the switches do and when to flip them.
fireflies_enforce_rate_limits: bool = True
# The root fields a key may run resolvers for in a minute and in a calendar day in UTC, a Free
# plan's: the `x-ratelimit-limit-api_burst` and `x-ratelimit-limit-api` api.fireflies.ai sent
# the key measured with on 2026-10-26 and 2026-10-29 (UTC), and the "30 requests" and "500
# requests" its limits page gives the plan.
fireflies_per_minute: int = 30
fireflies_per_day: int = 500

# --- usage telemetry (backlot.telemetry; docs/telemetry.md says what is sent) ---
telemetry: bool = True
# The `DO_NOT_TRACK` convention many developer tools honour, read without the prefix, from the
Expand Down
20 changes: 20 additions & 0 deletions backlot/express_http.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""What Express does alike for each vendor whose answers it writes."""

from __future__ import annotations

import base64
import hashlib
import re


def weak_etag(body: bytes) -> str:
"""Express's weak `ETag` for ``body``, as the `etag` package writes it: the body's length in
bytes, in hex, and the first 27 characters of the base64 SHA-1 of the body."""
digest = base64.b64encode(hashlib.sha1(body).digest()).decode("ascii")[:27]
return f'W/"{len(body):x}-{digest}"'


#: ``fresh``'s test for `no-cache` among the comma-separated parts of a request's `Cache-Control`,
#: the same in 0.5.2, which Express 4 asks, and in 2.0.0, which Express 5 asks, its `\s` written
#: out as the characters JavaScript's `\s` holds in latin-1, which a header value is read as.
NO_CACHE = re.compile(r"(?:^|,)[\t\n\v\f\r \xa0]*?no-cache[\t\n\v\f\r \xa0]*?(?:,|$)")
122 changes: 94 additions & 28 deletions backlot/graphql/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

Knows nothing about any vendor and nothing about :mod:`backlot.store`. A vendor builds one
:class:`Engine` at import time from its SDL and resolver map; its router reads the request body
with :mod:`backlot.graphql.body` and hands it to :meth:`Engine.execute_payload`, along with a
context dict (connection, caller, ``visible_ids``) that every resolver receives as
``info.context``.
with :mod:`backlot.graphql.body`, hands it to :meth:`Engine.resolve_payload`, and runs the
operation it chooses with :meth:`Engine.run`, along with a context dict (connection, caller,
``visible_ids``) that every resolver receives as ``info.context``.

Both vendors serve GraphQL through Apollo Server over graphql-js, so the engine answers as that pair
does: Apollo Server's checks of the body and of a persisted query come first, then graphql-js's
parse, validation and choice of operation (:meth:`Engine.resolve_payload`), then the coercion of
variables and the run itself (:meth:`Engine.run`), each refusal a :class:`Refusal` carrying Apollo
Server's ``code`` and message. A router that reads the credential between the two stages calls them
apart. A refusal made before execution carries no ``data`` entry; an error made as the operation
runs comes back beside ``data``, at 200. Each router turns the refusals into its vendor's envelope.
Server's ``code`` and message. Linear's router reads the credential between the two stages, and
Fireflies' counts the root fields of the operation the first chose once the second has run. A
refusal made before execution carries no ``data`` entry; an error made as the operation runs
comes back beside ``data``, at 200. Each router turns the refusals into its vendor's envelope.
"""

from __future__ import annotations
Expand All @@ -25,6 +26,8 @@

from graphql import (
DocumentNode,
ExecutionResult,
FragmentDefinitionNode,
GraphQLError,
GraphQLID,
GraphQLInputObjectType,
Expand All @@ -40,10 +43,14 @@
build_schema,
execute_sync,
get_operation_ast,
located_error,
parse,
type_from_ast,
validate,
)
from graphql.execution.collect_fields import collect_fields
from graphql.execution.values import get_argument_values, get_variable_values
from graphql.type.introspection import TypeMetaFieldDef

from backlot.graphql import body as request_body
from backlot.graphql import js_words
Expand Down Expand Up @@ -212,9 +219,13 @@ def refused(*refusals: Refusal) -> Result:


def _refusal(
message: str, code: str = BAD_REQUEST, status: int = 400, thrown: bool = False
message: str,
code: str = BAD_REQUEST,
status: int = 400,
thrown: bool = False,
headers: tuple[tuple[str, str], ...] = (),
) -> Result:
return refused(Refusal(message, code, status=status, thrown=thrown))
return refused(Refusal(message, code, status=status, headers=headers, thrown=thrown))


def _js_truthy(value: Any) -> bool:
Expand Down Expand Up @@ -270,6 +281,9 @@ def body_refusal(payload: Any) -> Result | None:
#: (UTC).
PERSISTED_QUERY_VERSION = "Unsupported persisted query version"
PERSISTED_QUERY_MISMATCH = "provided sha does not match query"
#: The `Cache-Control` Apollo Server sets on ``PersistedQueryNotFound``, which both vendors sent
#: with it on 2026-10-25 (UTC), by `POST` and on Linear by `GET`.
PERSISTED_QUERY_NOT_FOUND_HEADERS = (("cache-control", "private, no-cache, must-revalidate"),)


def _persisted_query(payload: dict) -> Any:
Expand All @@ -296,7 +310,12 @@ def persisted_query_refusal(payload: dict) -> Result | None:
return _refusal(PERSISTED_QUERY_VERSION, INTERNAL_SERVER_ERROR)
query = payload.get("query")
if not isinstance(query, str):
return _refusal("PersistedQueryNotFound", PERSISTED_QUERY_NOT_FOUND, status=200)
return _refusal(
"PersistedQueryNotFound",
PERSISTED_QUERY_NOT_FOUND,
status=200,
headers=PERSISTED_QUERY_NOT_FOUND_HEADERS,
)
# Both vendors hashed a query holding U+D800 as the same query with U+FFFD in its place on
# 2026-10-25 (UTC), the UTF-8 Node writes for a lone surrogate.
units = query.encode("utf-16-le", "surrogatepass").decode("utf-16-le", "replace")
Expand Down Expand Up @@ -472,7 +491,9 @@ def resolve_payload(

def run(self, operation: Operation, *, context: Any = None) -> Result:
"""Coerce the variables of ``operation``, refused with Apollo Server's code, and run it
with ``context``."""
with ``context``, the errors of the root arguments graphql-js refuses
(:meth:`_refused_root_arguments`) ahead of the run's at the other root fields, or in its
place where one is a non-null field's."""
variables = operation.variables
coercion = js_words.coerce_variable_values(
self.schema, list(operation.operation.variable_definitions), variables
Expand Down Expand Up @@ -502,13 +523,23 @@ def run(self, operation: Operation, *, context: Any = None) -> Result:
# A root type only `self._checked` has runs there, and one neither schema has is
# graphql-core's refusal.
on_a_root = getattr(self.schema, f"{operation.operation.operation.value}_type") is None
result = execute_sync(
self._checked if on_a_root else self.schema,
operation.document,
context_value=context,
variable_values=variables,
operation_name=operation.name,
argued, nulled = (
([], False) if on_a_root else self._refused_root_arguments(operation, variables)
)
if nulled:
result = ExecutionResult(None, argued)
else:
result = execute_sync(
self._checked if on_a_root else self.schema,
operation.document,
context_value=context,
variable_values=variables,
operation_name=operation.name,
)
if argued:
keys = {error.path[0] for error in argued}
ran = [e for e in result.errors or () if not e.path or e.path[0] not in keys]
result = ExecutionResult(result.data, [*argued, *ran])
# api.fireflies.ai and api.linear.app open a response carrying a field error with "errors"
# (2026-10-21), so the errors come first here. Each error's locations are graphql-js's. An
# error graphql-core made itself is in graphql-js's words and carries the code Apollo Server
Expand All @@ -534,6 +565,53 @@ def run(self, operation: Operation, *, context: Any = None) -> Result:
assigned=frozenset(assigned),
)

def _refused_root_arguments(
self, operation: Operation, variables: Any
) -> tuple[list[GraphQLError], bool]:
"""The errors of the root fields of ``operation`` whose arguments graphql-js refuses, in
the order the fields come, and whether the last is a non-null field's, which nulls the
data and ends them. graphql-js reads each query root field's arguments as it starts the
field, before any resolver's answer arrives, as Linear's resolvers answer asynchronously, so
these come ahead of every resolver's error. api.linear.app answered `Internal server error`
at a later `issue(id: $x)` sent `null`, ahead of an earlier `issue` it does not hold and of
an earlier `viewer`, and through a fragment, on 2026-10-21 and 2026-10-26 (UTC), and after
the same error at a `__type(name: $y)` sent `null` before it on 2026-10-26; and it answered
one or two `__type(name: $y)` sent `null` ahead of an earlier `issue` it does not hold, the
data null, and ahead of an `issue` before a served `__type`, on 2026-10-29. A refused
directive refuses none here, and the run answers it."""
root = self.schema.get_root_type(operation.operation.operation)
fragments = {
d.name.value: d
for d in operation.document.definitions
if isinstance(d, FragmentDefinitionNode)
}
coerced = get_variable_values(
self.schema, list(operation.operation.variable_definitions), variables or {}
)
try:
fields = collect_fields(
self.schema, fragments, coerced, root, operation.operation.selection_set
)
except GraphQLError:
return [], False
refused: list[GraphQLError] = []
for key, nodes in fields.items():
name = nodes[0].name.value
field = (
TypeMetaFieldDef
if name == "__type" and root is self.schema.query_type
else root.fields.get(name)
)
if field is None:
continue
try:
get_argument_values(field, nodes[0], coerced)
except GraphQLError as error:
refused.append(located_error(error, nodes, [key]))
if isinstance(field.type, GraphQLNonNull):
return refused, True
return refused, False

def execute(
self,
document: str,
Expand All @@ -546,18 +624,6 @@ def execute(
resolved = self.resolve(document, variables=variables, operation_name=operation_name)
return resolved if isinstance(resolved, Result) else self.run(resolved, context=context)

def execute_payload(
self,
payload: Any,
*,
context: Any = None,
on_document: Callable[[DocumentNode], Result | list[GraphQLError]] | None = None,
get: bool = False,
) -> Result:
""":meth:`resolve_payload`, then :meth:`run` the operation it chose."""
resolved = self.resolve_payload(payload, on_document=on_document, get=get)
return resolved if isinstance(resolved, Result) else self.run(resolved, context=context)


def _made_by_graphql(error: GraphQLError) -> bool:
"""Whether graphql-core made ``error`` itself as the operation ran, as graphql-js would have:
Expand Down
Loading
Loading