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.