p2-auth-backlog-low

opentype/backlogpriority/p2severity/lowtopic/authtopic/hardening

p2 · Auth backlog (low) — L1–L7

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.

L1 · Redesign integration API tokens before re-enabling

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.

L2 · 2FA / passkeys

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.

L3 · Login audit log

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.

L4 · HaveIBeenPwned check on password set

One fetch per signup/reset using HIBP's k-anonymity API. Reduces credential-stuffing surface materially. Free, ~50ms latency.

L5 · Confirm no auth secrets in 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.

L6 · CI: pre-build typecheck + lint

package.json build runs next build only. playwright.yml runs only e2e. Add a lint && tsc --noEmit step before the e2e job.

L7 · CI: npm audit --production + dependabot

Add npm audit --production --audit-level=high to the workflow. Enable Dependabot via .github/dependabot.yml for weekly PRs.

Implications

If skipped

  • L2–L7 stay aspirational: no 2FA/passkeys when users ask, no login forensics, no HIBP on password set, no CI guardrails on types or deps. Risk is slow accumulation (credential stuffing, blind deploys, stale dependencies) rather than one day-one outage.

Why this priority

  • p2 — explicitly post-launch nice-to-haves from the audit. L1 shipped in Phase C. Pick items here when p0/p1 product work calms down or a specific item becomes urgent (e.g. user demand for 2FA → promote L2).

When shipped

  • Incremental hardening and ops hygiene without blocking feature velocity.

Related

  • [[Projects/personal-finance-notion/context/audit-2026-05-17-auth|Audit doc]]
  • [[Projects/personal-finance-notion/personal-finance-notion|MOC]]