fix: assert which aws binary runs, because this script rewrites the whole config
Build and deploy / build-and-deploy (push) Failing after 4s

Round 2 returned an addendum after the previous commit, having re-checked its
own instrument. Two findings, one blocking on the next --apply.

This machine carries two AWS CLIs on PATH: /opt/homebrew/bin/aws 2.34.53 and
/usr/local/bin/aws 2.11.15 (April 2023). configure.mjs called bare `aws`, so
PATH decided. That matters because update-distribution is a full replace and
botocore parses a config against its own model, dropping members it does not
know — an old CLI reads a lossy config and writes the loss back, and --if-match
cannot catch it because the ETag is genuinely current.

Measured, which the review could not do: the older model is missing nine
members, and E1OK7G98KNKUTA carries two of them — GrpcConfig on the default
behaviour and on /api/*, both {Enabled: false}. So a round trip through the old
CLI would write back the same effective value and change nothing observable
today. That is precisely why it needed a guard rather than a look: nothing
reports it when that stops being true.

The script now resolves the binary, prints it and its version as the first line
of output, and exits 2 below a floor before any AWS call. Verified both ways.

Second finding: entry (av) claimed "no client-side validation of any kind"
stood between the 182-character Comment and the API, from reading one
validate.py without naming which CLI it came from — and the other install is
frozen, so it is unchecked rather than confirmed. That is CLAUDE.md's named
shape. Both records now name the instrument and version and lead with the claim
that needs no qualification: the Comment reached the API and came back
InvalidArgument, so nothing stopped it on the CLI that ran.

The second install's model independently confirms FunctionARN max 108, its
pattern, and the 128 on both Comment members.

Nothing was applied to the distribution and nothing was deployed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
Pouya Lajevardi
2026-09-04 14:32:11 -04:00
co-authored by Claude Opus 5
parent a07193d561
commit 07a8ff6989
4 changed files with 206 additions and 17 deletions
+34 -7
View File
@@ -329,6 +329,28 @@ dump** of the `*.pdf` behaviour it would add, 2 blank lines, the
`N change(s) to distribution …` header and the `DRY RUN — nothing was sent.`
footer `[measured 2026-09-04, exit 0, nothing written]`.
🛑 **THE FIRST LINE OF OUTPUT NAMES THE `aws` BINARY AND ITS VERSION. READ IT.**
This script **rewrites the whole distribution config**, and botocore drops
members its own model does not know — so an old CLI reads a lossy config and
writes the loss back, on a distribution serving 23 pages and the intake form.
`--if-match` cannot catch that: the ETag is genuinely current.
⚠️ **THIS MACHINE HAS CARRIED TWO CLIs**, `2.34.53` and `2.11.15` (April 2023),
both on `PATH` `[measured 2026-09-04]`. The older model does not know
`GrpcConfig`, and `E1OK7G98KNKUTA` carries it on **two** behaviours — both
`{Enabled: false}`, so the round trip is lossless *in effect* today, and nothing
would report it when that stops being true. It is also missing `ConnectionMode`,
`VpcOriginConfig`, `CacheTagConfig` and five more. The script now **refuses below
a floor** rather than leaving it to `which`:
```
resolved aws = /opt/homebrew/bin/aws (2.34.53)
```
If that line names `/usr/local/bin/aws` or a version below the floor, the run
exits **2 before any AWS call**. Run `which -a aws` and fix `PATH` — do not
lower the floor to get through.
🛑 **READ THE EXIT STATUS, AND IT HAS THREE VALUES.** `0` — everything this
script manages was applied or is already present. `2` — a usage error, before any
AWS call. **`3` — sections that could run did, and something was SKIPPED: read
@@ -507,13 +529,18 @@ adding `Comment` to the drift check would throw on this very policy and block
the run that attaches it.
**WHY NOTHING CAUGHT IT LOCALLY, AND THIS IS THE GENERAL LESSON.** Measured
2026-09-04: **`botocore/validate.py` checks neither `max` nor `pattern`** — its
`range_check()` reads only `min`, and the word `pattern` does not appear in the
file. And the 128 cap is not modelled as a constraint at all: on both policy
configs `Comment` is a bare `string`, and the number lives in the shape's
**`documentation` prose**. So **no client-side validation of any kind stood
between that 182-character string and the CloudFront API**, which is exactly why
the pre-flight below had to be built rather than relied upon.
2026-09-04 **against `aws-cli/2.34.53`'s bundled `botocore/validate.py`**: it
checks **neither `max` nor `pattern`** — `range_check()` reads only `min`, and
the word `pattern` does not appear in the file. And the 128 cap is not modelled
as a constraint at all: on both policy configs `Comment` is a bare `string`, and
the number lives in the shape's **`documentation` prose**.
⚠️ **THAT NAMES ONE VALIDATOR, DELIBERATELY.** This machine also carries
`aws-cli/2.11.15`, which is PyInstaller-frozen and whose `validate.py` cannot be
read — unchecked, not confirmed. The claim that holds without qualification is
the narrower and more useful one: **the 182-character `Comment` reached the API
and came back `InvalidArgument`, so nothing stopped it on the CLI that ran.**
That is why the pre-flight below had to be built rather than relied upon.
**BOTH POLICY COMMENTS ARE NOW UNDER 80 CHARACTERS**, and the dry run enforces
the limits it knows about — `infra/cloudfront/policy-shapes.mjs`,