| | 1 | = Use-case 0002 — Log in = |
| | 2 | |
| | 3 | '''Initiating actor:''' Visitor |
| | 4 | |
| | 5 | '''Other actors:''' — |
| | 6 | |
| | 7 | A registered user authenticates so the system can treat subsequent actions as a Trader. |
| | 8 | |
| | 9 | == Scenario == |
| | 10 | |
| | 11 | 1. Visitor chooses "Login" from the anonymous menu. |
| | 12 | 2. System prompts for username and password. |
| | 13 | 3. Visitor enters values. |
| | 14 | 4. System looks up the user: |
| | 15 | |
| | 16 | {{{ |
| | 17 | SELECT id, password_hash |
| | 18 | FROM project.users |
| | 19 | WHERE username = $1; |
| | 20 | }}} |
| | 21 | |
| | 22 | 5. If no row is returned, system responds "Invalid credentials." and scenario ends. |
| | 23 | 6. If a row is returned, system compares the stored hash against sha256 of the entered password. On mismatch it responds "Invalid credentials." and ends. |
| | 24 | 7. On match, system records the returned `id` and username in the session and displays the authenticated menu. |
| | 25 | |
| | 26 | === Alternate flow 4a — authenticated lookup with live balance === |
| | 27 | |
| | 28 | The system may combine identity lookup with live balance in a single query, for use cases that need both: |
| | 29 | |
| | 30 | {{{ |
| | 31 | SELECT id, available_balance, invested_balance |
| | 32 | FROM project.users |
| | 33 | WHERE username = $1 |
| | 34 | AND password_hash = encode(digest($2, 'sha256'), 'hex'); |
| | 35 | }}} |