integrations/README — replace stale Connector interface and fictional libsodium vault with the actual SignalSource pattern, SQLite token table, and real OAuth routes. recommender/README — document the SignalAggregator pipeline, current policy registry, and actual /recommend + /feedback contract shapes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.0 KiB
2.0 KiB
integrations
Third-party connectors and the token vault.
Signal source interface
Each connector implements SignalSource from @oo/shared-types:
interface SignalSource {
readonly id: string // e.g. "todoist"
fetchSignals(userId: string): Promise<Signal[]> // returns normalized Signal[]
act?(userId: string, signalId: string, action: string): Promise<void> // optional write-back
}
SignalAggregator (services/api/src/signals/aggregator.ts) fans out to all registered sources in parallel, isolating per-source failures.
Token vault
OAuth tokens stored in the integration_tokens SQLite table (services/api/src/db/schema.ts):
| Column | Description |
|---|---|
userId |
owner |
provider |
e.g. todoist |
accessToken |
OAuth access token (plain in dev; encrypted in prod via server secret store) |
tokenStatus |
active | needs_reconnect |
On a 401 from the upstream API, the connector marks the token needs_reconnect and publishes signals.integration.token_expired so the client can prompt re-auth.
Routes
| Method | Path | Description |
|---|---|---|
GET |
/api/integrations |
List connected integrations for current user |
GET |
/api/integrations/todoist/connect |
Start Todoist OAuth flow |
GET |
/api/integrations/todoist/callback |
OAuth callback — exchange code, store token |
DELETE |
/api/integrations/:provider |
Disconnect + delete token |
Connectors
| Connector | Status | Signals produced |
|---|---|---|
| Todoist | Phase 1 — active | task signals (today + overdue); done write-back |
| Google Calendar | Phase 2 — planned | event signals |
Extraction criteria
Extract to its own process when credential blast-radius isolation requires it (e.g. token vault with KMS-backed encryption needs to run in a hardened sidecar) or when connector volume justifies separate scaling.