Adds a synchronous checkPasswordPolicy() in @capakraken/shared that rejects common-list, trivial-pattern, sequential, and identity-containing passwords
Wires the check into all five password-mutation sites: first-admin setup, admin createUser, admin setUserPassword, invite acceptance, and password-reset
17 unit tests covering length bounds, repeats, sequences, blacklist (case-insensitive), and identity inclusion
What this blocks
>=12-char dictionary entries that would pass the length gate (rockyou top, predictable seasonal/admin-default patterns)
Trivial constructions: aaaaaaaaaaaa, abcabcabcabc, keyboard runs like abcdefghijkl
Passwords that include the user's email local-part or any name component (substrings >= 4 chars, case-insensitive)
Why
CDP epic #1 — addresses the open \ud83d\udd34 Block commonly chosen passwords item in #31. Active password-expiry tracking (passwordChangedAt on the User model + admin-configurable max age) is intentionally out of scope here and will land as a follow-up so this PR stays additive and migration-free.
Test plan
pnpm --filter @capakraken/shared exec vitest run (279 pass, +17 new)
pnpm --filter @capakraken/api exec vitest run (1945 pass)
pnpm --filter @capakraken/web exec vitest run (1285 pass)
## Summary
- Adds a synchronous `checkPasswordPolicy()` in `@capakraken/shared` that rejects common-list, trivial-pattern, sequential, and identity-containing passwords
- Wires the check into all five password-mutation sites: first-admin setup, admin createUser, admin setUserPassword, invite acceptance, and password-reset
- 17 unit tests covering length bounds, repeats, sequences, blacklist (case-insensitive), and identity inclusion
## What this blocks
- `>=12`-char dictionary entries that would pass the length gate (rockyou top, predictable seasonal/admin-default patterns)
- Trivial constructions: `aaaaaaaaaaaa`, `abcabcabcabc`, keyboard runs like `abcdefghijkl`
- Passwords that include the user's email local-part or any name component (substrings >= 4 chars, case-insensitive)
## Why
CDP epic #1 — addresses the open `\ud83d\udd34 Block commonly chosen passwords` item in #31. Active password-expiry tracking (`passwordChangedAt` on the `User` model + admin-configurable max age) is intentionally out of scope here and will land as a follow-up so this PR stays additive and migration-free.
## Test plan
- [x] `pnpm --filter @capakraken/shared exec vitest run` (279 pass, +17 new)
- [x] `pnpm --filter @capakraken/api exec vitest run` (1945 pass)
- [x] `pnpm --filter @capakraken/web exec vitest run` (1285 pass)
- [x] `pnpm --filter @capakraken/{web,api,shared} exec tsc --noEmit` clean
- [x] `pnpm lint` clean (0 errors)
Adds a synchronous policy check that blocks (1) the curated >=12-char
common-password list (rockyou top, predictable seasonal, admin defaults),
(2) trivial patterns (single-char repeat, short-pattern repeat, keyboard
or numeric sequences), and (3) passwords containing the user's email
local-part or any name component. Wired into all five password-mutation
sites: first-admin setup, admin createUser/setUserPassword, invite
acceptance, and password-reset.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CI typecheck failed because the discriminated union returned by
checkPasswordPolicy only exposes `reason` on the `{ ok: false }` branch.
Guard each `.reason` assertion with `if (!result.ok)` so the test file
typechecks under exactOptionalPropertyTypes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
All checks were successful
CI / Architecture Guardrails (pull_request) Successful in 6m11s
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
checkPasswordPolicy()in@capakraken/sharedthat rejects common-list, trivial-pattern, sequential, and identity-containing passwordsWhat this blocks
>=12-char dictionary entries that would pass the length gate (rockyou top, predictable seasonal/admin-default patterns)aaaaaaaaaaaa,abcabcabcabc, keyboard runs likeabcdefghijklWhy
CDP epic #1 — addresses the open
\ud83d\udd34 Block commonly chosen passwordsitem in #31. Active password-expiry tracking (passwordChangedAton theUsermodel + admin-configurable max age) is intentionally out of scope here and will land as a follow-up so this PR stays additive and migration-free.Test plan
pnpm --filter @capakraken/shared exec vitest run(279 pass, +17 new)pnpm --filter @capakraken/api exec vitest run(1945 pass)pnpm --filter @capakraken/web exec vitest run(1285 pass)pnpm --filter @capakraken/{web,api,shared} exec tsc --noEmitcleanpnpm lintclean (0 errors)9ef7114c77toe01074926eCI typecheck failed because the discriminated union returned by checkPasswordPolicy only exposes `reason` on the `{ ok: false }` branch. Guard each `.reason` assertion with `if (!result.ok)` so the test file typechecks under exactOptionalPropertyTypes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.