Skip to content

Commit 552d3db

Browse files
committed
Updating documents
1 parent e8852a3 commit 552d3db

3 files changed

Lines changed: 17 additions & 6 deletions

File tree

CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ These are the rules that must not be forgotten or looked up — they're the ones
1414
- Never put security codes/tokens in email **subjects** (they show on lock screens). Body only
1515
- On sensitive account changes (email, password, 2FA), notify the **old** email too
1616
- Never trust user-controlled redirect targets (e.g. `Referer`) without validating the path starts with `/`
17+
- Content-Security-Policy ships **strict** in prod (per-request nonce + `strict-dynamic`, via `Plugs.ContentSecurityPolicy` in the `:csp` pipeline). Add third-party origins through the `:csp_extra_sources` config — never by loosening the plug. Inline `<script>` tags must carry `@csp_nonce`. Dev-only routes (`/dev/*`) deliberately skip `:csp` so tooling (the Swoosh mailbox iframe, LiveDashboard) keeps working
1718

1819
**Error handling**
1920
- Always handle both `{:ok, _}` and `{:error, _}` from context calls — never `{:ok, x} = SomeContext.foo()`
@@ -115,6 +116,7 @@ The template already includes these — extend them, don't rebuild them.
115116
- Email + password registration, **link-based** email confirmation and password reset (1-hour `UserToken`s; the raw token rides in the email URL, only its SHA3-256 hash is stored). Session tokens use a 60-day sliding window
116117
- The `User` schema is deliberately minimal: `email`, `hashed_password`, `locale`, `confirmed_at`. Add profile fields (name, avatar, …) per project — there's no `name` column yet
117118
- Endpoint responses don't leak which emails are registered (resend-confirmation / forgot-password reply identically either way)
119+
- Account settings (`SettingsController`): link-confirmed **email change** (the link hits `/settings/email/apply-change`; the old address is notified — distinct from the public `/confirm-email` account-activation route), **password change** (invalidates the user's other sessions), and **account deletion**. All three re-verify the current password first
118120

119121
**Realtime** (`ElixirReactStarterWeb.{UserSocket, GlobalChannel, UserChannel}` + `assets/js/realtime/`)
120122
- Token-authed socket at `/socket`. The provider (mounted in `app-providers.tsx`) auto-joins `global` and `user:<id>` and survives Inertia navigation (keyed on user id, not the rotating token). Hooks: `useConnectionStatus`, `useGlobalChannel`, `useUserChannel`, `useChannel`, `use{Global,User}Event`, `pushChannel`

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ It's provided as-is, with no guarantees or warranties of any kind — use it at
3333
- **Theming** — light / dark / system with no flash of the wrong theme.
3434
- **Accessibility**[Radix UI][radix] primitives, [Biome][biome] a11y linting in CI, and [axe-core][axe] auditing in dev.
3535
- **Email**[Swoosh][swoosh] (HTML + text) via [Mailjet][mailjet] in production, with an in-browser mailbox in dev.
36-
- **Security** — rate-limited auth endpoints, Secure cookies, CSRF protection, and HTTPS/HSTS in production.
36+
- **Security** — rate-limited auth endpoints, a strict nonce-based [Content-Security-Policy][csp], Secure cookies, CSRF protection, and HTTPS/HSTS in production.
3737
- **Background jobs**[Oban][oban], configured and ready.
3838
- **Testing**[ExUnit][exunit] with a coverage gate, [ex_machina][exmachina] factories, and a [Playwright][playwright] E2E suite.
3939
- **Tooling & CI**[mise][mise]-pinned toolchain, [Biome][biome] / [Credo][credo] / [Dialyzer][dialyxir], and [GitHub Actions][gha].
@@ -157,6 +157,7 @@ Released under the **WTFPL** (see the `LICENSE` file) — do what the fuck you w
157157
[react-i18next]: https://react.i18next.com/
158158
[tailwind]: https://tailwindcss.com/
159159
[radix]: https://www.radix-ui.com/primitives
160+
[csp]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP
160161
[biome]: https://biomejs.dev/
161162
[axe]: https://github.com/dequelabs/axe-core
162163
[swoosh]: https://hexdocs.pm/swoosh/

docs/e2e-testing.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,15 @@ separate project.
1313
| Spec | Flow |
1414
| --- | --- |
1515
| `registration.spec.ts` | Sign up → confirm via the emailed link → land on the dashboard |
16-
| `login.spec.ts` | Log in to the dashboard; reject bad credentials with a visible error |
16+
| `login.spec.ts` | Log in; reject bad credentials; an unconfirmed login re-sends the confirmation link instead of starting a session |
17+
| `logout.spec.ts` | Log out from the header menu → protected pages bounce to `/login` |
18+
| `resend-confirmation.spec.ts` | Unconfirmed user requests a fresh link from `/login` → confirms |
19+
| `email-confirmation.spec.ts` | Re-clicking a used link keeps an already-confirmed user on the dashboard; a stale link signed out → resend page |
1720
| `reset-password.spec.ts` | Request a reset link → set a new password → log in with it |
21+
| `change-email.spec.ts` | Change email → confirm via the link to the new inbox → log in with it (+ wrong-password rejection) |
22+
| `change-password.spec.ts` | Change password → old one fails, new one works (+ wrong-password rejection) |
23+
| `delete-account.spec.ts` | Delete the account behind a password-confirm dialog → can no longer sign in (+ wrong-password rejection) |
24+
| `auth-guards.spec.ts` | Pipeline redirects: anonymous → `/login`, already signed-in → `/dashboard` |
1825
| `locale.spec.ts` | Switch the interface language (English → Spanish) |
1926

2027
## Prerequisites
@@ -79,9 +86,10 @@ they are unreachable in production and cannot affect real data.
7986

8087
### Link-based flows
8188

82-
Authentication here is link-based, so the registration and reset specs
83-
read the single-click URL out of the dev mailbox JSON
84-
(`/dev/mailbox/json`) via `fetchEmailLink/3` and navigate to it.
89+
Authentication here is link-based, so the link-driven specs (sign-up,
90+
password reset, email change, resend confirmation) read the single-click
91+
URL out of the dev mailbox JSON (`/dev/mailbox/json`) via
92+
`fetchEmailLink/3` and navigate to it.
8593

8694
## Writing a new test
8795

@@ -100,7 +108,7 @@ assets/
100108
tsconfig.e2e.json # node-typed TS project for the suite
101109
e2e/
102110
global-setup.ts # runs priv/repo/e2e.exs before the suite
103-
helpers.ts # uniqueEmail, provisionUser, loginAs, fetchEmailLink
111+
helpers.ts # uniqueEmail, provisionUser, loginAs, logoutViaMenu, gotoSettingsViaMenu, fetchEmailLink
104112
tests/ # one spec per flow
105113
priv/repo/e2e.exs # destructive per-run cleanup (dev/test only)
106114
lib/elixir_react_starter_web/controllers/dev_e2e_controller.ex # POST /dev/e2e/users

0 commit comments

Comments
 (0)