Skip to content

chore(drift): triage the baremetal commitment operations; serve the seven query parameters the refreshed contract declares - #884

Open
Huyvux12 wants to merge 3 commits into
stephrobert:mainfrom
Huyvux12:chore/drift-triage-baremetal-commitments
Open

Huyvux12 wants to merge 3 commits into
stephrobert:mainfrom
Huyvux12:chore/drift-triage-baremetal-commitments

Conversation

@Huyvux12

Copy link
Copy Markdown

Fixes #875

What

Three commits, 16 files, +646/−33, base main @ e23b49b:

  1. 8340c02 — triage: decline baremetal/v1 UpdateServerCommitment and UpgradeServerCommitment, baseline unknown 2 → 0.
  2. 67d677d — re-extract contracts/scaleway.json from the current upstream (the pre-push hook contracts-are-extracted requires the committed contract to match a fresh extraction; the committed one predated chore(drift): refresh the upstream coverage baseline #827) + docs/limits.md 712 → 718 schemas.
  3. 6ce30fb — serve the seven query parameters the refreshed contract declares, which TestNoDeclaredQueryParameterIsDroppedByItsHandler refused to let pass (13 Scaleway list operations read their query and still drop 24 declared parameters (the per-parameter half of #271) #277).

Why decline (the two operations)

SDK semantics (baremetal_sdk.go:3150, :3190): UpdateServerCommitment toggles auto-renewal on an existing commitment (ServerID + AutoRenewal bool); UpgradeServerCommitment starts or upgrades one to a period of one month to three years (ServerID + Period). Both return *Server; both are paid billing-term changes.

No client this project drives calls either:

  • Terraform provider: UpdateServerCommitment 0 hits, UpgradeServerCommitment 0 hits (positive control: UpdateServer resolves in internal/services/baremetal/server.go).
  • scw CLI: scw baremetal commitment is an empty parent node — baremetalCommitment() has Short/Long/Namespace/Resource only, no Verb, no Run, no subcommands; live scw baremetal commitment --help on scw 2.56.3 falls back to baremetal help. The only commitment-period args are fields on server create / server update, whose Run funcs call api.CreateServer / api.UpdateServer.
  • The pack never orders servers (baremetal.go: servers enter only via the state door; CreateServer already declined as "a paid commitment"). Same family as already-declined GetServerTypesAvailability.

The reason names what reopens it: "the first client measured on either path reopens it".

The issue's first question, answered

The two operations arrived with baseline refresh #827, commit 947325c (2026-10-28). The nightly drift job DID surface them as a diff (baseline unknown: [] → 2 entries), but by design it opens PRs on surface moves and issues only on scan failure — no issue was opened and no triage followed for 14 days.

The seven parameters (commit 3)

Served (5):

  • instance/v1 ListIPs server (string) + detached (bool): server filters by the attached server id, detached by whether one is attached at all (Attrs["server"] is {id, name} on attach, nil on detach). The SDK names them "Precisely one of Server, Detached must be set"; the handler applies each filter it is given, so both together narrow conjunctively rather than inventing which one wins.
  • ipam/v1 ListIPs regional (bool): every address here is regional, so regional=false matches nothing; an unparseable value is a 400 (queryBool, mirroring attached/is_ipv6).
  • marketplace/v2 ListLocalImages image_id (string): resolves the label through labelByID before the ubuntu_jammy default, so an id alone still names its image; an id outside the table, or one that disagrees with a label also sent, answers empty.

Refused with a 400 and a reason (2), documented in docs/limits.md:

  • version_id: this catalogue records no version for its images; answering the one image for an arbitrary version would claim a version nobody recorded. Measured: the Terraform provider references ListLocalImages nowhere.
  • security_group_ids: this pack records no security group on a private interface (create/update ignore the security_group_id the SDK's requests carry; both views omit it), and the SDK lets create/update set the interface's own group, so deriving it from the attached server would be a guess. Measured: the Terraform provider references SecurityGroupIDs nowhere.

Each new behaviour carries a test that fails without its fix and passes with it (verified by reverting each handler: all 4 tests fail on the unfixed tree).

Proof (per the maintainer's requirements on #875)

  • Base e23b49b. mise run drift:check clean (exit 0, 51.71s; scaleway 204 implemented / 344 declined / 0 unknown) + mise run check passed (exit 0, 346.27s, "local check passed", no FAIL) — these two are the proof.
  • The scw-cli conformance leg ran as a regression check only (exit 0, 131.32s): a declined operation has no route to drive, so the leg's green implies nothing about the decline (the maintainer verified tools/conformance/scaleway/scw-cli.sh mentions commitment zero times).
  • mise run evidence:update was not run as proof: it writes coverage/evidence.json and risks unrelated diff scope.
  • Falsify: replay of the 7 specs (address-domains, artefact-reasons, catalogue-is-served, command-tables-two-audiences, recorded-scaleway-fields, the-gateway-is-served-and-scanned, undriven-says-why) — all 7 pass (exit 0 each, restoration green after every mutation) on the 3-commit HEAD. Stock mise run falsify cannot start on this VM (it wraps commands in systemd-run --user --scope; no systemd user bus), so the replay used a local copy with only the systemd-run prefix removed, repo file untouched.
  • mise run docs:check passed (exit 0, 13.48s; README up to date).
  • mise run limits:check passing (exit 0; 61 sections, 123 issues cited) after docs: the limits page catches up, and a Linux reader installs without Homebrew (#857, #843) #878 re-dated the sections that made it fail pre-existing at the old base.
  • Debate round 1 (triage) and round 2 (full 3-commit diff): 0 blockers each, challenger-verified independently, including a live falsification of the image_id test.

Risks interrogated and excluded

… a measured absence of caller

Fixes stephrobert#875

Assisted-by: Muse (Muse Spark 1.3)
…pstream

The pre-push hook requires contracts/scaleway.json to match a fresh extraction. The committed contract predates the stephrobert#827 baseline refresh: it lacked the two baremetal commitment operations triaged in the previous commit, and the current upstream OpenAPI adds further fields (e.g. application_id). This refresh adds the two operations' contract entries and the other upstream drift; docs/limits.md carries the regenerated schema count 712 -> 718.

Assisted-by: Muse (Muse Spark 1.3)
…t declares

The contract re-extraction in the previous commit declares seven query
parameters the handlers never named, which TestNoDeclaredQueryParameterIsDroppedByItsHandler refuses to let pass (stephrobert#277). Five are served, two are refused with a reason — never dropped:

- instance/v1 ListIPs: `server` filters by the attached server id and
  `detached` by whether one is attached at all (Attrs["server"] is
  {id, name} on attach, nil on detach). The SDK names them precisely one
  of a pair; the handler applies each filter it is given, so both together
  narrow conjunctively rather than inventing which one wins.
- ipam/v1 ListIPs: `regional` is the opposite of the `zonal` filter the
  handler already serves — every address here is regional, so
  regional=false matches nothing and an unparseable value is a 400.
- marketplace/v2 ListLocalImages: `image_id` resolves the label through
  labelByID, so an id alone still names its image; an id outside the table,
  or one that disagrees with a label also sent, answers empty.
- marketplace/v2 ListLocalImages: `version_id` is refused with a 400 —
  this catalogue records no version for its images (docs/limits.md).
- instance/v2alpha1 ListPrivateNetworkInterfaces: `security_group_ids` is
  refused with a 400 — this pack records no security group on a private
  interface (create/update ignore the security_group_id the SDK's requests
  carry), and the SDK lets create/update set the interface's own group, so
  deriving it from the attached server would be a guess. Measured: the
  Terraform provider references SecurityGroupIDs nowhere, so no client this
  project drives passes it.

Each new behaviour carries a test that fails without its fix and passes
with it. Part of the stephrobert#875 PR: the triage there cannot be pushed without the
re-extraction, and the re-extraction cannot land without these.

Assisted-by: Muse (Muse Spark 1.3)

This branch has not been deployed

No deployments
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.

Two baremetal commitment operations arrived untriaged, and the baseline carries them as unknown

1 participant