forked from cartsnitch/cartsnitch
Compare commits
merge into: cs_betty/cartsnitch-fork-test:feature/public-endpoint-validation
cs_betty/cartsnitch-fork-test:main
cs_betty/cartsnitch-fork-test:barcode-betty/car-1078-email-worker-dragonfly-reset
cs_betty/cartsnitch-fork-test:uat
cs_betty/cartsnitch-fork-test:dev
cs_betty/cartsnitch-fork-test:betty/car-964-gitea-registry-v2
cs_betty/cartsnitch-fork-test:barcode-betty/gitea-registry
cs_betty/cartsnitch-fork-test:fix/dispose-engine-import
cs_betty/cartsnitch-fork-test:carl/car-933-gitea-registry
cs_betty/cartsnitch-fork-test:barcode-betty/fix-dispose-engine-import
cs_betty/cartsnitch-fork-test:betty/fix-dead-dispose-engine-import
cs_betty/cartsnitch-fork-test:betty/car-900-gitea-workflows
cs_betty/cartsnitch-fork-test:barcode-betty/move-workflows-to-gitea
cs_betty/cartsnitch-fork-test:betty/fix-gitea-ci-secrets
cs_betty/cartsnitch-fork-test:betty/car-869-gitea-actions-cartsnitch
cs_betty/cartsnitch-fork-test:betty/car-862-fix-auth-build
cs_betty/cartsnitch-fork-test:betty/car-812-uat-seed-tooling
cs_betty/cartsnitch-fork-test:betty/car-555-health-check-db
cs_betty/cartsnitch-fork-test:feature/dragonfly-rate-limiting
cs_betty/cartsnitch-fork-test:betty/car-749-remove-auth-ci
cs_betty/cartsnitch-fork-test:fix/car-741-login-redirect-race-clean
cs_betty/cartsnitch-fork-test:fix/car-741-login-redirect-race-v2
cs_betty/cartsnitch-fork-test:fix/car-741-login-redirect-race
cs_betty/cartsnitch-fork-test:fix/car-709-receiptwitness-grype-cves
cs_betty/cartsnitch-fork-test:fix/car-620-grype-ignore-and-cache-bust
cs_betty/cartsnitch-fork-test:fix/car-656-deploy-commit-guard
cs_betty/cartsnitch-fork-test:fix/car-663-bcrypt-cost-factor
cs_betty/cartsnitch-fork-test:fix/car-676-axe-color-contrast
cs_betty/cartsnitch-fork-test:betty/car-673-fix-e2e-playwright-mock-auth
cs_betty/cartsnitch-fork-test:fix/car-665-eslint-unused-vars
cs_betty/cartsnitch-fork-test:betty/car-548-email-verification
cs_betty/cartsnitch-fork-test:betty/car-552-redis-rate-limiting
cs_betty/cartsnitch-fork-test:fix/car-620-remaining-docker-cves
cs_betty/cartsnitch-fork-test:fix/car-620-grype-only-fixed
cs_betty/cartsnitch-fork-test:fix/car-616-remediate-docker-cves
cs_betty/cartsnitch-fork-test:feature/grype-image-scanning
cs_betty/cartsnitch-fork-test:fix/car-608-auth-health-check
cs_betty/cartsnitch-fork-test:fix/auth-config-validation
cs_betty/cartsnitch-fork-test:betty/car-553-redis-cache
cs_betty/cartsnitch-fork-test:betty/car-554-audit-logging
cs_betty/cartsnitch-fork-test:betty/car-551-remove-mock-auth
cs_betty/cartsnitch-fork-test:feature/trivy-image-scanning
cs_betty/cartsnitch-fork-test:betty/car-599-vite-audit-fix
cs_betty/cartsnitch-fork-test:betty/car-580-n1-normalization-query
cs_betty/cartsnitch-fork-test:fix/receiptwitness-config-validation
cs_betty/cartsnitch-fork-test:feature/cart-550-api-lifespan-pooling
cs_betty/cartsnitch-fork-test:fix/cors-security-headers
cs_betty/cartsnitch-fork-test:feature/public-endpoint-validation
cs_betty/cartsnitch-fork-test:fix/rate-limit-token-hash
cs_betty/cartsnitch-fork-test:fix/hardcoded-secrets
cs_betty/cartsnitch-fork-test:betty/fix-alembic-create-all-commit
cs_betty/cartsnitch-fork-test:betty/car-517-domain-tables-migration
cs_betty/cartsnitch-fork-test:betty/fix-alembic-model-import
cs_betty/cartsnitch-fork-test:betty/fix-session-cookie-parsing
cs_betty/cartsnitch-fork-test:betty/fix-api-database-url-fallback
cs_betty/cartsnitch-fork-test:betty/revert-sha256-session-hash
cs_betty/cartsnitch-fork-test:betty/fix-session-token-hash
cs_betty/cartsnitch-fork-test:betty/fix-secure-session-cookie
cs_betty/cartsnitch-fork-test:fix/alembic-version-table-width
cs_betty/cartsnitch-fork-test:betty/fix-uat-users-table-bootstrap
cs_betty/cartsnitch-fork-test:betty/fix-alembic-fresh-db
cs_betty/cartsnitch-fork-test:betty/fix-libpq5-dockerfile
cs_betty/cartsnitch-fork-test:fix/alembic-percent-escape
cs_betty/cartsnitch-fork-test:betty/fix-email-inbound-token-server-default
cs_betty/cartsnitch-fork-test:betty/fix-sha-tag-format-long
cs_betty/cartsnitch-fork-test:betty/fix-ci-dev-uat-branches
cs_betty/cartsnitch-fork-test:betty/fix-alembic-dockerfile
cs_betty/cartsnitch-fork-test:betty/fix-uat-trustedorigins
cs_betty/cartsnitch-fork-test:feat/sync-common-email-inbound-token
cs_betty/cartsnitch-fork-test:fix/ci-api-dockerfile-path
cs_betty/cartsnitch-fork-test:fix/ci-deploy-race
cs_betty/cartsnitch-fork-test:fix/email-in-address-hotfix
cs_betty/cartsnitch-fork-test:feat/ci-deploy-uat
cs_betty/cartsnitch-fork-test:fix/npm-audit-vulnerabilities
cs_betty/cartsnitch-fork-test:pr108
cs_betty/cartsnitch-fork-test:fix/inbound-email-500
cs_betty/cartsnitch-fork-test:fix/email-in-address-routing
cs_betty/cartsnitch-fork-test:feat/email-in-settings
cs_betty/cartsnitch-fork-test:sync/api-2026-04-03
cs_betty/cartsnitch-fork-test:sync/receiptwitness-2026-04-03
cs_betty/cartsnitch-fork-test:fix/api-date-schema-types
cs_betty/cartsnitch-fork-test:fix/dashboard-hardcoded-product-ids
cs_betty/cartsnitch-fork-test:fix/remove-timestamp-mixin-from-mismatched-models
cs_betty/cartsnitch-fork-test:feature/dev-seed-script
cs_betty/cartsnitch-fork-test:fix/user-id-str-type
cs_betty/cartsnitch-fork-test:fix/signed-cookie-parsing
cs_betty/cartsnitch-fork-test:fix/restore-token-hash
cs_betty/cartsnitch-fork-test:fix/secure-cookie-name
cs_betty/cartsnitch-fork-test:fix/frontend-api-routes
cs_betty/cartsnitch-fork-test:fix/session-token-hash
cs_betty/cartsnitch-fork-test:fix/api-v1-prefix
cs_betty/cartsnitch-fork-test:fix/registration-redirect
cs_betty/cartsnitch-fork-test:fix/lighthouse-ci-crash
cs_betty/cartsnitch-fork-test:fix/api-auto-migration
cs_betty/cartsnitch-fork-test:feat/e2e-journey-tests
cs_betty/cartsnitch-fork-test:fix/users-id-text
cs_betty/cartsnitch-fork-test:feat/lighthouse-ci
cs_betty/cartsnitch-fork-test:feat/axe-core-playwright
cs_betty/cartsnitch-fork-test:fix/deploy-dev-resilient
cs_betty/cartsnitch-fork-test:feat/ci-npm-audit
cs_betty/cartsnitch-fork-test:fix/dockerhub-login-cicd
cs_betty/cartsnitch-fork-test:fix/deploy-dev-resilient-v2
cs_betty/cartsnitch-fork-test:fix/auth-session-table-mapping
cs_betty/cartsnitch-fork-test:fix/api-dockerfile-libpq
cs_betty/cartsnitch-fork-test:fix/deploy-dev-resilience
cs_betty/cartsnitch-fork-test:feat/ci-api-image-build-v3
cs_betty/cartsnitch-fork-test:feat/ci-api-image-build-v2
cs_betty/cartsnitch-fork-test:feat/playwright-setup
cs_betty/cartsnitch-fork-test:feat/msw-integration-tests
cs_betty/cartsnitch-fork-test:feat/ci-api-image-build
cs_betty/cartsnitch-fork-test:fix/remove-polyrepo-ci-leftovers
cs_betty/cartsnitch-fork-test:fix/receiptwitness-local-common
cs_betty/cartsnitch-fork-test:feat/api-alembic-dockerfile
cs_betty/cartsnitch-fork-test:feat/ci-receiptwitness-build
cs_betty/cartsnitch-fork-test:fix/alembic-in-dockerfile
cs_betty/cartsnitch-fork-test:docs/uat-runbook
cs_betty/cartsnitch-fork-test:fix/hashed-password-nullable
cs_betty/cartsnitch-fork-test:feat/utility-functions-tests
cs_betty/cartsnitch-fork-test:fix/auth-url-same-origin
cs_betty/cartsnitch-fork-test:fix/auth-contract-mismatch
cs_betty/cartsnitch-fork-test:feat/add-auth-image-to-deploy-dev
cs_betty/cartsnitch-fork-test:fix/deploy-dev-kustomize-install-clean
cs_betty/cartsnitch-fork-test:feat/uat-seed-user
cs_betty/cartsnitch-fork-test:fix/seed-uat-ctofixes
cs_betty/cartsnitch-fork-test:feature/better-auth
cs_betty/cartsnitch-fork-test:fix/deploy-dev-install-kustomize
cs_betty/cartsnitch-fork-test:fix/deploy-dev-github-app-token-cross-repo
cs_betty/cartsnitch-fork-test:remove-trigger-uat
cs_betty/cartsnitch-fork-test:charlie/ci-remove-trigger-uat
cs_betty/cartsnitch-fork-test:feat/deploy-dev-uat-trigger
cs_betty/cartsnitch-fork-test:feature/repo-consolidation
cs_betty/cartsnitch-fork-test:content/shrinkflation-consumer-faq
cs_betty/cartsnitch-fork-test:content/launch-marketing-pages
cs_betty/cartsnitch-fork-test:debbie/proper-cache-and-dockerhub-cleanup
cs_betty/cartsnitch-fork-test:debbie/fix-frontend-docker-cache
cs_betty/cartsnitch-fork-test:fix/dockerfile-numeric-uid
cs_betty/cartsnitch-fork-test:fix/frontend-dockerfile-user-101
cs_betty/cartsnitch-fork-test:content/what-is-unit-price
cs_betty/cartsnitch-fork-test:content/cartsnitch-vs-flipp
cs_betty/cartsnitch-fork-test:fix/non-root-nginx
cs_betty/cartsnitch-fork-test:content/shrinkflation-series-social-copy
cs_betty/cartsnitch-fork-test:content/shrinkflation-top-10
cs_betty/cartsnitch-fork-test:content/fix-launch-stats
cs_betty/cartsnitch-fork-test:content/email-welcome-sequence-links
cs_betty/cartsnitch-fork-test:content/pre-launch-social-mar25-26
cs_betty/cartsnitch-fork-test:content/shrinkflation-series-alignment
cs_betty/cartsnitch-fork-test:content/shrinkflation-series-1-cereal
cs_betty/cartsnitch-fork-test:content/founder-blog-post
cs_betty/cartsnitch-fork-test:content/launch-calendar
cs_betty/cartsnitch-fork-test:content/seo-comparison-article
cs_betty/cartsnitch-fork-test:content/phase-2-onboarding-faq
cs_betty/cartsnitch-fork-test:fix/dockerhub-auth-rate-limit
cs_betty/cartsnitch-fork-test:test/arc-runner-validation
cs_betty/cartsnitch-fork-test:calver-tagging
cs_betty/cartsnitch-fork-test:frankie/add-marketing-content
cs_betty/cartsnitch-fork-test:fix/runner-label
cs_betty/cartsnitch-fork-test:fix/ci-runner-and-mirrors
cs_betty/cartsnitch-fork-test:fix/ci-runner-label
cs_betty/cartsnitch-fork-test:revert-ghcr-mirrors
cs_betty/cartsnitch-fork-test:fix/dockerfile-use-dockerhub-images
cs_betty/cartsnitch-fork-test:fix/ghcr-mirror-base-images
cs_betty/cartsnitch-fork-test:fix/ci-remove-dockerhub-login
cs_betty/cartsnitch-fork-test:fix/ci-docker-ratelimit
cs_betty/cartsnitch-fork-test:feature/dockerfile
cs_betty/cartsnitch-fork-test:feature/core-screens
cs_betty/cartsnitch-fork-test:feature/renovate-config
cs_betty/cartsnitch-fork-test:ci/add-github-actions
cartsnitch/cartsnitch:uat
cartsnitch/cartsnitch:dev
cartsnitch/cartsnitch:barcode-betty/car-1428-revert-deploy-base
cartsnitch/cartsnitch:main
cartsnitch/cartsnitch:barcode-betty/car-1374-checkout-ref-match-base
cartsnitch/cartsnitch:barcode-betty/car-1370-deploy-base-dev
cartsnitch/cartsnitch:barcode-betty/car-1303-widen-alembic-via-migration
cartsnitch/cartsnitch:betty/car-1078-email-worker-dragonfly-reset
cartsnitch/cartsnitch:betty/car-1218-lighthouse-ci
cartsnitch/cartsnitch:betty/car-1319-sha-tag-fix
cartsnitch/cartsnitch:betty/car-1318-frontend-kustomize-bump-target
cartsnitch/cartsnitch:betty/car-1276-auth-image-build-fix
cartsnitch/cartsnitch:betty/car-1276-auth-health-error-log
cartsnitch/cartsnitch:betty/car-1216-deploy-non-fail-merge
cartsnitch/cartsnitch:betty/car-1215-react-router-audit
cartsnitch/cartsnitch:barcode-betty/car-1078-email-worker-dragonfly-reset
cartsnitch/cartsnitch:betty/car-964-gitea-registry-v2
cartsnitch/cartsnitch:barcode-betty/gitea-registry
cartsnitch/cartsnitch:fix/dispose-engine-import
cartsnitch/cartsnitch:carl/car-933-gitea-registry
cartsnitch/cartsnitch:barcode-betty/fix-dispose-engine-import
cartsnitch/cartsnitch:betty/fix-dead-dispose-engine-import
cartsnitch/cartsnitch:betty/car-900-gitea-workflows
cartsnitch/cartsnitch:barcode-betty/move-workflows-to-gitea
cartsnitch/cartsnitch:betty/fix-gitea-ci-secrets
cartsnitch/cartsnitch:betty/car-869-gitea-actions-cartsnitch
cartsnitch/cartsnitch:betty/car-862-fix-auth-build
cartsnitch/cartsnitch:betty/car-812-uat-seed-tooling
cartsnitch/cartsnitch:betty/car-555-health-check-db
cartsnitch/cartsnitch:feature/dragonfly-rate-limiting
cartsnitch/cartsnitch:betty/car-749-remove-auth-ci
cartsnitch/cartsnitch:fix/car-741-login-redirect-race-clean
cartsnitch/cartsnitch:fix/car-741-login-redirect-race-v2
cartsnitch/cartsnitch:fix/car-741-login-redirect-race
cartsnitch/cartsnitch:fix/car-709-receiptwitness-grype-cves
cartsnitch/cartsnitch:fix/car-620-grype-ignore-and-cache-bust
cartsnitch/cartsnitch:fix/car-656-deploy-commit-guard
cartsnitch/cartsnitch:fix/car-663-bcrypt-cost-factor
cartsnitch/cartsnitch:fix/car-676-axe-color-contrast
cartsnitch/cartsnitch:betty/car-673-fix-e2e-playwright-mock-auth
cartsnitch/cartsnitch:fix/car-665-eslint-unused-vars
cartsnitch/cartsnitch:betty/car-548-email-verification
cartsnitch/cartsnitch:betty/car-552-redis-rate-limiting
cartsnitch/cartsnitch:fix/car-620-remaining-docker-cves
cartsnitch/cartsnitch:fix/car-620-grype-only-fixed
cartsnitch/cartsnitch:fix/car-616-remediate-docker-cves
cartsnitch/cartsnitch:feature/grype-image-scanning
cartsnitch/cartsnitch:fix/car-608-auth-health-check
cartsnitch/cartsnitch:fix/auth-config-validation
cartsnitch/cartsnitch:betty/car-553-redis-cache
cartsnitch/cartsnitch:betty/car-554-audit-logging
cartsnitch/cartsnitch:betty/car-551-remove-mock-auth
cartsnitch/cartsnitch:feature/trivy-image-scanning
cartsnitch/cartsnitch:betty/car-599-vite-audit-fix
cartsnitch/cartsnitch:betty/car-580-n1-normalization-query
cartsnitch/cartsnitch:fix/receiptwitness-config-validation
cartsnitch/cartsnitch:feature/cart-550-api-lifespan-pooling
cartsnitch/cartsnitch:fix/cors-security-headers
cartsnitch/cartsnitch:feature/public-endpoint-validation
cartsnitch/cartsnitch:fix/rate-limit-token-hash
cartsnitch/cartsnitch:fix/hardcoded-secrets
cartsnitch/cartsnitch:betty/fix-alembic-create-all-commit
cartsnitch/cartsnitch:betty/car-517-domain-tables-migration
cartsnitch/cartsnitch:betty/fix-alembic-model-import
cartsnitch/cartsnitch:betty/fix-session-cookie-parsing
cartsnitch/cartsnitch:betty/fix-api-database-url-fallback
cartsnitch/cartsnitch:betty/revert-sha256-session-hash
cartsnitch/cartsnitch:betty/fix-session-token-hash
cartsnitch/cartsnitch:betty/fix-secure-session-cookie
cartsnitch/cartsnitch:fix/alembic-version-table-width
cartsnitch/cartsnitch:betty/fix-uat-users-table-bootstrap
cartsnitch/cartsnitch:betty/fix-alembic-fresh-db
cartsnitch/cartsnitch:betty/fix-libpq5-dockerfile
cartsnitch/cartsnitch:fix/alembic-percent-escape
cartsnitch/cartsnitch:betty/fix-email-inbound-token-server-default
cartsnitch/cartsnitch:betty/fix-sha-tag-format-long
cartsnitch/cartsnitch:betty/fix-ci-dev-uat-branches
cartsnitch/cartsnitch:betty/fix-alembic-dockerfile
cartsnitch/cartsnitch:betty/fix-uat-trustedorigins
cartsnitch/cartsnitch:feat/sync-common-email-inbound-token
cartsnitch/cartsnitch:fix/ci-api-dockerfile-path
cartsnitch/cartsnitch:fix/ci-deploy-race
cartsnitch/cartsnitch:fix/email-in-address-hotfix
cartsnitch/cartsnitch:feat/ci-deploy-uat
cartsnitch/cartsnitch:fix/npm-audit-vulnerabilities
cartsnitch/cartsnitch:pr108
cartsnitch/cartsnitch:fix/inbound-email-500
cartsnitch/cartsnitch:fix/email-in-address-routing
cartsnitch/cartsnitch:feat/email-in-settings
cartsnitch/cartsnitch:sync/api-2026-04-03
cartsnitch/cartsnitch:sync/receiptwitness-2026-04-03
cartsnitch/cartsnitch:fix/api-date-schema-types
cartsnitch/cartsnitch:fix/dashboard-hardcoded-product-ids
cartsnitch/cartsnitch:fix/remove-timestamp-mixin-from-mismatched-models
cartsnitch/cartsnitch:feature/dev-seed-script
cartsnitch/cartsnitch:fix/user-id-str-type
cartsnitch/cartsnitch:fix/signed-cookie-parsing
cartsnitch/cartsnitch:fix/restore-token-hash
cartsnitch/cartsnitch:fix/secure-cookie-name
cartsnitch/cartsnitch:fix/frontend-api-routes
cartsnitch/cartsnitch:fix/session-token-hash
cartsnitch/cartsnitch:fix/api-v1-prefix
cartsnitch/cartsnitch:fix/registration-redirect
cartsnitch/cartsnitch:fix/lighthouse-ci-crash
cartsnitch/cartsnitch:fix/api-auto-migration
cartsnitch/cartsnitch:feat/e2e-journey-tests
cartsnitch/cartsnitch:fix/users-id-text
cartsnitch/cartsnitch:feat/lighthouse-ci
cartsnitch/cartsnitch:feat/axe-core-playwright
cartsnitch/cartsnitch:fix/deploy-dev-resilient
cartsnitch/cartsnitch:feat/ci-npm-audit
cartsnitch/cartsnitch:fix/dockerhub-login-cicd
cartsnitch/cartsnitch:fix/deploy-dev-resilient-v2
cartsnitch/cartsnitch:fix/auth-session-table-mapping
cartsnitch/cartsnitch:fix/api-dockerfile-libpq
cartsnitch/cartsnitch:fix/deploy-dev-resilience
cartsnitch/cartsnitch:feat/ci-api-image-build-v3
cartsnitch/cartsnitch:feat/ci-api-image-build-v2
cartsnitch/cartsnitch:feat/playwright-setup
cartsnitch/cartsnitch:feat/msw-integration-tests
cartsnitch/cartsnitch:feat/ci-api-image-build
cartsnitch/cartsnitch:fix/remove-polyrepo-ci-leftovers
cartsnitch/cartsnitch:fix/receiptwitness-local-common
cartsnitch/cartsnitch:feat/api-alembic-dockerfile
cartsnitch/cartsnitch:feat/ci-receiptwitness-build
cartsnitch/cartsnitch:fix/alembic-in-dockerfile
cartsnitch/cartsnitch:docs/uat-runbook
cartsnitch/cartsnitch:fix/hashed-password-nullable
cartsnitch/cartsnitch:feat/utility-functions-tests
cartsnitch/cartsnitch:fix/auth-url-same-origin
cartsnitch/cartsnitch:fix/auth-contract-mismatch
cartsnitch/cartsnitch:feat/add-auth-image-to-deploy-dev
cartsnitch/cartsnitch:fix/deploy-dev-kustomize-install-clean
cartsnitch/cartsnitch:feat/uat-seed-user
cartsnitch/cartsnitch:fix/seed-uat-ctofixes
cartsnitch/cartsnitch:feature/better-auth
cartsnitch/cartsnitch:fix/deploy-dev-install-kustomize
cartsnitch/cartsnitch:fix/deploy-dev-github-app-token-cross-repo
cartsnitch/cartsnitch:remove-trigger-uat
cartsnitch/cartsnitch:charlie/ci-remove-trigger-uat
cartsnitch/cartsnitch:feat/deploy-dev-uat-trigger
cartsnitch/cartsnitch:feature/repo-consolidation
cartsnitch/cartsnitch:content/shrinkflation-consumer-faq
cartsnitch/cartsnitch:content/launch-marketing-pages
cartsnitch/cartsnitch:debbie/proper-cache-and-dockerhub-cleanup
cartsnitch/cartsnitch:debbie/fix-frontend-docker-cache
cartsnitch/cartsnitch:fix/dockerfile-numeric-uid
cartsnitch/cartsnitch:fix/frontend-dockerfile-user-101
cartsnitch/cartsnitch:content/what-is-unit-price
cartsnitch/cartsnitch:content/cartsnitch-vs-flipp
cartsnitch/cartsnitch:fix/non-root-nginx
cartsnitch/cartsnitch:content/shrinkflation-series-social-copy
cartsnitch/cartsnitch:content/shrinkflation-top-10
cartsnitch/cartsnitch:content/fix-launch-stats
cartsnitch/cartsnitch:content/email-welcome-sequence-links
cartsnitch/cartsnitch:content/pre-launch-social-mar25-26
cartsnitch/cartsnitch:content/shrinkflation-series-alignment
cartsnitch/cartsnitch:content/shrinkflation-series-1-cereal
cartsnitch/cartsnitch:content/founder-blog-post
cartsnitch/cartsnitch:content/launch-calendar
cartsnitch/cartsnitch:content/seo-comparison-article
cartsnitch/cartsnitch:content/phase-2-onboarding-faq
cartsnitch/cartsnitch:fix/dockerhub-auth-rate-limit
cartsnitch/cartsnitch:test/arc-runner-validation
cartsnitch/cartsnitch:calver-tagging
cartsnitch/cartsnitch:frankie/add-marketing-content
cartsnitch/cartsnitch:fix/runner-label
cartsnitch/cartsnitch:fix/ci-runner-and-mirrors
cartsnitch/cartsnitch:fix/ci-runner-label
cartsnitch/cartsnitch:revert-ghcr-mirrors
cartsnitch/cartsnitch:fix/dockerfile-use-dockerhub-images
cartsnitch/cartsnitch:fix/ghcr-mirror-base-images
cartsnitch/cartsnitch:fix/ci-remove-dockerhub-login
cartsnitch/cartsnitch:fix/ci-docker-ratelimit
cartsnitch/cartsnitch:feature/dockerfile
cartsnitch/cartsnitch:feature/core-screens
cartsnitch/cartsnitch:feature/renovate-config
cartsnitch/cartsnitch:ci/add-github-actions
cs_betty/cartsnitch-fork-test:v2026.05.04
cs_betty/cartsnitch-fork-test:v2026.04.20
cs_betty/cartsnitch-fork-test:v2026.04.19.4
cs_betty/cartsnitch-fork-test:v2026.04.19.3
cs_betty/cartsnitch-fork-test:v2026.04.19.2
cs_betty/cartsnitch-fork-test:v2026.04.19
cs_betty/cartsnitch-fork-test:v2026.04.15.2
cs_betty/cartsnitch-fork-test:v2026.04.15
cs_betty/cartsnitch-fork-test:v2026.04.14.4
cs_betty/cartsnitch-fork-test:v2026.04.14.3
cs_betty/cartsnitch-fork-test:v2026.04.14.2
cs_betty/cartsnitch-fork-test:v2026.04.14
cs_betty/cartsnitch-fork-test:v2026.04.05
cs_betty/cartsnitch-fork-test:v2026.04.03.8
cs_betty/cartsnitch-fork-test:v2026.04.03.7
cs_betty/cartsnitch-fork-test:v2026.04.03.6
cs_betty/cartsnitch-fork-test:v2026.04.03.5
cs_betty/cartsnitch-fork-test:v2026.04.03.4
cs_betty/cartsnitch-fork-test:v2026.04.03.3
cs_betty/cartsnitch-fork-test:v2026.04.03.2
cs_betty/cartsnitch-fork-test:v2026.04.03
cs_betty/cartsnitch-fork-test:v2026.04.02
cs_betty/cartsnitch-fork-test:v2026.04.01.9
cs_betty/cartsnitch-fork-test:v2026.04.01.8
cs_betty/cartsnitch-fork-test:v2026.04.01.7
cs_betty/cartsnitch-fork-test:v2026.04.01.6
cs_betty/cartsnitch-fork-test:v2026.04.01.5
cs_betty/cartsnitch-fork-test:v2026.04.01.4
cs_betty/cartsnitch-fork-test:v2026.04.01.3
cs_betty/cartsnitch-fork-test:v2026.04.01.2
cs_betty/cartsnitch-fork-test:v2026.04.01
cs_betty/cartsnitch-fork-test:v2026.03.31.8
cs_betty/cartsnitch-fork-test:v2026.03.31.7
cs_betty/cartsnitch-fork-test:v2026.03.31.6
cs_betty/cartsnitch-fork-test:v2026.03.31.5
cs_betty/cartsnitch-fork-test:v2026.03.31.4
cs_betty/cartsnitch-fork-test:v2026.03.31.3
cs_betty/cartsnitch-fork-test:v2026.03.31.2
cs_betty/cartsnitch-fork-test:v2026.03.31
cs_betty/cartsnitch-fork-test:v2026.03.30.10
cs_betty/cartsnitch-fork-test:v2026.03.30.9
cs_betty/cartsnitch-fork-test:v2026.03.30.8
cs_betty/cartsnitch-fork-test:v2026.03.30.7
cs_betty/cartsnitch-fork-test:v2026.03.30.6
cs_betty/cartsnitch-fork-test:v2026.03.30.5
cs_betty/cartsnitch-fork-test:v2026.03.30.4
cs_betty/cartsnitch-fork-test:v2026.03.30.3
cs_betty/cartsnitch-fork-test:v2026.03.30.2
cs_betty/cartsnitch-fork-test:v2026.03.30
cs_betty/cartsnitch-fork-test:v2026.03.29.5
cs_betty/cartsnitch-fork-test:v2026.03.29.4
cs_betty/cartsnitch-fork-test:v2026.03.29.3
cs_betty/cartsnitch-fork-test:v2026.03.29.2
cs_betty/cartsnitch-fork-test:v2026.03.29
cs_betty/cartsnitch-fork-test:v2026.03.28.6
cs_betty/cartsnitch-fork-test:v2026.03.28.5
cs_betty/cartsnitch-fork-test:v2026.03.28.4
cs_betty/cartsnitch-fork-test:v2026.03.28.3
cs_betty/cartsnitch-fork-test:v2026.03.28.2
cs_betty/cartsnitch-fork-test:v2026.03.28
cs_betty/cartsnitch-fork-test:v2026.03.24.2
cs_betty/cartsnitch-fork-test:v2026.03.24
cs_betty/cartsnitch-fork-test:v2026.03.22.2
cs_betty/cartsnitch-fork-test:v2026.03.22
cs_betty/cartsnitch-fork-test:v2026.03.21.4
cs_betty/cartsnitch-fork-test:v2026.03.21.3
cs_betty/cartsnitch-fork-test:v2026.03.21.2
cs_betty/cartsnitch-fork-test:v2026.03.21
cs_betty/cartsnitch-fork-test:v2026.03.20.3
cs_betty/cartsnitch-fork-test:v2026.03.20.2
cs_betty/cartsnitch-fork-test:v2026.03.20
cartsnitch/cartsnitch:v2026.06.08
cartsnitch/cartsnitch:v2026.06.07
cartsnitch/cartsnitch:v2026.06.06
cartsnitch/cartsnitch:v2026.06.04
cartsnitch/cartsnitch:v2026.05.04
cartsnitch/cartsnitch:v2026.04.20
cartsnitch/cartsnitch:v2026.04.19.4
cartsnitch/cartsnitch:v2026.04.19.3
cartsnitch/cartsnitch:v2026.04.19.2
cartsnitch/cartsnitch:v2026.04.19
cartsnitch/cartsnitch:v2026.04.15.2
cartsnitch/cartsnitch:v2026.04.15
cartsnitch/cartsnitch:v2026.04.14.4
cartsnitch/cartsnitch:v2026.04.14.3
cartsnitch/cartsnitch:v2026.04.14.2
cartsnitch/cartsnitch:v2026.04.14
cartsnitch/cartsnitch:v2026.04.05
cartsnitch/cartsnitch:v2026.04.03.8
cartsnitch/cartsnitch:v2026.04.03.7
cartsnitch/cartsnitch:v2026.04.03.6
cartsnitch/cartsnitch:v2026.04.03.5
cartsnitch/cartsnitch:v2026.04.03.4
cartsnitch/cartsnitch:v2026.04.03.3
cartsnitch/cartsnitch:v2026.04.03.2
cartsnitch/cartsnitch:v2026.04.03
cartsnitch/cartsnitch:v2026.04.02
cartsnitch/cartsnitch:v2026.04.01.9
cartsnitch/cartsnitch:v2026.04.01.8
cartsnitch/cartsnitch:v2026.04.01.7
cartsnitch/cartsnitch:v2026.04.01.6
cartsnitch/cartsnitch:v2026.04.01.5
cartsnitch/cartsnitch:v2026.04.01.4
cartsnitch/cartsnitch:v2026.04.01.3
cartsnitch/cartsnitch:v2026.04.01.2
cartsnitch/cartsnitch:v2026.04.01
cartsnitch/cartsnitch:v2026.03.31.8
cartsnitch/cartsnitch:v2026.03.31.7
cartsnitch/cartsnitch:v2026.03.31.6
cartsnitch/cartsnitch:v2026.03.31.5
cartsnitch/cartsnitch:v2026.03.31.4
cartsnitch/cartsnitch:v2026.03.31.3
cartsnitch/cartsnitch:v2026.03.31.2
cartsnitch/cartsnitch:v2026.03.31
cartsnitch/cartsnitch:v2026.03.30.10
cartsnitch/cartsnitch:v2026.03.30.9
cartsnitch/cartsnitch:v2026.03.30.8
cartsnitch/cartsnitch:v2026.03.30.7
cartsnitch/cartsnitch:v2026.03.30.6
cartsnitch/cartsnitch:v2026.03.30.5
cartsnitch/cartsnitch:v2026.03.30.4
cartsnitch/cartsnitch:v2026.03.30.3
cartsnitch/cartsnitch:v2026.03.30.2
cartsnitch/cartsnitch:v2026.03.30
cartsnitch/cartsnitch:v2026.03.29.5
cartsnitch/cartsnitch:v2026.03.29.4
cartsnitch/cartsnitch:v2026.03.29.3
cartsnitch/cartsnitch:v2026.03.29.2
cartsnitch/cartsnitch:v2026.03.29
cartsnitch/cartsnitch:v2026.03.28.6
cartsnitch/cartsnitch:v2026.03.28.5
cartsnitch/cartsnitch:v2026.03.28.4
cartsnitch/cartsnitch:v2026.03.28.3
cartsnitch/cartsnitch:v2026.03.28.2
cartsnitch/cartsnitch:v2026.03.28
cartsnitch/cartsnitch:v2026.03.24.2
cartsnitch/cartsnitch:v2026.03.24
cartsnitch/cartsnitch:v2026.03.22.2
cartsnitch/cartsnitch:v2026.03.22
cartsnitch/cartsnitch:v2026.03.21.4
cartsnitch/cartsnitch:v2026.03.21.3
cartsnitch/cartsnitch:v2026.03.21.2
cartsnitch/cartsnitch:v2026.03.21
cartsnitch/cartsnitch:v2026.03.20.3
cartsnitch/cartsnitch:v2026.03.20.2
cartsnitch/cartsnitch:v2026.03.20
...
pull from: cs_betty/cartsnitch-fork-test:fix/rate-limit-token-hash
cs_betty/cartsnitch-fork-test:barcode-betty/car-1078-email-worker-dragonfly-reset
cs_betty/cartsnitch-fork-test:uat
cs_betty/cartsnitch-fork-test:main
cs_betty/cartsnitch-fork-test:dev
cs_betty/cartsnitch-fork-test:betty/car-964-gitea-registry-v2
cs_betty/cartsnitch-fork-test:barcode-betty/gitea-registry
cs_betty/cartsnitch-fork-test:fix/dispose-engine-import
cs_betty/cartsnitch-fork-test:carl/car-933-gitea-registry
cs_betty/cartsnitch-fork-test:barcode-betty/fix-dispose-engine-import
cs_betty/cartsnitch-fork-test:betty/fix-dead-dispose-engine-import
cs_betty/cartsnitch-fork-test:betty/car-900-gitea-workflows
cs_betty/cartsnitch-fork-test:barcode-betty/move-workflows-to-gitea
cs_betty/cartsnitch-fork-test:betty/fix-gitea-ci-secrets
cs_betty/cartsnitch-fork-test:betty/car-869-gitea-actions-cartsnitch
cs_betty/cartsnitch-fork-test:betty/car-862-fix-auth-build
cs_betty/cartsnitch-fork-test:betty/car-812-uat-seed-tooling
cs_betty/cartsnitch-fork-test:betty/car-555-health-check-db
cs_betty/cartsnitch-fork-test:feature/dragonfly-rate-limiting
cs_betty/cartsnitch-fork-test:betty/car-749-remove-auth-ci
cs_betty/cartsnitch-fork-test:fix/car-741-login-redirect-race-clean
cs_betty/cartsnitch-fork-test:fix/car-741-login-redirect-race-v2
cs_betty/cartsnitch-fork-test:fix/car-741-login-redirect-race
cs_betty/cartsnitch-fork-test:fix/car-709-receiptwitness-grype-cves
cs_betty/cartsnitch-fork-test:fix/car-620-grype-ignore-and-cache-bust
cs_betty/cartsnitch-fork-test:fix/car-656-deploy-commit-guard
cs_betty/cartsnitch-fork-test:fix/car-663-bcrypt-cost-factor
cs_betty/cartsnitch-fork-test:fix/car-676-axe-color-contrast
cs_betty/cartsnitch-fork-test:betty/car-673-fix-e2e-playwright-mock-auth
cs_betty/cartsnitch-fork-test:fix/car-665-eslint-unused-vars
cs_betty/cartsnitch-fork-test:betty/car-548-email-verification
cs_betty/cartsnitch-fork-test:betty/car-552-redis-rate-limiting
cs_betty/cartsnitch-fork-test:fix/car-620-remaining-docker-cves
cs_betty/cartsnitch-fork-test:fix/car-620-grype-only-fixed
cs_betty/cartsnitch-fork-test:fix/car-616-remediate-docker-cves
cs_betty/cartsnitch-fork-test:feature/grype-image-scanning
cs_betty/cartsnitch-fork-test:fix/car-608-auth-health-check
cs_betty/cartsnitch-fork-test:fix/auth-config-validation
cs_betty/cartsnitch-fork-test:betty/car-553-redis-cache
cs_betty/cartsnitch-fork-test:betty/car-554-audit-logging
cs_betty/cartsnitch-fork-test:betty/car-551-remove-mock-auth
cs_betty/cartsnitch-fork-test:feature/trivy-image-scanning
cs_betty/cartsnitch-fork-test:betty/car-599-vite-audit-fix
cs_betty/cartsnitch-fork-test:betty/car-580-n1-normalization-query
cs_betty/cartsnitch-fork-test:fix/receiptwitness-config-validation
cs_betty/cartsnitch-fork-test:feature/cart-550-api-lifespan-pooling
cs_betty/cartsnitch-fork-test:fix/cors-security-headers
cs_betty/cartsnitch-fork-test:feature/public-endpoint-validation
cs_betty/cartsnitch-fork-test:fix/rate-limit-token-hash
cs_betty/cartsnitch-fork-test:fix/hardcoded-secrets
cs_betty/cartsnitch-fork-test:betty/fix-alembic-create-all-commit
cs_betty/cartsnitch-fork-test:betty/car-517-domain-tables-migration
cs_betty/cartsnitch-fork-test:betty/fix-alembic-model-import
cs_betty/cartsnitch-fork-test:betty/fix-session-cookie-parsing
cs_betty/cartsnitch-fork-test:betty/fix-api-database-url-fallback
cs_betty/cartsnitch-fork-test:betty/revert-sha256-session-hash
cs_betty/cartsnitch-fork-test:betty/fix-session-token-hash
cs_betty/cartsnitch-fork-test:betty/fix-secure-session-cookie
cs_betty/cartsnitch-fork-test:fix/alembic-version-table-width
cs_betty/cartsnitch-fork-test:betty/fix-uat-users-table-bootstrap
cs_betty/cartsnitch-fork-test:betty/fix-alembic-fresh-db
cs_betty/cartsnitch-fork-test:betty/fix-libpq5-dockerfile
cs_betty/cartsnitch-fork-test:fix/alembic-percent-escape
cs_betty/cartsnitch-fork-test:betty/fix-email-inbound-token-server-default
cs_betty/cartsnitch-fork-test:betty/fix-sha-tag-format-long
cs_betty/cartsnitch-fork-test:betty/fix-ci-dev-uat-branches
cs_betty/cartsnitch-fork-test:betty/fix-alembic-dockerfile
cs_betty/cartsnitch-fork-test:betty/fix-uat-trustedorigins
cs_betty/cartsnitch-fork-test:feat/sync-common-email-inbound-token
cs_betty/cartsnitch-fork-test:fix/ci-api-dockerfile-path
cs_betty/cartsnitch-fork-test:fix/ci-deploy-race
cs_betty/cartsnitch-fork-test:fix/email-in-address-hotfix
cs_betty/cartsnitch-fork-test:feat/ci-deploy-uat
cs_betty/cartsnitch-fork-test:fix/npm-audit-vulnerabilities
cs_betty/cartsnitch-fork-test:pr108
cs_betty/cartsnitch-fork-test:fix/inbound-email-500
cs_betty/cartsnitch-fork-test:fix/email-in-address-routing
cs_betty/cartsnitch-fork-test:feat/email-in-settings
cs_betty/cartsnitch-fork-test:sync/api-2026-04-03
cs_betty/cartsnitch-fork-test:sync/receiptwitness-2026-04-03
cs_betty/cartsnitch-fork-test:fix/api-date-schema-types
cs_betty/cartsnitch-fork-test:fix/dashboard-hardcoded-product-ids
cs_betty/cartsnitch-fork-test:fix/remove-timestamp-mixin-from-mismatched-models
cs_betty/cartsnitch-fork-test:feature/dev-seed-script
cs_betty/cartsnitch-fork-test:fix/user-id-str-type
cs_betty/cartsnitch-fork-test:fix/signed-cookie-parsing
cs_betty/cartsnitch-fork-test:fix/restore-token-hash
cs_betty/cartsnitch-fork-test:fix/secure-cookie-name
cs_betty/cartsnitch-fork-test:fix/frontend-api-routes
cs_betty/cartsnitch-fork-test:fix/session-token-hash
cs_betty/cartsnitch-fork-test:fix/api-v1-prefix
cs_betty/cartsnitch-fork-test:fix/registration-redirect
cs_betty/cartsnitch-fork-test:fix/lighthouse-ci-crash
cs_betty/cartsnitch-fork-test:fix/api-auto-migration
cs_betty/cartsnitch-fork-test:feat/e2e-journey-tests
cs_betty/cartsnitch-fork-test:fix/users-id-text
cs_betty/cartsnitch-fork-test:feat/lighthouse-ci
cs_betty/cartsnitch-fork-test:feat/axe-core-playwright
cs_betty/cartsnitch-fork-test:fix/deploy-dev-resilient
cs_betty/cartsnitch-fork-test:feat/ci-npm-audit
cs_betty/cartsnitch-fork-test:fix/dockerhub-login-cicd
cs_betty/cartsnitch-fork-test:fix/deploy-dev-resilient-v2
cs_betty/cartsnitch-fork-test:fix/auth-session-table-mapping
cs_betty/cartsnitch-fork-test:fix/api-dockerfile-libpq
cs_betty/cartsnitch-fork-test:fix/deploy-dev-resilience
cs_betty/cartsnitch-fork-test:feat/ci-api-image-build-v3
cs_betty/cartsnitch-fork-test:feat/ci-api-image-build-v2
cs_betty/cartsnitch-fork-test:feat/playwright-setup
cs_betty/cartsnitch-fork-test:feat/msw-integration-tests
cs_betty/cartsnitch-fork-test:feat/ci-api-image-build
cs_betty/cartsnitch-fork-test:fix/remove-polyrepo-ci-leftovers
cs_betty/cartsnitch-fork-test:fix/receiptwitness-local-common
cs_betty/cartsnitch-fork-test:feat/api-alembic-dockerfile
cs_betty/cartsnitch-fork-test:feat/ci-receiptwitness-build
cs_betty/cartsnitch-fork-test:fix/alembic-in-dockerfile
cs_betty/cartsnitch-fork-test:docs/uat-runbook
cs_betty/cartsnitch-fork-test:fix/hashed-password-nullable
cs_betty/cartsnitch-fork-test:feat/utility-functions-tests
cs_betty/cartsnitch-fork-test:fix/auth-url-same-origin
cs_betty/cartsnitch-fork-test:fix/auth-contract-mismatch
cs_betty/cartsnitch-fork-test:feat/add-auth-image-to-deploy-dev
cs_betty/cartsnitch-fork-test:fix/deploy-dev-kustomize-install-clean
cs_betty/cartsnitch-fork-test:feat/uat-seed-user
cs_betty/cartsnitch-fork-test:fix/seed-uat-ctofixes
cs_betty/cartsnitch-fork-test:feature/better-auth
cs_betty/cartsnitch-fork-test:fix/deploy-dev-install-kustomize
cs_betty/cartsnitch-fork-test:fix/deploy-dev-github-app-token-cross-repo
cs_betty/cartsnitch-fork-test:remove-trigger-uat
cs_betty/cartsnitch-fork-test:charlie/ci-remove-trigger-uat
cs_betty/cartsnitch-fork-test:feat/deploy-dev-uat-trigger
cs_betty/cartsnitch-fork-test:feature/repo-consolidation
cs_betty/cartsnitch-fork-test:content/shrinkflation-consumer-faq
cs_betty/cartsnitch-fork-test:content/launch-marketing-pages
cs_betty/cartsnitch-fork-test:debbie/proper-cache-and-dockerhub-cleanup
cs_betty/cartsnitch-fork-test:debbie/fix-frontend-docker-cache
cs_betty/cartsnitch-fork-test:fix/dockerfile-numeric-uid
cs_betty/cartsnitch-fork-test:fix/frontend-dockerfile-user-101
cs_betty/cartsnitch-fork-test:content/what-is-unit-price
cs_betty/cartsnitch-fork-test:content/cartsnitch-vs-flipp
cs_betty/cartsnitch-fork-test:fix/non-root-nginx
cs_betty/cartsnitch-fork-test:content/shrinkflation-series-social-copy
cs_betty/cartsnitch-fork-test:content/shrinkflation-top-10
cs_betty/cartsnitch-fork-test:content/fix-launch-stats
cs_betty/cartsnitch-fork-test:content/email-welcome-sequence-links
cs_betty/cartsnitch-fork-test:content/pre-launch-social-mar25-26
cs_betty/cartsnitch-fork-test:content/shrinkflation-series-alignment
cs_betty/cartsnitch-fork-test:content/shrinkflation-series-1-cereal
cs_betty/cartsnitch-fork-test:content/founder-blog-post
cs_betty/cartsnitch-fork-test:content/launch-calendar
cs_betty/cartsnitch-fork-test:content/seo-comparison-article
cs_betty/cartsnitch-fork-test:content/phase-2-onboarding-faq
cs_betty/cartsnitch-fork-test:fix/dockerhub-auth-rate-limit
cs_betty/cartsnitch-fork-test:test/arc-runner-validation
cs_betty/cartsnitch-fork-test:calver-tagging
cs_betty/cartsnitch-fork-test:frankie/add-marketing-content
cs_betty/cartsnitch-fork-test:fix/runner-label
cs_betty/cartsnitch-fork-test:fix/ci-runner-and-mirrors
cs_betty/cartsnitch-fork-test:fix/ci-runner-label
cs_betty/cartsnitch-fork-test:revert-ghcr-mirrors
cs_betty/cartsnitch-fork-test:fix/dockerfile-use-dockerhub-images
cs_betty/cartsnitch-fork-test:fix/ghcr-mirror-base-images
cs_betty/cartsnitch-fork-test:fix/ci-remove-dockerhub-login
cs_betty/cartsnitch-fork-test:fix/ci-docker-ratelimit
cs_betty/cartsnitch-fork-test:feature/dockerfile
cs_betty/cartsnitch-fork-test:feature/core-screens
cs_betty/cartsnitch-fork-test:feature/renovate-config
cs_betty/cartsnitch-fork-test:ci/add-github-actions
cartsnitch/cartsnitch:uat
cartsnitch/cartsnitch:dev
cartsnitch/cartsnitch:barcode-betty/car-1428-revert-deploy-base
cartsnitch/cartsnitch:main
cartsnitch/cartsnitch:barcode-betty/car-1374-checkout-ref-match-base
cartsnitch/cartsnitch:barcode-betty/car-1370-deploy-base-dev
cartsnitch/cartsnitch:barcode-betty/car-1303-widen-alembic-via-migration
cartsnitch/cartsnitch:betty/car-1078-email-worker-dragonfly-reset
cartsnitch/cartsnitch:betty/car-1218-lighthouse-ci
cartsnitch/cartsnitch:betty/car-1319-sha-tag-fix
cartsnitch/cartsnitch:betty/car-1318-frontend-kustomize-bump-target
cartsnitch/cartsnitch:betty/car-1276-auth-image-build-fix
cartsnitch/cartsnitch:betty/car-1276-auth-health-error-log
cartsnitch/cartsnitch:betty/car-1216-deploy-non-fail-merge
cartsnitch/cartsnitch:betty/car-1215-react-router-audit
cartsnitch/cartsnitch:barcode-betty/car-1078-email-worker-dragonfly-reset
cartsnitch/cartsnitch:betty/car-964-gitea-registry-v2
cartsnitch/cartsnitch:barcode-betty/gitea-registry
cartsnitch/cartsnitch:fix/dispose-engine-import
cartsnitch/cartsnitch:carl/car-933-gitea-registry
cartsnitch/cartsnitch:barcode-betty/fix-dispose-engine-import
cartsnitch/cartsnitch:betty/fix-dead-dispose-engine-import
cartsnitch/cartsnitch:betty/car-900-gitea-workflows
cartsnitch/cartsnitch:barcode-betty/move-workflows-to-gitea
cartsnitch/cartsnitch:betty/fix-gitea-ci-secrets
cartsnitch/cartsnitch:betty/car-869-gitea-actions-cartsnitch
cartsnitch/cartsnitch:betty/car-862-fix-auth-build
cartsnitch/cartsnitch:betty/car-812-uat-seed-tooling
cartsnitch/cartsnitch:betty/car-555-health-check-db
cartsnitch/cartsnitch:feature/dragonfly-rate-limiting
cartsnitch/cartsnitch:betty/car-749-remove-auth-ci
cartsnitch/cartsnitch:fix/car-741-login-redirect-race-clean
cartsnitch/cartsnitch:fix/car-741-login-redirect-race-v2
cartsnitch/cartsnitch:fix/car-741-login-redirect-race
cartsnitch/cartsnitch:fix/car-709-receiptwitness-grype-cves
cartsnitch/cartsnitch:fix/car-620-grype-ignore-and-cache-bust
cartsnitch/cartsnitch:fix/car-656-deploy-commit-guard
cartsnitch/cartsnitch:fix/car-663-bcrypt-cost-factor
cartsnitch/cartsnitch:fix/car-676-axe-color-contrast
cartsnitch/cartsnitch:betty/car-673-fix-e2e-playwright-mock-auth
cartsnitch/cartsnitch:fix/car-665-eslint-unused-vars
cartsnitch/cartsnitch:betty/car-548-email-verification
cartsnitch/cartsnitch:betty/car-552-redis-rate-limiting
cartsnitch/cartsnitch:fix/car-620-remaining-docker-cves
cartsnitch/cartsnitch:fix/car-620-grype-only-fixed
cartsnitch/cartsnitch:fix/car-616-remediate-docker-cves
cartsnitch/cartsnitch:feature/grype-image-scanning
cartsnitch/cartsnitch:fix/car-608-auth-health-check
cartsnitch/cartsnitch:fix/auth-config-validation
cartsnitch/cartsnitch:betty/car-553-redis-cache
cartsnitch/cartsnitch:betty/car-554-audit-logging
cartsnitch/cartsnitch:betty/car-551-remove-mock-auth
cartsnitch/cartsnitch:feature/trivy-image-scanning
cartsnitch/cartsnitch:betty/car-599-vite-audit-fix
cartsnitch/cartsnitch:betty/car-580-n1-normalization-query
cartsnitch/cartsnitch:fix/receiptwitness-config-validation
cartsnitch/cartsnitch:feature/cart-550-api-lifespan-pooling
cartsnitch/cartsnitch:fix/cors-security-headers
cartsnitch/cartsnitch:feature/public-endpoint-validation
cartsnitch/cartsnitch:fix/rate-limit-token-hash
cartsnitch/cartsnitch:fix/hardcoded-secrets
cartsnitch/cartsnitch:betty/fix-alembic-create-all-commit
cartsnitch/cartsnitch:betty/car-517-domain-tables-migration
cartsnitch/cartsnitch:betty/fix-alembic-model-import
cartsnitch/cartsnitch:betty/fix-session-cookie-parsing
cartsnitch/cartsnitch:betty/fix-api-database-url-fallback
cartsnitch/cartsnitch:betty/revert-sha256-session-hash
cartsnitch/cartsnitch:betty/fix-session-token-hash
cartsnitch/cartsnitch:betty/fix-secure-session-cookie
cartsnitch/cartsnitch:fix/alembic-version-table-width
cartsnitch/cartsnitch:betty/fix-uat-users-table-bootstrap
cartsnitch/cartsnitch:betty/fix-alembic-fresh-db
cartsnitch/cartsnitch:betty/fix-libpq5-dockerfile
cartsnitch/cartsnitch:fix/alembic-percent-escape
cartsnitch/cartsnitch:betty/fix-email-inbound-token-server-default
cartsnitch/cartsnitch:betty/fix-sha-tag-format-long
cartsnitch/cartsnitch:betty/fix-ci-dev-uat-branches
cartsnitch/cartsnitch:betty/fix-alembic-dockerfile
cartsnitch/cartsnitch:betty/fix-uat-trustedorigins
cartsnitch/cartsnitch:feat/sync-common-email-inbound-token
cartsnitch/cartsnitch:fix/ci-api-dockerfile-path
cartsnitch/cartsnitch:fix/ci-deploy-race
cartsnitch/cartsnitch:fix/email-in-address-hotfix
cartsnitch/cartsnitch:feat/ci-deploy-uat
cartsnitch/cartsnitch:fix/npm-audit-vulnerabilities
cartsnitch/cartsnitch:pr108
cartsnitch/cartsnitch:fix/inbound-email-500
cartsnitch/cartsnitch:fix/email-in-address-routing
cartsnitch/cartsnitch:feat/email-in-settings
cartsnitch/cartsnitch:sync/api-2026-04-03
cartsnitch/cartsnitch:sync/receiptwitness-2026-04-03
cartsnitch/cartsnitch:fix/api-date-schema-types
cartsnitch/cartsnitch:fix/dashboard-hardcoded-product-ids
cartsnitch/cartsnitch:fix/remove-timestamp-mixin-from-mismatched-models
cartsnitch/cartsnitch:feature/dev-seed-script
cartsnitch/cartsnitch:fix/user-id-str-type
cartsnitch/cartsnitch:fix/signed-cookie-parsing
cartsnitch/cartsnitch:fix/restore-token-hash
cartsnitch/cartsnitch:fix/secure-cookie-name
cartsnitch/cartsnitch:fix/frontend-api-routes
cartsnitch/cartsnitch:fix/session-token-hash
cartsnitch/cartsnitch:fix/api-v1-prefix
cartsnitch/cartsnitch:fix/registration-redirect
cartsnitch/cartsnitch:fix/lighthouse-ci-crash
cartsnitch/cartsnitch:fix/api-auto-migration
cartsnitch/cartsnitch:feat/e2e-journey-tests
cartsnitch/cartsnitch:fix/users-id-text
cartsnitch/cartsnitch:feat/lighthouse-ci
cartsnitch/cartsnitch:feat/axe-core-playwright
cartsnitch/cartsnitch:fix/deploy-dev-resilient
cartsnitch/cartsnitch:feat/ci-npm-audit
cartsnitch/cartsnitch:fix/dockerhub-login-cicd
cartsnitch/cartsnitch:fix/deploy-dev-resilient-v2
cartsnitch/cartsnitch:fix/auth-session-table-mapping
cartsnitch/cartsnitch:fix/api-dockerfile-libpq
cartsnitch/cartsnitch:fix/deploy-dev-resilience
cartsnitch/cartsnitch:feat/ci-api-image-build-v3
cartsnitch/cartsnitch:feat/ci-api-image-build-v2
cartsnitch/cartsnitch:feat/playwright-setup
cartsnitch/cartsnitch:feat/msw-integration-tests
cartsnitch/cartsnitch:feat/ci-api-image-build
cartsnitch/cartsnitch:fix/remove-polyrepo-ci-leftovers
cartsnitch/cartsnitch:fix/receiptwitness-local-common
cartsnitch/cartsnitch:feat/api-alembic-dockerfile
cartsnitch/cartsnitch:feat/ci-receiptwitness-build
cartsnitch/cartsnitch:fix/alembic-in-dockerfile
cartsnitch/cartsnitch:docs/uat-runbook
cartsnitch/cartsnitch:fix/hashed-password-nullable
cartsnitch/cartsnitch:feat/utility-functions-tests
cartsnitch/cartsnitch:fix/auth-url-same-origin
cartsnitch/cartsnitch:fix/auth-contract-mismatch
cartsnitch/cartsnitch:feat/add-auth-image-to-deploy-dev
cartsnitch/cartsnitch:fix/deploy-dev-kustomize-install-clean
cartsnitch/cartsnitch:feat/uat-seed-user
cartsnitch/cartsnitch:fix/seed-uat-ctofixes
cartsnitch/cartsnitch:feature/better-auth
cartsnitch/cartsnitch:fix/deploy-dev-install-kustomize
cartsnitch/cartsnitch:fix/deploy-dev-github-app-token-cross-repo
cartsnitch/cartsnitch:remove-trigger-uat
cartsnitch/cartsnitch:charlie/ci-remove-trigger-uat
cartsnitch/cartsnitch:feat/deploy-dev-uat-trigger
cartsnitch/cartsnitch:feature/repo-consolidation
cartsnitch/cartsnitch:content/shrinkflation-consumer-faq
cartsnitch/cartsnitch:content/launch-marketing-pages
cartsnitch/cartsnitch:debbie/proper-cache-and-dockerhub-cleanup
cartsnitch/cartsnitch:debbie/fix-frontend-docker-cache
cartsnitch/cartsnitch:fix/dockerfile-numeric-uid
cartsnitch/cartsnitch:fix/frontend-dockerfile-user-101
cartsnitch/cartsnitch:content/what-is-unit-price
cartsnitch/cartsnitch:content/cartsnitch-vs-flipp
cartsnitch/cartsnitch:fix/non-root-nginx
cartsnitch/cartsnitch:content/shrinkflation-series-social-copy
cartsnitch/cartsnitch:content/shrinkflation-top-10
cartsnitch/cartsnitch:content/fix-launch-stats
cartsnitch/cartsnitch:content/email-welcome-sequence-links
cartsnitch/cartsnitch:content/pre-launch-social-mar25-26
cartsnitch/cartsnitch:content/shrinkflation-series-alignment
cartsnitch/cartsnitch:content/shrinkflation-series-1-cereal
cartsnitch/cartsnitch:content/founder-blog-post
cartsnitch/cartsnitch:content/launch-calendar
cartsnitch/cartsnitch:content/seo-comparison-article
cartsnitch/cartsnitch:content/phase-2-onboarding-faq
cartsnitch/cartsnitch:fix/dockerhub-auth-rate-limit
cartsnitch/cartsnitch:test/arc-runner-validation
cartsnitch/cartsnitch:calver-tagging
cartsnitch/cartsnitch:frankie/add-marketing-content
cartsnitch/cartsnitch:fix/runner-label
cartsnitch/cartsnitch:fix/ci-runner-and-mirrors
cartsnitch/cartsnitch:fix/ci-runner-label
cartsnitch/cartsnitch:revert-ghcr-mirrors
cartsnitch/cartsnitch:fix/dockerfile-use-dockerhub-images
cartsnitch/cartsnitch:fix/ghcr-mirror-base-images
cartsnitch/cartsnitch:fix/ci-remove-dockerhub-login
cartsnitch/cartsnitch:fix/ci-docker-ratelimit
cartsnitch/cartsnitch:feature/dockerfile
cartsnitch/cartsnitch:feature/core-screens
cartsnitch/cartsnitch:feature/renovate-config
cartsnitch/cartsnitch:ci/add-github-actions
cs_betty/cartsnitch-fork-test:v2026.05.04
cs_betty/cartsnitch-fork-test:v2026.04.20
cs_betty/cartsnitch-fork-test:v2026.04.19.4
cs_betty/cartsnitch-fork-test:v2026.04.19.3
cs_betty/cartsnitch-fork-test:v2026.04.19.2
cs_betty/cartsnitch-fork-test:v2026.04.19
cs_betty/cartsnitch-fork-test:v2026.04.15.2
cs_betty/cartsnitch-fork-test:v2026.04.15
cs_betty/cartsnitch-fork-test:v2026.04.14.4
cs_betty/cartsnitch-fork-test:v2026.04.14.3
cs_betty/cartsnitch-fork-test:v2026.04.14.2
cs_betty/cartsnitch-fork-test:v2026.04.14
cs_betty/cartsnitch-fork-test:v2026.04.05
cs_betty/cartsnitch-fork-test:v2026.04.03.8
cs_betty/cartsnitch-fork-test:v2026.04.03.7
cs_betty/cartsnitch-fork-test:v2026.04.03.6
cs_betty/cartsnitch-fork-test:v2026.04.03.5
cs_betty/cartsnitch-fork-test:v2026.04.03.4
cs_betty/cartsnitch-fork-test:v2026.04.03.3
cs_betty/cartsnitch-fork-test:v2026.04.03.2
cs_betty/cartsnitch-fork-test:v2026.04.03
cs_betty/cartsnitch-fork-test:v2026.04.02
cs_betty/cartsnitch-fork-test:v2026.04.01.9
cs_betty/cartsnitch-fork-test:v2026.04.01.8
cs_betty/cartsnitch-fork-test:v2026.04.01.7
cs_betty/cartsnitch-fork-test:v2026.04.01.6
cs_betty/cartsnitch-fork-test:v2026.04.01.5
cs_betty/cartsnitch-fork-test:v2026.04.01.4
cs_betty/cartsnitch-fork-test:v2026.04.01.3
cs_betty/cartsnitch-fork-test:v2026.04.01.2
cs_betty/cartsnitch-fork-test:v2026.04.01
cs_betty/cartsnitch-fork-test:v2026.03.31.8
cs_betty/cartsnitch-fork-test:v2026.03.31.7
cs_betty/cartsnitch-fork-test:v2026.03.31.6
cs_betty/cartsnitch-fork-test:v2026.03.31.5
cs_betty/cartsnitch-fork-test:v2026.03.31.4
cs_betty/cartsnitch-fork-test:v2026.03.31.3
cs_betty/cartsnitch-fork-test:v2026.03.31.2
cs_betty/cartsnitch-fork-test:v2026.03.31
cs_betty/cartsnitch-fork-test:v2026.03.30.10
cs_betty/cartsnitch-fork-test:v2026.03.30.9
cs_betty/cartsnitch-fork-test:v2026.03.30.8
cs_betty/cartsnitch-fork-test:v2026.03.30.7
cs_betty/cartsnitch-fork-test:v2026.03.30.6
cs_betty/cartsnitch-fork-test:v2026.03.30.5
cs_betty/cartsnitch-fork-test:v2026.03.30.4
cs_betty/cartsnitch-fork-test:v2026.03.30.3
cs_betty/cartsnitch-fork-test:v2026.03.30.2
cs_betty/cartsnitch-fork-test:v2026.03.30
cs_betty/cartsnitch-fork-test:v2026.03.29.5
cs_betty/cartsnitch-fork-test:v2026.03.29.4
cs_betty/cartsnitch-fork-test:v2026.03.29.3
cs_betty/cartsnitch-fork-test:v2026.03.29.2
cs_betty/cartsnitch-fork-test:v2026.03.29
cs_betty/cartsnitch-fork-test:v2026.03.28.6
cs_betty/cartsnitch-fork-test:v2026.03.28.5
cs_betty/cartsnitch-fork-test:v2026.03.28.4
cs_betty/cartsnitch-fork-test:v2026.03.28.3
cs_betty/cartsnitch-fork-test:v2026.03.28.2
cs_betty/cartsnitch-fork-test:v2026.03.28
cs_betty/cartsnitch-fork-test:v2026.03.24.2
cs_betty/cartsnitch-fork-test:v2026.03.24
cs_betty/cartsnitch-fork-test:v2026.03.22.2
cs_betty/cartsnitch-fork-test:v2026.03.22
cs_betty/cartsnitch-fork-test:v2026.03.21.4
cs_betty/cartsnitch-fork-test:v2026.03.21.3
cs_betty/cartsnitch-fork-test:v2026.03.21.2
cs_betty/cartsnitch-fork-test:v2026.03.21
cs_betty/cartsnitch-fork-test:v2026.03.20.3
cs_betty/cartsnitch-fork-test:v2026.03.20.2
cs_betty/cartsnitch-fork-test:v2026.03.20
cartsnitch/cartsnitch:v2026.06.08
cartsnitch/cartsnitch:v2026.06.07
cartsnitch/cartsnitch:v2026.06.06
cartsnitch/cartsnitch:v2026.06.04
cartsnitch/cartsnitch:v2026.05.04
cartsnitch/cartsnitch:v2026.04.20
cartsnitch/cartsnitch:v2026.04.19.4
cartsnitch/cartsnitch:v2026.04.19.3
cartsnitch/cartsnitch:v2026.04.19.2
cartsnitch/cartsnitch:v2026.04.19
cartsnitch/cartsnitch:v2026.04.15.2
cartsnitch/cartsnitch:v2026.04.15
cartsnitch/cartsnitch:v2026.04.14.4
cartsnitch/cartsnitch:v2026.04.14.3
cartsnitch/cartsnitch:v2026.04.14.2
cartsnitch/cartsnitch:v2026.04.14
cartsnitch/cartsnitch:v2026.04.05
cartsnitch/cartsnitch:v2026.04.03.8
cartsnitch/cartsnitch:v2026.04.03.7
cartsnitch/cartsnitch:v2026.04.03.6
cartsnitch/cartsnitch:v2026.04.03.5
cartsnitch/cartsnitch:v2026.04.03.4
cartsnitch/cartsnitch:v2026.04.03.3
cartsnitch/cartsnitch:v2026.04.03.2
cartsnitch/cartsnitch:v2026.04.03
cartsnitch/cartsnitch:v2026.04.02
cartsnitch/cartsnitch:v2026.04.01.9
cartsnitch/cartsnitch:v2026.04.01.8
cartsnitch/cartsnitch:v2026.04.01.7
cartsnitch/cartsnitch:v2026.04.01.6
cartsnitch/cartsnitch:v2026.04.01.5
cartsnitch/cartsnitch:v2026.04.01.4
cartsnitch/cartsnitch:v2026.04.01.3
cartsnitch/cartsnitch:v2026.04.01.2
cartsnitch/cartsnitch:v2026.04.01
cartsnitch/cartsnitch:v2026.03.31.8
cartsnitch/cartsnitch:v2026.03.31.7
cartsnitch/cartsnitch:v2026.03.31.6
cartsnitch/cartsnitch:v2026.03.31.5
cartsnitch/cartsnitch:v2026.03.31.4
cartsnitch/cartsnitch:v2026.03.31.3
cartsnitch/cartsnitch:v2026.03.31.2
cartsnitch/cartsnitch:v2026.03.31
cartsnitch/cartsnitch:v2026.03.30.10
cartsnitch/cartsnitch:v2026.03.30.9
cartsnitch/cartsnitch:v2026.03.30.8
cartsnitch/cartsnitch:v2026.03.30.7
cartsnitch/cartsnitch:v2026.03.30.6
cartsnitch/cartsnitch:v2026.03.30.5
cartsnitch/cartsnitch:v2026.03.30.4
cartsnitch/cartsnitch:v2026.03.30.3
cartsnitch/cartsnitch:v2026.03.30.2
cartsnitch/cartsnitch:v2026.03.30
cartsnitch/cartsnitch:v2026.03.29.5
cartsnitch/cartsnitch:v2026.03.29.4
cartsnitch/cartsnitch:v2026.03.29.3
cartsnitch/cartsnitch:v2026.03.29.2
cartsnitch/cartsnitch:v2026.03.29
cartsnitch/cartsnitch:v2026.03.28.6
cartsnitch/cartsnitch:v2026.03.28.5
cartsnitch/cartsnitch:v2026.03.28.4
cartsnitch/cartsnitch:v2026.03.28.3
cartsnitch/cartsnitch:v2026.03.28.2
cartsnitch/cartsnitch:v2026.03.28
cartsnitch/cartsnitch:v2026.03.24.2
cartsnitch/cartsnitch:v2026.03.24
cartsnitch/cartsnitch:v2026.03.22.2
cartsnitch/cartsnitch:v2026.03.22
cartsnitch/cartsnitch:v2026.03.21.4
cartsnitch/cartsnitch:v2026.03.21.3
cartsnitch/cartsnitch:v2026.03.21.2
cartsnitch/cartsnitch:v2026.03.21
cartsnitch/cartsnitch:v2026.03.20.3
cartsnitch/cartsnitch:v2026.03.20.2
cartsnitch/cartsnitch:v2026.03.20
1 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bc5e03e7a0 |
fix(security): use SHA-256 hash for rate limit key instead of token suffix
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
2 changed files with 35 additions and 3 deletions
@@ -4,6 +4,7 @@ Uses in-memory sliding window as fallback, Redis/DragonflyDB when available.
|
||||
Per-IP limiting on public endpoints, per-token limiting on authenticated endpoints.
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import time
|
||||
from collections import defaultdict
|
||||
from threading import Lock
|
||||
@@ -71,8 +72,8 @@ def _get_rate_limit_key(request: Request) -> tuple[str, _SlidingWindowCounter]:
|
||||
auth_header = request.headers.get("authorization", "")
|
||||
if auth_header.startswith("Bearer "):
|
||||
token = auth_header[7:]
|
||||
# Use last 16 chars of token as key to avoid storing full tokens
|
||||
return f"token:{token[-16:]}", _auth_limiter
|
||||
token_hash = hashlib.sha256(token.encode()).hexdigest()
|
||||
return f"token:{token_hash}", _auth_limiter
|
||||
|
||||
# Fallback to IP for unauthenticated non-public endpoints
|
||||
return f"ip:{_get_client_ip(request)}", _public_limiter
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
"""Tests for rate limiting middleware."""
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from cartsnitch_api.middleware.rate_limit import _SlidingWindowCounter
|
||||
from cartsnitch_api.middleware.rate_limit import _SlidingWindowCounter, _get_rate_limit_key
|
||||
|
||||
|
||||
class TestSlidingWindowCounter:
|
||||
@@ -53,3 +55,32 @@ async def test_health_skips_rate_limit(client):
|
||||
resp = await client.get("/health")
|
||||
assert resp.status_code == 200
|
||||
assert "x-ratelimit-limit" not in resp.headers
|
||||
|
||||
|
||||
class TestGetRateLimitKey:
|
||||
def _make_request(self, auth_header: str = "") -> MagicMock:
|
||||
req = MagicMock()
|
||||
req.url.path = "/purchases"
|
||||
req.headers = {"authorization": auth_header} if auth_header else {}
|
||||
return req
|
||||
|
||||
def test_distinct_tokens_produce_distinct_keys(self):
|
||||
req1 = self._make_request("Bearer token_alpha_12345")
|
||||
req2 = self._make_request("Bearer token_beta_67890")
|
||||
key1, _ = _get_rate_limit_key(req1)
|
||||
key2, _ = _get_rate_limit_key(req2)
|
||||
assert key1 != key2
|
||||
|
||||
def test_same_token_produces_same_key(self):
|
||||
req1 = self._make_request("Bearer same_token_value_abc")
|
||||
req2 = self._make_request("Bearer same_token_value_abc")
|
||||
key1, _ = _get_rate_limit_key(req1)
|
||||
key2, _ = _get_rate_limit_key(req2)
|
||||
assert key1 == key2
|
||||
|
||||
def test_key_does_not_contain_raw_token_suffix(self):
|
||||
raw_token = "my_secret_jwt_token_xyz"
|
||||
req = self._make_request(f"Bearer {raw_token}")
|
||||
key, _ = _get_rate_limit_key(req)
|
||||
assert raw_token[-16:] not in key
|
||||
assert raw_token not in key
|
||||
|
||||
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.