feat(conformance): sign JWTs per-case in the harness (closes #41)#54
Merged
Conversation
Enable the 12 pending auth cases (1460-1464, 1468-1474) by minting and
signing a bearer token from each case's request.jwt block:
- Bier.HttpCase signs the payload as-is with jose (symbolic
sign_with: hs256_test_secret -> the PostgREST testCfg secret), so
deliberately-invalid claims reach the server untouched.
- Cases 1468-1473 set jwt-aud, conflicting with the shared instance's
jwt_aud: nil, so they run on dedicated variant instances.
- Drop the :jwt pending arm from the conformance generator.
Running the cases exposed lib-side conformance bugs, fixed here:
Bier.JWT collapsed non-numeric exp/nbf/iat, wrong-typed aud, and
audience mismatch into :jwt_invalid (PGRST301 "JWSError
JWSInvalidSignature") and only type-checked aud when jwt-aud was
configured. It now returns distinct reasons ({:claim_not_number, claim},
:aud_not_string, :not_in_audience), type-checks aud unconditionally, and
FallbackController maps each to PGRST303 with PostgREST's exact message.
All 45 auth-area cases pass; full suite green except the pre-existing
PostGIS geojson cases (#15).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
milmazz
force-pushed
the
jwt-signing-harness-41
branch
from
July 3, 2026 18:47
cb02efb to
81eb0bb
Compare
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.
Summary
Closes #41 by teaching the conformance harness to mint and sign a JWT from each case's
request.jwtblock, enabling the 12 pending auth cases (1460–1464, 1468–1474). Enabling them immediately exposed lib-side conformance bugs in the JWT error mapping, fixed in the same change — the first real end-to-end exercise of the verification path from #35.Harness
Bier.HttpCase.perform/1signs the case'spayloadwith jose and sends it asAuthorization: Bearer. The symbolicsign_with: hs256_test_secretresolves to PostgREST's testCfg secret via a map in the harness (same pattern as the asymmetric JWK inBier.ConformanceServer), keeping the YAML declarative.exp) that the server must reject, so the harness must not validate or coerce them.jwt-aud: youraudience, which is mutually exclusive with the shared instance'sjwt_aud: nil, so they are added to@variant_case_idsand run on dedicated instances. 1474 (jwt-aud: null) matches the shared config and stays put.:jwtarm of thepending_reasoncond is gone.Library fixes the cases exposed
Bier.JWTdetected non-numericexp/nbf/iat, wrong-typedaud, and audience mismatches, but collapsed them all into:jwt_invalid, rendered asPGRST301/"JWSError JWSInvalidSignature". PostgREST v14.12 returnsPGRST303with specific messages. It also skippedaudtype-checking entirely when nojwt-audwas configured, accepting object-valuedaudclaims with a 200.Bier.JWTnow returns distinct reasons:{:claim_not_number, claim},:aud_not_string,:not_in_audience;audis type-checked unconditionally while membership is still only enforced whenjwt-audis configured (empty-arrayaudremains "no audience").Bier.Plugs.FallbackControllermaps each to 401PGRST303with PostgREST's exact wording (The JWT 'exp' claim must be a number,The JWT 'aud' claim must be a string or an array of strings,JWT not in audience).Testing
mix test --only area:auth— 45 tests, 0 failures (was 33 runnable + 12 pending).mix precommit— every gate passes; the only test failures are the pre-existing PostGIS geojson cases 1616–1618 ([conformance][env] PostGIS not installed for GeoJSON cases (1616-1618) #15), unrelated to this change.🤖 Generated with Claude Code