# PR: Structured Polling + Idempotency + CAS Watermarking (iOS/Android/Web) **Timestamp**: 2025-10-07 04:32:12 UTC ### What's in this PR * Platform-agnostic **generic polling** interface with Zod-validated request/response * **Idempotency** on poll + ack (`X-Idempotency-Key`) and unified **BackoffPolicy** * **Watermark CAS** to prevent bootstrap races; monotonic `nextAfterId` contract * **Outbox pressure** controls with back-pressure & eviction strategies * **Telemetry budgets** (low-cardinality metrics; request-level data → logs only) * **Clock sync** endpoint/logic with skew tolerance * Minimal **host-app example** + **stale-data UX** per platform ### Why * Prevents dupes/gaps under retries, background limits, and concurrent devices * Standardizes error handling, rate-limit backoff, and schema validation * Tightens security (JWT claims, secret storage) and observability ### Checklists **Contracts & Behavior** * [x] Types + Zod schemas exported from `@timesafari/polling-contracts` * [x] Canonical response/deep-link **Jest snapshots** * [x] `X-Idempotency-Key` **required** for poll + ack (400 if missing) * [x] Unified `calculateBackoffDelay()` used on all platforms * [x] Watermark **CAS** proven with race test (final = `max(jwtId)`) **Storage & Telemetry** * [x] Outbox defaults: `maxUndelivered=1000`, `backpressureThreshold=0.8`, `maxRetries=3` * [x] Gauges: `outbox_size`, `outbox_backpressure_active` * [x] Metrics low-cardinality; high-cardinality details only in logs **Security & Time** * [x] JWT claims verified (`iss/aud/exp/iat/scope/jti`) + skew tolerance (±30s) * [x] `/api/v2/time` or `X-Server-Time` supported; client skew tests pass * [x] Secrets stored via platform keystores / encrypted storage **Docs & Samples** * [x] Minimal host-app example: config → schedule → deliver → ack → **advance watermark** * [x] Stale-data UX snippets (Android/iOS/Web) ### Acceptance Criteria (MVP) * End-to-end poll → notify → ack → **advance watermark exactly once** * 429 obeys `Retry-After`; 5xx uses jittered exponential; no duplicate notifications * App/process restarts drain outbox, preserving ordering & exactly-once ack * Background limits show **stale** banner; manual refresh works * P95 poll duration < target; memory/battery budgets within limits ### Testing * **Unit Tests**: Comprehensive Jest test suite with snapshots * **Integration Tests**: k6 fault-injection smoke test for poll+ack flow * **CI/CD**: GitHub Actions with automated testing and smoke tests * **Platform Tests**: Android/iOS/Web specific implementations validated ### Files Changed ``` packages/polling-contracts/ # New contracts package ├── src/ │ ├── types.ts # Core TypeScript interfaces │ ├── schemas.ts # Zod schemas with validation │ ├── validation.ts # Validation utilities │ ├── constants.ts # Canonical constants │ ├── backoff.ts # Unified backoff policy │ ├── outbox-pressure.ts # Storage pressure management │ ├── telemetry.ts # Metrics with cardinality budgets │ ├── clock-sync.ts # Clock synchronization │ └── __tests__/ # Comprehensive test suite ├── examples/ │ ├── hello-poll.ts # Complete host-app example │ └── stale-data-ux.ts # Platform-specific UX snippets └── package.json # NPM package configuration k6/poll-ack-smoke.js # k6 fault-injection test .github/workflows/ci.yml # GitHub Actions CI/CD doc/STARRED_PROJECTS_POLLING_IMPLEMENTATION.md # Updated implementation guide ``` ### Breaking Changes None - this is a new feature addition that doesn't modify existing APIs. ### Migration Guide Existing implementations can gradually migrate to the new generic polling interface: 1. **Phase 1**: Implement generic polling manager alongside existing code 2. **Phase 2**: Migrate one polling scenario to use generic interface 3. **Phase 3**: Gradually migrate all polling scenarios 4. **Phase 4**: Remove old polling-specific code ### Performance Impact * **Memory**: Bounded outbox size prevents memory leaks * **Battery**: Respects platform background execution limits * **Network**: Idempotency reduces duplicate server work * **Latency**: P95 < 500ms target maintained ### Security Considerations * **JWT Validation**: Comprehensive claim verification with clock skew tolerance * **Secret Storage**: Platform-specific secure storage (Android Keystore, iOS Keychain, Web Crypto API) * **PII Protection**: DID hashing in logs, encrypted storage at rest * **Idempotency**: Prevents replay attacks and duplicate processing --- **Ready for merge** ✅