feat(scaleway): the API gateway's own route, and a scan that can name it - #782
Merged
Merged
Conversation
`GET /metadata` is what the SDK asks before building a `srn://…` client-side, and this emulator answered 404 to it. Measured through `feint proxy --record`: one apply plus destroy of the conformance fixture sent **148 of them, all refused** — 148 of that run's 169 refusals (#776). Nothing failed, because the callers discard the error and the SRN stays empty. That is luck rather than a decision, and the shape of #257 exactly. THE INSTRUMENT MOVED BEFORE THE HANDLER COULD `Route.Operation` must name an operation the drift scan finds, and the scan walked `api/<product>/<version>` only. `Client.GetAPIMetadata` lives in `scw/` and hangs off `*Client`, so it failed two of the walk's criteria at once: a route declaring it would have been an orphan, and all three baselines carry zero. The scan now reads the gateway package on a criterion of its own. Reusing issuesRequest was measured wrong IN BOTH DIRECTIONS, which is the part worth recording: that matcher is written for the product packages, where the request literal is a QUALIFIED scw.ScalewayRequest, delegation targets an unexported method, and the transport is `recv.client.Do`. Inside `scw/` the literal is unqualified, `Do` is exported and called on the receiver, and there is no `client` field — so it returned `Client.Do`, the transport every call goes through, and `Config.String`, a formatter, and missed the one operation that matters. Building a request is the honest criterion: `Do` receives one, `String` never sees one. It answers exactly one method today and will answer a second the day Scaleway adds one, which is the scan's job rather than a leak. My own pre-measurement was wrong too, and the coincidence was nasty: a grep for `.Do(` or `ScalewayRequest{` counted "83 methods, one issues a request". The right answer is also one — a different one. THE CONTRACT DESCRIBES IT RATHER THAN EXEMPTING IT TestEveryRouteMatchesItsContract requires the operation to exist in the document, and Scaleway publishes one document per product. Rather than weaken that guard, the extraction grew a `--gateway` fragment, the same escape `--error-shape` already uses for a shape the SDK reads and the documents do not carry. So the response is validated, and a collision with an extracted name is refused rather than silently won. THE VALUES ARE THE REAL CLOUD'S A read-only shot at an fr-par account, 2026-09-14 and again 2026-09-15, no resource created, committed as corpus/scaleway/scw-gateway.jsonl. A committed corpus is sanitised, so it grades the status and the field tree and NOT the values; those are held by the contract fragment and by a test that writes them out rather than reading them from the handler. THREE GUARDS SAID NO, AND EACH WAS RIGHT - TestScanProductAndVersionAreCarried: an operation with no version. The gateway declares none, on scan_outscale.go's precedent — so the test now asserts BOTH halves: a product operation carries a version, the gateway carries none. - TestEveryRouteFallsUnderADeclaredPrefix: `/metadata` under no declared prefix, which would answer a near miss in net/http's plain text. - TestEveryDeclaredPrefixLooksLikeAScalewayProduct: `/metadata` is not shaped like `/<product>/v<N>/`. The exception is named rather than admitted by a looser regex, and held from the other side: if the path leaves the list, the test says the exception now permits nothing. PROVEN - `drift:check` green, `scw: 1 implemented, 0 declined, 0 unknown (of 1)`. - `corpus:check` replays the recording. - conformance:leg -- probe, scw-cli and fields: green. `probe` drives the route from its API description, which no unit test does; `fields` is the only leg where the omission gate judges. - Six mutations, each compiling and each biting, including the one that changes the domain — every SRN a client builds from it would be silently wrong. - `mise run prepush` green; evidence.json records it driven, `contract: clean`. ONE THING I CANNOT EXPLAIN `falsify -- recorded-scaleway-fields` failed once, in a way its own five mutations did not: they all bit, and the post-restoration run of the whole tree came back red. It has been green on the four runs since. `go test ./...` passes in the repository, and a byte-for-byte reproduction of the copy falsify builds — same exclusions — passes too. So the cause is not identified, and this says so rather than calling it flaky on one green. Assisted-by: Claude Code (claude-opus-5)
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.
GET /metadatais what the SDK asks before building asrn://…client-side,and this emulator answered 404 to it. Measured through
feint proxy --record:one apply plus destroy of the conformance fixture sent 148 of them, all
refused — 148 of that run's 169 refusals (#776).
Nothing failed, because the callers discard the error and the SRN stays empty.
That is luck rather than a decision, and the shape of #257 exactly.
THE INSTRUMENT MOVED BEFORE THE HANDLER COULD
Route.Operationmust name an operation the drift scan finds, and the scanwalked
api/<product>/<version>only.Client.GetAPIMetadatalives inscw/and hangs off
*Client, so it failed two of the walk's criteria at once: a routedeclaring it would have been an orphan, and all three baselines carry zero.
The scan now reads the gateway package on a criterion of its own. Reusing
issuesRequest was measured wrong IN BOTH DIRECTIONS, which is the part worth
recording: that matcher is written for the product packages, where the request
literal is a QUALIFIED scw.ScalewayRequest, delegation targets an unexported
method, and the transport is
recv.client.Do. Insidescw/the literal isunqualified,
Dois exported and called on the receiver, and there is noclientfield — so it returnedClient.Do, the transport every call goesthrough, and
Config.String, a formatter, and missed the one operation thatmatters.
Building a request is the honest criterion:
Doreceives one,Stringneversees one. It answers exactly one method today and will answer a second the day
Scaleway adds one, which is the scan's job rather than a leak.
My own pre-measurement was wrong too, and the coincidence was nasty: a grep for
.Do(orScalewayRequest{counted "83 methods, one issues a request". Theright answer is also one — a different one.
THE CONTRACT DESCRIBES IT RATHER THAN EXEMPTING IT
TestEveryRouteMatchesItsContract requires the operation to exist in the
document, and Scaleway publishes one document per product. Rather than weaken
that guard, the extraction grew a
--gatewayfragment, the same escape--error-shapealready uses for a shape the SDK reads and the documents do notcarry. So the response is validated, and a collision with an extracted name is
refused rather than silently won.
THE VALUES ARE THE REAL CLOUD'S
A read-only shot at an fr-par account, 2026-09-14 and again 2026-09-15, no
resource created, committed as corpus/scaleway/scw-gateway.jsonl. A committed
corpus is sanitised, so it grades the status and the field tree and NOT the
values; those are held by the contract fragment and by a test that writes them
out rather than reading them from the handler.
THREE GUARDS SAID NO, AND EACH WAS RIGHT
declares none, on scan_outscale.go's precedent — so the test now asserts BOTH
halves: a product operation carries a version, the gateway carries none.
/metadataunder no declared prefix,which would answer a near miss in net/http's plain text.
/metadatais not shapedlike
/<product>/v<N>/. The exception is named rather than admitted by alooser regex, and held from the other side: if the path leaves the list, the
test says the exception now permits nothing.
PROVEN
drift:checkgreen,scw: 1 implemented, 0 declined, 0 unknown (of 1).corpus:checkreplays the recording.probedrives the routefrom its API description, which no unit test does;
fieldsis the only legwhere the omission gate judges.
the domain — every SRN a client builds from it would be silently wrong.
mise run prepushgreen; evidence.json records it driven,contract: clean.ONE THING I CANNOT EXPLAIN
falsify -- recorded-scaleway-fieldsfailed once, in a way its own fivemutations did not: they all bit, and the post-restoration run of the whole tree
came back red. It has been green on the four runs since.
go test ./...passesin the repository, and a byte-for-byte reproduction of the copy falsify builds —
same exclusions — passes too. So the cause is not identified, and this says so
rather than calling it flaky on one green.
Assisted-by: Claude Code (claude-opus-5)
Closes #776
🤖 Generated with Claude Code