Skip to content

v0.37.1 — assert the wire headers are sent, not merely declared

Choose a tag to compare

@rustyconover rustyconover released this 05 Aug 00:03
· 202 commits to main since this release

Two new shared-suite groups. Ports may see new failures — that is the point.

Both close the same gap in two more places: a rule asserted where it is declared and never where it applies.

TestErrorHeader — the error flag must be sent

A failed RPC answers HTTP 200. The error rides the body as an EXCEPTION batch, because the call reached the method and the method raised — so the status line says nothing, and X-VGI-RPC-Error: true is the entire signal that distinguishes a failure from a result.

The suite required that header to appear in Access-Control-Expose-Headers and never checked that any response carried it. A port could expose a header it never sends and pass clean. Exposing what you do not emit is not the smaller bug; both leave a client reading a failure as success.

Two assertions, both directions:

test_error_response_sets_the_flag a raising method answers 200 with X-VGI-RPC-Error: true
test_success_response_does_not_set_the_flag a successful call does not

The second matters as much as the first: a flag set on every response carries no information, which is the same outage as never setting it.

Ungated — every HTTP port runs these.

TestRequestId — the correlation id must agree with the log

X-Request-ID on the response and request_id in the access log must name the same request. An id present on the response but absent from the log, or different between them, is worse than having none — it looks like a working trail right up to the moment someone tries to follow it.

test_response_carries_a_request_id an id is emitted, generated when none was sent
test_inbound_request_id_is_echoed a caller's id is propagated, not replaced
test_generated_ids_differ_between_requests a minted id is not a constant
test_request_id_matches_the_access_log header and record name the same request

docs/access-log-spec.md §4.4 makes propagation a SHOULD, so the header cases skip for a port that emits nothing rather than failing it. Agreement is not optional: a port that emits both must make them equal.

The correlation case needs to read what the server logged, so it is gated on a new optional fixture:

conformance_http_access_log  ->  (port, path)

a worker started with --access-log PATH. Omit it and only that one case skips.

The sweep

These were found by looking for every place the suite checks an advertisement without checking the corresponding behaviour — the shape behind the last three bugs. No further instances exist. Everything else already asserts behaviour:

capability behaviour assertion
VGI-Max-Request-Bytes 413 on an oversized inline body
VGI-Max-Response-Bytes strict-cap group raises on overshoot
VGI-Supported-Encodings test_empty_advertisement_means_never_compressed
VGI-Sticky-Default-TTL drives a real expiry from the advertised value
VGI-Sticky-Enabled / echo headers round-trip asserted
VGI-Proxy-Proof-Required enforcement asserted
VGI-Auth-Reason / -Proxy-Required asserted on real 401 responses
VGI-Upload-URL-Support / -Max-Upload-Bytes upload flow exercised

For porters

If TestErrorHeader fails, check that your error path sets X-VGI-RPC-Error: true on the 200 it returns — and that your success path does not. If TestRequestId::test_request_id_matches_the_access_log fails, your header and your log are naming different requests, which no amount of grepping will reveal in production.

Both groups were verified by sabotage before shipping: suppressing the flag, setting it unconditionally, minting an id instead of echoing one, and stamping a different id on the response each fail the case that covers them.


Upgrading: no action for library users — this is conformance tooling. No public API changes; no wire-protocol changes; protocol_hash unchanged.