Review: Stripe webhooks unreachable — basketball-api Tailscale Funnel not routing public traffic
Verdict: APPROVED
Re-review after refinement. Previous review
review-836-2026-04-04 returned NEEDS_REFINEMENT with 6 recommendations. All 5 [BODY] recommendations addressed. The 1 [SCOPE] recommendation (arch-basketball-api note) was accepted as discovered scope, non-blocking.Template Completeness
- [x] Type — Bug
- [x] Lineage — references #340, explains discovery path
- [x] Repo — corrected: lists both
ldraney/pal-e-services(funnel infra) andforgejo_admin/basketball-api(webhook endpoint) - [x] What Broke — rewritten: correctly states funnel exists but public traffic doesn't reach endpoint. Includes dollar impact ($780 jersey + $375+ tryout).
- [x] Repro Steps — 4-step reproduction from off-tailnet perspective
- [x] Expected Behavior — clear, references working westsidekingsandqueens comparison
- [x] Environment — detailed: namespace, webhook ID, funnel ingress name, comparison hostname
- [x] Investigation Targets — 4 investigation areas (operator logs, ACL nodeAttrs, operator pod status, working vs broken diff)
- [x] Acceptance Criteria — 4 criteria, all testable
- [x] Related — references project page, originating issue, key files
Traceability
- [x] story:WS-S18 label — "As a parent, I want to receive a branded email with jersey ordering link so that I can order without bringing cash" — verified in project-westside-basketball user-stories section under Parent stories
- [x] story note verified — found in project-westside-basketball user-stories section
- [x] arch:basketball-api label — present on board item
- [ ] arch note MISSING — no
arch-basketball-apinote found in pal-e-docs. [SCOPE] Create architecture note arch-basketball-api. Non-blocking per original review agreement. - [x] Forgejo issue — forgejo_admin/basketball-api#343, open
File Targets
- [x]
pal-e-services/terraform/services.tf(~line 177) — verified:kubernetes_ingress_v1.service_funnelresource at line 177 withfor_eachovervar.servicesfiltered byv.funnel. Annotationtailscale.com/funnel = "true"at line 184. - [x]
pal-e-services/k3s.tfvars(~line 178) — verified:basketball-apiservice block at line 178 withfunnel = trueat line 182. - [x]
basketball-api/src/basketball_api/routes/webhooks.py— verified:@router.post("/stripe")endpoint at line 263. Handler validates stripe-signature header, constructs events, routes checkout.session.completed through generic order, legacy jersey, and tryout registration handlers.
Repo Placement
CORRECTED from previous review. Issue now correctly identifies both repos:
ldraney/pal-e-services for funnel infrastructure and forgejo_admin/basketball-api for the webhook endpoint. The Forgejo issue is filed on basketball-api which is acceptable — the webhook endpoint is the affected service, and the fix may land in either repo depending on root cause (ACL in pal-e-platform, operator config in pal-e-services, or something else). Investigation-type bugs are appropriately filed on the affected service.Dependencies
- Board item #823 — forgejo_admin/basketball-api#340 "Jersey checkout load failed" — originating symptom, independent fix.
- Board item #719 — "Stripe webhook not syncing payment to order status" — directly related, QA blocked until funnel works.
- Board item #720 — "Legacy jersey webhook handler missing payment_status guard" — downstream, matters once webhooks reachable.
- Tailscale ACL
nodeAttrsfunnel permission — verified inpal-e-platform/terraform/modules/networking/main.tfline 82-87: grantsfunnelattr to["autogroup:member", "tag:k8s"]. Investigation target correctly identified in issue.
Acceptance Criteria
- AC1 "Root cause identified (ACL, operator, or funnel config issue)" — appropriate for investigation bug. Agent can document root cause.
- AC2 "Public internet traffic reaches basketball-api.tail5b443a.ts.net" — REWRITTEN per previous review. Testable via
curlfrom off-tailnet host. - AC3 "Stripe webhook test event delivered successfully to /webhooks/stripe" — testable via Stripe dashboard "Send test webhook."
- AC4 "New jersey payment triggers checkout.session.completed with pending_webhooks=0" — testable via Stripe CLI or real payment. Good AC.
- Yussuf Duro data remediation AC removed per previous review recommendation. Separate scope confirmed.
Blast Radius
If basketball-api funnel isn't routing public traffic, other Terraform-managed funnels with
funnel = true may be affected. Verified via kubectl get ingress -A: 26 funnels exist across the cluster. Platform funnels (Grafana, Forgejo, Harbor, etc.) are confirmed working — they are managed by pal-e-platform, not pal-e-services. The pal-e-services service_funnel resource manages funnels for: platform-validation, basketball-api, pal-e-docs, and others. If the issue is specific to the pal-e-services funnel codepath, other services managed by the same resource could be affected. Low regression risk since current state is already broken.Decomposition Assessment
- 3 file targets across 2 repos — at the limit but acceptable for investigation
- 4 acceptance criteria — under the 5 threshold
- Sequential investigation (find root cause → fix) — cannot parallelize
- No decomposition needed. Single agent pass.
Recommendation
No action needed. All previous [BODY] recommendations addressed. The [SCOPE] recommendation for arch-basketball-api note remains as discovered scope — non-blocking for ticket advancement.