diff --git a/.config/make/lint-fmt.mak b/.config/make/lint-fmt.mak index ea4682e72..f473845e2 100644 --- a/.config/make/lint-fmt.mak +++ b/.config/make/lint-fmt.mak @@ -60,6 +60,11 @@ body-cache-whitelist-check: ## Check the body-cache eligibility gate stays a fai @echo "🧱 Checking body-cache whitelist guard..." ./scripts/check_body_cache_whitelist.sh +.PHONY: s3s-footprint-check +s3s-footprint-check: ## Check the s3s dependency footprint ratchet stays frozen + @echo "đŸ“Ļ Checking s3s footprint ratchet..." + ./scripts/check_s3s_footprint.sh + .PHONY: fips-wording-check fips-wording-check: ## Check outward docs do not make unsupported FIPS claims @echo "đŸ“Ŗ Checking FIPS wording guard..." diff --git a/.config/make/pre-commit.mak b/.config/make/pre-commit.mak index ad46d7e7d..12eb9693e 100644 --- a/.config/make/pre-commit.mak +++ b/.config/make/pre-commit.mak @@ -19,13 +19,13 @@ planning-docs-check: ## Check that no planning-type documents are committed ./scripts/check_no_planning_docs.sh .PHONY: pre-commit -pre-commit: fmt-check unsafe-code-check architecture-migration-check logging-guardrails-check tokio-io-uring-check extension-schema-check body-cache-whitelist-check fips-wording-check doc-paths-check planning-docs-check quick-check ## Run fast pre-commit checks without clippy/full tests +pre-commit: fmt-check unsafe-code-check architecture-migration-check logging-guardrails-check tokio-io-uring-check extension-schema-check body-cache-whitelist-check s3s-footprint-check fips-wording-check doc-paths-check planning-docs-check quick-check ## Run fast pre-commit checks without clippy/full tests @echo "✅ All pre-commit checks passed!" .PHONY: pre-pr -pre-pr: fmt-check unsafe-code-check architecture-migration-check logging-guardrails-check tokio-io-uring-check extension-schema-check body-cache-whitelist-check fips-wording-check doc-paths-check planning-docs-check log-analyzer-rules-check clippy-check test ## Run full pre-PR checks with clippy and tests +pre-pr: fmt-check unsafe-code-check architecture-migration-check logging-guardrails-check tokio-io-uring-check extension-schema-check body-cache-whitelist-check s3s-footprint-check fips-wording-check doc-paths-check planning-docs-check log-analyzer-rules-check clippy-check test ## Run full pre-PR checks with clippy and tests @echo "✅ All pre-PR checks passed!" .PHONY: dev-check -dev-check: fmt-check unsafe-code-check architecture-migration-check logging-guardrails-check tokio-io-uring-check extension-schema-check body-cache-whitelist-check fips-wording-check doc-paths-check planning-docs-check quick-check ## Run fast local development checks +dev-check: fmt-check unsafe-code-check architecture-migration-check logging-guardrails-check tokio-io-uring-check extension-schema-check body-cache-whitelist-check s3s-footprint-check fips-wording-check doc-paths-check planning-docs-check quick-check ## Run fast local development checks @echo "✅ Fast development checks passed!" diff --git a/.github/workflows/ci-docs-only.yml b/.github/workflows/ci-docs-only.yml index 91fb1767d..17eca6cba 100644 --- a/.github/workflows/ci-docs-only.yml +++ b/.github/workflows/ci-docs-only.yml @@ -114,6 +114,9 @@ jobs: - name: Check body-cache whitelist guard run: ./scripts/check_body_cache_whitelist.sh + - name: Check s3s footprint ratchet + run: ./scripts/check_s3s_footprint.sh + - name: Check no planning docs committed run: ./scripts/check_no_planning_docs.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c696c874b..656967bb1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -149,6 +149,9 @@ jobs: - name: Check body-cache whitelist guard run: ./scripts/check_body_cache_whitelist.sh + - name: Check s3s footprint ratchet + run: ./scripts/check_s3s_footprint.sh + - name: Check no planning docs committed run: ./scripts/check_no_planning_docs.sh diff --git a/scripts/README.md b/scripts/README.md index 1885201f8..66094e541 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -34,6 +34,7 @@ their issue closes. | `check_migration_gate_count.sh` | ci-gate | Migration-critical test gate with committed count floor (`.config/migration-gate-floor.txt`) | ci.yml Test and Lint; `docs/testing/README.md` | | `check_no_planning_docs.sh` | ci-gate | Blocks committed planning-type documents | ci.yml Quick Checks; `make pre-commit` | | `check_no_tokio_io_uring.sh` | ci-gate | Keeps tokio's io-uring backend disabled | ci.yml Quick Checks | +| `check_s3s_footprint.sh` | ci-gate | Lower-only ratchet freezing the direct s3s surface ahead of the s3gate migration | ci.yml Quick Checks; `make pre-commit` | | `check_unsafe_code_allowances.sh` | ci-gate | Unsafe-code allowance ledger guard | ci.yml Quick Checks | | `layer-dependency-baseline.txt` | ci-gate (data) | Committed baseline consumed by `check_layer_dependencies.sh` | arch-checks skill | | `static.sh` | ci-gate | Static-build helper executed inside image builds | `Dockerfile.source`, `Dockerfile.decommission-local` | diff --git a/scripts/check_s3s_footprint.sh b/scripts/check_s3s_footprint.sh new file mode 100755 index 000000000..a70cdeb11 --- /dev/null +++ b/scripts/check_s3s_footprint.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash +# Ratchet guard freezing the s3s dependency footprint ahead of the +# s3gate/gateway migration (rustfs/backlog#1677, review finding F1; +# acceptance criteria recorded in rustfs/backlog#1733). +# +# The migration's goal is to shrink the direct s3s surface, so new code must +# not grow it. Two counters are ratcheted, baselines verified on 2026-08-05: +# +# - files importing s3s: rg -l 's3s::' --type rust (files) +# - s3_error! invocation lines: rg -c 's3_error!' --type rust (summed) +# +# Either count exceeding its baseline fails the check with the offending +# delta. Baselines are LOWER-ONLY: when a PR shrinks the footprint, lower the +# matching baseline in the same PR so the ratchet stays tight. Never raise a +# baseline to get green (AGENTS.md, Verification Before PR) — route new S3 +# API code through the gateway abstractions instead of importing s3s +# directly. +# +# Usage: scripts/check_s3s_footprint.sh + +set -euo pipefail + +cd "$(dirname "$0")/.." + +# Baselines verified on 2026-08-05. Lower-only; see header. +S3S_IMPORT_FILES_BASELINE=236 +S3_ERROR_LINES_BASELINE=1686 + +TMP_DIR="$(mktemp -d)" +trap 'rm -rf "$TMP_DIR"' EXIT + +# rg exits 1 on zero matches (a legitimate count of 0 at the end of the +# migration) and >1 on real errors; only the latter may abort the check. +run_rg_to() { + local out="$1" rg_status=0 + shift + rg "$@" >"$out" || rg_status=$? + if ((rg_status > 1)); then + echo "error: 'rg $*' failed with status $rg_status" >&2 + exit 1 + fi +} + +run_rg_to "$TMP_DIR/import_files" -l 's3s::' --type rust +run_rg_to "$TMP_DIR/error_lines" -c 's3_error!' --type rust + +s3s_import_files="$(grep -c . "$TMP_DIR/import_files" || true)" +s3_error_lines="$(awk -F: '{sum += $NF} END {print sum + 0}' "$TMP_DIR/error_lines")" + +for value in "$s3s_import_files" "$s3_error_lines"; do + if ! [[ "$value" =~ ^[0-9]+$ ]]; then + echo "error: could not compute s3s footprint counts (got: '$value')" >&2 + exit 1 + fi +done + +status=0 + +check_ratchet() { + local label="$1" count="$2" baseline="$3" inspect_cmd="$4" + + if ((count > baseline)); then + echo "❌ s3s footprint ratchet violation: $label is $count, baseline is $baseline (+$((count - baseline)))" >&2 + echo " New code must not widen the s3s surface being removed by the s3gate migration" >&2 + echo " (rustfs/backlog#1677 F1, rustfs/backlog#1733). Use the gateway abstractions" >&2 + echo " instead of importing s3s directly. To find the offenders, compare" >&2 + echo " '$inspect_cmd' against origin/main." >&2 + status=1 + elif ((count < baseline)); then + echo "â„šī¸ s3s footprint shrank: $label is $count, baseline is $baseline ($((count - baseline)))." >&2 + echo " Lower the baseline in scripts/check_s3s_footprint.sh in this PR to keep the ratchet tight." >&2 + else + echo "s3s footprint OK: $label is $count (baseline: $baseline)" + fi +} + +check_ratchet "files importing s3s" "$s3s_import_files" "$S3S_IMPORT_FILES_BASELINE" \ + "rg -l 's3s::' --type rust" +check_ratchet "s3_error! invocation lines" "$s3_error_lines" "$S3_ERROR_LINES_BASELINE" \ + "rg -c 's3_error!' --type rust" + +if ((status != 0)); then + exit 1 +fi + +echo "✅ s3s footprint ratchet check passed"