diff --git a/Dockerfile.test b/Dockerfile.test index 2846d2e..89c37c9 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -11,4 +11,3 @@ COPY . . RUN --mount=type=secret,id=test_db_url,required=true \ export TEST_DATABASE_URL="$(cat /run/secrets/test_db_url)" && \ cargo test -p db --test ai_credits --test ai_credits_reaper -- --test-threads=1 -# re-run: nxtgauge_test now has seed data (free plan) diff --git a/crates/db/migrations/20260813000000_fix_ai_credits_timestamp_types.down.sql b/crates/db/migrations/20260813000000_fix_ai_credits_timestamp_types.down.sql new file mode 100644 index 0000000..add65ed --- /dev/null +++ b/crates/db/migrations/20260813000000_fix_ai_credits_timestamp_types.down.sql @@ -0,0 +1,20 @@ +BEGIN; + +ALTER TABLE ai_usage_logs + ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC'; + +ALTER TABLE ai_feature_costs + ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC', + ALTER COLUMN updated_at TYPE TIMESTAMP USING updated_at AT TIME ZONE 'UTC'; + +ALTER TABLE user_ai_subscriptions + ALTER COLUMN current_period_start TYPE TIMESTAMP USING current_period_start AT TIME ZONE 'UTC', + ALTER COLUMN current_period_end TYPE TIMESTAMP USING current_period_end AT TIME ZONE 'UTC', + ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC', + ALTER COLUMN updated_at TYPE TIMESTAMP USING updated_at AT TIME ZONE 'UTC'; + +ALTER TABLE ai_plans + ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC', + ALTER COLUMN updated_at TYPE TIMESTAMP USING updated_at AT TIME ZONE 'UTC'; + +COMMIT; diff --git a/crates/db/migrations/20260813000000_fix_ai_credits_timestamp_types.up.sql b/crates/db/migrations/20260813000000_fix_ai_credits_timestamp_types.up.sql new file mode 100644 index 0000000..ef2e09c --- /dev/null +++ b/crates/db/migrations/20260813000000_fix_ai_credits_timestamp_types.up.sql @@ -0,0 +1,37 @@ +-- Fix ai_plans/user_ai_subscriptions/ai_feature_costs/ai_usage_logs timestamp +-- columns: they were created (by whatever earlier, pre-20260703210000 +-- mechanism made these tables) as `TIMESTAMP` (no timezone), but +-- crates/db/src/models/ai_credits.rs maps every one of these to +-- `DateTime`, which sqlx requires the column to be `TIMESTAMPTZ` for. +-- Discovered via crates/db/tests/ai_credits.rs failing with: +-- ColumnDecode { ... "TIMESTAMPTZ" is not compatible with SQL type "TIMESTAMP" } +-- This is a real, live bug, not just a test-setup gap: any production code +-- path that SELECTs current_period_start/current_period_end (or any of the +-- other columns below) via these structs would hit the same decode error. +-- +-- `AT TIME ZONE 'UTC'` reinterprets the existing naive values as UTC wall-clock +-- time when adding the zone (the correct, lossless conversion given every +-- write path uses NOW()/DEFAULT NOW() with no other timezone handling +-- anywhere in this codebase) rather than converting through the session's +-- local timezone. + +BEGIN; + +ALTER TABLE ai_plans + ALTER COLUMN created_at TYPE TIMESTAMPTZ USING created_at AT TIME ZONE 'UTC', + ALTER COLUMN updated_at TYPE TIMESTAMPTZ USING updated_at AT TIME ZONE 'UTC'; + +ALTER TABLE user_ai_subscriptions + ALTER COLUMN current_period_start TYPE TIMESTAMPTZ USING current_period_start AT TIME ZONE 'UTC', + ALTER COLUMN current_period_end TYPE TIMESTAMPTZ USING current_period_end AT TIME ZONE 'UTC', + ALTER COLUMN created_at TYPE TIMESTAMPTZ USING created_at AT TIME ZONE 'UTC', + ALTER COLUMN updated_at TYPE TIMESTAMPTZ USING updated_at AT TIME ZONE 'UTC'; + +ALTER TABLE ai_feature_costs + ALTER COLUMN created_at TYPE TIMESTAMPTZ USING created_at AT TIME ZONE 'UTC', + ALTER COLUMN updated_at TYPE TIMESTAMPTZ USING updated_at AT TIME ZONE 'UTC'; + +ALTER TABLE ai_usage_logs + ALTER COLUMN created_at TYPE TIMESTAMPTZ USING created_at AT TIME ZONE 'UTC'; + +COMMIT;