Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d9b6176
feat(objectstore): persist neutral object bytes atomically
stephrobert Nov 6, 2026
d0e335c
feat(s3): prove explicit gateway byte transfers with AWS CLI
stephrobert Nov 6, 2026
f129a0f
feat(objectstore): bound retained bytes and concurrent uploads
stephrobert Nov 6, 2026
3d3ed3a
feat(s3): mount persistent object bytes on the existing port
stephrobert Nov 6, 2026
7c3e087
feat(s3): prove private Scaleway bucket lifecycle
stephrobert Nov 7, 2026
be0463d
test(s3): measure Exoscale ignoring endpoint prefixes
stephrobert Nov 7, 2026
0915951
feat(s3): route Exo uploads through explicit same-port hosts
stephrobert Nov 7, 2026
ff2df80
feat(s3): prove Exo listing and multi-range downloads
stephrobert Nov 7, 2026
fc9258d
feat(s3): prove Exo transactional bulk deletion
stephrobert Nov 7, 2026
22dbc19
feat(s3): persist and prove multipart upload sessions
stephrobert Nov 7, 2026
a601a59
feat(objectstore): add durable named checkpoints and explicit garbage…
stephrobert Nov 7, 2026
2702f8d
feat(s3): the Exoscale bucket cycle, the shared S3 discovery and the …
stephrobert Nov 9, 2026
39fbf52
feat(outscale): an OOS door, declared on five measurements and nothin…
stephrobert Nov 9, 2026
e7a13c7
feat(outscale): octl drives the OOS door, and the bucket listing stop…
stephrobert Nov 9, 2026
ef963ef
Merge remote-tracking branch 'origin/main' into feat/850-object-stora…
stephrobert Nov 9, 2026
2cc2c75
feat(outscale): bytes through the OOS door, out and back, compared by…
stephrobert Nov 9, 2026
6f6383d
docs(outscale): record two OOS discovery answers, and say which two a…
stephrobert Nov 9, 2026
143630c
feat(cli): feint run lands a hardcoded-endpoint client locally, and t…
stephrobert Nov 9, 2026
876c58c
feat(cli): Terraform reaches the local door through feint run, with n…
stephrobert Nov 9, 2026
bd2f9a1
docs: the hardcoded Terraform refusal fell, and its premise was the w…
stephrobert Nov 9, 2026
3ac3268
ci: the hardcoded-endpoint witness runs on every pull request, and th…
stephrobert Nov 9, 2026
4b677ca
fix(conformance): three starters arm the byte store, and a marked ref…
stephrobert Nov 9, 2026
df1874a
feat(stacks): an Exoscale stack reaches local object storage, and no …
stephrobert Nov 9, 2026
b8dfc6d
fix(conformance): the SOS door is asked for, not assumed, so the imag…
stephrobert Nov 9, 2026
0691306
test(cli): the authority test reads its own CA instead of stat'ing it…
stephrobert Nov 10, 2026
e52e1c7
fix(cli): feint run accepts the fakes feint env publishes, derived ra…
stephrobert Nov 11, 2026
56179a2
feat(scaleway): a snapshot import reads the object, so a surveyed sta…
stephrobert Nov 11, 2026
4e20595
fix(ci): move the Go pin to 1.26.11, and say where the question is asked
stephrobert Nov 11, 2026
386a158
chore(release): 0.15.0
stephrobert Nov 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/breaking_configuration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ body:
attributes:
label: Versions
description: Feint, the client, and the provider — `feint version`, `terraform version`.
placeholder: "feint 0.14.0, terraform 1.13.3, scaleway/scaleway 2.81.0"
placeholder: "feint 0.15.0, terraform 1.13.3, scaleway/scaleway 2.81.0"
validations:
required: true

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/adoption-metrics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
cache: false

# The data branch, in a directory of its own. It carries no code, only
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
# No go.sum to key a cache on: the zero-dependency rule keeps this module
# dependency-free, and a pre-commit hook fails if the file ever
# appears. Pointing the cache at it warned on every run and never
Expand Down
129 changes: 125 additions & 4 deletions .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
cache: false

# No browser is installed here: the runner image ships Google Chrome, and
Expand Down Expand Up @@ -93,7 +93,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
cache: false

# The same build the release performs (static, trimmed), because the
Expand Down Expand Up @@ -208,7 +208,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
# No go.sum to key a cache on: the zero-dependency rule keeps this module
# dependency-free, and a pre-commit hook fails if the file ever
# appears. Pointing the cache at it warned on every run and never
Expand Down Expand Up @@ -236,8 +236,21 @@ jobs:
# version of #572 taught the two of them and left this one, and five
# jobs went red at 44 s with "the declared project did not list under
# its own name: []". Held by TestEveryConformanceEmulatorDeclaresTheSameProjects.
#
# --objectstore, for the probe rather than for any client suite:
# exoscale/v2.list-sos-buckets-usage reads the byte inventory and
# answers 503 without one, while its schema declares a 200 body, so
# the probe counts it as a route answering the wrong shape. Missing
# here while mise.toml had it is PR #605 to the letter -- two of
# three starters taught a flag -- and it cost four red jobs.
# TestEveryConformanceEmulatorArmsTheSameObjectStore holds it now.
objects="$(mktemp -d)"
chmod 0700 "$objects"
echo "FEINT_OBJECTS=${objects}" >> "$GITHUB_ENV"
/tmp/feint start --addr 127.0.0.1:4599 --contracts contracts \
--projects default,platform-prod --timeout 60s
--projects default,platform-prod --timeout 60s \
--objectstore "${objects}/objects" \
--s3-doors scaleway/fr-par,exoscale/ch-dk-2,exoscale/ch-gva-2
# The doorway step of the Outscale Terraform suite evals the real
# output of `feint env` rather than restating it, so the script needs
# the binary this job just built — the repo-root default it falls
Expand Down Expand Up @@ -550,8 +563,116 @@ jobs:
if: always()
run: /tmp/feint stop --addr 127.0.0.1:4599 || true

# The byte store is this job's own side effect on the runner, and a runner
# is reused. Removing it is the same discipline `feint run` follows for
# its authority: whatever a run creates, the run takes away.
- name: Remove the byte store
if: always()
run: rm -rf "${FEINT_OBJECTS:-/nonexistent}"

- name: Dump the emulator state on failure
if: failure()
run: |
curl -s http://127.0.0.1:4599/_feint/health || true
curl -s http://127.0.0.1:4599/_feint/routes || true

# The hardcoded-endpoint path, driven by a real Terraform on the runner's own
# network. A job of its own rather than a leg of the matrix above, for the
# reason the page job gives: it needs something no other leg does, here a
# local mirror of the pinned provider.
#
# It exists so that the capability stops being a measurement somebody
# reproduces and becomes a gate. #850's criterion is a "generated/bounded
# capability statement, not hand-edited marketing prose", and a sentence can
# only be generated from an instrument that runs — which is what this is.
# capability.go's matrix admits a row only when the conformance workflow
# drives the pair, so without this job the row cannot honestly exist.
#
# The witness refuses to run inside a network namespace, deliberately: a pass
# obtained in one would prove the namespace's containment rather than the
# command's. A GitHub runner has eth0 beside lo, so it qualifies, and that is
# the whole point of running it here — this is an ordinary machine.
hardcoded-endpoint:
name: hardcoded endpoint
runs-on: ubuntu-24.04
timeout-minutes: 20
permissions:
contents: read
steps:
- name: Harden runner
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
with:
egress-policy: audit
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.11'
cache: false

# The workflow-level pin, same checksums as the other two jobs that
# install this client: one client, one version, wherever it is proved.
- name: Install Terraform
run: |
set -euo pipefail
workdir="$(mktemp -d)"
base="https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}"
asset="terraform_${TERRAFORM_VERSION}_linux_amd64.zip"
tools/ci/fetch.sh "${base}/${asset}" "${workdir}/${asset}"
tools/ci/fetch.sh "${base}/terraform_${TERRAFORM_VERSION}_SHA256SUMS" "${workdir}/sums"
(cd "${workdir}" && grep " ${asset}$" sums | sha256sum -c -)
sudo unzip -o "${workdir}/${asset}" terraform -d /usr/local/bin
terraform version

# A MIRROR, not a plugin cache, and not at the same path as either. The
# witness was green once and red the second time on a developer's machine
# because TF_PLUGIN_CACHE_DIR pointed at the -plugin-dir directory: the
# first run unpacks into the mirror and every later run fails with
# "cannot install existing provider directory to itself". A runner is
# fresh each time and would never have shown it, which is exactly why it
# is written down here.
#
# The provider version is the one the witness pins in its own
# configuration; it is deliberately not a workflow variable, because the
# measurement belongs to the test that makes the claim.
- name: Mirror the pinned Scaleway provider
run: |
set -euo pipefail
mkdir -p "${RUNNER_TEMP}/tf-mirror" "${RUNNER_TEMP}/tf-seed"
version="$(grep -oE 'version = "= [0-9]+\.[0-9]+\.[0-9]+"' \
internal/cli/run_terraform_conformance_test.go | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"
test -n "${version}"
printf 'terraform {\n required_providers {\n scaleway = {\n source = "scaleway/scaleway"\n version = "= %s"\n }\n }\n}\n' \
"${version}" > "${RUNNER_TEMP}/tf-seed/main.tf"
cd "${RUNNER_TEMP}/tf-seed"
terraform providers mirror -platform=linux_amd64 "${RUNNER_TEMP}/tf-mirror"

# The witness itself. It starts its own door and byte store, drives
# `feint run`, and proves the bytes by digest rather than by exit code:
# a request that went anywhere else cannot put them in the local store.
- name: Terraform reaches the local door through feint run
env:
FEINT_TF_PLUGIN_DIR: ${{ runner.temp }}/tf-mirror
run: |
go test -tags=conformance ./internal/cli \
-run '^TestScalewayTerraformStorageThroughFeintRunOnTheHostNetwork$' \
-count=1 -v -timeout 15m

# A leftover authority is this job's own leak if there is one, and the
# diagnostic that finds it is the one shipped for the purpose.
- name: No interception authority outlived the run
if: always()
run: |
set -uo pipefail
# doctor's own exit code is not the verdict here: it fails on any
# FAIL check, and this step asks one question only. So the report is
# captured, printed, and then searched.
go run ./cmd/feint doctor --vm off > doctor.txt 2>&1 || true
grep -A2 'interception authority' doctor.txt
if grep -q 'outlived their' doctor.txt; then
echo "this job left an interception authority behind" >&2
exit 1
fi
2 changes: 1 addition & 1 deletion .github/workflows/corpus-cloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
cache: false

# Asserted, never skipped. A job that quietly did nothing when the credential was absent
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/drift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
# No go.sum to key a cache on: the zero-dependency rule keeps this module
# dependency-free, and a pre-commit hook fails if the file ever
# appears. Pointing the cache at it warned on every run and never
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/falsify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
# No go.sum to key a cache on: the zero-dependency rule keeps this
# module dependency-free.
cache: false
Expand Down
28 changes: 25 additions & 3 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,29 @@ jobs:
# the pin to a minor — that was tried and is recorded above as the
# thing that made CI resolve a version nobody named. It is a reason to
# expect this line to move often, and to keep moving it by hand.
go-version: '1.26.10'
#
# AND A FOURTH TIME, to 1.26.11 on 2026-11-11: GO-2026-6859, an
# HTTP/1 server crash on a MaxBytesReader header race in net/http,
# found in go1.26.10 and fixed in go1.26.11. Same shape as the three
# above — nothing in this repository was the cause, nothing here
# could fix it, the pin is what moves.
#
# FOUR TIMES IS A PATTERN, AND THE PATTERN IS WHERE THE QUESTION IS
# ASKED. govulncheck runs in this workflow and nowhere else: not in
# `mise run prepush`, not in .pre-commit-config.yaml. That absence is
# deliberate and CLAUDE.md states the reason — prepush is offline,
# deterministic and a few seconds long, while govulncheck queries
# vuln.go.dev and its verdict changes without a single line of this
# repository changing. A gate like that in a hook fails on the
# network rather than on the code, and teaches --no-verify.
#
# So the answer is not to move it into the hook: it is that a scan
# whose verdict moves on its own belongs on a SCHEDULE, the way
# drift.yml already scans the upstream surface every night and opens
# a pull request. Until that exists, this red lands on whoever
# happens to push next, which is what it did all four times.
# Tracked in the issue this comment's commit names.
go-version: '1.26.11'
# No go.sum to key a cache on: the zero-dependency rule keeps this module
# dependency-free, and a pre-commit hook fails if the file ever
# appears. Pointing the cache at it warned on every run and never
Expand Down Expand Up @@ -200,7 +222,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
cache: false

- name: Every operation that changed hands is named, or signed
Expand Down Expand Up @@ -256,7 +278,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
cache: false

- name: go build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
cache: false # a release build must not consume a cache a PR could poison

- name: Build
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/runtime-proof.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
# No go.sum to key a cache on: the zero-dependency rule keeps this
# module dependency-free.
cache: false
Expand Down Expand Up @@ -620,7 +620,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
cache: false

- name: Install Incus (Zabbly stable, key fingerprint pinned)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.26.10'
go-version: '1.26.11'
# No go.sum to key a cache on: the zero-dependency rule keeps this
# module dependency-free.
cache: false
Expand Down
Loading
Loading