feat: production run — Q61 ramp, /404/, CloudFront router, cutover runbook
Build and deploy / build-and-deploy (push) Failing after 4s
Build and deploy / build-and-deploy (push) Failing after 4s
Five items of Pouya's production run, 2026-09-01.
Q61 — scroll-padding-top becomes a max() ramp on `10lh - 83px`, with the
plain calc() first as the fallback for engines without `lh`. Hidden focus
stops under minimumFontSize=32: 290 of 1,455 -> 0, control build still
290. Default settings byte-identical (0 differences over 352 page-widths x
17 fields). The 12 residual cells at minimumFontSize=16/20 are pre-existing
and unchanged-or-better; reported, not widened, per instruction.
Intake backend + CloudFront — docs/09-cutover-runbook.md is the
copy-paste sequence for admin execution: every command followed by its
verification and expected output, rollback per part, and Part 10 is Q60's
TTL test. infra/cloudfront/router.js is the trailing-slash function
(30-case suite; 8 fail against the pre-review version, incl. a
protocol-relative open redirect). infra/cloudfront/configure.mjs is
dry-run-by-default and idempotent. scripts/intake-env.mjs emits the six
Lambda env vars from src/data/site.ts.
Four launch blockers found by reading the running system:
- handler.mjs wrote pk/sk; the live table's key is submissionId with no
sort key, so every submission would have failed validation silently
- the Lambda invoke permission is scoped to the old route path
- 22 of 23 pages 403 without the router function
- there was no 404 page; src/pages/404.astro adds it
Claims audit (D20 cutover pass) — five gloss over-reaches corrected on
/practice/energy/, /practice/insurance/ (x2), /practice/technology/ and
/med-arb/. Three findings left open for Pouya: Q62, the /med-arb/ gloss,
and Q60.
Q62 — one frozen-tripwire pattern added under the freeze's own breach
exception, with a probe and four negative fixtures. check:claims exits 1
until the false /legal/privacy/ sentence is corrected, so both deploy
paths are blocked by a mechanism rather than by memory.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
co-authored by
Claude Opus 5
parent
ca1c2524e1
commit
bd282aa47d
+21
-6
@@ -69,7 +69,7 @@ case "$caller" in
|
||||
echo >&2
|
||||
echo "REFUSING: that is the broadly-permissioned personal user." >&2
|
||||
echo "AGENTS.md §10 — never use user/pouya to deploy. Use the scoped" >&2
|
||||
echo "deploy user (Q22: not yet created)." >&2
|
||||
echo "deploy user, adr-sml-deploy — PROVISIONED, AGENTS.md §7." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -157,7 +157,7 @@ location=$(curl -sS -o /dev/null -w '%{redirect_url}' -X POST \
|
||||
-H "Origin: https://adr.smlcompany.ca" \
|
||||
-H 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data 'deploy-route-probe=1' \
|
||||
"https://adr.smlcompany.ca/api/intake" 2>/dev/null || true)
|
||||
"https://adr.smlcompany.ca/api/intake" || true)
|
||||
if [ "$rc" -ne 0 ]; then
|
||||
echo >&2
|
||||
echo "WARNING: the POST to /api/intake did not complete (curl exit $rc)." >&2
|
||||
@@ -169,10 +169,25 @@ else
|
||||
echo >&2
|
||||
echo "WARNING: POST /api/intake returned $code (expected 303 to" >&2
|
||||
echo "/contact/could-not-send/); redirect was '${location:-none}'." >&2
|
||||
echo "404 means the CloudFront /api/* behaviour is missing. 403 can mean the" >&2
|
||||
echo "same thing — CloudFront rejecting a method the default behaviour does" >&2
|
||||
echo "not allow — or the handler refusing the Origin. Either way the form is" >&2
|
||||
echo "not verified working. See docs/06-deployment.md's cutover checklist." >&2
|
||||
# 404 IS AMBIGUOUS BETWEEN THREE CAUSES and the distribution's custom error
|
||||
# response hides the one string that would separate them: API Gateway's
|
||||
# {"message":"Not Found"} is replaced by /404.html, because custom error
|
||||
# responses are distribution-wide. So name the causes and the one command that
|
||||
# tells them apart. Corrected 2026-09-01 by `adversarial-reviewer`; the earlier
|
||||
# text named only the CloudFront behaviour.
|
||||
echo "404 means one of three things, and \`aws apigatewayv2 get-routes" >&2
|
||||
echo "--api-id <id> --query 'Items[].RouteKey'\` separates them in one call:" >&2
|
||||
echo " - the CloudFront /api/* behaviour is missing (docs/09 Part 3);" >&2
|
||||
echo " - the POST /api/intake route is missing or misspelled (Part 6.2);" >&2
|
||||
echo " - the route exists and the distribution's 404 mapping is showing you" >&2
|
||||
echo " /404.html instead of the API's own body." >&2
|
||||
echo "403 means CloudFront rejected the method, or the handler refused the" >&2
|
||||
echo "Origin — check the behaviour uses Managed-AllViewerExceptHostHeader," >&2
|
||||
echo "because a policy that drops Origin turns every real submission into a" >&2
|
||||
echo "403. 500 means the Lambda invoke permission for this route is missing" >&2
|
||||
echo "(Part 6.1) — the function is never entered, so CloudWatch is silent." >&2
|
||||
echo "Either way the form is not verified working. See docs/09-cutover-" >&2
|
||||
echo "runbook.md Part 7.1 and docs/06's cutover checklist." >&2
|
||||
fi
|
||||
|
||||
echo "==> Deployed to https://adr.smlcompany.ca ($(git rev-parse --short HEAD))"
|
||||
|
||||
Reference in New Issue
Block a user