3 Commits

Author SHA1 Message Date
ebbbdbdfb8 fix(web): make session cookie secure flag conditional on production
Setting Secure on http://localhost cookies works in Chrome (localhost
exception) but Firefox/Safari silently drop them, so dev users hit
'redirect to /login on every click' after a 'successful' login. Switch
to secure: NODE_ENV === 'production'. Public deploy still gets
Secure-only.

Also swap the login footer copy from a CLI hint to 'Forget Password?
Contact IT' — operator-friendly, doesn't leak the bootstrap
mechanism on the public sign-in screen.

Test updated to assert secure=true under prod NODE_ENV and a new test
locks in secure=false in dev.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 18:19:59 +08:00
5b4787d10e fix(web): typed-routes + redirect-mock signatures in auth.ts
Next.js 16 typed-routes (experimental.typedRoutes in next.config.ts)
narrows redirect()'s parameter to RouteImpl<T>, which a runtime
string from the form can't satisfy. Cast to any with a comment for
the two redirect call sites in auth.ts.

The auth.test.ts redirectMock used `() =>` zero-arg signature, which
typescript rejected once the action started passing the path through.
Change to `(_path: string) =>` so the signature matches and the test
still passes (vitest's esbuild-transpiled run was fine; tsc caught it).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 17:54:59 +08:00
cedd623466 feat(web): loginAction + logoutAction (with TDD)
Username + password verified against the operators row, bcrypt
compare regardless of user-found state for timing equivalence,
DUMMY_HASH precomputed and committed. 10/5min IP rate limit, no
password ever logged. Issues a 30-day HttpOnly+Secure+SameSite=Lax
cookie on success, redirects via safeRedirect(next). 12 unit tests
covering correct creds, wrong username, wrong password, missing
password_hash, empty/long inputs, case-insensitive match, rate-limit
trigger, no-password-leak, safe redirect, unsafe redirect, logout.
2026-05-10 17:50:41 +08:00