feat(loyalty): Google Wallet production readiness — 10 hardening items
Some checks failed
Some checks failed
- Fix rate limiter to extract real client IP and handle sync/async endpoints - Rate-limit public enrollment (10/min) and program info (30/min) endpoints - Add 409 Conflict to non-retryable status codes in retry decorator - Cache private key in get_save_url() to avoid re-reading JSON per call - Make update_class() return bool success status with error-level logging - Move Google Wallet config from core to loyalty module config - Document time.sleep() safety in retry decorator (threadpool execution) - Add per-card retry (1 retry, 2s delay) to wallet sync task - Add logo URL reachability check (HEAD request) to validate_config() - Add 26 comprehensive unit tests for GoogleWalletService Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ from app.modules.loyalty.schemas import (
|
||||
)
|
||||
from app.modules.loyalty.services import card_service, program_service, wallet_service
|
||||
from app.modules.tenancy.exceptions import StoreNotFoundException
|
||||
from middleware.decorators import rate_limit
|
||||
|
||||
storefront_router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -37,6 +38,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@storefront_router.get("/loyalty/program")
|
||||
@rate_limit(max_requests=30, window_seconds=60)
|
||||
def get_program_info(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
@@ -62,6 +64,7 @@ def get_program_info(
|
||||
|
||||
|
||||
@storefront_router.post("/loyalty/enroll")
|
||||
@rate_limit(max_requests=10, window_seconds=60)
|
||||
def self_enroll(
|
||||
request: Request,
|
||||
data: CardEnrollRequest,
|
||||
|
||||
Reference in New Issue
Block a user