From c48e30df1febc79fca1bc6a877983ebdf4dd6672 Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Mon, 27 Apr 2026 23:15:02 +0200 Subject: [PATCH] fix(M10): bump pending-TTL to 5min + repair MD3 contrast on pair page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TTL: 2 min was te kort voor handmatig curl-paste-confirm-testen — gebruiker zag 'Pairing verlopen' voor hij kon bevestigen. Bumpt naar 5 min (gelijk aan approved-TTL): nog steeds tight voor security, ruim voor menselijke reactie. - app/api/auth/pair/start/route.ts: PENDING_TTL_MS 120s → 300s - lib/auth/pair-cookie.ts: MAX_AGE_SECONDS 120 → 300 - __tests__/api/pair-start.test.ts: maxAge en expires_at-window meegegroeid Kleuren: bevestigingspagina gebruikte bg-destructive/10 + text-destructive- foreground — beide lichte kleuren, te weinig contrast. Vervangen door MD3 container-tokens (zelfde patroon als components/auth/auth-form.tsx): - error-state: bg-error-container + text-error-container-foreground + border-l-4 border-error - approved-state: bg-success-container + foreground + accent-border - cancelled-state: bg-surface-container-high + neutral foreground Quality gates: lint 0 errors, tsc clean, vitest 139/139. Co-Authored-By: Claude Opus 4.7 (1M context) --- __tests__/api/pair-start.test.ts | 8 ++++---- app/(app)/m/pair/pair-confirmation.tsx | 14 ++++++++------ app/api/auth/pair/start/route.ts | 2 +- lib/auth/pair-cookie.ts | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/__tests__/api/pair-start.test.ts b/__tests__/api/pair-start.test.ts index c29281a..8c7207f 100644 --- a/__tests__/api/pair-start.test.ts +++ b/__tests__/api/pair-start.test.ts @@ -62,10 +62,10 @@ describe('POST /api/auth/pair/start', () => { expect(arg.desktop_token_hash).toMatch(/^[a-f0-9]{64}$/) expect(arg.secret_hash).not.toBe(body.mobileSecret) expect(arg.status).toBe('pending') - // expires_at ~120s in toekomst + // expires_at ~5 min in toekomst const dt = new Date(arg.expires_at).getTime() - Date.now() - expect(dt).toBeGreaterThan(115_000) - expect(dt).toBeLessThan(125_000) + expect(dt).toBeGreaterThan(295_000) + expect(dt).toBeLessThan(305_000) }) it('zet HttpOnly Path-scoped s4m_pair cookie met Max-Age 120', async () => { @@ -78,7 +78,7 @@ describe('POST /api/auth/pair/start', () => { httpOnly: true, sameSite: 'lax', path: '/api/auth/pair', - maxAge: 120, + maxAge: 300, }) }) diff --git a/app/(app)/m/pair/pair-confirmation.tsx b/app/(app)/m/pair/pair-confirmation.tsx index fc5c42e..9d92b0d 100644 --- a/app/(app)/m/pair/pair-confirmation.tsx +++ b/app/(app)/m/pair/pair-confirmation.tsx @@ -110,18 +110,18 @@ export function PairConfirmation() { if (state.kind === 'invalid') { return ( -
+

Kan deze QR-code niet gebruiken

-

{state.error}

+

{state.error}

) } if (state.kind === 'approved') { return ( -
+

Klaar — je kunt deze tab sluiten.

-

+

Het apparaat met de QR-code is nu ingelogd als {state.username}.

@@ -130,9 +130,11 @@ export function PairConfirmation() { if (state.kind === 'cancelled') { return ( -
+

Geannuleerd

-

Er is geen sessie aangemaakt op het andere apparaat.

+

+ Er is geen sessie aangemaakt op het andere apparaat. +

) } diff --git a/app/api/auth/pair/start/route.ts b/app/api/auth/pair/start/route.ts index 409714d..2062887 100644 --- a/app/api/auth/pair/start/route.ts +++ b/app/api/auth/pair/start/route.ts @@ -20,7 +20,7 @@ import { checkRateLimit } from '@/lib/rate-limit' export const runtime = 'nodejs' -const PENDING_TTL_MS = 2 * 60 * 1000 // 2 min — komt overeen met s4m_pair Max-Age +const PENDING_TTL_MS = 5 * 60 * 1000 // 5 min — komt overeen met s4m_pair Max-Age const UA_MAX = 255 // matcht VarChar(255) op login_pairings.desktop_ua const IP_MAX = 45 // matcht VarChar(45) — IPv6 max length diff --git a/lib/auth/pair-cookie.ts b/lib/auth/pair-cookie.ts index a782f51..e977ee7 100644 --- a/lib/auth/pair-cookie.ts +++ b/lib/auth/pair-cookie.ts @@ -8,7 +8,7 @@ import { cookies } from 'next/headers' const COOKIE_NAME = 's4m_pair' -const MAX_AGE_SECONDS = 120 // gelijk aan pending-TTL van LoginPairing +const MAX_AGE_SECONDS = 300 // gelijk aan pending-TTL van LoginPairing (5 min) const COOKIE_PATH = '/api/auth/pair' export async function setPairCookie(desktopToken: string): Promise {