{{ message }}
Repository navigation
A claim that lives only in the payload cannot be refused cheaply - #169
Merged
Merged
Conversation
Review of the ingress found the shape this fixes. The ingress cannot read a request body until it has authenticated, checked for a replay, and decompressed up to 16 MiB — so a claim carried only in the payload puts every refusal that depends on it below that read. Anyone with a GitHub account could mint a token for a repository they own and post a small gzip that inflates to 16 MiB, repeatedly, to be told the same thing one indexed lookup already knew. The code now travels in x-backthread-claim as well, from the same single read of the environment, so the ingress decides before it inflates anything. The payload keeps its copy: that is the published contract and the auditable record of what was sent. The ingress cross-checks the two and refuses a disagreement, so the body can only ever agree with what authorised the request. Sending both is required, not redundant — which is why the source guard pins ONE claimFromEnv call feeding both.
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.

Follow-up to #168, from the ingress review. Not yet published —
@backthread/ci@0.3.0is tagged only after the ingress that consumes this is deployed.What review found
The ingress cannot read a request body until it has authenticated, checked for a replay, and decompressed up to 16 MiB (8 MiB on the wire). A claim carried only in the payload therefore puts every refusal that depends on it below that read.
Concretely: anyone with a GitHub account creates a repository, adds a workflow minting an OIDC token for our audience, and posts a ~32 KiB gzip that inflates to just under 16 MiB. Before claims existed that cost us one indexed Supabase read and a
repo_not_connected404 with the body unread. With the claim in the payload it costs a Supabase read, a KV read, a 16 MiB inflate and aJSON.parse— roughly 500× amplification per request, repeatable, on the way to the same 404.What changes
The code now also travels in
x-backthread-claim, from the same single read of the environment. The ingress decides before it inflates anything, so a caller without a live claim naming their own repository gets the cheap 404 back.The payload keeps its
claimfield. That is the published wire contract and the auditable record of what was sent, and removing it would be a breaking change to a field0.2.0already ships. The ingress cross-checks the two and refuses a disagreement withclaim_header_mismatch, so the body can only ever agree with what authorised the request and never steer it.Sending both is therefore required rather than redundant — which is why the source guard pins exactly one
claimFromEnvcall feeding both, and pins that the header name comes from the shared constant rather than a typed string.Measured
@backthread/ci363 tests, 0 fail. Typecheck clean on both projects.check-no-internal-refsOK. Floor raised 361 → 363.Reasoning
written by the agent in-session via
backthread/add-reasoning-to-prsDecisions
0.2.0published, and keeping it gives the request an auditable record of its own intent that the gate already validates. The cost is that a client can now contradict itself, which the ingress answers withclaim_header_mismatch.Trade-offs
validate.tsbounds it. The ingress applies the same grammar before using it, but the two definitions of "a plausible code" now live on either side of a boundary the version gate does not cover. Check: ifCLAIM_REis ever loosened, loosen the ingress's copy in the same release.