D3 Demo Script - AY2627S1-CS3219-P23/foc GitHub Wiki

D3 Demo Script β€” curl walkthrough (skeleton)

Proves Order + Credit work without the UI and that identity-and-relationship rules are backend-enforced. Same conventions as the D2 script: run top to bottom, every call prints its HTTP status, stop the web container first.

✍️ Skeleton β€” request bodies below are the proposed contracts from the D3 design page (Part 1 Β§4). Fill in real paths/DTOs as the endpoints merge; delete this callout when the script runs end-to-end.

docker compose stop web        # backends keep running

Prereqs: stack up (docker compose up -d --build), .env set. Port variables below follow the AGENTS.md port-claiming convention β€” fill in the ports order/credit claim.

#!/usr/bin/env bash
set -euo pipefail

USERS=http://localhost:8087
ORDERS=http://localhost:TODO_ORDER_PORT
CREDITS=http://localhost:TODO_CREDIT_PORT

j() { curl -s -w '\n%{http_code}\n' -H 'Content-Type: application/json' "$@"; }
# token() helper as in the D2 script; REQ_T = requester, COU_T = courier, ADM_T = admin

### 1. Sign-up β†’ provision (P2): new user's balance = initial allocation, reserved 0
# j -H "Authorization: Bearer $REQ_T" "$CREDITS/credits/me"

### 2. Idempotent provisioning (P2): repeat the internal provision call for the same userId β†’ recorded outcome, no double allocation

### 3. Create request (P1/P2): reserve on create; balance moves available→reserved
# j -X POST "$ORDERS/requests" -H "Authorization: Bearer $REQ_T" \
#   -d '{"supplierId":1,"dropoffLocation":"COM3-01-19","item":"...","creditAmount":3,"deadline":"..."}'

### 4. Insufficient balance (P2): creditAmount > available β†’ 422, request NOT created

### 5. Self-accept blocked (P1 authz): requester's own token on accept β†’ 403

### 6. Single-winner accept (P1 concurrency): two tokens accept in parallel β†’ one 200, one 409
# (parallel curl with & and wait, print both statuses)

### 7. Unrelated user mutation blocked (P1 authz): third token on collect/complete β†’ 403

### 8. Happy path: accept β†’ collect β†’ arrive β†’ complete; balances before/after (reserve β†’ transfer to courier)

### 9. Duplicate completion (P1/P2): repeat complete β†’ recorded outcome, one payment (NFR2.2.1)

### 10. Cancel + release (P2): new request, requester cancels from CREATED β†’ reserved returns to available

### 11. Courier withdraw (P1): accept then courier cancel β†’ back to CREATED, relisted, reservation still held

### 12. Async workflow (P3): watch the notification on the second browser/STOMP client ≀5 s;
###     then in RabbitMQ mgmt UI (localhost:15672) publish a fixture event twice β†’ deduped;
###     publish malformed body β†’ DLQ on first rejection

### 13. Expiry (P1): request with near deadline β†’ EXPIRED + release (mechanism per the decided option)

### 14. Admin view (P1): GET /users/{id}/requests with ADM_T β†’ 200; with USER token β†’ 403

Afterwards: docker compose start web, repeat the flow in the UI at desktop and mobile widths; docker compose stop order-db mid-demo shows healthcheck + recovery (P4).

Notes

  • Steps 3–14 bodies are the proposed contract β€” align with the implementation when the endpoints land.
  • Keep the D2 script's Mailpit trick for any OTP step.
  • RabbitMQ fixture payloads: copy from foc-contracts/src/main/resources/contracts/*.example.json.