diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 037c107..78a0dd9 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -161,5 +161,39 @@ jobs: --distribution-id "${CLOUDFRONT_DISTRIBUTION_ID}" \ --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 run: echo "Deployed to https://adr.smlcompany.ca — commit ${GITHUB_SHA:0:7}" diff --git a/docs/06-deployment.md b/docs/06-deployment.md index 2018b07..d298fe3 100644 --- a/docs/06-deployment.md +++ b/docs/06-deployment.md @@ -447,6 +447,17 @@ Then invalidate `/*`. (`docs/05`). Not expressible in handler code, and it is carrying load the unimplementable 3-second timing check was specified to carry — see `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 ONE BACKS A PUBLISHED PROMISE AND MUST NOT BE TICKED FROM THE HANDLER CODE.** `/legal/privacy/` states that a record is *"deleted automatically