diff --git a/api/src/app.ts b/api/src/app.ts index da563112c..6bd2c2246 100644 --- a/api/src/app.ts +++ b/api/src/app.ts @@ -31,12 +31,11 @@ import dashboardRoutes from './routes/dashboard.js'; import { setupSwagger } from './swagger.js'; import { initializeCAIA } from './services/caia.js'; -// Validate SESSION_SECRET in production -if (process.env.NODE_ENV === 'production' && !process.env.SESSION_SECRET) { - throw new Error('SESSION_SECRET environment variable is required in production'); +// Validate SESSION_SECRET is set (required in all environments) +if (!process.env.SESSION_SECRET) { + throw new Error('SESSION_SECRET environment variable is required. Set it in your .env.local file.'); } - -const sessionSecret = process.env.SESSION_SECRET || 'dev-only-secret-do-not-use-in-production'; +const sessionSecret: string = process.env.SESSION_SECRET; // CSRF protection setup const { csrfSynchronisedProtection, generateToken } = csrfSync({ diff --git a/api/src/db/seed.ts b/api/src/db/seed.ts index 49c316d9b..c1b2844bf 100644 --- a/api/src/db/seed.ts +++ b/api/src/db/seed.ts @@ -76,7 +76,8 @@ async function seed() { { email: 'jack.brown@ship.local', name: 'Jack Brown' }, ]; - const passwordHash = await bcrypt.hash('admin123', 10); + const seedPassword = process.env.SEED_USER_PASSWORD || 'admin123'; + const passwordHash = await bcrypt.hash(seedPassword, 10); let usersCreated = 0; for (const member of teamMembers) { diff --git a/e2e/fixtures/isolated-env.ts b/e2e/fixtures/isolated-env.ts index 66e77270c..eef89b140 100644 --- a/e2e/fixtures/isolated-env.ts +++ b/e2e/fixtures/isolated-env.ts @@ -134,6 +134,7 @@ export const test = base.extend< ...process.env, PORT: String(port), DATABASE_URL: dbUrl, + SESSION_SECRET: process.env.SESSION_SECRET || 'test-session-secret', CORS_ORIGIN: '*', // Allow any origin during tests NODE_ENV: 'test', // Prevent dotenv from overriding our DATABASE_URL @@ -309,8 +310,9 @@ async function runMigrations(dbUrl: string): Promise { * - Issues with various states */ async function seedMinimalTestData(pool: Pool): Promise { - // Hash the test password - const passwordHash = await bcrypt.hash('admin123', 10); + // Hash the test password (uses env var with test default) + const testPassword = process.env.TEST_USER_PASSWORD || 'admin123'; + const passwordHash = await bcrypt.hash(testPassword, 10); // Create workspace with sprint_start_date 3 months ago (matches full seed) const threeMonthsAgo = new Date(); diff --git a/web/src/hooks/useAuth.tsx b/web/src/hooks/useAuth.tsx index 2d8f79d14..a20600462 100644 --- a/web/src/hooks/useAuth.tsx +++ b/web/src/hooks/useAuth.tsx @@ -10,7 +10,7 @@ import { api, UserInfo, Workspace } from '@/lib/api'; import { useWorkspace, WorkspaceWithRole } from '@/contexts/WorkspaceContext'; // Cache key for offline auth -const AUTH_CACHE_KEY = 'ship:auth-cache'; +const AUTH_CACHE_KEY = import.meta.env.VITE_AUTH_CACHE_KEY || 'ship:auth-cache'; interface CachedAuth { user: UserInfo;