Repository navigation
Added
-
A stack preflight reads what a configuration declares, before anything
starts (#888).feint runreads the Terraform or OpenTofu stack its child
would read and refuses, before the lab is up, a configuration declaring a type
a pack refuses;feint doctor --stack <dir>asks the same question outright,
changing nothing.--preflighttakesauto(the default, refuses only a
declined type),strict(also refuses an unmeasured one) andoff;
--preflight-jsonandfeint doctor --stack-jsonwrite the report where CI
can read it. A refusal is exit 1: 2 is drift, and the codes are a contract.What it replaces, measured on 2026-11-12 with provider outscale/outscale
1.8.0: a stack with three declined types applied 48 resources, failed with two
404s, left 50 entries in the state, and never attempted the third declined
type at all, because its dependencies had failed — so fixing the two visible
errors bought a second full apply to find the third. The preflight names all
three in 12 ms, with nothing created.compatiblemeans a recorded run applied and destroyed those types against
this emulator. It is not a promise about every attribute, nor about anything
past the control plane, and a type whose product is outside the drift scan
reads asunknownrather than refused.docs/limits.mdsays what the reading
cannot cover. -
feint checkpointandfeint reset(#853): a checkpoint records the
control plane and the object bytes under one name, and a reset returns the
lab to it — destroying what the checkpoint does not hold, starting again what
the host no longer holds, and putting each pack's firewall rule sets back on
the runtime. The verdict is not the operation's own: it compares what a
client can observe, control plane, bytes read back through the doors, and
what the host holds, and it saysdid not convergerather than reporting the
intention. -
A Linux install route in the Quick Start (#843), under the Homebrew one
and generated from the same version the install page is pinned to. Six lines,
and they verify: the bytes are checked against the publishedchecksums.txt
before anything is installed. What that does not prove is said rather than
implied — it proves the bytes match the list, not who wrote the list, and the
signature over the list stays indocs/install.md. -
feint runowns the lab (#848): with no--endpointit starts an
emulator, waits for it, resolves the provider environment the wayfeint env
does, runs the command and stops everything it started.--providernarrows
the exports to one pack,--keep-on-failureleaves a failed run's lab up and
prints the exact command to reach and remove it,--json <path>writes the
receipt where it is asked for, and--runtimeasks the host for a machine
runtime before anything starts, with the refusalfeint upmakes. The exit
code is the child's, and stdout belongs to the child alone. -
A run removes the variables a pack measured as a way back to the real
cloud, rather than only overriding them:OSC_PROFILEmakes the Outscale
provider 1.1.x read~/.osc/config.jsonand ignore the endpoint export
entirely (#342), so overriding does not help and the variable has to go. The
names are discovered from the packs' ownEnvHazards, not kept in a second
list here.
Changed
-
The Outscale example stack pins its provider exactly (#873, #898), at
1.8.1, where it floated at~> 1.7.docs/clients.md's row for it goes
from "resolved fresh on each run, so the version that answered is not knowable
here" to "exact: the version that answered". The floor was right and the
floating part was the accident #778 measured on another stack: two engines
resolving one constraint to two different versions, both reporting success.
The module's own~> 1.7stays, deliberately — it is a floor for reuse, and
Terraform intersects it with the root's pin. -
The API descriptions are re-extracted, and Outscale's document moved from
1.42.0to1.43.2(#900), 655 schemas to 656:RequestedSnapshotMode
added,Snapshot,FiltersSnapshot,AccessKey,ApiAccessPolicyand
UpdateApiAccessPolicyRequestchanged. Scaleway's baremetal options moved
with them, gainingprivate_network,public_bandwidth,remote_access,
licenseandcertification. No newly declared query parameter lands on a
route this emulator mounts, which is the case that would have cost code. -
The coverage headline names the population it counted. It read "Of the
548 operations upstream declares" while the Scaleway scan covers 11 of the 56
products in that SDK, so a third of the provider was printed as the provider.
A stack using a product outside the scan reaches the real endpoint, and the
README now says which scan it is talking about. -
README.mdstops saying object storage is out of scope. It shipped in
0.15.0; the sentence sat outside the generated blocks, wherefeint docs --checkcould not reach it. -
A tag is refused while an open milestone claims a version already tagged
(#877).v0.14.0andv0.15.0were both published while milestones named
after them stayed open with 19 and 10 issues, so the tracker said two
released versions were unfinished.tools/release/milestone-gate.shasks
before each tag, and says when it could not measure rather than refusing for
a reason that is not about the repository. -
docs/limits.mdcaught up with behaviour that changed months ago (#857).
Eleven sections cited issues that had closed since anyone last read them;
three were false, including a heading saying the Exoscale Terraform provider
is refused when it has been driving the pack since September. -
The boundary of this product is written down (#196, #733):
docs/limits.mdstates that feint never manages a resource whose loss would
matter. Two current texts had said opposite things for two months, neither
citing the other. -
feint runleaves stdout to the command it runs. Its own prose goes to
stderr and the JSON receipt to a path. Measured rather than reasoned: the
first version wrote the receipt to stdout, and replaying a surveyed stack
madeterraform applyprint its plan into the same stream, so the receipt
was unparseable exactly when the run was real. -
A run refuses a measured escape it has no door for, before the child
starts. Not every hazard: the ones the packs report are what this command
intercepts, so the question is whether THIS run mounts a door for the pack
that reported it. The receipt also reports the runtime and the capabilities
the emulator declares, rather than the mode that was asked for.
Fixed
-
Six query parameters a served route declared and dropped in silence
(#884, #875). The Scaleway API description had not been re-extracted since
2026-10-19 while the documents moved under it; a fresh extraction answered
+328 lines, holding twenty-one newly declared query parameters, six of them on
routes this emulator serves.server,detached,regional,image_id,
version_idandsecurity_group_idsare now served, or refused by name.
version_idis refused before anything else is resolved, so a request
carrying it with an unknown label is told which argument is the problem rather
than answered "no such image". Found by an outside contributor, as a side
effect of a triage. -
The nightly drift scan reports a debt, not only an arrival (#892, #886).
The gate asked whether something appeared that is not in the committed
baseline, and the baseline records the unknown operations — so the first
refresh after an arrival wrote it down and every later night found nothing
new while the operation was still undecided. Measured: two baremetal
commitment operations sat undecided for fourteen green nights. Three more
halves of the same mechanism moved with it: the pull request now carries the
API descriptions it regenerated, which had not travelled since 2026-10-19; the
triage view covers the eleven products the gate scans rather than three, so an
operation outside those three can now be named; and a source that could not be
measured makes the night red instead of reading as an absence of drift. -
The drift report finds its own issue by title, not by label alone (#894).
The lookup was--label driftplus the newest match, and three open issues
wear that label. With the backlog empty, the first quiet night would have
closed the issue carrying the work still to do, with the words "Every
operation upstream is triaged". -
The falsification replay fits its budget, and a ceiling it reached is a
measured fact (#893, #890). The scheduled run of 2026-11-12 was cancelled
after 210.3 minutes against thetimeout-minutes: 210it declares for itself,
and the issue it opened called that the run's own infrastructure. The cost was
in the repository: instrumented on one spec, the two full test suites it runs
per spec were 45 of 53 seconds, which across a replay is 242 baselines and 242
restorations for some fifteen distinct questions. The baseline is now answered
once per packages and environment, and the restoration is read off the bytes
of the files that were mutated. Eight./internal/cli/specs, 54 mutations,
every one still biting: 441 s before, 181 s after. The night report tells a
budget reached from a runner lost, and names the duration and the ceiling. -
A test asked the kernel for a promise it never made (#896). The free-port
probe closes its listener before answering, so the same port may be handed
straight back; a test required two consecutive probes to differ. Measured over
two thousand pairs on one station: one came back identical. It asserts
loopback and bindable now, which is what the function promises — its own
comment opens with "Racy by nature". -
A reset puts a firewall rule back on the interface, not only in the store
(#871).Surveyanswers names, and a rule set whose content changed keeps its
name, so nothing in the observation could see the difference: a reset reported
convergence while the runtime went on enforcing the rules of a state the
checkpoint does not describe. Reproduced with a TCP connection under
--vm incusbefore being fixed. The same pass fixed a reset starting the
machine of a record the checkpoint describes as stopped, and then writing
runningover the state it had been asked to return to. -
The reset verdict compares the bytes of an object, not just its name
(#871). It read the digest from a fieldListObjectsV2does not emit, so the
field was always empty and two different contents under one key compared
equal. Each object is now fetched and hashed by the observer. -
feint runfails when it did not keep a promise (#871). Only
did not convergeused to fail the run, so a failed reset, one that could not
be read back, and a lab this command owned and could not stop all left the
exit code at the child's. -
A checkpoint is whole or it is the previous one (#871). The bytes were
saved before the control-plane snapshot, so a failure in the second step left
an earlier checkpoint of that name holding its old store beside the new object
references. -
Named checkpoints stop overwriting each other (#871): the emulator holds
any number and the CLI wrote one file per instance, socheckpoint Athen
checkpoint Bmadereset Aimpossible. -
The
gofmtpre-commit hook fails when gofmt cannot run (#829). It read
the list of offending files and never the exit code, so any failure of gofmt
produced an empty list and the hook reportedPassed. Its window is a fresh
clone beforemise trust, which is a new contributor's first commit. -
A balancer verdict is drawn from twenty-four connections, not six (#559).
Six is a coin flipped six times: a balancer that works sent every connection
to one side about one run in thirty-two, so the dataplane suite reddened on a
subject that was behaving. The same arithmetic ran the other way after an
unlink, as a false green over a real defect.
Proved against
The clients
| Client | Version | Pinned in | Drives, in CI |
|---|---|---|---|
scw |
2.56.3 | .github/workflows/conformance.yml (SCW_VERSION) |
Scaleway |
| Terraform | 1.13.3 | .github/workflows/conformance.yml (TERRAFORM_VERSION) |
Exoscale, Outscale, Scaleway |
| OpenTofu | 1.12.5 | .github/workflows/conformance.yml (TOFU_VERSION) |
Exoscale, Outscale, Scaleway |
octl |
0.0.32 | .github/workflows/conformance.yml (OCTL_VERSION) |
Outscale |
exo |
1.95.6 | .github/workflows/conformance.yml (EXO_VERSION) |
Exoscale |
The Terraform providers
The client above is the engine; what answers this emulator is the provider.
Each row is one required_providers entry, read where it is written.
| Fixture or stack | Provider | Constraint | What that is worth | Applied in CI |
|---|---|---|---|---|
tools/conformance/faults |
outscale/outscale |
~> 1.7 |
constraint: resolved fresh on each run, so the version that answered is not knowable here | yes |
tools/conformance/outscale/terraform |
outscale/outscale |
~> 1.7 |
constraint: resolved fresh on each run, so the version that answered is not knowable here | yes |
tools/conformance/outscale/terraform-doorway |
outscale/outscale |
~> 1.7 |
constraint: resolved fresh on each run, so the version that answered is not knowable here | yes |
tools/conformance/scaleway/terraform |
scaleway/scaleway |
2.83.0 |
exact: the version that answered | yes |
examples/stacks/exoscale |
exoscale/exoscale |
0.72.0 |
exact: the version that answered | yes |
examples/stacks/exoscale |
hashicorp/aws |
6.72.0 |
exact: the version that answered | yes |
examples/stacks/outscale |
outscale/outscale |
1.8.1 |
exact: the version that answered | yes |
examples/stacks/outscale/modules/net |
outscale/outscale |
~> 1.7 |
constraint: resolved fresh on each run, so the version that answered is not knowable here | yes |
examples/stacks/scaleway |
scaleway/scaleway |
2.83.0 |
exact: the version that answered | yes |
examples/quickstart/outscale |
outscale/outscale |
~> 1.7 |
constraint: resolved fresh on each run, so the version that answered is not knowable here | yes |
examples/quickstart/scaleway |
scaleway/scaleway |
2.83.0 |
exact: the version that answered | yes |
Read the third column narrowly, because it is the one a consumer pins against.
An exact constraint names the version that answered. A constraint is
resolved by terraform init -upgrade on the runner, every run, so the version
that answered is not knowable from this repository — it is a floor, not a
proof. Not pinned is not pinned: nothing here says which version ran, and
no number is invented to fill the cell.
Every stack under examples/stacks/ is applied on every pull request.
Generated from the conformance workflow and the fixtures at this tag.
A newer client is not known to work until the pin moves and the suite
passes on it: docs/clients.md says what each cell is worth.