From a4355e1ef3e9084a99880ee739e95f6b45fdc691 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Sat, 9 May 2026 10:17:04 -0700 Subject: [PATCH] refactor(auth): drop JWT_EXPIRY env var (family TTL is canonical) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The JWT lifetime is now pinned to SESSION_TTL_SECONDS (30 days) inside issueSessionCookie, so JWT_EXPIRY had no effect after the prior commits. Removing the field from Config and the env read in loadConfig lets the TypeScript compiler verify no caller was still relying on it. Per the family invariant ('coherence across apps is a feature'), the per-app override is intentionally gone — a deploy with stale JWT_EXPIRY in .env will now silently use the 30-day family default regardless of the value. Test fixtures (Config literals in setup.ts, login-handler.test.ts, lockout-service.test.ts) and config.test.ts assertions updated to match the new shape. --- src/config.ts | 2 -- tests/helpers/setup.ts | 1 - tests/unit/config.test.ts | 4 ---- tests/unit/lockout-service.test.ts | 1 - tests/unit/login-handler.test.ts | 1 - 5 files changed, 9 deletions(-) diff --git a/src/config.ts b/src/config.ts index 63f93f1..763a1bf 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,7 +2,6 @@ export interface Config { port: number; host: string; jwtSecret: string; - jwtExpiry: string; dbPath: string; uploadDir: string; logFile: string; @@ -28,7 +27,6 @@ export function loadConfig(): Config { port: parseInt(process.env.PORT ?? '3000', 10), host: process.env.HOST ?? '0.0.0.0', jwtSecret, - jwtExpiry: process.env.JWT_EXPIRY ?? '7d', dbPath: process.env.DB_PATH ?? './data/nanodrop.db', uploadDir: process.env.UPLOAD_DIR ?? './data/uploads', logFile: process.env.LOG_FILE ?? './data/nanodrop.log', diff --git a/tests/helpers/setup.ts b/tests/helpers/setup.ts index 2c466b1..fa9c1d4 100644 --- a/tests/helpers/setup.ts +++ b/tests/helpers/setup.ts @@ -67,7 +67,6 @@ export function createTestApp(overrides: Partial = {}): TestContext { port: 0, host: '127.0.0.1', jwtSecret: 'test-secret-key', - jwtExpiry: '1h', dbPath: ':memory:', uploadDir, logFile, diff --git a/tests/unit/config.test.ts b/tests/unit/config.test.ts index f0b80e9..fc4fa07 100644 --- a/tests/unit/config.test.ts +++ b/tests/unit/config.test.ts @@ -15,7 +15,6 @@ describe('config', () => { process.env.JWT_SECRET = 'test-secret'; delete process.env.PORT; delete process.env.HOST; - delete process.env.JWT_EXPIRY; delete process.env.DB_PATH; delete process.env.UPLOAD_DIR; delete process.env.LOG_FILE; @@ -35,7 +34,6 @@ describe('config', () => { expect(config.port).toBe(3000); expect(config.host).toBe('0.0.0.0'); - expect(config.jwtExpiry).toBe('7d'); expect(config.dbPath).toBe('./data/nanodrop.db'); expect(config.uploadDir).toBe('./data/uploads'); expect(config.logFile).toBe('./data/nanodrop.log'); @@ -55,7 +53,6 @@ describe('config', () => { process.env.JWT_SECRET = 'my-secret'; process.env.PORT = '4000'; process.env.HOST = '127.0.0.1'; - process.env.JWT_EXPIRY = '1d'; process.env.COOKIE_SECURE = 'true'; process.env.TRUST_PROXY = 'true'; process.env.MAX_FILE_SIZE = '52428800'; @@ -66,7 +63,6 @@ describe('config', () => { expect(config.port).toBe(4000); expect(config.host).toBe('127.0.0.1'); expect(config.jwtSecret).toBe('my-secret'); - expect(config.jwtExpiry).toBe('1d'); expect(config.cookieSecure).toBe(true); expect(config.trustProxy).toBe(true); expect(config.maxFileSize).toBe(52428800); diff --git a/tests/unit/lockout-service.test.ts b/tests/unit/lockout-service.test.ts index 5d8cddb..595a415 100644 --- a/tests/unit/lockout-service.test.ts +++ b/tests/unit/lockout-service.test.ts @@ -10,7 +10,6 @@ function makeConfig(overrides: Partial = {}): Config { port: 0, host: '127.0.0.1', jwtSecret: 'x', - jwtExpiry: '1h', dbPath: ':memory:', uploadDir: '/tmp', logFile: '/tmp/x.log', diff --git a/tests/unit/login-handler.test.ts b/tests/unit/login-handler.test.ts index db9ca90..2a3042c 100644 --- a/tests/unit/login-handler.test.ts +++ b/tests/unit/login-handler.test.ts @@ -17,7 +17,6 @@ function makeConfig(overrides: Partial = {}): Config { port: 0, host: '127.0.0.1', jwtSecret: 'x', - jwtExpiry: '1h', dbPath: ':memory:', uploadDir: '/tmp', logFile: '/tmp/x.log',