Proxy Hesychia Stripe webhooks off the static site (#42)
Sync runner checkout / sync (push) Successful in 7s

## Summary
- Closes #41.
- Stripe live endpoint `we_1TzDNHDV0RPXOyxGCOftavHV` posts to `https://hesychia.ai/api/finance/webhooks/stripe/`. On 2026-10-09 the `chat_web_app` prod vhost returned HTTP 405 fifteen times (`request_time` 0.000, User-Agent Stripe). `pending_webhooks` stayed 1.
- `try_files` falls through to `index.html`, and nginx rejects POST on that static file. The Django handler on `chat_backend` never sees the body.
- `chat_web_app` now proxies `/api/finance/webhooks/` to the same-env `chat_backend` port (`8003` prod, `8013` beta) via `host.docker.internal`. `Host` is the backend public hostname so `ALLOWED_HOSTS` matches. Other static apps are unchanged.

## Test plan
- [ ] `ansible-playbook playbooks/site.yml --syntax-check` (or the web-static portion) renders without error
- [ ] Redeploy web-static (`scripts/deploy.sh` path that runs the web-static role) so `nginx.conf` reloads
- [ ] `curl -i -X POST http://127.0.0.1:8082/api/finance/webhooks/stripe/` from an app host reaches Django (400 invalid signature or 503 missing secret), not 405
- [ ] Stripe Dashboard: resend a failed event to the Hesychia.ai endpoint and confirm 2xx

Reviewed-on: #42
This commit was merged in pull request #42.
This commit is contained in:
westfarn committed 2026-10-10 04:54:04 -07:00
1 parent 7f570b40a2
commit a84350fe60
3 files changed
+40

No files matched your search

+9
View File
@@ -119,6 +119,10 @@ app_catalog:
# Document root served by nginx and written by `npm run build:<env>`.
# {env} is replaced with the entry's env (beta/prod).
webroot_pattern: "/var/www/{env}.chat.aimloperations/html"
# hesychia.ai Stripe/RevenueCat webhooks hit this vhost. Proxy the prefix
# to chat_backend so POST is not answered 405 by the SPA index.html.
api_backend: chat_backend
api_proxy_prefix: /api/finance/webhooks/
chat_backend:
type: django
repo: "{{ git_base_url }}/ai_ml_operations/chat_backend.git"
@@ -126,6 +130,11 @@ app_catalog:
compose_file: docker-compose.prod.yml
web_service: web
migrate_cmd: "uv run python manage.py migrate --noinput"
# Host header the static-site webhook proxy sends. Must be in Django
# ALLOWED_HOSTS (see chat_backend DJANGO_ALLOWED_HOSTS).
public_hosts:
prod: chatbackend.aimloperations.com
beta: beta.chatbackend.aimloperations.com
monica_site:
type: django
repo: "{{ git_base_url }}/ai_ml_operations/monica_site.git"