Status: open (L1 elevated to Phase C) · Severity: LOW · Source: [[Projects/personal-finance-notion/context/audit-2026-05-17-auth|Auth audit 2026-05-17 §LOW]]
2026-05-18 update. L1 shipped in [[Projects/personal-finance-notion/backlog/done/p0-authjs-phase-c-hardening|Phase C]] (
01d9ac3). L2–L7 unchanged.
Nice-to-haves and longer-term hardening. Pick up after launch + the M1–M5 patch.
Currently dormant (INTEGRATION_API_TOKEN_PREFIX unset → 503 from src/lib/integrations/requireIntegrationUser.ts). When the BCA email AI agent integration is re-enabled, the current Bearer = PREFIX + User._id (hex) design needs to be replaced — Mongo _id is not a secret (timestamp + machine + counter; can leak via API serialisation).
Design: per-user random API keys (32 bytes), hashed at rest, listable + revocable from a settings page, scoped (e.g. transactions:write), explicit expiry. New integrationKeys collection.
For a finance app this will come up in user feedback fast. Plan for v1.1. WebAuthn / passkeys preferred over TOTP for new builds — no shared-secret theft, better UX on iOS/Android.
User.lastLogin is set, but no per-event log. Capture IP + UA + timestamp + outcome in a new loginEvents collection. Powers a "recent sessions" UI and forensics for incident response.
One fetch per signup/reset using HIBP's k-anonymity API. Reduces credential-stuffing surface materially. Free, ~50ms latency.
NEXT_PUBLIC_*Pre-launch sanity check (still worth doing post-launch as a recurring sweep): grep for NEXT_PUBLIC_ and confirm only intentionally-public values are there. OPENROUTER_API_KEY, JWT_SECRET_KEY*, MONGODB_URI must be server-side only.
package.json build runs next build only. playwright.yml runs only e2e. Add a lint && tsc --noEmit step before the e2e job.
npm audit --production + dependabotAdd npm audit --production --audit-level=high to the workflow. Enable Dependabot via .github/dependabot.yml for weekly PRs.