Skip to content

feat(scaleway): the API gateway's own route, and a scan that can name it - #782

Merged
stephrobert merged 1 commit into
mainfrom
feat/scaleway-serves-the-gateway-metadata
Sep 15, 2026
Merged

stephrobert merged 1 commit into
mainfrom
feat/scaleway-serves-the-gateway-metadata

Conversation

@stephrobert

Copy link
Copy Markdown
Owner

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)

Closes #776

🤖 Generated with Claude Code

`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)
@stephrobert
stephrobert merged commit 8e0c2d7 into main Sep 15, 2026
31 checks passed
@stephrobert
stephrobert deleted the feat/scaleway-serves-the-gateway-metadata branch September 15, 2026 07:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The Scaleway gateway serves GET /metadata, this emulator answers 404 to it 148 times per apply

1 participant