fix: give the Gitea workflow the intake route check the local script has

scripts/deploy-local.sh's header requires the two deploy paths to match on
everything that determines what gets published, and the route check that
replaced the stale INTAKE_ENDPOINT guard had only been added to one of them.

The check POSTs to /api/intake with no Origin header. 404 means the CloudFront
/api/* behaviour is missing; 403 means routed and refused by the handler's own
Origin check, which is a pass — and is why the probe is safe against
production, since it is rejected before any DynamoDB write or any email. It
warns rather than failing, because by that point the site is already deployed.

docs/06 now records it on the cutover item it protects, so that item no longer
rests on someone reading the list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
Pouya Lajevardi
2026-08-31 10:59:12 -04:00
co-authored by Claude Opus 5
parent 210bc25a26
commit 9f2d83c32f
2 changed files with 45 additions and 0 deletions
+34
View File
@@ -161,5 +161,39 @@ jobs:
--distribution-id "${CLOUDFRONT_DISTRIBUTION_ID}" \ --distribution-id "${CLOUDFRONT_DISTRIBUTION_ID}" \
--paths "/*" --paths "/*"
# Mirrors the same step in scripts/deploy-local.sh, because that script's
# header requires the two paths to match on everything that determines
# what gets published - and this replaced the INTAKE_ENDPOINT guard.
#
# The contact form posts to the same-origin path /api/intake, which only
# works if a CloudFront behaviour routes /api/* to the HTTP API origin
# AGENTS.md §7 records. Nothing in the build can know whether it exists.
#
# 404 means not routed. 403 means routed and REFUSED, which is the correct
# answer here: the handler checks the Origin header and this request sends
# none, so it is rejected before any DynamoDB write or any email. That is
# why the probe is safe to run against production.
#
# It warns rather than failing: the site is already deployed by this point,
# and failing the job would not un-deploy it.
- name: Intake route check
run: |
code=$(curl -sS -o /dev/null -w '%{http_code}' -X POST \
--max-time 15 \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data 'deploy-route-probe=1' \
"https://adr.smlcompany.ca/api/intake" || echo 000)
case "$code" in
404|000)
echo "WARNING: POST /api/intake returned $code."
echo "The contact form posts there. 404 means the CloudFront /api/*"
echo "behaviour is missing; 000 means the request did not complete."
echo "See docs/06-deployment.md's cutover checklist."
;;
*)
echo "POST /api/intake -> $code (routed; 403 is the Origin check)"
;;
esac
- name: Summary - name: Summary
run: echo "Deployed to https://adr.smlcompany.ca — commit ${GITHUB_SHA:0:7}" run: echo "Deployed to https://adr.smlcompany.ca — commit ${GITHUB_SHA:0:7}"
+11
View File
@@ -447,6 +447,17 @@ Then invalidate `/*`.
(`docs/05`). Not expressible in handler code, and it is carrying load (`docs/05`). Not expressible in handler code, and it is carrying load
the unimplementable 3-second timing check was specified to carry — see the unimplementable 3-second timing check was specified to carry — see
`docs/05` §Three deviations. `docs/05` §Three deviations.
✅ **BOTH DEPLOY PATHS NOW WARN IF ITEM 1 IS MISSING**, so this does not
rest on someone reading this list. `scripts/deploy-local.sh` and
`.gitea/workflows/deploy.yml` each end with an **Intake route check**: a
`POST` to `/api/intake` with no `Origin`. **404 means not routed. 403 means
routed and refused**, which is the handler's `Origin` check doing its job
and is therefore a pass — and is why the probe is safe against production:
it is rejected before any DynamoDB write or any email. It warns rather than
failing, because by that point the site is already deployed and failing the
job would not un-deploy it. This replaced an `INTAKE_ENDPOINT` guard that
blocked deploys on a variable nothing read.
- [ ] **DYNAMODB TTL ENABLED ON THE TABLE, AND VERIFIED BY A TEST RECORD. THIS - [ ] **DYNAMODB TTL ENABLED ON THE TABLE, AND VERIFIED BY A TEST RECORD. THIS
ONE BACKS A PUBLISHED PROMISE AND MUST NOT BE TICKED FROM THE HANDLER ONE BACKS A PUBLISHED PROMISE AND MUST NOT BE TICKED FROM THE HANDLER
CODE.** `/legal/privacy/` states that a record is *"deleted automatically CODE.** `/legal/privacy/` states that a record is *"deleted automatically