test(l0): prove the dollar-collapse guard fires — and name the real envsubst
The implementation landed in the preceding WIP commit had never been executed. This finishes it: the arithmetic is re-measured, the guard and its allowlist are attacked, and the header's one factual error is corrected. WHAT ENVSUBST ACTUALLY IS. The header credited `github.com/drone/envsubst`. The pinned flux 2.4.0 binary in the dev image embeds `github.com/fluxcd/pkg/[email protected]` — Flux's own fork of drone/envsubst ("This package is a fork of drone/envsubst", its README) — read straight out of the binary with `grep -ao`. Same behaviour, different module; the header now says so and says how to check, because a claim about a dependency that nobody can re-derive is how the last wrong assumption survived. RE-MEASURED, NOT ASSERTED. Every row of the DOLLAR-RUN ARITHMETIC table was re-run through `flux envsubst` (flux 2.4.0, DEFINED=VALUE) and every row holds: `$$`->`$`, `$$$`->`$$`, `$${D}`->`${D}`, `$$${D}`->`$VALUE` (odd run: the brace is LIVE), `$$$${D}`->`$${D}`, `DO $$ x $$;`->`DO $ x $;`, and `$$${ARR[0]}` dies with "missing closing brace" while `$${ARR[0]}` is fine. `--strict` output was byte-identical to non-strict, exit 0 both ways (`cmp`) — strict mode is blind to this whole class, which is why a source assertion is the only guard available. The header now carries the 30-second reproduction, flagged to be re-measured on any FLUX_VERSION bump. END TO END ON THE REAL PATH. With the pre-16b7fcd manifest restored, `kubectl kustomize apps/wave-0` emits `DO $$` — valid SQL, and exactly what the `kubectl apply` verification saw — while the same stream through `flux envsubst --strict` emits `DO $` and `$;` and exits 0. That two-command contrast IS the incident. THE GUARD IS NOT TRIVIALLY SATISFIABLE — 16 adversarial cases, all as intended, run against a throwaway copy of the tree so nothing could be left behind: * an unmarked `$$` under a substituted path FAILS (DOLLAR-COLLAPSE); so do an odd `$$${...}` (DOLLAR-HALF-ESCAPED) and an even `$$$${...}` (OVER-ESCAPED); * a stale entry FAILS three ways — context no longer in the file, context that only covers an already-accepted `$${` escape and so excuses nothing, and a path that is not a file in the repo; * the allowlist cannot blanket-exempt a path: a 2-char context is rejected (<24), a `.*` wildcard is matched VERBATIM and therefore rejected as stale, a 24-char context carrying no dollar run is rejected, a 4-char reason is rejected (<40) — and, the central case, a genuine entry covers only the span its context matches, so a SECOND `$$` elsewhere in the same file still fails. Two genuine entries for two real occurrences do pass, so the mechanism is usable rather than merely unsatisfiable; * the CLASS, not the instance: the pre-fix `DO $$ ... $$;` reconstructed in a NEW ConfigMap under apps/wave-2 fails at both dollar runs, and restoring the real pre-16b7fcd apps/wave-0/nextcloud-db.yaml verbatim fails the check at lines 384 and 391. The guard rejects the exact commit that broke production. The scratch fixtures lived only in the throwaway copy; `git status` on this branch stayed clean throughout, which is the other half of the last attempt's unfinished business. LEGITIMATE USES EXIST AND STAY GREEN. 18 `$${...}` escapes (unifi cloud-init, the gitea and nextcloud OIDC bootstrap scripts, two longhorn comments) pass unremarked, and the 2 non-braced `$$` occurrences are the two allowlist entries. Those two are shell comments inside block scalars, and `kubectl kustomize` confirms the comment text really does survive into the stream envsubst reads — so they are genuine, reaching content whose collapse is cosmetic, not a hypothetical the allowlist was invented to excuse. STILL NOT PROVEN, AND STILL NOT PROXIED: that a change was verified through a substituting path. Which command a human ran is a fact about a shell session; git stores the manifest, never the invocation, so it is not statically decidable here and no honest formulation exists. Grepping commit prose for `kubectl apply` would be satisfiable by rewording and would fire on the break-glass runbooks whose whole content is that command. The answer is to move the proof off the verification path and onto the source, which is what assertion (7) does. No ci/l0.sh stage: the `conformance.home.k3s/scope: "whole-repo"` annotation is what wires it, and whole-repo-invariants-wired fails the gate on a hand-written stage. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
1 parent
377fa205ea
commit
830983b791
2 files changed
+28
-7
No files matched your search
@@ -62,10 +62,14 @@
|
||||
#
|
||||
# DOLLAR-RUN ARITHMETIC — the exact rule, MEASURED, not inferred (see assertion (7))
|
||||
# ---------------------------------------------------------------------------------
|
||||
# envsubst here is `github.com/drone/envsubst`, vendored by fluxcd/pkg/kustomize and exposed
|
||||
# by the `flux envsubst` CLI ("replicate the behavior of the Flux Kustomization post-build
|
||||
# substitutions" — its own --help). Its scanner walks the input left to right; on a `$` it
|
||||
# looks at the NEXT byte:
|
||||
# envsubst here is `github.com/fluxcd/pkg/envsubst` v1.1.0 — Flux's own maintained FORK of
|
||||
# `github.com/drone/envsubst` ("This package is a fork of drone/envsubst", its README) — and it
|
||||
# is exposed by the `flux envsubst` CLI ("replicate the behavior of the Flux Kustomization
|
||||
# post-build substitutions", its own --help). Named from the binary, not from memory: the
|
||||
# pinned flux 2.4.0 in the dev image embeds the Go module path
|
||||
# `/home/runner/go/pkg/mod/github.com/fluxcd/pkg/[email protected]/parse`
|
||||
# (`grep -ao 'github.com/fluxcd/pkg/envsubst[^ ]*' "$(command -v flux)"`). Its scanner walks
|
||||
# the input left to right; on a `$` it looks at the NEXT byte:
|
||||
# * another `$` -> BOTH are consumed and ONE `$` is emitted. This is UNCONDITIONAL. What
|
||||
# follows the pair is irrelevant — `{`, a letter, a digit, a semicolon,
|
||||
# a newline, end of input. `$$` is not "the escape for `${`"; it is the
|
||||
@@ -98,8 +102,23 @@
|
||||
# cannot parse, fails the ENTIRE Kustomization (proven above with $$${ARR[0]}, which
|
||||
# aborted the whole stream while $${ARR[0]} on the line before it was fine).
|
||||
# `--strict` reports NONE of this: every row of that table except the parse error was
|
||||
# accepted SILENTLY by `flux envsubst --strict`, exit 0. Strict mode cannot see this class,
|
||||
# so a source-level assertion is the only available guard.
|
||||
# accepted SILENTLY by `flux envsubst --strict`, exit 0, and its output was BYTE-IDENTICAL to
|
||||
# non-strict (`cmp`). Strict mode cannot see this class, so a source-level assertion is the
|
||||
# only available guard.
|
||||
#
|
||||
# TO REPRODUCE THE TABLE (30 seconds, no cluster) — it is a measurement, so re-measure it
|
||||
# after any FLUX_VERSION bump in infra/devcontainer/versions.env. Open the toolbox with
|
||||
# `./infra/devcontainer/dev.sh` and run these INSIDE it (do NOT pipe into `dev.sh run` from
|
||||
# the host: it starts the container with `-it`, so a piped stdin hangs):
|
||||
# printf '[$$] [$$$] [$${D}] [$$${D}] [DO $$ x $$;]\n' | D=VALUE flux envsubst
|
||||
# -> [$] [$$] [${D}] [$VALUE] [DO $ x $;]
|
||||
# And end-to-end, on the actual delivery path, with the pre-16b7fcd manifest checked out
|
||||
# (`git show 16b7fcd^:apps/wave-0/nextcloud-db.yaml > apps/wave-0/nextcloud-db.yaml`):
|
||||
# kubectl kustomize apps/wave-0 | grep 'DO \$' -> "DO $$" (the kubectl path)
|
||||
# kubectl kustomize apps/wave-0 | flux envsubst --strict | grep 'DO \$'
|
||||
# -> "DO $" (the FLUX path), exit 0
|
||||
# (`kubectl kustomize` IS the kustomize build here; the image ships no standalone binary.)
|
||||
# That two-command contrast IS the 2026-09-13 incident, and is why review missed it.
|
||||
# ${...}, ${a b}, ${ARR[0]} (UNESCAPED) -> HARD PARSE ERROR ("unable to parse
|
||||
# variable name" / "missing closing brace") which fails the
|
||||
# WHOLE Kustomization — every resource in the path, not just
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
#
|
||||
# WHY THIS FILE EXISTS
|
||||
# --------------------
|
||||
# Flux's postBuild substitution runs github.com/drone/envsubst over everything a
|
||||
# Flux's postBuild substitution runs github.com/fluxcd/pkg/envsubst (Flux's fork of
|
||||
# github.com/drone/envsubst; the module path is embedded in the pinned flux 2.4.0
|
||||
# binary, and check.sh's header says how to read it back out) over everything a
|
||||
# substituted Kustomization renders, and that scanner consumes dollars in PAIRS,
|
||||
# emitting ONE dollar per pair — unconditionally, wherever they appear, not only in
|
||||
# front of a brace. A run of N dollars becomes floor(N/2) dollars, and an ODD run
|
||||
|
||||
Reference in new issue
Block a user