R2 event receiver (Phase 5b)
workers/r2-event-receiver is the Cloudflare Worker that bridges
customer R2 event notifications into our AWS SQS s3_ingest queue. It
replaces the role EventBridge plays for AWS customers β R2 canβt
target an external HTTPS endpoint directly, so customers deploy a tiny
forwarder Worker (template fetched from the dashboard) that POSTs to
this receiver.
One-time setup
-
Deploy the CDK Integrations stack (creates the IAM user):
Terminal window cd infra/cdknpx cdk deploy AccessiblePdfIntegrationsStack-productionNote the
R2EventReceiverUserArnoutput. -
Create an access key for that IAM user:
Terminal window aws iam create-access-key --user-name accessible-pdf-production-r2-event-receiverSave the
AccessKeyId+SecretAccessKeyimmediately β AWS will not show the secret again. -
Configure CF Worker bindings. Sensitive values use
wrangler secret put; non-sensitive ones go in[vars]inwrangler.toml:Vars (already set or set in
wrangler.toml):AWS_REGION(e.g.us-east-1)SQS_QUEUE_URL(from QueueStack output)SUPABASE_URL(e.g.https://xxx.supabase.co)
Secrets:
Terminal window cd workers/r2-event-receiverwrangler secret put AWS_ACCESS_KEY_ID --env production # from step 2wrangler secret put AWS_SECRET_ACCESS_KEY --env production # from step 2wrangler secret put SUPABASE_SERVICE_KEY --env production # service-role JWT -
Deploy the Worker:
Terminal window npm run deploy -
Wire the custom domain (one-time, in CF dashboard):
r2-event.theaccessible.orgβaccessible-r2-event-receiver.
Operational notes
- The Worker rate-limits each
integrationIdto 100 requests / 10 s. Customers exceeding that get 429s; their R2 Queue redelivers, so events are not lost (assuming the Queueβs retention window covers the burst). - The Worker validates
event_source_secretagainst Supabase before signing+sending to SQS, so junk POSTs canβt drive up SQS bills. - Rotating an integrationβs secret (
POST .../event-source-secret/rotate) invalidates any customer Worker template generated before the rotation. The dashboard surfaces a note about this. Old events fail fast at the receiver (401) and at the consumer (Phase 5a check).
Key rotation
- Rotate the IAM userβs access key annually:
Terminal window aws iam create-access-key --user-name accessible-pdf-production-r2-event-receiver# Update CF Worker secrets with the new pairwrangler secret put AWS_ACCESS_KEY_ID --env productionwrangler secret put AWS_SECRET_ACCESS_KEY --env production# Once traffic flows green on the new key, retire the old oneaws iam delete-access-key --user-name accessible-pdf-production-r2-event-receiver \--access-key-id <OLD_KEY_ID>
Troubleshooting
| Symptom | Likely cause |
|---|---|
| All events 401 at receiver | Customer Worker template stale (secret rotated). Re-copy from dashboard. |
| All events 502 at receiver | AWS_* secrets wrong, or IAM user lacks sqs:SendMessage. |
| Events accepted (202) but nothing happens | Check S3IngestLambda CloudWatch logs β likely event_unauthorized due to secret drift between receiver and consumer. |
| Customer sees 429s | Their R2 traffic exceeds 100 events / 10 s. Bump the rate-limit binding in wrangler.toml if legitimate. |