docs(refactor): add integration point refactor analysis and implementation plan
Add comprehensive documentation and implementation artifacts for refactoring the plugin to use app-provided content fetchers instead of hardcoded TimeSafari integration. Changes: - Add integration-point-refactor-analysis.md with complete ADR, interfaces, migration plan, and 7-PR breakdown - Add INTEGRATION_REFACTOR_QUICK_START.md for quick reference on new machines - Add src/types/content-fetcher.ts with TypeScript SPI interfaces - Add examples/native-fetcher-android.kt with Kotlin implementation skeleton - Add examples/js-fetcher-typescript.ts with TypeScript implementation skeleton - Add tests/fixtures/test-contract.json for golden contract testing Architecture Decisions: - Dual-path SPI: Native Fetcher (background) + JS Fetcher (foreground only) - Background reliability: Native SPI only, no JS bridging in workers - Reversibility: Legacy code behind feature flag for one minor release - Test contract: Single JSON fixture for both fetcher paths This provides complete specification for implementing the refactor in 7 PRs, starting with SPI shell and progressing through background workers, deduplication, failure policies, and finally legacy code removal. All documentation is self-contained and ready for implementation on any machine.
This commit is contained in:
268
docs/INTEGRATION_REFACTOR_QUICK_START.md
Normal file
268
docs/INTEGRATION_REFACTOR_QUICK_START.md
Normal file
@@ -0,0 +1,268 @@
|
||||
# Integration Point Refactor - Quick Start Guide
|
||||
|
||||
**Author**: Matthew Raymer
|
||||
**Date**: 2025-10-29
|
||||
**Status**: 🎯 **REFERENCE** - Quick start for implementation on any machine
|
||||
|
||||
## Overview
|
||||
|
||||
This guide helps you get started implementing the Integration Point Refactor on any machine. All planning and specifications are documented in the codebase.
|
||||
|
||||
## Key Documents
|
||||
|
||||
1. **`docs/integration-point-refactor-analysis.md`** - Complete analysis + improvement directive
|
||||
- Architecture decisions (ADR-001)
|
||||
- Public interfaces (TypeScript + Kotlin)
|
||||
- Migration plan (7 PRs)
|
||||
- Acceptance criteria
|
||||
- Risk register
|
||||
|
||||
2. **`src/types/content-fetcher.ts`** - TypeScript type definitions
|
||||
- `NotificationContent` interface
|
||||
- `JsNotificationContentFetcher` interface
|
||||
- `SchedulingPolicy` interface
|
||||
- `FetchContext` interface
|
||||
|
||||
3. **`examples/native-fetcher-android.kt`** - Kotlin native fetcher skeleton
|
||||
- Complete example implementation
|
||||
- Registration pattern
|
||||
- Error handling
|
||||
|
||||
4. **`examples/js-fetcher-typescript.ts`** - TypeScript JS fetcher skeleton
|
||||
- Foreground fetcher implementation
|
||||
- Policy configuration example
|
||||
|
||||
5. **`tests/fixtures/test-contract.json`** - Golden test contract
|
||||
- Shared fixture for both JS and Native fetchers
|
||||
- Failure scenarios
|
||||
|
||||
## Implementation Roadmap (7 PRs)
|
||||
|
||||
### PR1 — SPI Shell
|
||||
**Status**: Ready to start
|
||||
**Files to create**:
|
||||
- Kotlin/Swift interface definitions
|
||||
- TypeScript types (already in `src/types/content-fetcher.ts`)
|
||||
- `SchedulingPolicy` implementation (plugin side)
|
||||
- No behavior change yet
|
||||
|
||||
**Reference**: Section B in analysis doc
|
||||
|
||||
### PR2 — Background Workers
|
||||
**Status**: After PR1
|
||||
**Tasks**:
|
||||
- Wire Native SPI in WorkManager/BGTasks
|
||||
- Metrics skeleton
|
||||
- Cache store
|
||||
|
||||
**Reference**: Section C1 (Background Reliability)
|
||||
|
||||
### PR3 — JS Fetcher Path
|
||||
**Status**: After PR2
|
||||
**Tasks**:
|
||||
- Foreground bridge
|
||||
- Event bus
|
||||
- Dev harness screen
|
||||
|
||||
**Reference**: Section B1 (TypeScript interfaces)
|
||||
|
||||
### PR4 — Dedupe/Idempotency
|
||||
**Status**: After PR3
|
||||
**Tasks**:
|
||||
- Bloom/filter store
|
||||
- `dedupeKey` enforcement
|
||||
- Tests
|
||||
|
||||
**Reference**: Section C3 (Idempotency & De-duplication)
|
||||
|
||||
### PR5 — Failure Policy
|
||||
**Status**: After PR4
|
||||
**Tasks**:
|
||||
- Retry taxonomy (Section E)
|
||||
- Backoff implementation
|
||||
- Cache fallback
|
||||
- Structured errors
|
||||
|
||||
### PR6 — Docs & Samples
|
||||
**Status**: After PR5
|
||||
**Tasks**:
|
||||
- INTEGRATION_GUIDE.md (when to use which fetcher)
|
||||
- SCHEDULING_POLICY.md (all configuration knobs)
|
||||
- Copy-paste snippets
|
||||
|
||||
### PR7 — Feature Flag Legacy
|
||||
**Status**: After PR6
|
||||
**Tasks**:
|
||||
- Guard legacy TimeSafari code behind flag
|
||||
- Regression tests
|
||||
- Changelog for major removal
|
||||
|
||||
**Reference**: Section H (Migration Plan)
|
||||
|
||||
## Architecture Decisions
|
||||
|
||||
### ADR-001: Dual-Path SPI
|
||||
- **Native Fetcher** (Kotlin/Swift) - Required for background
|
||||
- **JS Fetcher** (TypeScript) - Optional, foreground only
|
||||
- Legacy code behind feature flag for one minor release
|
||||
|
||||
See: Section A in analysis doc
|
||||
|
||||
## Interface Contracts
|
||||
|
||||
### TypeScript (Host App)
|
||||
```typescript
|
||||
// From src/types/content-fetcher.ts
|
||||
interface JsNotificationContentFetcher {
|
||||
fetchContent(context: FetchContext): Promise<NotificationContent[]>;
|
||||
}
|
||||
|
||||
// Plugin API additions
|
||||
interface DailyNotificationPlugin {
|
||||
setJsContentFetcher(fetcher: JsNotificationContentFetcher): void;
|
||||
enableNativeFetcher(enable: boolean): Promise<void>;
|
||||
setPolicy(policy: SchedulingPolicy): Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
### Android SPI (Native)
|
||||
```kotlin
|
||||
interface NativeNotificationContentFetcher {
|
||||
suspend fun fetchContent(context: FetchContext): List<NotificationContent>
|
||||
}
|
||||
```
|
||||
|
||||
See: Section B in analysis doc
|
||||
|
||||
## Key Constraints
|
||||
|
||||
### Background Workers
|
||||
- **Android**: WorkManager - NO JS bridging, native SPI only
|
||||
- **iOS**: BGAppRefreshTask/BGProcessingTask - native SPI only
|
||||
- **Tasks**: Keep < 30s, respect backoff
|
||||
|
||||
### Security
|
||||
- JWT generation in host app only
|
||||
- No TimeSafari DTOs in plugin
|
||||
- Tokens never serialized through JS in background
|
||||
|
||||
### Deduplication
|
||||
- Use `dedupeKey` (fallback `id`)
|
||||
- Bloom/filter for recent keys
|
||||
- Horizon: `dedupeHorizonMs` (default 24h)
|
||||
|
||||
See: Sections C, D in analysis doc
|
||||
|
||||
## Failure Handling
|
||||
|
||||
| Class | Examples | Behavior |
|
||||
|-------|----------|----------|
|
||||
| Retryable | 5xx, network, timeout | Backoff per policy |
|
||||
| Unretryable | 4xx auth, schema error | Log, skip batch |
|
||||
| Partial | Some items bad | Enqueue valid subset |
|
||||
| Over-quota | 429 | Honor Retry-After |
|
||||
|
||||
See: Section E in analysis doc
|
||||
|
||||
## Testing Requirements
|
||||
|
||||
### Golden Contract
|
||||
- Single JSON fixture (`tests/fixtures/test-contract.json`)
|
||||
- Run through both JS and Native fetchers
|
||||
- Compare normalized outputs
|
||||
- Contract tests must pass
|
||||
|
||||
### Failure Scenarios
|
||||
- Network chaos (drop, latency)
|
||||
- 401 → refresh → 200
|
||||
- 429 with Retry-After
|
||||
- Malformed items (skip, don't crash)
|
||||
|
||||
See: Section G in analysis doc
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
Before considering this complete:
|
||||
|
||||
- ✅ Native fetcher runs with app killed
|
||||
- ✅ JS fetcher **never** required for background
|
||||
- ✅ Same inputs → same outputs (parity tests green)
|
||||
- ✅ No TimeSafari imports/types in plugin
|
||||
- ✅ No duplicate notifications within `dedupeHorizonMs`
|
||||
- ✅ Metrics visible, error classes distinguished
|
||||
- ✅ Docs include copy-paste snippets
|
||||
- ✅ Battery/quotas respected
|
||||
|
||||
See: Section J in analysis doc
|
||||
|
||||
## Open Questions (Resolve Before PR3)
|
||||
|
||||
1. **iOS capabilities**: Which BG task identifiers/intervals acceptable?
|
||||
2. **Token hardening**: DPoP or JWE now or later?
|
||||
3. **User controls**: Per-plan snooze/mute in metadata?
|
||||
|
||||
See: Section K in analysis doc
|
||||
|
||||
## Getting Started Checklist
|
||||
|
||||
When starting on a new machine:
|
||||
|
||||
- [ ] Read `docs/integration-point-refactor-analysis.md` (full context)
|
||||
- [ ] Review `src/types/content-fetcher.ts` (TypeScript interfaces)
|
||||
- [ ] Review `examples/native-fetcher-android.kt` (Kotlin pattern)
|
||||
- [ ] Review `examples/js-fetcher-typescript.ts` (JS pattern)
|
||||
- [ ] Review `tests/fixtures/test-contract.json` (test contract)
|
||||
- [ ] Start with **PR1 - SPI Shell** (no behavior change)
|
||||
- [ ] Follow 7-PR plan sequentially
|
||||
- [ ] Run contract tests after each PR
|
||||
|
||||
## File Locations
|
||||
|
||||
```
|
||||
docs/
|
||||
integration-point-refactor-analysis.md # Complete spec
|
||||
INTEGRATION_REFACTOR_QUICK_START.md # This file
|
||||
|
||||
src/types/
|
||||
content-fetcher.ts # TypeScript interfaces
|
||||
|
||||
examples/
|
||||
native-fetcher-android.kt # Kotlin example
|
||||
js-fetcher-typescript.ts # TypeScript example
|
||||
|
||||
tests/fixtures/
|
||||
test-contract.json # Golden contract
|
||||
```
|
||||
|
||||
## Next Actions
|
||||
|
||||
1. **Start PR1** (SPI Shell)
|
||||
- Create Kotlin interface in plugin
|
||||
- Create Swift interface (if iOS support needed)
|
||||
- Wire up TypeScript types (already done)
|
||||
- Add `SchedulingPolicy` to plugin
|
||||
|
||||
2. **Review examples** before implementing
|
||||
- Understand data flow
|
||||
- See error handling patterns
|
||||
- Note registration points
|
||||
|
||||
3. **Plan testing** early
|
||||
- Set up contract test infrastructure
|
||||
- Prepare mock fetchers for testing
|
||||
|
||||
## Questions?
|
||||
|
||||
All specifications are in `docs/integration-point-refactor-analysis.md`. Refer to:
|
||||
- Section B for interfaces
|
||||
- Section C for policies
|
||||
- Section E for failure handling
|
||||
- Section I for PR breakdown
|
||||
- Section J for acceptance criteria
|
||||
|
||||
---
|
||||
|
||||
**Status**: Reference guide
|
||||
**Last Updated**: 2025-10-29
|
||||
**Maintainer**: Plugin development team
|
||||
|
||||
Reference in New Issue
Block a user