feat: park the two policy changes the pricing plan forbids; robots.txt stands in
Build and deploy / build-and-deploy (push) Failing after 4s
Build and deploy / build-and-deploy (push) Failing after 4s
The third --apply of 2026-09-04 reached update-distribution and was rejected atomically: "Distributions with the Free pricing plan can't have the following features: Custom origin request policy, Custom response headers policy." Pouya's ruling: both are PARKED as unavailable — a platform constraint, not a defect. The pre-flight added in the previous commit could not have caught this, and that is the point: every limit in PAYLOAD_LIMITS is a property of the payload, while this is a property of the account, reported only by the call the pre-flight exists to avoid. Both sections now stop before creating anything. The plan is not in the CloudFront API — checked across 167 operations, no operation, shape, member or documentation string mentions one, and PriceClass_All is the edge-location price class, not the plan. So the gate is a constant, PLAN_ALLOWS_CUSTOM_POLICIES, and the two sections report as PARKED under their own heading rather than as skips: the previous commit made a skip exit 3, and a constraint true on every run would have made 3 permanent. Proven with a shim that refuses every mutating verb: --apply now makes zero of them. Substitute (a): Disallow: /pouya-lajevardi-bio.pdf in robots.txt, placed before Allow:/ so first-match crawlers honour it too. It is not an equivalent and the file says so — it stops the PDF being fetched, solving the duplicate-of-/bio/ problem, but does not de-index a URL linked from /bio/ and /about/. Verified: syntax, a match simulation under both crawler semantics, and that the sitemap does not list the PDF. Substitute (b): the WAF web ACL CreatedByCloudFront-f8fbf256 is already attached — 925 WCU, three AWS managed rule groups, no rate-based statement. That corrects §9 Q65, which framed WAF as a cost decision about adding one and named the now-unappliable header forwarding as its groundwork. The real question is one rule on an ACL already paid for, and a rate-based rule matches the viewer address directly, so the capability is superseded rather than lost. Reviewed in two rounds by me rather than a separate agent, per instruction. Nothing was applied to the distribution and nothing was deployed; robots.txt needs one site deploy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
co-authored by
Claude Opus 5
parent
07a8ff6989
commit
17e316dc1d
@@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Applies the five distribution changes the site needs, as one reviewable
|
||||
* transaction. `docs/09-cutover-runbook.md` Part 3 is what calls it.
|
||||
* Applies the distribution changes the site needs, as one reviewable
|
||||
* transaction. ⚠️ **THREE OF THE FIVE ARE APPLICABLE; 4 AND 5 ARE PARKED** —
|
||||
* the pricing plan forbids both a custom response headers policy and a custom
|
||||
* origin request policy, so they are reported and skipped rather than attempted.
|
||||
* See `PLAN_ALLOWS_CUSTOM_POLICIES` below and `AGENTS.md` §7. `docs/09-cutover-runbook.md` Part 3 is what calls it.
|
||||
*
|
||||
* 1. FunctionAssociations on the default behaviour -> `router.js`, viewer
|
||||
* request. Without it 22 of 23 pages return S3's AccessDenied XML.
|
||||
@@ -494,7 +497,42 @@ function findPdfPolicy() {
|
||||
would both miscount and send an `update-distribution` carrying a config
|
||||
nothing mutated. Skips get their own list and their own heading. */
|
||||
const skipped = [];
|
||||
if (!defaultRhpId) {
|
||||
/* ⚠️ PARKED, NOT SKIPPED, AND THE DISTINCTION IS THE EXIT STATUS. A skip means
|
||||
something unexpected happened and someone should look; these two are a
|
||||
standing platform constraint that will be true on every run until the pricing
|
||||
plan changes. Counting them as skips would make `exit 3` permanent, and a
|
||||
signal that is always on is not a signal. */
|
||||
const parked = [];
|
||||
|
||||
/**
|
||||
* 🛑 **SECTIONS 4 AND 5 CANNOT BE APPLIED ON THIS DISTRIBUTION'S PRICING PLAN.**
|
||||
* The third `--apply` of 2026-09-04 reached `update-distribution` and was
|
||||
* rejected atomically:
|
||||
*
|
||||
* Distributions with the Free pricing plan can't have the following features:
|
||||
* Custom origin request policy, Custom response headers policy
|
||||
*
|
||||
* ⚠️ **AND IT FAILED AT THE LAST CALL, AFTER BOTH POLICIES HAD BEEN CREATED** —
|
||||
* the whole point of the pre-flight is to fail before that, so both sections now
|
||||
* stop here instead. `AGENTS.md` §7 records the plan; `docs/06` closes both
|
||||
* items; `docs/09` Part 3 has all three attempts.
|
||||
*
|
||||
* ⚠️ **THIS IS A CONSTANT AND NOT A PROBE, BECAUSE THE PRICING PLAN IS NOT IN
|
||||
* THE API.** Checked 2026-09-04 against the CloudFront model: 167 operations,
|
||||
* and not one shape, member or documentation string mentions a pricing plan.
|
||||
* `PriceClass_All` on this distribution is the EDGE-LOCATION price class, a
|
||||
* different and much older concept — do not read it as the plan. The only
|
||||
* signal AWS gives is the `update-distribution` rejection itself, which is the
|
||||
* thing this exists to avoid. So: flip this to `true` when the plan changes,
|
||||
* and the two sections come back exactly as they were.
|
||||
*/
|
||||
const PLAN_ALLOWS_CUSTOM_POLICIES = false;
|
||||
|
||||
if (!PLAN_ALLOWS_CUSTOM_POLICIES) {
|
||||
parked.push(
|
||||
`${PDF_PATTERN} / ${PDF_POLICY_NAME} — a custom response headers policy is not available on this distribution's pricing plan. The stand-in is \`Disallow: /pouya-lajevardi-bio.pdf\` in public/robots.txt`,
|
||||
);
|
||||
} else if (!defaultRhpId) {
|
||||
skipped.push(
|
||||
`${PDF_PATTERN} / ${PDF_POLICY_NAME} — the default behaviour has no ResponseHeadersPolicyId, so there is nothing to clone the security headers from`,
|
||||
);
|
||||
@@ -952,7 +990,11 @@ const apiBehaviour = (cfg.CacheBehaviors?.Items ?? []).find(
|
||||
(b) => b.PathPattern === PATH_PATTERN,
|
||||
);
|
||||
|
||||
if (!apiBehaviour) {
|
||||
if (!PLAN_ALLOWS_CUSTOM_POLICIES) {
|
||||
parked.push(
|
||||
`${PATH_PATTERN} / ${ORP_NAME} — a custom origin request policy is not available on this distribution's pricing plan. Superseded rather than merely parked: the WAF web ACL already attached to this distribution is where a per-IP rule belongs (AGENTS.md §7)`,
|
||||
);
|
||||
} else if (!apiBehaviour) {
|
||||
/* Unreachable in practice — section 3 either found it or pushed it — so if it
|
||||
fires, something above changed. Skip rather than throw, for the reason
|
||||
section 4 gives: sections 1-3 have already staged their mutations. */
|
||||
@@ -1160,6 +1202,18 @@ console.log('');
|
||||
comment on `skipped`. A skip means section 4 did nothing and the PDF is
|
||||
probably not noindexed; that is louder than a silent omission and quieter
|
||||
than a false change. */
|
||||
if (parked.length) {
|
||||
console.log(
|
||||
`· ${parked.length} thing(s) PARKED — not available on this distribution's pricing plan:`,
|
||||
);
|
||||
for (const k of parked) console.log(` – ${k}`);
|
||||
console.log(
|
||||
' This is expected and does not affect the exit status. AGENTS.md §7',
|
||||
);
|
||||
console.log(' records the plan; flip PLAN_ALLOWS_CUSTOM_POLICIES if it');
|
||||
console.log(' changes. Sections 1-3 are unaffected.');
|
||||
console.log('');
|
||||
}
|
||||
if (skipped.length) {
|
||||
console.log(`⚠ ${skipped.length} thing(s) SKIPPED, not changed:`);
|
||||
for (const k of skipped) console.log(` ! ${k}`);
|
||||
@@ -1182,8 +1236,10 @@ const exitCode = skipped.length ? EXIT_SKIPPED : 0;
|
||||
if (changes.length === 0) {
|
||||
console.log(
|
||||
skipped.length
|
||||
? 'NOTHING TO CHANGE — but see the skips above; the distribution does NOT carry all five.'
|
||||
: 'NOTHING TO CHANGE — the distribution already carries all five.',
|
||||
? 'NOTHING TO CHANGE — but see the skips above; the distribution does NOT carry everything this script manages.'
|
||||
: parked.length
|
||||
? 'NOTHING TO CHANGE — the distribution carries everything this script can apply on the current pricing plan. The parked items above are not among them.'
|
||||
: 'NOTHING TO CHANGE — the distribution already carries all five.',
|
||||
);
|
||||
process.exit(exitCode);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user