feat(web): self-service cheie/creds + admin web + email signup (PRD 3.3b)
US-007: rute web proprii /cont/roteste-cheie + /cont/rar-creds scoped pe sesiune (C13), sectiune "Contul meu" cu cheie afisata o data. US-010: rol admin (users.is_admin) + require_admin->403 + CLI set-admin + bootstrap primul cont=admin (count_admins in BEGIN IMMEDIATE, anti-race). US-011: panou /admin (activare/dezactivare conturi, CSRF + PRG), link admin + logout pe dashboard. US-012: app/email.py notify_signup best-effort degradat fara SMTP + config smtp_*. Fix: migrare defensiva users.is_admin/email_verified in _migrate. VERIFY x2 context curat (PASS) + /code-review high. 393 teste pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# PRD 3.3 — Self-onboarding web (login email+parola → emite cheie)
|
||||
|
||||
**Stare**: verify-pass (3.3a) — 3.3b deschis
|
||||
**Stare**: inchis (3.3a + 3.3b livrate)
|
||||
|
||||
> **Decizii la poarta EXECUTE (2026-06-17, confirmate de utilizator):**
|
||||
> - **Livrabila sparta in doua faze** (scope 12 stories prea mare pentru un singur EXECUTE):
|
||||
@@ -479,3 +479,43 @@ izolare pe 2 conturi (`tests/test_mapari_scope.py`).
|
||||
Suita finala: **361 passed, 0 fail.** Findings low/by-design neactionate (documentate): dev-fallback cont 1
|
||||
cand `web_auth_required=False` (C12, intentionat — atentie ops la deploy prod), 500 rar la DB-locked in signup,
|
||||
`request.client is None` → bucket rate-limit 'unknown' partajat.
|
||||
|
||||
## Progres executie 3.3b (lead)
|
||||
|
||||
> Sub-livrabila 3.3b (self-service cheie/creds + admin web + email). Decizii confirmate la poarta:
|
||||
> primul cont care se inregistreaza devine admin (bootstrap automat); US-012 livrare DEGRADATA fara
|
||||
> SMTP (helper `app/email.py` best-effort no-op + log `SIGNUP` deja existent din 3.3a).
|
||||
|
||||
Valuri (fisiere disjuncte intre stories paralele):
|
||||
- **Val 1:** US-010 (`users.py`/`session.py`/`tools/account.py`/`main.py` handler) ‖ US-007 (`routes.py`/`_cont.html`/`dashboard.html`)
|
||||
- **Val 2:** US-011 (`admin_routes.py` nou/`admin.html`/`main.py` register) ‖ US-012 (`email.py` nou/`config.py`/`auth_routes.py`)
|
||||
|
||||
- [x] **US-010** — rol admin (`is_admin`) + helper-e (`count_admins`/`set_admin`/`is_account_admin`/`list_admin_emails`) + `require_admin`→`AdminRequired`→403 + CLI `set-admin`. 13 teste. Bootstrap (primul cont=admin) cablat in signup de US-012 (evita conflict pe auth_routes.py).
|
||||
- [x] **US-007** — sectiune "Contul meu" (`/_fragments/cont`): rotire cheie (afisata o data) + creds RAR pe ruta web proprie scoped pe sesiune (`POST /cont/roteste-cheie`, `POST /cont/rar-creds`, C13, NU endpointul API). 5 teste.
|
||||
- [x] **US-011** — panou `/admin` (`admin_routes.py`): conturi in asteptare/active + activare/dezactivare (require_admin + CSRF + PRG); contul dev id=1 fara butoane. Link "Panou admin" pe dashboard doar pentru admini + buton logout. 5 + 2 teste.
|
||||
- [x] **US-012** — `app/email.py` `notify_signup` best-effort (no-op fara `smtp_host`, prinde orice exceptie SMTP, timeout 5s) + config `smtp_*` + cablaj signup: bootstrap admin (primul cont = admin via `count_admins==0`) + notificare degradata dupa `set_session`. 5 teste.
|
||||
- [x] **Fix migrare (din VERIFY r1):** `_migrate` adauga defensiv `users.is_admin`/`email_verified` pe DB cu tabela `users` fara ele (idempotent, guard pe existenta tabelei). 2 teste.
|
||||
|
||||
## Raport VERIFY (3.3b)
|
||||
|
||||
> Doua runde de verificare independenta (subagent context curat, §5.6).
|
||||
|
||||
**Runda 1 — FAIL (1 criteriu):** suita 391 pass, toate criteriile US-007/010/011/012 confirmate + sweep
|
||||
securitate complet (toate rutele noi `/cont/*`, `/_fragments/cont`, `/admin*` sub `require_login`/`require_admin`
|
||||
+ `verify_csrf` pe POST; `/cont/*` scoped strict pe sesiune, nu accepta `account_id` din form; `/admin` nu
|
||||
expune hash/chei/creds in clar). DAR `_migrate` nu adauga defensiv `users.is_admin`/`email_verified` →
|
||||
o tabela `users` fara ele ar ceda cu `OperationalError` (acelasi tip de gap ca C1 pe `accounts.active`). → fix.
|
||||
|
||||
**Fix:** bloc `# Coloane users` in `app/db.py::_migrate` (guard pe existenta tabelei + ALTER idempotent). 2 teste.
|
||||
|
||||
**Runda 2 — PASS global (subagent NOU):**
|
||||
- Suita: **393 passed**, 0 fail.
|
||||
- Fix migrare confirmat (test pe `users` minima fara coloane → `_migrate` → coloane prezente; idempotent).
|
||||
- E2E mod prod (`web_auth_required=true`): `GET /admin` fara cookie → 303 `/login`; non-admin logat → 403;
|
||||
`POST /admin/activate` fara CSRF → 403. Rute `/cont/*` scoped pe sesiune, CSRF enforce, parola RAR niciodata in `value=`.
|
||||
- US-010 bootstrap (primul signup → `is_admin=1`, al doilea → 0), CLI `set-admin`, `require_admin`→403 confirmate.
|
||||
- US-012 `notify_signup` best-effort no-op fara SMTP + nu blocheaza signup + log `SIGNUP` pastrat.
|
||||
- Regresia de aur: `test_import_e2e` + `test_api` + `test_worker_active_gate` = 31 pass.
|
||||
|
||||
**Verdict: PASS.** Send live RAR ramane de confirmat manual la deploy (fara creds/retea in mediul VERIFY).
|
||||
La deploy prod: `AUTOPASS_session_secret` persistent, `AUTOPASS_WEB_AUTH_REQUIRED=true`, optional `AUTOPASS_smtp_*`.
|
||||
|
||||
Reference in New Issue
Block a user