Merge PR #22: Fix CI pipeline failures in cartsnitch/api
Fixes:
- Remove cache: pip from setup-python to fix intermittent tar corruption
- Add CARTSNITCH_SERVICE_KEY and CARTSNITCH_FERNET_KEY test env vars
Reviewed-by: Savannah Savings (CTO)
Approved-by: Checkout Charlie (QA)
- Remove 'cache: pip' from setup-python in lint, typecheck, test jobs to fix
intermittent 'archive/tar: write too long' errors on act_runner pods
- Add CARTSNITCH_SERVICE_KEY and CARTSNITCH_FERNET_KEY to test job env
to satisfy Settings pydantic model requirements
Co-Authored-By: Paperclip <noreply@paperclip.ing>
fix: remove dead dispose_engine import from API main.py [CAR-932]
Moves dispose_engine import from module scope into the lifespan function
where it is actually used. Fixes ImportError crashing API pods.
Reviewed-by: cs_charlie (QA)
Approved-by: cs_savannah (CTO)
CI-override: pre-existing failures unrelated to this change
The top-level import of dispose_engine from cartsnitch_api.database was
unused at module scope - the lifespan function already imported it locally.
This dead import caused ImportError at module load, crashing the API pods.
Fix: move dispose_engine import inside the lifespan function where it is
actually used, and remove the dead top-level import.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add dev.cartsnitch.com and uat.cartsnitch.com to the CORS origins list
to match the infra HTTPRoute domains and fix auth blocking on UAT.
Refs: CAR-992
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The on.push and on.pull_request triggers only listed [main, dev].
The deploy-uat job condition checks for refs/heads/uat but the
workflow never fires on uat pushes. Add uat to both trigger lists.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add deploy-dev and deploy-uat jobs to update infra overlays
- Add Grype vulnerability scan step with APT_CACHE_BUST
- Remove cartsnitch-common install from typecheck and test jobs
- Fix CLAUDE.md: API has its own local models, no cartsnitch-common dep
- Add .grype.yaml from monorepo root
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add deploy-dev and deploy-uat jobs to update infra overlays
- Add Grype vulnerability scan step with APT_CACHE_BUST
- Remove cartsnitch-common install from typecheck and test jobs
- Fix CLAUDE.md: API has its own local models, no cartsnitch-common dep
- Add .grype.yaml from monorepo root
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Promotes UAT to main including PR #209 (N+1 UPC query fix with SQL containment).
UAT regression: passed (Deal Dottie)
Security review: passed (Stockboy Steve)
CI required checks: all green
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add rate_limit_auth_requests (5/min) and rate_limit_auth_window_seconds (60) settings
- Add rate_limit_redis_enabled flag for opt-in Redis usage
- Refactor _SlidingWindowCounter into InMemorySlidingWindow class
- Add RedisSlidingWindow using sorted sets with fallback to in-memory
- Add third _auth_strict_limiter for POST /auth/* paths (5 req/min)
- Add protocol-based backend selection at module load time
- Update tests for auth strict limiter and Redis fallback behavior
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Merges Grype-based container image vulnerability scanning and Docker CVE remediation to production.
- CI workflow: build→scan→push pattern with only-fixed flag for all 4 Docker images
- Dockerfile hardening: apt-get/apk upgrade in all build and prod stages
- UAT: PASS (Deal Dottie), Security: PASS (Stockboy Steve)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add async Redis client using redis-py with connection pooling
- Implement get/set/delete with graceful degradation when unavailable
- Add TTL support (default 300s) via SETEX
- Add cache invalidation hooks for price and product changes
- Use pattern-based SCAN for bulk invalidation
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add rate_limit_auth_requests (5/min) and rate_limit_auth_window_seconds (60)
settings to config.py
- Refactor rate_limit.py to use protocol/ABC pattern with InMemorySlidingWindow
and RedisSlidingWindow implementations
- Add RedisSlidingWindow using sorted sets for distributed rate limiting
- Add auth_strict_limiter for /auth/* POST endpoints (5 req/min per IP)
- Fall back to in-memory when Redis is unavailable
- Update tests to cover new functionality
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add connection pool config to SQLAlchemy async engine (pool_size=10, max_overflow=20, pool_pre_ping, pool_recycle)
- Implement Redis connection pool in CacheClient with initialize/close lifecycle
- Wire lifespan startup/shutdown to initialize and dispose pools
- Add dispose_engine() for graceful DB pool cleanup on shutdown
Closes CAR-550
Co-Authored-By: Paperclip <noreply@paperclip.ing>