refactor(auth): drop JWT_EXPIRY env var (family TTL is canonical)

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.
This commit is contained in:
2026-05-09 10:17:04 -07:00
parent 0f0c2f0e96
commit a4355e1ef3
5 changed files with 0 additions and 9 deletions

View File

@@ -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',

View File

@@ -67,7 +67,6 @@ export function createTestApp(overrides: Partial<Config> = {}): TestContext {
port: 0,
host: '127.0.0.1',
jwtSecret: 'test-secret-key',
jwtExpiry: '1h',
dbPath: ':memory:',
uploadDir,
logFile,

View File

@@ -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);

View File

@@ -10,7 +10,6 @@ function makeConfig(overrides: Partial<Config> = {}): Config {
port: 0,
host: '127.0.0.1',
jwtSecret: 'x',
jwtExpiry: '1h',
dbPath: ':memory:',
uploadDir: '/tmp',
logFile: '/tmp/x.log',

View File

@@ -17,7 +17,6 @@ function makeConfig(overrides: Partial<Config> = {}): Config {
port: 0,
host: '127.0.0.1',
jwtSecret: 'x',
jwtExpiry: '1h',
dbPath: ':memory:',
uploadDir: '/tmp',
logFile: '/tmp/x.log',