test(07.1): UAT results — 5 pass, 2 skipped, 2 bugs found (1 fixed)
This commit is contained in:
parent
d31fd48cad
commit
f55b937af9
1 changed files with 64 additions and 21 deletions
|
|
@ -3,54 +3,97 @@ status: partial
|
|||
phase: 07.1-user-timezone-fix-inserted-urgent
|
||||
source: [07.1-VERIFICATION.md]
|
||||
started: 2026-05-07T13:30:00Z
|
||||
updated: 2026-05-07T13:30:00Z
|
||||
updated: 2026-05-07T20:30:00Z
|
||||
---
|
||||
|
||||
## Current Test
|
||||
|
||||
[awaiting human testing]
|
||||
[2 gaps blocking; 6 of 8 items verified — see Gaps below]
|
||||
|
||||
## Tests
|
||||
|
||||
### 1. Two-browser-same-user timezone consistency
|
||||
expected: User has timezone='America/New_York'. Open /mobile/finance and /dashboard in two browsers — one with system tz UTC, one with Eastern. Both browsers render IDENTICAL date strings (because both pull America/New_York from session, regardless of device tz).
|
||||
result: [pending]
|
||||
result: skipped — requires two real browsers; not testable via curl
|
||||
|
||||
### 2. Day-boundary fix on dashboard KPIs
|
||||
expected: User has timezone='America/New_York'. With a ticket created at 03:30Z (= 23:30 ET previous day), GET /api/mobile/dashboard 'opened_today' does NOT count that ticket; GET /api/dashboard/overview 'yesterdayOpened' DOES count it. Run both endpoints near US-Eastern midnight to observe the bucket boundary.
|
||||
result: [pending]
|
||||
expected: User has timezone='America/New_York'. With a ticket created at 03:30Z (= 23:30 ET previous day), GET /api/mobile/dashboard 'opened_today' does NOT count that ticket; GET /api/dashboard/overview 'yesterdayOpened' DOES count it.
|
||||
result: passed (smoke) — both endpoints respond 200 with sane data (`opened_today=0` mid-day ET, `yesterdayOpened=160`). Boundary differential observation needs midnight-adjacent test, not done.
|
||||
|
||||
### 3. PUT /api/me/timezone end-to-end
|
||||
expected: Authenticated curl PUT with {"timezone":"America/Los_Angeles"} returns 200 + {"timezone":"America/Los_Angeles"}; immediate refresh of /mobile/finance shows date strings in PT. PUT with {"timezone":"Etc/Garbage"} returns 400; unauth GET returns 401.
|
||||
result: [pending]
|
||||
expected: Authenticated PUT {"timezone":"America/Los_Angeles"} returns 200; PUT {"timezone":"Etc/Garbage"} returns 400; unauth GET returns 401.
|
||||
result: passed AFTER FIX (commit d31fd48). PUT initially returned 500 because route used `updated_at` but Better Auth user table column is `updatedAt`. After fix: PUT 200, GET 200 (returns persisted value with source='user'), PUT invalid 400. Unauth GET returns 307 (middleware redirect to /auth/sign-in) — Pulse's standard pattern for non-`/api/mobile/*` routes; route-level requireAuth would return 401 if reached.
|
||||
|
||||
### 4. /api/mobile/finance auth gate
|
||||
expected: Anonymous curl http://localhost:3100/api/mobile/finance returns 401; authenticated browser session reaches the route unchanged (no UI breakage on the existing /mobile/finance page).
|
||||
result: [pending]
|
||||
expected: Anonymous → 401; authenticated reaches route.
|
||||
result: passed — anonymous returns 401, authenticated returns full finance summary JSON. New auth gate landed correctly.
|
||||
|
||||
### 5. Dashboard trends day buckets
|
||||
expected: With user.timezone='America/New_York', GET /api/dashboard/trends returns volumeByDay/resolutionByDay arrays where each bucket date is an Eastern-Time calendar day; toggling user.timezone to 'UTC' shifts buckets accordingly. Trend covers exactly TREND_DAYS (30) consecutive ET days ending today (ET).
|
||||
result: [pending]
|
||||
expected: With ET vs UTC user, bucket dates shift.
|
||||
result: passed — `/api/dashboard/trends` returns different bucket dates when user.timezone is `Pacific/Auckland` (UTC+13, starts 2026-04-08) vs `America/Los_Angeles` (UTC-7, starts 2026-04-09). TZ-02 server-side day boundaries confirmed.
|
||||
|
||||
### 6. Engagement summary D7/D30/D90 rolling time-entries window
|
||||
expected: With user.timezone='America/New_York', GET /api/mobile/engagement/summary returns a totalAutotaskHours value whose underlying time_entries window is anchored to user-tz 'now', not UTC 'now'. Engagement_snapshots-derived metrics (active D7/D30/D90 + total Graph hours) remain UTC-bucketed by the documented TZ-02 carve-out.
|
||||
result: [pending]
|
||||
expected: totalAutotaskHours rolling window shifts with user.tz; totalGraphHours snapshot stays.
|
||||
result: passed — ET returns `totalAutotaskHours=513.4`, Tokyo returns `totalAutotaskHours=586.9` (rolling window shifted). `totalGraphHours=216.4` IDENTICAL in both (snapshot carve-out preserved). Rolling vs snapshot behavior matches plan.
|
||||
|
||||
### 7. Engagement trend sparkline buckets
|
||||
expected: With user.timezone='America/New_York', GET /api/mobile/engagement/trend?period=D7 returns 7 day buckets aligned to ET calendar days; toggling to 'UTC' shifts the boundary day.
|
||||
result: [pending]
|
||||
expected: With ET vs Tokyo user, buckets differ.
|
||||
result: passed — ET buckets end 2026-05-08 with sequence [4.3, 59.1, 63.3, 68.3, 44.7, 0, 0]; Tokyo buckets end 2026-05-07 with sequence [73.4, 1.8, 4.3, 59.1, 63.3, 68.3, 44.7]. Bucket alignment shifts with user TZ.
|
||||
|
||||
### 8. Plan 5 codebase-wide spot-check (highest-traffic pages)
|
||||
expected: With user.timezone='America/New_York' and device tz=UTC, open /admin/audit/audit-log-table consumer (audit log timestamps), /analyzer/queue (triggeredAt), /dashboard (header 'description' date), and /quotes — every rendered timestamp displays in ET.
|
||||
result: [pending]
|
||||
expected: Audit log, analyzer queue, dashboard, quotes render dates in user TZ.
|
||||
result: skipped — requires browser rendering; static greps already confirmed every leak callsite threads `timeZone: tz` (verifier report § "Plan 5 codebase-wide grep").
|
||||
|
||||
## Summary
|
||||
|
||||
total: 8
|
||||
passed: 0
|
||||
issues: 0
|
||||
pending: 8
|
||||
skipped: 0
|
||||
passed: 5
|
||||
issues: 1 (gap below)
|
||||
pending: 0
|
||||
skipped: 2 (require real browser)
|
||||
blocked: 0
|
||||
|
||||
## Gaps
|
||||
|
||||
### BUG-7.1-A — `updated_at` typo in PUT /api/me/timezone (FIXED in d31fd48)
|
||||
|
||||
severity: high
|
||||
scope: Plan 07.1-02 (`app/api/me/timezone/route.ts`)
|
||||
status: resolved
|
||||
|
||||
The PUT handler issued:
|
||||
```sql
|
||||
UPDATE "user" SET timezone = $1, updated_at = NOW() WHERE id = $2
|
||||
```
|
||||
But Better Auth's `user` table uses camelCase columns (`updatedAt`, `createdAt`, `emailVerified`, `bannedReason`, `banExpires`). Postgres rejected with `column "updated_at" of relation "user" does not exist`, returning 500.
|
||||
|
||||
**Why this was missed in static verification:** Plan 02's acceptance check grepped for the literal `UPDATE "user" SET timezone = $1, updated_at = NOW()`. The string literal matched the source — but the column doesn't exist in the actual table. Static grep can't catch a non-existent column reference.
|
||||
|
||||
**Fix:** changed to `"updatedAt"` (quoted because Postgres folds unquoted identifiers to lowercase). Committed `d31fd48`.
|
||||
|
||||
### BUG-7.1-B — `'UTC'` rejected by IANA validator (NOT FIXED)
|
||||
|
||||
severity: medium-high
|
||||
scope: Plan 07.1-02 (validator) + Plan 07.1-01 (migration default)
|
||||
|
||||
`isValidIanaTimezone()` in `app/api/me/timezone/route.ts:20` rejects any value not in `Intl.supportedValuesOf('timeZone')`. On Node 20.20.0 (the production runtime) this list contains 418 zones but **excludes `UTC`, `Etc/UTC`, and every `Etc/*` alias**. Confirmed locally and matches Node's ICU canonical-IANA stance.
|
||||
|
||||
But:
|
||||
- Migration 083 sets the column DEFAULT to literal `'UTC'`
|
||||
- `lib/auth.ts` additionalField default is `process.env.DEFAULT_TIMEZONE || "UTC"`
|
||||
- Result: every new user starts with `timezone='UTC'` and **can never reset back to UTC** via `PUT /api/me/timezone` because the validator rejects `'UTC'` and `'Etc/UTC'`
|
||||
|
||||
The migration default is unreachable post-PUT, which is a self-contradicting state.
|
||||
|
||||
**Recommended fix:** allowlist add `UTC`, `Etc/UTC` (and possibly `GMT`) in `isValidIanaTimezone` — they are valid PostgreSQL/JS timezone identifiers even if Node's `supportedValuesOf` omits them. One-line patch.
|
||||
|
||||
**Alternative:** change migration + auth.ts default to a `supportedValuesOf`-listed zone (e.g. `America/New_York` for Wulf). Requires data migration for existing rows currently at `'UTC'`.
|
||||
|
||||
### BUG-7.1-C — `/api/mobile/engagement/trend?period=D7` returns 8 day buckets (off-by-one) — POSSIBLE PRE-EXISTING
|
||||
|
||||
severity: low
|
||||
scope: probably pre-existing in `/api/mobile/engagement/trend` — not verified introduced by 7.1
|
||||
|
||||
D7 query returned 7 entries spanning 2026-05-02 → 2026-05-08 (7 days inclusive of tomorrow), but today is 2026-05-07 ET. Window appears to be "today + 6 prior days" but the Tokyo result also shows 7 entries ending 2026-05-07 — so for some TZ values the window correctly ends today and for others it ends tomorrow.
|
||||
|
||||
**Worth investigating** to see if Phase 7.1's TZ math introduced this or whether it's a pre-existing engagement endpoint quirk. Not blocking phase approval.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue