# RB-05 — drop the BSN-bearing query and body snippet from the ZGW failure message Status: **implemented** · 2026-08-27 · Source findings: `07-bio2-compliance.md` BIO-009 · `99-backlog.md` RB-05 ## What was wrong `ZgwHttpClient.SendWithRetryAsync` built its failure message as ```csharp $"ZGW {req.Method} {req.RequestUri} failed: {(int)res.StatusCode} {snippet}" ``` with `snippet` being up to 500 characters of the **response body**. That message is not transient: `Program.cs`'s submit endpoint catches it and stores it as `Aanvraag.ZgwError` in SQLite, and logs it. Two BSN paths into it: - **the query string.** ZGW filters travel as query parameters, and the citizen-scoped zaken list filters on `rol__betrokkeneIdentificatie__natuurlijkPersoon__inpBsn=`. - **the body snippet.** OpenZaak's error responses echo the offending request, so a rejected `POST /rollen` (whose body carries `BetrokkeneIdentificatie(aanvraag.Owner)`) comes back with the BSN in it. The two `"returned null body"` throws in `GetAsync`/`PostAsync` interpolated the same url. ## What changed | File | Change | | ------------------------ | --------------------------------------------------------------------------------- | | `Zgw/ZgwHttpClient.cs` | `Redact(url)` (path only) at all three sites; snippet → `res.ReasonPhrase` | | `ZgwDivergenceTests.cs` | **new** `A_recorded_divergence_carries_no_response_body_and_no_query_string` | Status + path is enough to route a failure to the right endpoint. The diagnostic detail that was lost already has a deliberate home: `ZGW_DEBUG_HTTP=1` wires `ZgwDiagnosticHandler`, which logs the full url and request bytes — opt-in, dev-only, and not persisted. ## The test Fails the `statustypen` GET (the only call in that fixture whose url carries a query string) after the zaak POST succeeds, then asserts on the persisted `ZgwError`: no `"stub failure"` (the body snippet), no `"?"` (the query string), but still the path and the `503`. **Confirmed it fails without the fix** — restoring the old interpolation turns it red on both counts. ## Verification `dotnet format --verify-no-changes` clean. `dotnet test`: **253 passed, 1 failed** — the pre-existing `OpenZaakIntegrationTests.Admin_cases_…`, which needs a live container.