# QA personas — convention

This document describes how to run human QA against the live backend at
`https://nexx-api.srv.acebox.eu` without polluting the seeded `demo.*`
users.

## When to use which kind of user

| Scenario | Use |
|---|---|
| Existing-user login, JWT, session restore, company context | seeded `demo.buyer.admin@example.com` / `demo.supplier.admin@example.com` / `demo.both.admin@example.com` (password `demo-pass-123`) |
| Registration, email verification, password reset, invite-on-unregistered | register a fresh QA persona per the convention below |
| Anything that mutates demo company data | do not — open a fresh persona |

Seeded `demo.*` users were backfilled to `email_verified=true` by
migration 0012, so they pass the company-onboarding gate without going
through the verify flow. They are the right tool for any QA that is **not**
about the auth flow itself.

## Naming convention for fresh QA personas

Use this email shape so the agents and humans can recognize a QA persona at
a glance, and so cleanup can be done in one command later:

```
qa.<scenario>@<tester-controlled-domain>
```

Examples:

- `qa.register@<your-domain>` — first-time signup smoke
- `qa.invite@<your-domain>` — accept an invitation
- `qa.passwordreset@<your-domain>` — password reset flow
- `qa.unverified@<your-domain>` — drives the EMAIL_NOT_VERIFIED 403 paths

`<your-domain>` should be a real mailbox the tester controls so verification
and reset emails actually arrive. Anyone with `nexx-platform@acebox.eu`
SMTP delivery should reach normal mail providers; check spam on first run
since SPF/DKIM for `acebox.eu` is not yet tuned.

## Password

Use any strong password the tester remembers. `demo-pass-123` is reserved
for seeded users; do not reuse it for new QA personas to keep the two pools
distinct.

## What lives in prod DB right now (2026-05-18, after slices 1-5 smoke)

| id | email | state | source |
|---|---|---|---|
| 8 | smoke.stage1@example.com | verified | slice 1 smoke |
| 9 | alex@acebox.eu | unverified | slice 1 smoke (registered so Alex receives the verify email visually) |
| 10 | smoke.slice2@example.com | verified + MANAGER in Demo Buyer SIA | slice 2/5 smoke |
| 11 | smoke.slice3@example.com | verified, password reset to `new-pass-9999` | slice 3 smoke |
| 12 | smoke.slice4@example.com | verified, owns Smoke Slice4 SIA | slice 4 smoke |
| 13 | smoke.invitee@example.com | verified, MANAGER in Demo Buyer SIA via invite | slice 5 smoke |

Companies created by smoke:

- id=6 `Smoke Slice4 SIA` (owner user 12)
- id=7 `Demo Regression SIA` (owner demo.buyer.admin — slice 4 regression)

These are kept as disposable QA personas — Andrii can authenticate against
them and observe end-to-end behavior. They will be wiped by a one-off
cleanup when the pilot freezes the dataset.

## How to wipe everything `smoke.*` later

Wipe is a destructive prod operation and is intentionally **not** automated
in this repo. The shell snippet below is documentation, not a script —
run it deliberately:

```bash
ssh gabby@192.168.1.3 "cd /home/gabby/apps/nexx && \
  docker compose -f docker/docker-compose.yml exec -T nexx-app \
  python manage.py shell -c '
from django.contrib.auth import get_user_model
from core.models import Company
User = get_user_model()
User.objects.filter(email__startswith=\"smoke.\").delete()
User.objects.filter(email=\"alex@acebox.eu\").delete()
Company.objects.filter(name__in=[\"Smoke Slice4 SIA\",\"Demo Regression SIA\"]).delete()
'"
```

## How frontend QA tooling can list current personas

If smoke evidence tooling needs the list programmatically:

```http
GET /api/internal/v1/admin/logs/?path=auth/register/&statusMin=200&statusMax=299
Authorization: Bearer <any logged-in JWT>
```

Each 201 response logs the email in body_preview (post PII-redaction of
passwords / tokens / Authorization — the email itself is kept). Pre-pilot
the endpoint will be role-restricted, but for current QA this works.
