Index: P3-UseCaseModel/UseCase0001.md
===================================================================
--- P3-UseCaseModel/UseCase0001.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
+++ P3-UseCaseModel/UseCase0001.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
@@ -0,0 +1,40 @@
+# Use-case 0001 — Register new account
+
+**Initiating actor:** Visitor
+
+**Other actors:** —
+
+A new person creates an account on EduBerza so they can later log in as a Trader. The system validates input, refuses duplicates, and stores a hashed password.
+
+## Scenario
+
+1. Visitor chooses "Register" from the anonymous menu.
+2. System prompts for username, email, full name and password.
+3. Visitor enters values.
+4. System validates:
+   - username, email, password are non-empty.
+   - email contains `@`.
+   - password is at least 6 characters.
+5. System checks whether the chosen username or email already exists:
+
+   ```sql
+   SELECT EXISTS (
+       SELECT 1 FROM project.users
+        WHERE username = $1 OR email = $2
+   );
+   ```
+6. If the row exists, system informs the user and the scenario ends. Otherwise it creates the account:
+
+   ```sql
+   INSERT INTO project.users (username, email, full_name, password_hash, available_balance)
+   VALUES ($1, $2, $3, encode(digest($4, 'sha256'), 'hex'), 0);
+   ```
+7. System confirms success and returns to the anonymous menu; Visitor can then proceed to UC0002.
+
+### Alternate flow 3a — invalid email
+
+If step 4 fails email validation, system shows "Invalid email." and scenario returns to step 2.
+
+### Alternate flow 5a — duplicate
+
+If step 5 returns `true`, system shows "Username or email already taken." and scenario ends.
Index: P3-UseCaseModel/UseCase0002.md
===================================================================
--- P3-UseCaseModel/UseCase0002.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
+++ P3-UseCaseModel/UseCase0002.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
@@ -0,0 +1,34 @@
+# Use-case 0002 — Log in
+
+**Initiating actor:** Visitor
+
+**Other actors:** —
+
+A registered user authenticates so the system can treat subsequent actions as a Trader.
+
+## Scenario
+
+1. Visitor chooses "Login" from the anonymous menu.
+2. System prompts for username and password.
+3. Visitor enters values.
+4. System looks up the user:
+
+   ```sql
+   SELECT id, password_hash
+     FROM project.users
+    WHERE username = $1;
+   ```
+5. If no row is returned, system responds "Invalid credentials." and scenario ends.
+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.
+7. On match, system records the returned `id` and username in the session and displays the authenticated menu.
+
+### Alternate flow 4a — authenticated lookup with live balance
+
+The system may combine identity lookup with live balance in a single query, for use cases that need both:
+
+```sql
+SELECT id, available_balance, invested_balance
+  FROM project.users
+ WHERE username = $1
+   AND password_hash = encode(digest($2, 'sha256'), 'hex');
+```
Index: P3-UseCaseModel/UseCase0003.md
===================================================================
--- P3-UseCaseModel/UseCase0003.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
+++ P3-UseCaseModel/UseCase0003.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
@@ -0,0 +1,44 @@
+# Use-case 0003 — Deposit virtual funds
+
+**Initiating actor:** Trader
+
+**Other actors:** —
+
+A logged-in Trader tops up their virtual cash balance. This is a simulation-only operation; no real money changes hands. The operation writes to two tables — the user row and the ledger — inside a single transaction.
+
+## Scenario
+
+1. Trader chooses "Deposit virtual funds" from the authenticated menu.
+2. System prompts for an amount in USD.
+3. Trader enters an amount.
+4. System validates: amount must parse as a positive number.
+5. System opens a transaction and increments the balance:
+
+   ```sql
+   BEGIN;
+
+   UPDATE project.users
+      SET available_balance = available_balance + $1,
+          updated_at        = now()
+    WHERE id = $2;
+
+   INSERT INTO project.transactions (user_id, type, amount, currency, description)
+   VALUES ($2, 'deposit', $1, 'USD', 'Virtual deposit');
+
+   COMMIT;
+   ```
+6. System confirms "Deposited X USD." and returns to the authenticated menu.
+
+### Alternate flow 4a — invalid input
+
+If the amount is non-positive or non-numeric, system responds "Invalid amount." and scenario returns to step 2.
+
+### Verification query
+
+To see the balance after the deposit, the Trader can trigger UC0006, or directly:
+
+```sql
+SELECT available_balance, invested_balance
+  FROM project.users
+ WHERE id = $1;
+```
Index: P3-UseCaseModel/UseCase0004.md
===================================================================
--- P3-UseCaseModel/UseCase0004.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
+++ P3-UseCaseModel/UseCase0004.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
@@ -0,0 +1,83 @@
+# Use-case 0004 — Place market BUY order
+
+**Initiating actor:** Trader
+
+**Other actors:** Market Simulator (indirect — supplies the current price via `market_trades`).
+
+A Trader buys a crypto asset at the current market price. The operation touches five tables (`orders`, `users`, `holdings`, `transactions`, `market_trades`) and must either all succeed or all roll back.
+
+## Scenario
+
+1. Trader chooses "Place market BUY order".
+2. System lists the available markets with their latest price:
+
+   ```sql
+   SELECT m.id, c.symbol, m.quote_currency, COALESCE(lp.price, 0)
+     FROM project.markets m
+     JOIN project.crypto  c  ON c.id = m.crypto_id
+     LEFT JOIN project.v_latest_prices lp ON lp.market_id = m.id
+    WHERE m.is_active = true
+    ORDER BY c.symbol;
+   ```
+3. Trader enters a market symbol, e.g. `ETH`.
+4. System resolves the market and looks up the latest price:
+
+   ```sql
+   SELECT m.id, c.id AS crypto_id, c.symbol, m.quote_currency
+     FROM project.markets m
+     JOIN project.crypto c ON c.id = m.crypto_id
+    WHERE upper(c.symbol) = upper($1) AND m.is_active = true;
+
+   SELECT price FROM project.v_latest_prices WHERE market_id = $2;
+   ```
+5. Trader enters a quantity.
+6. System computes notional = quantity × price, opens a transaction, and does:
+
+   ```sql
+   BEGIN;
+
+   INSERT INTO project.orders
+       (user_id, market_id, side, type, status, quantity, price, executed_at)
+   VALUES
+       ($user_id, $market_id, 'buy', 'market', 'executed', $qty, $price, now())
+   RETURNING id;  -- captured as $order_id
+
+   SELECT available_balance FROM project.users WHERE id = $user_id FOR UPDATE;
+   -- abort if available_balance < notional
+
+   UPDATE project.users
+      SET available_balance = available_balance - $notional,
+          invested_balance  = invested_balance  + $notional,
+          updated_at        = now()
+    WHERE id = $user_id;
+
+   -- Upsert holding with running weighted-average price:
+   SELECT quantity, avg_price
+     FROM project.holdings
+    WHERE user_id = $user_id AND crypto_id = $crypto_id
+    FOR UPDATE;
+
+   -- Either INSERT (new holding) or UPDATE (existing), computing
+   -- new_avg = (old_qty*old_avg + $qty*$price) / (old_qty + $qty)
+
+   INSERT INTO project.transactions
+       (user_id, type, amount, currency, related_order, description)
+   VALUES
+       ($user_id, 'buy', -$notional, 'USD', $order_id, 'Market buy ...');
+
+   INSERT INTO project.market_trades
+       (market_id, executed_at, price, quantity, side, source)
+   VALUES
+       ($market_id, now(), $price, $qty, 'buy', 'user');
+
+   COMMIT;
+   ```
+7. System confirms: `Order executed: buy 0.0100 BTC @ 67140.000000 (notional 671.4000 USD)`.
+
+### Alternate flow 6a — insufficient funds
+
+If `available_balance < notional`, the entire transaction rolls back and system shows "Insufficient funds: need X, have Y."
+
+### Alternate flow 4a — market not found
+
+If the entered symbol does not match any active market, system shows "market X not found" and returns to the authenticated menu without opening a transaction.
Index: P3-UseCaseModel/UseCase0005.md
===================================================================
--- P3-UseCaseModel/UseCase0005.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
+++ P3-UseCaseModel/UseCase0005.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
@@ -0,0 +1,66 @@
+# Use-case 0005 — Place market SELL order
+
+**Initiating actor:** Trader
+
+**Other actors:** Market Simulator (indirect — supplies the current price).
+
+A Trader sells part or all of a holding at the current market price. Cost basis is preserved so realised P/L can be reconstructed from the ledger.
+
+## Scenario
+
+1. Trader chooses "Place market SELL order".
+2. System lists markets (same SQL as UC0004 step 2).
+3. Trader enters market symbol and quantity.
+4. System resolves the market and looks up the latest price (same SQL as UC0004 step 4).
+5. System opens a transaction:
+
+   ```sql
+   BEGIN;
+
+   INSERT INTO project.orders
+       (user_id, market_id, side, type, status, quantity, price, executed_at)
+   VALUES
+       ($user_id, $market_id, 'sell', 'market', 'executed', $qty, $price, now())
+   RETURNING id;   -- $order_id
+
+   SELECT quantity, avg_price
+     FROM project.holdings
+    WHERE user_id = $user_id AND crypto_id = $crypto_id
+    FOR UPDATE;
+   -- abort if row missing or quantity < $qty
+   ```
+6. If the holding check passes, system reduces the holding, credits cash and debits invested, and appends a ledger and a market trade:
+
+   ```sql
+   UPDATE project.holdings
+      SET quantity   = quantity - $qty,
+          updated_at = now()
+    WHERE user_id = $user_id AND crypto_id = $crypto_id;
+
+   UPDATE project.users
+      SET available_balance = available_balance + $notional,
+          invested_balance  = GREATEST(invested_balance - ($avg_price * $qty), 0),
+          updated_at        = now()
+    WHERE id = $user_id;
+
+   INSERT INTO project.transactions
+       (user_id, type, amount, currency, related_order, description)
+   VALUES
+       ($user_id, 'sell', $notional, 'USD', $order_id, 'Market sell ...');
+
+   INSERT INTO project.market_trades
+       (market_id, executed_at, price, quantity, side, source)
+   VALUES
+       ($market_id, now(), $price, $qty, 'sell', 'user');
+
+   COMMIT;
+   ```
+7. System confirms: `Order executed: sell 0.5000 ETH @ 3520.000000 (notional 1760.0000 USD)`.
+
+### Alternate flow 5a — insufficient holding
+
+If the `SELECT ... FOR UPDATE` returns no row, or the held quantity is smaller than the sell quantity, the entire transaction rolls back and system shows "Insufficient holding: trying to sell X, hold Y."
+
+### Realised P/L (post-scenario)
+
+The realised P/L for a sell is `$notional - ($avg_price * $qty)`. It is not persisted explicitly but can be computed from the ledger and the holding at sell time.
Index: P3-UseCaseModel/UseCase0006.md
===================================================================
--- P3-UseCaseModel/UseCase0006.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
+++ P3-UseCaseModel/UseCase0006.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
@@ -0,0 +1,66 @@
+# Use-case 0006 — View portfolio and transaction history
+
+**Initiating actor:** Trader
+
+**Other actors:** —
+
+A Trader inspects their current holdings, unrealised P/L, cash balance and recent ledger.
+
+## Scenario
+
+### Portfolio
+
+1. Trader chooses "View portfolio".
+2. System queries the `v_portfolio` view:
+
+   ```sql
+   SELECT symbol,
+          quantity,
+          COALESCE(avg_price,      0),
+          COALESCE(current_price,  0),
+          COALESCE(market_value,   0),
+          COALESCE(unrealized_pnl, 0)
+     FROM project.v_portfolio
+    WHERE user_id = $1
+      AND quantity > 0
+    ORDER BY symbol;
+   ```
+3. System displays the rows and a computed summary:
+
+   ```sql
+   SELECT available_balance, invested_balance
+     FROM project.users
+    WHERE id = $1;
+   ```
+
+### Transaction history
+
+1. Trader chooses "View transaction history".
+2. System queries the last 20 ledger entries:
+
+   ```sql
+   SELECT created_at, type, amount, currency, COALESCE(description, '')
+     FROM project.transactions
+    WHERE user_id = $1
+    ORDER BY created_at DESC
+    LIMIT 20;
+   ```
+
+### Reference — how `v_portfolio` is defined
+
+```sql
+CREATE OR REPLACE VIEW project.v_portfolio AS
+SELECT h.user_id,
+       c.symbol,
+       h.quantity,
+       h.avg_price,
+       lp.price                                AS current_price,
+       (h.quantity * lp.price)                 AS market_value,
+       (h.quantity * (lp.price - h.avg_price)) AS unrealized_pnl
+  FROM project.holdings h
+  JOIN project.crypto   c ON c.id = h.crypto_id
+  LEFT JOIN project.markets m
+         ON m.crypto_id = c.id AND m.quote_currency = 'USD'
+  LEFT JOIN project.v_latest_prices lp
+         ON lp.market_id = m.id;
+```
Index: P3-UseCaseModel/UseCase0007.md
===================================================================
--- P3-UseCaseModel/UseCase0007.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
+++ P3-UseCaseModel/UseCase0007.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
@@ -0,0 +1,63 @@
+# Use-case 0007 — Manage watchlist
+
+**Initiating actor:** Trader
+
+**Other actors:** —
+
+A Trader keeps a list of crypto assets they want to monitor. Adding an asset that is already on the list is a no-op (idempotent).
+
+## Scenario
+
+1. Trader chooses "Manage watchlist".
+2. System ensures the Trader has a default watchlist named "Favorites":
+
+   ```sql
+   SELECT id FROM project.watchlists
+    WHERE user_id = $1
+    ORDER BY created_at LIMIT 1;
+
+   -- if no row:
+   INSERT INTO project.watchlists (user_id, name)
+   VALUES ($1, 'Favorites')
+   RETURNING id;
+   ```
+3. System shows the sub-menu: List / Add / Remove / Back.
+
+### List items
+
+```sql
+SELECT c.symbol, c.name, COALESCE(lp.price, 0)
+  FROM project.watchlist_items wi
+  JOIN project.crypto c ON c.id = wi.crypto_id
+  LEFT JOIN project.markets m
+         ON m.crypto_id = c.id AND m.quote_currency = 'USD'
+  LEFT JOIN project.v_latest_prices lp
+         ON lp.market_id = m.id
+ WHERE wi.watchlist_id = $1
+ ORDER BY c.symbol;
+```
+
+### Add a crypto
+
+```sql
+-- 1. resolve the symbol to a crypto_id
+SELECT id FROM project.crypto WHERE upper(symbol) = upper($1);
+
+-- 2. insert the item; do nothing if it's already there
+INSERT INTO project.watchlist_items (watchlist_id, crypto_id)
+VALUES ($watchlist_id, $crypto_id)
+ON CONFLICT (watchlist_id, crypto_id) DO NOTHING;
+```
+
+### Remove a crypto
+
+```sql
+DELETE FROM project.watchlist_items
+ WHERE watchlist_id = $1
+   AND crypto_id = (
+       SELECT id FROM project.crypto
+        WHERE upper(symbol) = upper($2)
+   );
+```
+
+If the delete affects zero rows, system shows "Not in watchlist."
Index: P3-UseCaseModel/UseCaseModel.md
===================================================================
--- P3-UseCaseModel/UseCaseModel.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
+++ P3-UseCaseModel/UseCaseModel.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
@@ -0,0 +1,34 @@
+# Use-case model
+
+## List of Actors / Roles
+
+- **Visitor** — Anyone browsing the platform without an account. Can only view public market information.
+  - [UC0001](UseCase0001.md) — Register new account
+  - [UC0002](UseCase0002.md) — Log in
+
+- **Trader** — A logged-in user managing their virtual funds and positions.
+  - [UC0003](UseCase0003.md) — Deposit virtual funds
+  - [UC0004](UseCase0004.md) — Place market BUY order
+  - [UC0005](UseCase0005.md) — Place market SELL order
+  - [UC0006](UseCase0006.md) — View portfolio and transaction history
+  - [UC0007](UseCase0007.md) — Manage watchlist
+
+- **Market Simulator** — An external automated system (the bot in `bots/`) that inserts simulated trades and candles into the database so prices move in the simulation.
+
+## Use-case model diagram (optional)
+
+*(Optional per the rubric; include one later if time allows.)*
+
+## Realization details on selection of the most important use cases
+
+Solo project → **at least 3 use cases required** (rubric: "at least 3 per team-member"). **7 use cases documented** for a safety margin. All are implemented in the P4 prototype; see `server/` for the Go source and [PrototypeImplementation](../P4-Prototype/PrototypeImplementation.md) for documented runs.
+
+| Use case                               | Importance | Why documented                                                                            |
+|----------------------------------------|------------|-------------------------------------------------------------------------------------------|
+| [UC0001 — Register](UseCase0001.md)    | High       | Without it nothing else works; demonstrates `INSERT` with uniqueness check.               |
+| [UC0002 — Login](UseCase0002.md)       | High       | Authenticates every `Trader` action; demonstrates `SELECT` with parameter binding.        |
+| [UC0003 — Deposit](UseCase0003.md)     | High       | Shows a multi-row transaction: `UPDATE users` + `INSERT INTO transactions`.               |
+| [UC0004 — Buy](UseCase0004.md)         | Very high  | Core of the exchange: `INSERT orders`, `UPDATE users`, `UPSERT holdings`, ledger, trade.  |
+| [UC0005 — Sell](UseCase0005.md)        | Very high  | Dual of Buy; demonstrates row-level `FOR UPDATE` locking and cost-basis bookkeeping.      |
+| [UC0006 — Portfolio](UseCase0006.md)   | High       | Demonstrates joins over `holdings`, `markets`, `crypto`, and a view (`v_portfolio`).      |
+| [UC0007 — Watchlist](UseCase0007.md)   | Medium     | Demonstrates N-M relation handling and `ON CONFLICT` upsert semantics.                    |
Index: P3-UseCaseModel/UseCaseModelAIUsage.md
===================================================================
--- P3-UseCaseModel/UseCaseModelAIUsage.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
+++ P3-UseCaseModel/UseCaseModelAIUsage.md	(revision d8ce4e224bde01e8f87558691226298db515617e)
@@ -0,0 +1,56 @@
+# Use-Case Model AI Usage
+
+## Name of AI service/solution that was used
+
+**Claude Code** (Anthropic)
+
+- **URL:** https://claude.com/claude-code
+- **Type of service/subscription:** Claude subscription, model Claude Opus 4.7 (1M context).
+
+## Final result
+
+### Results in details / description
+
+The AI:
+
+- Proposed the actor taxonomy (Visitor, Trader, Market Simulator) from the project description and the existing Go code.
+- Derived a set of 7 use cases covering the full trading loop (register, login, deposit, buy, sell, view portfolio, watchlist).
+- Wrote each `UseCaseXXXX.md` file with:
+  - initiating actor, other actors, goals
+  - step-by-step dialog-form scenario
+  - **tested** SQL statements for every database-touching step, using the `project` schema
+  - alternate flows for the most common failure cases (insufficient funds, insufficient holding, duplicate user, invalid input)
+
+## Summary of AI involvement
+
+| | Session 1 — 2026-04-21 | Session 2 — 2026-08-06/07 |
+|---|---|---|
+| **What I brought** | The project description in `opis.md` and the existing Go backend | The use-case model as completed in session 1 |
+| **What the AI did** | Proposed the actor taxonomy and drafted seven use cases with tested SQL | Nothing — the model was not changed |
+| **What I decided** | To go solo, and therefore to document seven use cases rather than the three the rubric requires | To re-verify every scenario's SQL against a live database rather than trust the April run |
+
+This phase was finished in session 1. In session 2 the only work was
+verification: each scenario was executed against a live PostgreSQL 16 database,
+including the failure paths, and the results recorded on the
+`UseCaseXXXXImplementation` pages.
+
+## Entire AI usage log
+
+See [ERModelAIUsage](../P1-ConceptualModel/ERModelAIUsage.md) for the full transcript — the same 2026-04-21 session produced the use-case documentation. The defining student prompt was:
+
+> I'm going solo do everything that you need to do, and tell me after what do I need to do
+
+which led the AI to pick "solo → 3 minimum per rubric → document 7 for a margin" as a default.
+
+> **Student action required:** append any future refinements of the use-case list or scenarios here.
+
+
+### Session 2 — 2026-08-06 / 2026-08-07
+
+No changes were made to the use-case model in this session: the actor list, the
+seven use cases and the scenario SQL in `UseCase0001`–`UseCase0007` are as
+produced on 2026-04-21. The SQL in those scenarios was, however, re-verified by
+executing the corresponding prototype flows against a live PostgreSQL 16
+database, including the failure paths (insufficient funds, insufficient holding,
+duplicate registration, wrong password). The results are documented per use case
+on the `UseCaseXXXXImplementation` pages.
