Remove dangerous default values for jwt_secret_key, service_key, and
fernet_key. Add startup validation that raises RuntimeError if these
secrets are not set via environment variables or contain placeholder
values.
Add test fixture to provide explicit test values for these secrets,
ensuring existing tests continue to pass.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
CTO review: APPROVED. Migration creates all 9 domain tables in correct FK order with idempotent guards. env.py commit fix resolves SQLAlchemy 2.0 DDL persistence issue.
SQLAlchemy 2.0 removed implicit autocommit; without an explicit
connection.commit() DDL changes from create_all() are rolled back
when the connection closes, leaving fresh databases without tables.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The models/__init__.py imports all ORM model classes (Store, Product,
Coupon, etc.) which registers their table definitions with Base.metadata.
Importing Base directly from models.base skips this registration, so
alembic's create_all() on fresh databases fails to create app tables.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Better-Auth sets the session cookie as "token.sessionId". The DB stores
only the token part, so passing the full compound value caused 401s.
Splits on "." for both cookie and Bearer paths.
Tests added for compound cookie, raw token cookie (regression), and
compound Bearer token.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
API config.py now reads CARTSNITCH_DATABASE_URL first, falls back to
DATABASE_URL (which the infra K8s overlay sets for all pods), and finally
falls back to the hardcoded default. Also normalizes plain postgresql://
to postgresql+asyncpg:// for the asyncpg driver.
Fixes CAR-510.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Better-auth v1.5.6 stores raw 32-char tokens in sessions.token, not SHA-256
hashes. The SHA-256 fix from PR #136 causes all authenticated API calls to
return 401 because the UAT sessions table contains raw tokens.
- Remove hashlib from dependencies.py; compare tokens directly
- Remove hashlib from conftest.py; store raw tokens in test DB
- Remove hashlib from test_expired_session_rejected; use raw tokens
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Better-Auth v1.2+ stores SHA-256(raw_token) in the sessions.token
column. The cookie/Bearer header carries the raw token, so the API was
doing a plain-text lookup that would never match a hashed value —
causing all authenticated endpoints to return 401.
- Add hashlib import and hash token in _validate_session_token()
- Update conftest._create_test_user_and_session() to store hashed tokens
- Update test_expired_session_rejected() to store hashed tokens
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Better-auth sets the session cookie with the __Secure- prefix on HTTPS
deployments. The API was only reading the plain cookie name, causing all
authenticated calls to return 401 in dev/UAT/prod environments.
Check __Secure-better-auth.session_token first, fall back to
better-auth.session_token for HTTP local dev compatibility.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Default varchar(32) alembic_version column truncates long revision IDs
like 003_make_users_hashed_password_nullable (39 chars) on fresh databases.
Set version_table_column_width=128 in both context.configure() calls.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Create migration 007 to raw-SQL CREATE TABLE IF NOT EXISTS the users table
as a safety net for fresh databases where Base.metadata.create_all() may
fail due to import errors before the table is created.
Wrap the create_all call in env.py with try/except so alembic never crashes
due to create_all failures — migrations already handle table creation.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
psycopg2 compiled against libpq-dev in the build stage now has
its runtime dependency (libpq5) available in the prod stage.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Better-Auth creates users via raw SQL INSERT (not through SQLAlchemy),
so it bypasses ORM defaults and causes HTTP 500 on sign-up/sign-in.
Adds PostgreSQL server_default so INSERT without email_inbound_token
auto-generates a URL-safe token matching Python secrets.token_urlsafe(16).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The sha_tag output is a 40-char SHA, but docker/metadata-action
defaults to short (7-char) SHA tags. This caused UAT pods to fail
image pulls because kustomization tags didn't match GHCR tags.
Change type=sha,prefix=sha- to type=sha,prefix=sha-,format=long
in all four build jobs (cartsnitch, auth, receiptwitness, api).
Fixes CAR-482.
Co-Authored-By: Paperclip <noreply@paperclip.ing>