Files
.github/company/agents/savannah-savings/playbooks/uat-playbook.md
T
Pawla Abdul 3032f2fc0e chore: sync company/ export snapshot with current configuration
- Removes rollback-rhonda (decommissioned agent)
- Adds deal-dottie agent files (AGENTS.md, mcp.json)
- Updates .paperclip.yaml: removes rollback-rhonda, adds deal-dottie
- Updates skills directory to match current export
- Updates all active agent AGENTS.md files and memory/life files

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-06 08:59:29 +00:00

24 KiB

CTO UAT Playbook — CartSnitch

Owner: Savannah Savings (CTO) Last updated: 2026-03-30 Purpose: Single source of truth for all UAT test knowledge. Rhonda never reads this file. CTO uses it to create atomic task descriptions.


1. Environment Reference

Item Value
Dev URL https://cartsnitch.dev.farh.net
Production URL https://cartsnitch.farh.netNEVER test here
Playwright MCP playwright at http://playwright:8931/mcp
Mobile viewport 375 x 812 (iPhone — mobile-first PWA)
Auth provider Authentik at https://auth.farh.net

2. Test Data

Item Value
Seed user email uat@cartsnitch.com
Seed user password CartSnitch-UAT-2026!
Registration email pattern uat+{timestamp}@cartsnitch.com
Registration password CartSnitch-UAT-2026! (meets strength requirements)
Registration display name UAT Test

3. User Journey Catalog

ID Area Key Checks Fragile?
J1 Playwright Connectivity browser_navigate to about:blank succeeds No
J2 Environment Health Dev loads, CartSnitch UI renders, no critical JS errors Yes
J3 Registration (happy path) Form renders, POST returns 2xx, redirect works Yes
J4 Registration (validation) Empty fields, bad email, weak password show errors Yes
J5 Registration (duplicate) Same email twice shows proper error, not crash Yes
J6 Login (new account) POST returns 2xx, session active, dashboard renders Yes
J7 Login (seed user) uat@cartsnitch.com works, API returns 2xx Yes
J8 Login (invalid creds) Wrong password/email shows error, not crash Yes
J9 Session Persistence Refresh page, still logged in Yes
J10 Forgot Password Form renders, submit shows confirmation, API 2xx No
J11 Dashboard Renders sections, no JS errors, mobile layout OK No
J12 Purchases List or empty state, API 2xx No
J13 Purchase Detail Detail page renders, API 2xx No
J14 Products Catalog or empty state, API 2xx No
J15 Product Detail Details render, price history visible No
J16 Store Comparison Comparison data renders No
J17 Coupons List or empty state, API 2xx No
J18 Alerts List or empty state, API 2xx No
J19 Settings Page renders, all tabs/sections work No
J20 Account Linking Page renders, interactive elements work No
J21 Logout Redirect to login or landing page No
J22 Access Control All protected routes redirect when logged out Yes
J23 Navigation Bottom nav works, back button works, no 404s No
J24 Console Error Audit Session-accumulated errors documented No

4. Journey Details

J1: Playwright Connectivity

Preconditions: None (first test always)

Steps:

  1. Call browser_navigate with url about:blank
  2. PASS: Page loads without error

If PASS: Proceed to J2. If FAIL: Block task. Comment: "Playwright MCP server unreachable — cannot perform UAT. Error: {exact error}." Assign to CTO with status todo.


J2: Environment Health

Preconditions: J1 passed

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net
  2. PASS: Page loads (no DNS failure, no timeout, no 5xx)
  3. Call browser_snapshot
  4. PASS: Page contains recognizable CartSnitch UI (navigation, header, or login form)
  5. Call browser_console_messages
  6. PASS: No critical JS errors (Uncaught TypeError, ChunkLoadError, React render errors)
  7. Call browser_take_screenshot

If PASS: Proceed to auth tests. If FAIL at step 2 (hard failure): Block task. Comment with exact error, URL, screenshot if partial load. Assign to CTO with status todo. If FAIL at step 4 (blank page): Take screenshot, capture console errors, block task. If FAIL at step 6 (JS errors but page loads): Note errors, continue testing, report as medium severity.


J3: Registration (happy path) [KNOWN FRAGILE]

Preconditions: J2 passed. Not logged in. 3 production escapes: CAR-126, CAR-128, CAR-147.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/register
  2. Call browser_resize with width 375, height 812
  3. Call browser_snapshot
  4. PASS: Registration form visible with name/display_name, email, and password fields
  5. Call browser_fill_form with: email = uat+{timestamp}@cartsnitch.com, password = CartSnitch-UAT-2026!, name/display_name = UAT Test
  6. Call browser_click on the submit/register button
  7. Call browser_network_requests
  8. PASS: POST to registration endpoint returned HTTP 2xx (not 4xx or 5xx)
  9. Call browser_snapshot
  10. PASS: User redirected to dashboard or login page, no error message visible
  11. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Registration happy path. API returned 2xx. Screenshot attached." Mark done. If FAIL at step 8 (API error): This is CRITICAL. Comment: "Registration API returned {status code}. Auth contract may be broken. See CAR-126/CAR-128/CAR-147 history." Assign to CTO with status todo. If FAIL at step 10 (visual): Comment with screenshot and what was expected vs actual. Assign to CTO with status todo.

Note for CTO (decomposition): Always record the email used so subsequent login tasks can reference it.


J4: Registration (validation errors)

Preconditions: J2 passed. On /register page.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/register
  2. Call browser_resize with width 375, height 812
  3. Call browser_click on submit button (empty fields)
  4. Call browser_snapshot
  5. PASS: Field-level error messages visible
  6. Call browser_fill_form with email = notanemail, password = x, name = T
  7. Call browser_click on submit button
  8. Call browser_snapshot
  9. PASS: Validation errors for malformed email and/or weak password
  10. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Registration validation errors display correctly." Mark done. If FAIL: Comment with which validation was missing and screenshot. Assign to CTO with status todo.


J5: Registration (duplicate email)

Preconditions: J3 passed (an account was created with a known email).

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/register
  2. Call browser_resize with width 375, height 812
  3. Call browser_fill_form with the SAME email used in J3, password = CartSnitch-UAT-2026!, name = Duplicate Test
  4. Call browser_click on submit button
  5. Call browser_network_requests
  6. PASS: API returned an error status (409 or 422 expected, not 500)
  7. Call browser_snapshot
  8. PASS: User-friendly error message about duplicate email (not a crash, not a generic "something went wrong")
  9. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Duplicate registration handled correctly." Mark done. If FAIL (500 or crash): CRITICAL. Comment with API response and screenshot. Assign to CTO with status todo.


J6: Login (new account) [KNOWN FRAGILE]

Preconditions: J3 passed (fresh account exists).

Steps:

  1. If logged in, navigate to logout first, then:
  2. Call browser_navigate to https://cartsnitch.dev.farh.net/login
  3. Call browser_resize with width 375, height 812
  4. Call browser_snapshot
  5. PASS: Login form visible with email and password fields
  6. Call browser_fill_form with email = (email from J3), password = CartSnitch-UAT-2026!
  7. Call browser_click on login/submit button
  8. Call browser_network_requests
  9. PASS: POST to login endpoint returned HTTP 2xx
  10. Call browser_snapshot
  11. PASS: Redirected to dashboard, authenticated state visible (user name/avatar, or logout button)
  12. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Login with new account. API returned 2xx. Dashboard loaded." Mark done. If FAIL at step 9 (API error): CRITICAL. Comment: "Login API returned {status}. Credentials were valid (account created in J3)." Assign to CTO with status todo.


J7: Login (seed user) [KNOWN FRAGILE]

Preconditions: J2 passed. Logged out.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/login
  2. Call browser_resize with width 375, height 812
  3. Call browser_fill_form with email = uat@cartsnitch.com, password = CartSnitch-UAT-2026!
  4. Call browser_click on login/submit button
  5. Call browser_network_requests
  6. PASS: POST to login endpoint returned HTTP 2xx
  7. Call browser_snapshot
  8. PASS: Dashboard renders, authenticated state visible
  9. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Seed user login. API returned 2xx." Mark done. If FAIL at step 6 (API error): HIGH. Seed user may not exist in dev. Comment: "Seed user login failed, API returned {status}." Assign to CTO with status todo.


J8: Login (invalid credentials)

Preconditions: J2 passed. Logged out.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/login
  2. Call browser_resize with width 375, height 812
  3. Call browser_fill_form with email = uat@cartsnitch.com, password = WrongPassword123!
  4. Call browser_click on login/submit button
  5. Call browser_snapshot
  6. PASS: Error message visible (not a crash, not a blank page, not a redirect to dashboard)
  7. Call browser_fill_form with email = nonexistent@cartsnitch.com, password = CartSnitch-UAT-2026!
  8. Call browser_click on login/submit button
  9. Call browser_snapshot
  10. PASS: Error message visible
  11. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Invalid login attempts show proper error messages." Mark done. If FAIL: Comment with what happened instead. Assign to CTO with status todo.


J9: Session Persistence

Preconditions: Logged in (from J6 or J7).

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/settings
  2. Call browser_snapshot
  3. PASS: Settings page renders (user is still authenticated)
  4. Call browser_navigate to https://cartsnitch.dev.farh.net/
  5. Call browser_snapshot
  6. PASS: Dashboard renders (still authenticated after navigation)
  7. Call browser_navigate to https://cartsnitch.dev.farh.net/ (page refresh)
  8. Call browser_snapshot
  9. PASS: Still authenticated after refresh (session persists)
  10. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Session persists across navigation and page refresh." Mark done. If FAIL (session lost): HIGH. Comment: "Session did not persist. After {step}, user was logged out." Assign to CTO with status todo.


J10: Forgot Password

Preconditions: J2 passed. On login page or can navigate there.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/forgot-password
  2. Call browser_resize with width 375, height 812
  3. Call browser_snapshot
  4. PASS: Forgot password form renders with email field
  5. Call browser_fill_form with email = uat@cartsnitch.com
  6. Call browser_click on submit button
  7. Call browser_network_requests
  8. PASS: API returned 2xx
  9. Call browser_snapshot
  10. PASS: Confirmation message visible (e.g., "Check your email")
  11. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Forgot password flow works. API returned 2xx." Mark done. If FAIL: Comment with which step failed. Assign to CTO with status todo.


J11: Dashboard

Preconditions: Logged in.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/
  2. Call browser_resize with width 375, height 812
  3. Call browser_snapshot
  4. PASS: Dashboard renders with expected sections (not blank, not error page)
  5. Call browser_console_messages
  6. PASS: No critical JS errors
  7. PASS: No horizontal overflow, no overlapping elements at 375px width
  8. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Dashboard renders correctly at mobile viewport." Mark done. If FAIL: Comment with what's broken and screenshot. Assign to CTO with status todo.


J12: Purchases Page

Preconditions: Logged in.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/purchases
  2. Call browser_resize with width 375, height 812
  3. Call browser_snapshot
  4. PASS: Purchase list or empty state renders
  5. Call browser_network_requests
  6. PASS: API call for purchases returned 2xx
  7. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Purchases page renders. API returned 2xx." Mark done. If FAIL: Comment with details. Assign to CTO with status todo.


J13: Purchase Detail

Preconditions: Logged in. J12 passed.

Steps:

  1. If purchases exist from J12, click into one. If no purchases exist, skip this journey.
  2. Call browser_snapshot
  3. PASS: Purchase detail page renders with receipt/order information
  4. Call browser_network_requests
  5. PASS: API returned 2xx
  6. Call browser_take_screenshot

If ALL PASS (or skipped due to no data): Comment: "UAT PASS — Purchase detail renders." or "SKIP — No purchases to test." Mark done. If FAIL: Comment with details. Assign to CTO with status todo.


J14: Products Page

Preconditions: Logged in.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/products
  2. Call browser_resize with width 375, height 812
  3. Call browser_snapshot
  4. PASS: Product catalog or empty state renders
  5. Call browser_network_requests
  6. PASS: API returned 2xx
  7. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Products page renders. API returned 2xx." Mark done. If FAIL: Comment with details. Assign to CTO with status todo.


J15: Product Detail

Preconditions: Logged in. J14 passed.

Steps:

  1. If products exist from J14, click into one. If no products, skip.
  2. Call browser_snapshot
  3. PASS: Product detail renders with price information
  4. Call browser_network_requests
  5. PASS: API returned 2xx
  6. Call browser_take_screenshot

If ALL PASS (or skipped): Comment accordingly. Mark done. If FAIL: Comment with details. Assign to CTO with status todo.


J16: Store Comparison

Preconditions: Logged in. Product exists.

Steps:

  1. If a "Compare" link or /compare/{productId} is accessible from J15, navigate there. If not, skip.
  2. Call browser_snapshot
  3. PASS: Comparison data renders
  4. Call browser_take_screenshot

If ALL PASS (or skipped): Comment accordingly. Mark done. If FAIL: Comment with details. Assign to CTO with status todo.


J17: Coupons Page

Preconditions: Logged in.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/coupons
  2. Call browser_resize with width 375, height 812
  3. Call browser_snapshot
  4. PASS: Coupon list or empty state renders
  5. Call browser_network_requests
  6. PASS: API returned 2xx
  7. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Coupons page renders. API returned 2xx." Mark done. If FAIL: Comment with details. Assign to CTO with status todo.


J18: Alerts Page

Preconditions: Logged in.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/alerts
  2. Call browser_resize with width 375, height 812
  3. Call browser_snapshot
  4. PASS: Alerts list or empty state renders
  5. Call browser_network_requests
  6. PASS: API returned 2xx
  7. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Alerts page renders. API returned 2xx." Mark done. If FAIL: Comment with details. Assign to CTO with status todo.


J19: Settings Page

Preconditions: Logged in.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/settings
  2. Call browser_resize with width 375, height 812
  3. Call browser_snapshot
  4. PASS: Settings page renders
  5. Click any visible tabs or sections
  6. Call browser_snapshot
  7. PASS: Tab/section content loads
  8. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Settings page renders, tabs work." Mark done. If FAIL: Comment with details. Assign to CTO with status todo.


J20: Account Linking Page

Preconditions: Logged in.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/account-linking
  2. Call browser_resize with width 375, height 812
  3. Call browser_snapshot
  4. PASS: Account linking page renders (store connection UI or empty state)
  5. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Account linking page renders." Mark done. If FAIL: Comment with details. Assign to CTO with status todo.


J21: Logout

Preconditions: Logged in.

Steps:

  1. Call browser_snapshot to identify logout button/link
  2. Call browser_click on the logout element
  3. Call browser_snapshot
  4. PASS: Redirected to login page or public landing page
  5. PASS: No authenticated UI elements visible
  6. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Logout works, redirected to login." Mark done. If FAIL: Comment with details. Assign to CTO with status todo.


J22: Access Control (Unauthenticated)

Preconditions: Logged out (J21 passed).

Protected routes to test:

  • /purchases
  • /products
  • /coupons
  • /alerts
  • /settings
  • /account-linking
  • / (dashboard/root)

Steps (repeat for each route):

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/{route}
  2. Call browser_snapshot
  3. PASS: Redirected to login page (not a blank page, not the actual protected content, not an error)

After all routes tested: 4. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — All protected routes redirect to login when unauthenticated." Mark done. If ANY route accessible without auth: HIGH severity. Comment: "Protected route /{route} is accessible without authentication." Assign to CTO with status todo.


J23: Navigation

Preconditions: Logged in.

Steps:

  1. Call browser_navigate to https://cartsnitch.dev.farh.net/
  2. Call browser_resize with width 375, height 812
  3. Call browser_snapshot to identify bottom nav / sidebar menu items
  4. Click each navigation item one by one
  5. After each click, call browser_snapshot
  6. PASS: Each target page loads (no 404, no blank page)
  7. Call browser_navigate_back several times
  8. Call browser_snapshot
  9. PASS: App state is consistent after back navigation (no broken state)
  10. Call browser_take_screenshot

If ALL PASS: Comment: "UAT PASS — Navigation works correctly at mobile viewport." Mark done. If FAIL: Comment with which nav item or back action failed. Assign to CTO with status todo.


J24: Console Error Audit

Preconditions: Last test — run after all other journeys.

Steps:

  1. Call browser_console_messages
  2. Review all accumulated errors from the session
  3. Document any: Uncaught errors, Failed to fetch, NetworkError, ChunkLoadError, React rendering errors
  4. PASS: No undocumented critical errors exist
  5. If >5 unique console errors across session: note as MEDIUM severity

If PASS: Comment: "UAT PASS — Console audit. {N} unique errors found: {summary}." Mark done. If new critical errors found: Comment with full list. Assign to CTO with status todo.


5. Known Fragile Areas

Area History Risk Extra Verification
Authentication (registration + login) 3 escapes: CAR-126 (basePath mismatch), CAR-128 (auth client config), CAR-147 (API contract mismatch) Silent API failures behind working UI Always check browser_network_requests for 2xx. A rendered form with a broken backend is a false positive.
Frontend/API contract CAR-147: frontend sent wrong field name, expected wrong response shape Fields renamed without frontend update After every form submission, verify the POST/PUT returned 2xx via browser_network_requests.
Dev environment availability CAR-127 (dev doesn't load), CAR-52 (CrashLoopBackOff) Pods not running, image pull failures Always run J1+J2 first. Never assume dev is healthy.
Auth service deployment CAR-39 (image doesn't exist), CAR-141 (wrong env var) Auth service up but misconfigured Verify login actually works at the API level, not just that the form renders.

6. Severity Definitions

Severity Definition Blocks UAT?
critical Core flow broken, app unusable. Login crashes, registration API returns 500, app won't load. Yes
high Major feature non-functional, security flaw. Protected routes accessible without auth, session doesn't persist, page shows wrong data. Yes
medium Feature degraded but usable. Slow load (>5s), unclear validation message, mobile layout broken, >5 console warnings. No (warning)
low Cosmetic. Typo, slight alignment, missing hover state. No (warning)

7. Defect Report Template

### Defect: {short description}
- **Severity:** critical | high | medium | low
- **Journey:** J{N} — {name}
- **Known Fragile Area:** yes/no
- **Steps to reproduce:**
  1. {step}
  2. {step}
- **Expected:** {what should happen}
- **Actual:** {what happened}
- **API response:** {status code from browser_network_requests, or N/A}
- **Console errors:** {from browser_console_messages, or none}
- **Screenshot:** attached

8. Decomposition Guide

Standard 5-Slot Pattern Per Deploy

Slot Subtask Source Journeys When
1 Playwright + environment readiness J1 + J2 Always first
2 Auth verification J3-J10 (subset based on scope) Always — auth is fragile
3 Feature-specific tests J{scope} based on PR Based on what changed
4 Navigation + access control smoke J21 + J22 + J23 Every deploy
5 Console error audit J24 Always last

Sizing

  • Small/targeted PR (e.g., auth fix, single page fix): 3-5 subtasks
  • Medium PR (e.g., new feature, multi-page change): 5-8 subtasks
  • Large PR (e.g., major refactor, auth overhaul): 8-12 subtasks
  • Full regression (major release, post-infra change): All 24 journeys as individual tasks

Scope-Based Journey Selection

Change Type Required Journeys
Auth service change J1-J10, J21-J22, J24
Frontend-only change J1-J2, J11-J20, J23-J24
Full deployment (both services) J1-J24 (all)
Infrastructure change J1-J2, J7, J11, J24 (health + smoke)
Single page fix (e.g., /coupons) J1-J2, J7, J{page}, J23-J24

Dependency Chains

  • J3 creates account used by J5, J6
  • J6 or J7 must pass before J9, J11-J20 (need authenticated session)
  • J21 must run before J22 (need logged-out state)
  • J24 is always last (aggregates session errors)

Parallelization

After auth (J3-J10) passes, page tests J11-J20 can run as independent parallel tasks (each logs in independently). J21-J23 should run sequentially after page tests.

Task Description Template

Every subtask CTO creates for Rhonda follows this format:

## What
{One sentence: specific test to run}

## Steps
1) Call `browser_navigate` to {url}
2) Call `browser_resize` with width 375, height 812
3) Call `browser_snapshot` — PASS: {what should be visible}
4) Call `browser_fill_form` with {exact fields and values}
5) Call `browser_click` on {exact element}
6) Call `browser_network_requests` — PASS: {endpoint} returned {expected status}
7) Call `browser_snapshot` — PASS: {expected visual state}
8) Call `browser_take_screenshot`

**If ALL PASS:** Mark issue done. Post comment: "UAT PASS — {journey name}. {key detail}. Screenshot attached."
**If ANY FAIL:** Set status todo. Assign to CTO (22731e25-f40f-48bd-a16e-28e1bbef5946). Post comment: "UAT FAIL — Step {N} failed. Expected: {X}. Actual: {Y}. Screenshot attached."

Rules for task descriptions:

  • Every step is a single Playwright MCP tool call
  • Inline PASS criteria after every verification step
  • Include exact field values, URLs, credentials
  • No references to external documents — task is fully self-contained
  • No conditional logic — if auth fails in a page test, just report the failure
  • No severity assessment — CTO determines severity from the report

9. Maturation Log

Track playbook changes here after each UAT cycle.

Date Change Reason
2026-03-30 Initial playbook created CAR-198: UAT overhaul