Files
crowd-funder-for-time-pwa/doc/notification-debug-panel.md
Jose Olarte III f23fe65078 docs(notifications): document debug panel auth settings and bypassAuth
Add doc/notification-debug-panel.md as the canonical panel reference.
Update ngrok guides, README, and analysis doc to describe independent
Backend URL, Test Mode, and Skip JWT Authentication settings, including
recommended configs for hosted test servers vs local ngrok.
2026-07-07 19:21:18 +08:00

9.0 KiB
Raw Permalink Blame History

Notification Debug Panel

Created: 2026-07-07
Audience: Developers testing notification registration, refresh, and WAKEUP_PING flows on native (iOS/Android) dev builds.

The Notification Debug Panel is a dev-only UI for exercising the same notification orchestration paths the production app uses: FCM token registration, backend refresh, wakeup handling, and local schedule inspection. It does not duplicate scheduling logic.


Access

  1. Use a non-production build (for example build:android:dev, build:ios:dev, or vite dev with a non-production mode).
  2. Open Account → enable Show All General Advanced Functions.
  3. Open Notification Debug Panel (route /dev/notifications).

On native platforms, grant notification permission when prompted so FCM token registration and the debug actions work.


Configuration (Backend Testing)

Settings persist in localStorage via NotificationDebugConfig.ts:

Key Default Purpose
notificationDebug.backendBaseUrl (unset — use APP_SERVER) Override which notification server receives API calls
notificationDebug.testMode true Sent in JSON request bodies (testMode: true/false)
notificationDebug.bypassAuth false When true, omit JWT Authorization headers on notification API calls

All notification API requests (/notifications/register, /notifications/refresh, /debug/send-wakeup, etc.) obtain headers through getNotificationApiHeaders() in notificationApiAuth.ts.

Notification Backend URL

Paste a base URL (no trailing slash) and tap Save Backend URL. This changes only which server the app calls (getNotificationApiBaseUrl()). It does not disable JWT authentication.

Leave empty to use the built-in default (APP_SERVER from VITE_APP_SERVER).

Test Mode

When enabled (default if never saved), register and refresh requests include "testMode": true in the JSON body. The backend can use this to return dev-friendly schedules or route test traffic separately from production.

Test Mode is independent of authentication. It does not control whether Authorization headers are sent.

Skip JWT Authentication (Local Development Only)

When off (default), the app resolves the active DID and sends Authorization: Bearer … on notification API calls.

When on, requests include only Content-Type: application/json — for local servers (localhost or ngrok) that intentionally accept unauthenticated notification requests during development.

Enable this only for local development backends that do not require JWT. Hosted shared test servers that require normal app authentication should leave this off.

The panel Backend Status section shows the active URL, testMode, and bypassAuth values.


Hosted test server

Example: https://test-notify-api.timesafari.app

Setting Value
Notification Backend URL https://test-notify-api.timesafari.app
Test Mode ON (if the server expects testMode: true)
Skip JWT Authentication OFF

Ensure the app has an active identity (DID) with a valid endorser session so JWT headers can be built.

Local localhost / ngrok development

Example: https://abc123.ngrok-free.app or http://127.0.0.1:3000

Setting Value
Notification Backend URL Your local or ngrok URL
Test Mode ON or OFF — match what your local notification-wakeup-service expects
Skip JWT Authentication ON only if the local server accepts unauthenticated requests; OFF if it validates JWT like production

Backend Testing actions

Action What it does
Register Token Now POST {backend}/notifications/register with current FCM token, deviceId, platform, and testMode. Forces re-registration (bypasses duplicate-token skip).
Refresh Notifications POST {backend}/notifications/refresh — same path used after a real WAKEUP_PING. Applies returned schedule to the native plugin.
Simulate WAKEUP_PING (Local) Calls the refresh API directly (no FCM). Quick test of backend URL + auth + refresh parsing without push delivery.
Send Real WAKEUP_PING POST {backend}/debug/send-wakeup; server sends a real FCM data message with data.type = "WAKEUP_PING". Exercises backend → FCM → Capacitor listener → refresh → reschedule. Background the app before expecting delivery.

Current FCM Token displays the last token from Capacitor/Firebase registration. Event Log shows the last 100 [Notifications] messages (also visible in logcat / Xcode console on native).


Other panel sections

Section Purpose
Mock Timing Presets Interval for mock refresh timestamps (30 sec 10 min).
Trigger Mock Refresh Applies synthetic future timestamps locally — no backend call.
Wakeup Ping Simulator Runs the production push handler with a synthetic WAKEUP_PING payload (no FCM, no backend).
Flood Test Runs 20 sequential mock refreshes (stress test).
Pending Notification Inspector Lists locally scheduled notifications (iOS; Android may show unavailable).
Clear Notifications Clears/cancels all plugin-scheduled notifications on native.

Programmatic override (optional)

From a WebView dev console (chrome://inspect on Android, Safari Web Inspector on iOS):

import {
  setBackendBaseUrl,
  setTestMode,
  setBypassAuth,
  getNotificationApiBaseUrl,
} from "@/services/notifications";

setBackendBaseUrl("https://abc123.ngrok-free.app");
setTestMode(true);
setBypassAuth(true); // local dev only
getNotificationApiBaseUrl();

Troubleshooting

401 Unauthorized (registerToken failed: unauthorized)

Likely causes: JWT required but Skip JWT Authentication is off and the session is missing or expired; or JWT sent but the server rejected it.

Checks:

  1. Panel Backend StatusbypassAuth: false for hosted servers.
  2. App has an active DID and endorser login.
  3. Event Log: look for Using authenticated notification request vs Using debug unauthenticated notification request.
  4. For hosted test server: keep Skip JWT Authentication OFF.

Fixes: Sign in / restore identity; refresh endorser session; for local ngrok without JWT support, enable Skip JWT Authentication.

registerToken auth unavailable / Waiting for auth before registration

The app deferred registration because JWT could not be built (no active DID or empty token) and Skip JWT Authentication is off.

Fixes: Complete identity setup in the app, or enable Skip JWT Authentication only for an intentionally unauthenticated local backend.

Failed to fetch / network error

Likely causes: Backend down, wrong URL, stale ngrok tunnel, device offline, or TLS/certificate issues.

Checks: Panel Backend Status URL; curl -sS "$URL/health" from your machine; ngrok inspect UI for incoming requests.

Fixes: Restart backend and ngrok; Save Backend URL with the current HTTPS forwarding URL (no trailing slash).

Backend unreachable / no requests in ngrok

Same as above. Confirm the Active URL in the panel matches your running tunnel or local server port.

Register succeeds but Send Real WAKEUP_PING does not trigger refresh

Real WAKEUP_PING success only means the backend accepted the wakeup request and attempted FCM delivery. Missing pushNotificationReceived / Refresh completed (WAKEUP_PING) indicates an FCM delivery or background execution issue — not necessarily a bad wakeup API call.

Checks: App backgrounded (not force-stopped); FCM token matches registration; Simulate WAKEUP_PING (Local) works (isolates FCM from refresh API).

See platform-specific guides for extended ngrok and FCM workflows:


Key source files

File Purpose
src/components/dev/NotificationDebugPanel.vue Dev UI
src/services/notifications/NotificationDebugConfig.ts Backend URL, testMode, bypassAuth persistence
src/services/notifications/notificationApiAuth.ts JWT vs unauthenticated headers
src/services/notifications/notificationApiDebugMode.ts Auth bypass gate
src/services/notifications/NotificationDebugService.ts Panel action handlers
src/services/notifications/NotificationService.ts POST /notifications/register
src/services/notifications/NativeNotificationService.ts POST /notifications/refresh, WAKEUP_PING handler