Stripe webhooks unreachable — basketball-api Tailscale Funnel not routing public traffic #343
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/basketball-api#343
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type
Bug
Lineage
Discovered while investigating forgejo_admin/basketball-api#340 (jersey "load failed"). The original issue was transient, but investigation revealed this systemic webhook delivery failure.
Repo
ldraney/pal-e-services(funnel infra) andforgejo_admin/basketball-api(webhook endpoint)What Broke
The Tailscale Funnel for
basketball-api.tail5b443a.ts.netexists in k8s (basketball-api-funnelingress withtailscale.com/funnel: "true"), but public internet traffic does not reach the endpoint. The hostname resolves to100.117.254.123(Tailscale internal IP) from within the Tailnet, but Stripe's servers on the public internet cannot connect.Every
checkout.session.completedevent since ~March 25 haspending_webhooks=1. Parents pay via Stripe but the database never updates — jersey orders stuck atpendingwith no option/size/number recorded.Confirmed affected: 6 jersey payments ($780 total) were manually synced on 2026-04-05 after discovery. 14 older tryout registration payments ($375+) from March 6-13 also unrecorded.
The webhook handler at
POST /webhooks/stripeworks correctly when reachable (returns 400 on missing signature, 200 with valid events). The problem is purely network/funnel routing.Repro Steps
basketball-api.tail5b443a.ts.netpending_webhooks=1)kubectl get ingress -n basketball-api basketball-api-funnelshows funnel exists with correct annotationsExpected Behavior
Public internet traffic should reach
basketball-api.tail5b443a.ts.net/webhooks/stripeso Stripe can deliver webhook events. The funnel should route external requests through to the basketball-api k8s service, likewestsidekingsandqueens.tail5b443a.ts.netdoes for the frontend.Environment
https://basketball-api.tail5b443a.ts.net/webhooks/stripewe_1T9I5sR9SdzWqVXM1WBWMDBvbasketball-api-funnel(exists,tailscale.com/funnel: "true")westsidekingsandqueens.tail5b443a.ts.netfunnel works correctlyInvestigation targets
nodeAttrs— verify funnel permission is granted for this hostnamekubectl logs -n tailscale deploy/operatorfor errorsAcceptance Criteria
basketball-api.tail5b443a.ts.net/webhooks/stripecheckout.session.completedwithpending_webhooks=0Related
project-westside-basketball— project this affectsforgejo_admin/basketball-api#340— original symptom (Daniel's "load failed")pal-e-services/terraform/services.tf(~line 177, funnel config),pal-e-services/k3s.tfvars(~line 178),basketball-api/src/basketball_api/routes/webhooks.py(webhook handler)Scope Review: NEEDS_REFINEMENT
Review note:
review-836-2026-04-04The Tailscale Funnel for basketball-api already exists and has been deployed for 40 days. The k8s ingress
basketball-api-funnelis present in the cluster withtailscale.com/funnel: "true"annotation and assigned hostnamebasketball-api.tail5b443a.ts.net. The issue's core assumption is incorrect.Issues found:
terraform/modules/networking/main.tf(pal-e-platform) manages platform funnels. Service funnels live inpal-e-services/terraform/services.tfwhere basketball-api already hasfunnel = true.arch-basketball-apinote exists in pal-e-docs.Stripe webhooks unreachable — basketball-api needs Tailscale Funnelto Stripe webhooks unreachable — basketball-api Tailscale Funnel not routing public trafficScope Review: APPROVED
Review note:
review-836-2026-04-04-r2Re-review after refinement — all 5 [BODY] recommendations from the previous review addressed. Problem statement correctly describes funnel-exists-but-unreachable. File targets verified against codebase. Repo placement corrected to identify both pal-e-services and basketball-api. AC1 rewritten to test actual reachability. Yussuf Duro data remediation split out.
Remaining discovered scope (non-blocking):
arch-basketball-apiarchitecture note does not exist in pal-e-docs.