Skip to content

fix: billing_client.py 404s against the real billing-service route - #82

Merged
man4ish merged 1 commit into
mainfrom
fix/billing-client-missing-prefix
Oct 4, 2026
Merged

man4ish merged 1 commit into
mainfrom
fix/billing-client-missing-prefix

Conversation

@man4ish

@man4ish man4ish commented Oct 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

organization_has_active_plan() called http://billing-service:8005/organizations/{id}/subscription, but billing-service's own router is mounted at /billing (app/routers/billing.py's APIRouter(prefix="/billing")) -- the real path is /billing/organizations/{id}/subscription.

Impact: every call this function ever made 404'd against the real service in a real deployment. The fail-closed-on-404 branch then correctly (but for the wrong reason) treated that as "no subscription at all," blocking self-service API key creation for every organization, always, regardless of actual subscription status -- found while testing a brand-new non-admin account's "Create key" flow against a live stack.

Why the unit suite never caught it: every test in test_billing_client.py mocks httpx.get directly, so none of them ever exercised the real URL against the real billing-service router. The one test that came closest (asserting the URL) used .endswith(...), which is satisfied by both the correct and the broken path -- tightened to an exact-match assertion so this exact bug class can't silently recur.

Test plan

  • pytest tests/test_billing_client.py -q -- 9 passed
  • Reproduced the 404 directly against the real billing-service container before fixing, confirmed the fix resolves it on the same live stack (full round trip: license login -> create key -> succeeds)

🤖 Generated with Claude Code

…te without its /billing router prefix

organization_has_active_plan() called
http://billing-service:8005/organizations/{id}/subscription, but
billing-service's own router is mounted at /billing
(app/routers/billing.py's APIRouter(prefix="/billing")) -- the real
path is /billing/organizations/{id}/subscription. Every call this
function ever made 404'd against the real service, which the fail-
closed-on-404 branch then correctly (but wrongly, given the actual
cause) treated as "no subscription at all" -- blocking self-service
API key creation for every organization, always, regardless of real
subscription status.

Caught via a live-stack smoke test, not this module's own unit suite:
every test here mocks httpx.get directly, so none of them ever
exercised the real URL against the real billing-service router. The
one test that came closest (asserting the URL) used .endswith(), which
is satisfied by both the correct and the broken path -- tightened to
an exact match so this exact bug class can't silently recur.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@man4ish
man4ish merged commit a322ff8 into main Oct 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant