docs(phase-2): add validation strategy

This commit is contained in:
Arthur Belleville 2026-05-14 21:19:41 +02:00
parent d2af5d227b
commit 0d62b9988d
No known key found for this signature in database

View file

@ -0,0 +1,83 @@
---
phase: 2
slug: authentication
status: draft
nyquist_compliant: false
wave_0_complete: false
created: 2026-05-14
---
# Phase 2 — Validation Strategy
> Per-phase validation contract for feedback sampling during execution.
---
## Test Infrastructure
| Property | Value |
|----------|-------|
| **Framework** | Go `testing` + `go test` (stdlib) |
| **Config file** | `backend/go.mod` (no separate config) |
| **Quick run command** | `cd backend && go test ./internal/auth/...` |
| **Full suite command** | `cd backend && go test ./...` |
| **Estimated runtime** | ~1530 seconds (argon2 tests use reduced params) |
DB-touching tests require `TEST_DATABASE_URL` pointing at the compose-managed Postgres (see Phase 1 pattern in `backend/internal/db/pool_test.go`). Each test runs in a transaction that rolls back, OR uses a per-test schema name to avoid cross-contamination.
---
## Sampling Rate
- **After every task commit:** Run `go test ./internal/auth/...`
- **After every plan wave:** Run `go test ./...`
- **Before `/gsd-verify-work`:** Full suite must be green
- **Max feedback latency:** 30 seconds
---
## Per-Task Verification Map
Filled by planner as PLAN.md tasks are emitted. Each task with `type: execute` must have an `<automated>` verify command OR an explicit Wave 0 dependency. Tasks creating templ/HTML output may need a small Go test that renders the component and asserts the resulting HTML contains expected markers.
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
| (to be filled by planner) | | | | | | | | | ⬜ pending |
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
---
## Wave 0 Requirements
- [ ] `backend/internal/auth/password_test.go` — argon2 hash/verify round-trip with reduced test params
- [ ] `backend/internal/auth/session_test.go` — token generate + SHA-256 lookup, expiry semantics
- [ ] `backend/internal/auth/ratelimit_test.go` — per-key bucket allow/deny with injectable clock
- [ ] `backend/internal/auth/middleware_test.go` — ResolveSession context plumbing, RequireAuth 303 / HX-Redirect
- [ ] Reuse `backend/internal/db/pool_test.go` Postgres harness for users/sessions integration tests
*Existing Go test infrastructure (Phase 1) covers framework setup — no new tooling install needed.*
---
## Manual-Only Verifications
| Behavior | Requirement | Why Manual | Test Instructions |
|----------|-------------|------------|-------------------|
| Cookie is `HttpOnly` and `Secure` in non-dev environments | AUTH-03 | Browser DevTools required to inspect cookie attributes from a live response | Run `ENV=staging` server, hit `/login`, submit valid creds, open DevTools → Application → Cookies; confirm `HttpOnly=true`, `Secure=true`, `SameSite=Lax` |
| `/login` page visual layout matches Phase 1 design system | AUTH-01 / D-69 | Visual assertion | Open `http://localhost:8080/login`, confirm Button/Card/Badge styling from `internal/web/ui` is applied; confirm `/signup` mirrors |
| HTMX inline form-error swap on bad credentials | AUTH-02 | Requires browser to evaluate `HX-Request` round-trip | Submit `/login` with bad password via HTMX form; only the form fragment swaps with "Invalid email or password" — no full page reload |
| Rate-limit error fragment shows after 6th failed login | AUTH-06 | Requires browser to observe 429 + swap | Submit 6 wrong-password attempts in <60s from same IP; 6th returns 429 with "Too many attempts" inline fragment |
---
## Validation Sign-Off
- [ ] All tasks have `<automated>` verify or Wave 0 dependencies
- [ ] Sampling continuity: no 3 consecutive tasks without automated verify
- [ ] Wave 0 covers all MISSING references
- [ ] No watch-mode flags
- [ ] Feedback latency < 30s
- [ ] `nyquist_compliant: true` set in frontmatter
**Approval:** pending