docs: plan background JWT pool/expiry and plugin configureNativeFetcher handoff
Add plan-background-jwt-pool-and-expiry.md (Phase A/B, expiryDays + buffer sizing, pool size 100). Add plugin-feedback-daily-notification-configureNativeFetcher-jwt-pool.md for daily-notification-plugin: optional jwtTokens on configureNativeFetcher. Link plan to plugin doc and endorser-jwt-background-prefetch-options.md.
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# Plugin feedback: `configureNativeFetcher` — optional JWT pool for background API calls
|
||||
|
||||
**Date:** 2026-03-27 PST
|
||||
**Target repo:** `@timesafari/daily-notification-plugin` (daily-notification-plugin)
|
||||
**Consuming app:** crowd-funder-for-time-pwa (TimeSafari)
|
||||
**Related app plan:** `doc/plan-background-jwt-pool-and-expiry.md` (Phase B, Option B1)
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The host app’s **`NativeNotificationContentFetcher`** (`TimeSafariNativeFetcher` on Android) calls Endorser with a Bearer JWT set via **`configureNativeFetcher`**. For **background** prefetch, the token must stay valid until WorkManager runs (often **minutes later**); Endorser may also reject **duplicate** JWT strings across days.
|
||||
|
||||
The **app** will mint a **pool** of distinct JWTs (see app plan) and needs the plugin to **accept and persist** that pool so native code can select a token **without JavaScript** at prefetch time.
|
||||
|
||||
**Requested change (plugin):** extend **`configureNativeFetcher`** to accept an optional **JWT pool** alongside the existing **`jwtToken`**, persist it in the same storage the host already relies on (e.g. SharedPreferences / app group), and document how **`NativeNotificationContentFetcher`** implementations should read it.
|
||||
|
||||
---
|
||||
|
||||
## Motivation
|
||||
|
||||
| Issue | Why plugin support helps |
|
||||
|-------|---------------------------|
|
||||
| Single short-lived `jwtToken` | Expires before background fetch |
|
||||
| Server duplicate-JWT rules | Need many distinct bearer strings over time |
|
||||
| No JS in WorkManager | Pool must be readable **only** from native |
|
||||
|
||||
---
|
||||
|
||||
## Proposed API (TypeScript / Capacitor)
|
||||
|
||||
**Extend** existing `configureNativeFetcher` options (names indicative — align with plugin naming conventions):
|
||||
|
||||
```ts
|
||||
configureNativeFetcher(options: {
|
||||
apiBaseUrl: string;
|
||||
activeDid: string;
|
||||
/** Primary token; keep for backward compatibility and Phase A (single long-lived JWT). */
|
||||
jwtToken: string;
|
||||
/**
|
||||
* Optional. Distinct JWT strings for background use (e.g. one per day slot).
|
||||
* If omitted, behavior matches today (single jwtToken only).
|
||||
*/
|
||||
jwtTokens?: string[];
|
||||
});
|
||||
```
|
||||
|
||||
**Alternatives** (if size limits matter for bridge payload):
|
||||
|
||||
- `jwtTokenPoolJson: string` — JSON array string of JWT strings (single string across the bridge).
|
||||
|
||||
**Validation (plugin):**
|
||||
|
||||
- If `jwtTokens` present: length **≤** a sane cap (host will use ~100; plugin may enforce max e.g. 128).
|
||||
- Empty array: treat as “no pool” (same as omitting).
|
||||
|
||||
---
|
||||
|
||||
## Android
|
||||
|
||||
1. **Parse** new fields in `DailyNotificationPlugin.configureNativeFetcher` (or equivalent).
|
||||
2. **Persist** pool under the same prefs namespace used for other TimeSafari / dual-schedule data, or a **documented** key prefix (e.g. `jwt_token_pool` as JSON array string).
|
||||
3. **Document** for host implementers: `NativeNotificationContentFetcher` should:
|
||||
- Prefer **pool entry** for `fetchContent` when pool is non-empty (selection policy is **host** responsibility — e.g. day index % length), **or**
|
||||
- Expose a small helper the host fetcher calls to resolve “current” bearer.
|
||||
4. **Clear** pool when `configureNativeFetcher` is called with a new identity / empty pool / logout path (coordinate with host).
|
||||
5. **Backward compatibility:** if only `jwtToken` is sent, behavior **unchanged** from current release.
|
||||
|
||||
---
|
||||
|
||||
## iOS
|
||||
|
||||
When `configureNativeFetcher` exists on iOS, mirror Android: accept optional pool, persist, document read path for native fetcher.
|
||||
|
||||
---
|
||||
|
||||
## Versioning & release
|
||||
|
||||
- Bump **plugin semver** (minor: new optional fields).
|
||||
- Publish package; consuming app bumps **`@timesafari/daily-notification-plugin`** and updates `nativeFetcherConfig.ts` to pass `jwtTokens` when Phase B ships.
|
||||
|
||||
---
|
||||
|
||||
## References (host app)
|
||||
|
||||
| Topic | Location |
|
||||
|--------|----------|
|
||||
| End-to-end plan (Phase A/B, pool sizing) | `doc/plan-background-jwt-pool-and-expiry.md` |
|
||||
| Android fetcher | `android/.../TimeSafariNativeFetcher.java` |
|
||||
| Current configure call | `src/services/notifications/nativeFetcherConfig.ts` |
|
||||
| JWT options (expired token context) | `doc/endorser-jwt-background-prefetch-options.md` |
|
||||
|
||||
---
|
||||
|
||||
*This document is intended to be copied or linked from PRs in **daily-notification-plugin**; keep app-specific details in the app plan.*
|
||||
Reference in New Issue
Block a user