From 30e565909fcae13f6a654571f480c1a4974a7ee8 Mon Sep 17 00:00:00 2001 From: Giorgio Gilestro Date: Wed, 27 May 2026 14:48:00 +0200 Subject: [PATCH] ticker-validate: mount router at /api/ticker/* Co-Authored-By: Claude Opus 4.7 --- app/main.py | 2 ++ tests/test_ticker_validate.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/app/main.py b/app/main.py index 9499a34..fe987f5 100644 --- a/app/main.py +++ b/app/main.py @@ -25,6 +25,7 @@ from app.routers import polar_webhook as polar_webhook_router from app.routers import public as public_router from app.routers import stripe_billing as stripe_router from app.routers import sync as sync_router +from app.routers import ticker_validate as ticker_validate_router from app.routers import universe as universe_router from app.services.feeds_bootstrap import bootstrap_feeds @@ -89,6 +90,7 @@ app.include_router(auth_router.router, tags=["auth"]) app.include_router(email_router.router, tags=["email"]) app.include_router(api_router.router, prefix="/api", tags=["api"]) app.include_router(universe_router.router, prefix="/api", tags=["universe"]) +app.include_router(ticker_validate_router.router, prefix="/api", tags=["ticker-validate"]) app.include_router(sync_router.router, tags=["portfolio-sync"]) # Polar webhook (no bearer-token auth — authenticity via HMAC). Path # `/api/polar/webhook` is set on the route itself so the URL Polar diff --git a/tests/test_ticker_validate.py b/tests/test_ticker_validate.py index 8e640b3..a610e37 100644 --- a/tests/test_ticker_validate.py +++ b/tests/test_ticker_validate.py @@ -242,3 +242,37 @@ async def test_fetch_yahoo_historical_walks_back_to_preceding_trading_day(monkey assert close == 185.92 assert currency == "USD" assert actual == "2024-01-12" + + +def test_validate_route_requires_paid(): + """Static check that the /ticker/validate route is gated by require_paid.""" + from app.routers.ticker_validate import router + from app.services.access import require_paid + + route = next( + r for r in router.routes + if getattr(r, "path", "") == "/ticker/validate" + ) + dep_callables = [d.call for d in route.dependant.dependencies] + assert require_paid in dep_callables + + +def test_historical_route_requires_paid(): + from app.routers.ticker_validate import router + from app.services.access import require_paid + + route = next( + r for r in router.routes + if getattr(r, "path", "") == "/ticker/historical" + ) + dep_callables = [d.call for d in route.dependant.dependencies] + assert require_paid in dep_callables + + +def test_routes_mounted_under_api_prefix(): + """Confirm the router is mounted on the FastAPI app under /api.""" + from app.main import app + + paths = {getattr(r, "path", "") for r in app.routes} + assert "/api/ticker/validate" in paths + assert "/api/ticker/historical" in paths