diff --git a/.planning/phases/09-user-profile-preferences-new/09-HUMAN-UAT.md b/.planning/phases/09-user-profile-preferences-new/09-HUMAN-UAT.md index e088e34..81f5231 100644 --- a/.planning/phases/09-user-profile-preferences-new/09-HUMAN-UAT.md +++ b/.planning/phases/09-user-profile-preferences-new/09-HUMAN-UAT.md @@ -1,60 +1,93 @@ --- -status: partial +status: diagnosed phase: 09-user-profile-preferences-new source: [09-VERIFICATION.md] started: 2026-05-10T11:58:07Z -updated: 2026-05-10T11:58:07Z +updated: 2026-05-11T02:30:00Z --- ## Current Test -[awaiting human testing] +[testing complete] ## Tests ### 1. /mobile/profile full render (4 sections) expected: Sign in, navigate to /mobile/profile on a mobile-sized browser. Four Cards render in order with no console errors. Timezone Combobox shows saved timezone; Theme shows active selection; Notifications shows matrix or empty-state; Channels shows configured state. -result: [pending] +result: issue +reported: "interface looks fine, but the ntfy feature should use https://ntfy.wulfconsulting.cloud with user 'pulse', token in .env (NTFY_PULSE_TOKEN), and read-write access scoped to noc-* and soc-* topics. Publish format: POST https://ntfy.wulfconsulting.cloud/{topic} with Authorization: Bearer and Content-Type: text/plain." +severity: major +note: UI part of test 1 passes — the issue is feature integration target. ntfy is currently pointed at public ntfy.sh and mints pulse-* topics, neither of which fits the company ntfy infrastructure. ### 2. More drawer Profile & preferences link expected: Open More drawer from mobile shell. Identity row is tappable link and 'Profile & preferences' row appears above Sign-out. Both links navigate to /mobile/profile; Sign-out remains with destructive styling. -result: [pending] +result: pass ### 3. Timezone Combobox save and debounce expected: Change timezone in Combobox. 400ms delay, PUT fires, sonner toast appears ("Timezone updated"), current-time line updates. No immediate PUT (400ms debounce enforced). -result: [pending] +result: pass ### 4. Theme radio rows + write-through + cross-device persistence expected: Tap 'Dark' in Theme section. Reload in a different session. Theme switches immediately (next-themes); PUT /api/me/theme succeeds; new session loads Dark theme. -result: [pending] +result: pass +note: Initially failed with "Failed to update theme" — root cause was PUT route using `updated_at` (unquoted snake_case) but Better Auth's `"user"` table uses `"updatedAt"` (quoted camelCase). Fixed in 041fb16. Verified working on retry. Same bug found and fixed in app/api/settings/profile/route.ts and lib/bootstrap.ts (3dd379d). ### 5. Teams webhook inline error on 400 expected: Enter `https://evil.com` in Teams URL input and save. Inline `text-xs text-destructive` error under input; no 'Channel saved' toast. -result: [pending] +result: pass +note: User confirmed both the inline error (under input) and the generic "Failed to save channel" toast appeared. No success toast. Spec requirement is satisfied — the inline error gives the actionable reason. ### 6. ntfy custom topic inline error on 400 expected: Open 'Edit advanced', enter `bad space` as custom topic, save. Inline error 'topic must match ^[A-Za-z0-9_-]{6,64}$' below Input. -result: [pending] +result: pass ### 7. ThemeToggle desktop write-through expected: Use desktop ThemeToggle to switch theme. Open /mobile/profile in another session. Both sessions show same theme. -result: [pending] +result: pass ### 8. Admin channels Owner column + filter expected: As admin, open /admin/workflow/channels. Confirm Owner badges; test filter widget. Global rows show 'Global' badge; personal rows show 'Personal: email'; filter hides/shows by type. -result: [pending] +result: pass ### 9. Admin executions fallback filter expected: As admin, open /admin/workflow/executions. Toggle 'Show only fallbacks'. Only rows with user_route_fallback appear; empty state message when none exist. -result: [pending] +result: pass ## Summary total: 9 -passed: 0 -issues: 0 -pending: 9 +passed: 8 +issues: 1 +pending: 0 skipped: 0 blocked: 0 ## Gaps + +- truth: "Personal ntfy channels publish to the company ntfy infrastructure with bearer auth and a reserved topic prefix" + status: failed + reason: "User reported: ntfy feature should use https://ntfy.wulfconsulting.cloud (not ntfy.sh) with the existing `pulse` admin user, bearer token from NTFY_PULSE_TOKEN in .env. Topic prefix `pulse-me-` (noc-*/soc-* are reserved for NOC/SOC operations)." + severity: major + test: 1 + root_cause: | + Personal channel implementation was scaffolded against the public ntfy.sh server with a `pulse-` topic prefix and no enforced auth. The production deployment uses a private ntfy instance (https://ntfy.wulfconsulting.cloud) requiring bearer auth, and the `pulse-` prefix was an arbitrary placeholder — production needs the namespaced `pulse-me-` prefix to coexist with reserved `noc-*`/`soc-*` ACLs. + artifacts: + - path: "lib/services/personal-channels.ts" + issue: "mintNtfyTopic mints `pulse-XXXXXXXX`; NTFY_TOPIC_RE accepts any [A-Za-z0-9_-]{6,64}; sendChannelTest defaults to https://ntfy.sh and reads auth_token from channel.config instead of env." + - path: "lib/services/pipeline-steps/notify.ts" + issue: "ntfy publish (when route_to_user resolves to ntfy) inherits the same defaults — public server, no enforced bearer auth." + - path: "lib/services/ticket-digest-service.ts" + issue: "Other ntfy publish caller — same defaults." + - path: "components/mobile/profile/ProfileChannelsSection.tsx" + issue: "QR code + subscribe link point at https://ntfy.sh/{topic}; custom-topic inline error message references the generic regex pattern, not the required prefix." + missing: + - "Env vars: NTFY_BASE_URL (server, default https://ntfy.wulfconsulting.cloud), NEXT_PUBLIC_NTFY_BASE_URL (client, same default)." + - "mintNtfyTopic() must mint `pulse-me-XXXXXXXX` (keep 8 hex chars entropy)." + - "NTFY_TOPIC_RE must enforce `^pulse-me-[A-Za-z0-9-]{6,64}$` for personal topics; reject `pulse-`, `noc-`, `soc-`, arbitrary names." + - "sendChannelTest (ntfy case) must default server_url to NTFY_BASE_URL and ALWAYS send Authorization: Bearer ${NTFY_PULSE_TOKEN} for personal channels (drop the channel.config.auth_token path here)." + - "Notify pipeline ntfy publish + ticket-digest-service ntfy publish must use the same base URL + bearer auth pattern." + - "ProfileChannelsSection QR + subscribe link target NEXT_PUBLIC_NTFY_BASE_URL; inline error copy updated to 'Topic must start with pulse-me-'." + - "Cleanup: any test rows in notification_channels with `pulse-` topic prefix should be deleted (notification_channels table introduced in migration 085, low-volume QA data only)." + out_of_scope: + - "Admin override to set custom server_url / auth_token per-channel (currently supported via channel.config for legacy ntfy.sh use cases — leave that path; only PERSONAL channels are forced to the company server)." + debug_session: ""