refactor: architecture revision — modular monolith, auth-commit, event protobuf, privacy-from-day-0
- ADR-0003: modular monolith for Phase 0 with documented extraction triggers - ADR-0004: Auth.js + OIDC-shaped boundary; dedicated provider when mobile ships - ADR-0005: protobuf for events, OpenAPI for HTTP, schema-registry CI gate - New architecture docs: data-model, metrics (magic proxies), privacy (Phase-0 feature) - Prime directives updated: privacy-as-feature, modular-by-package-deployable-by-stage - Roadmap revised: Apple OAuth deferred to M1; web push in M1; k3s intermediate; tip-kind-aware UI - PLAN updated: Phase-0 deletion endpoint, metrics baseline, compose profiles, import-boundary lint - License decision in README (ARR with OSS plan in Phase 5)
This commit is contained in:
78
README.md
78
README.md
@@ -69,48 +69,59 @@ docs/ architecture, adr, api
|
||||
|
||||
## Roadmap
|
||||
|
||||
### Phase 0 — Prototype *(M0)*
|
||||
Goal: a single user can sign in, connect Todoist, and see one random Todoist task on a black page.
|
||||
- [ ] Monorepo scaffold, CI skeleton, docker-compose dev env
|
||||
- [ ] `auth` service with Google OAuth
|
||||
- [ ] `integrations/todoist` OAuth2 flow + encrypted token vault
|
||||
- [ ] `recommender` service with `RandomPolicy` (v0)
|
||||
- [ ] `apps/web` — three pages (sign-in, connect, tip)
|
||||
- [ ] Deploy to a single VM via docker-compose
|
||||
### Phase 0 — Walking skeleton *(M0)*
|
||||
Goal: a single user signs in with Google, connects Todoist, and sees one random Todoist task on a black page. Deletion works.
|
||||
- [ ] Monorepo scaffold, CI skeleton, docker-compose dev env with `core`/`full` profiles
|
||||
- [ ] `auth` on Auth.js with Google provider; OIDC-shaped boundary (ADR-0004)
|
||||
- [ ] `integrations/todoist` OAuth2 flow + encrypted token vault + provider-side revocation
|
||||
- [ ] `recommender` with `RandomPolicy`; stable `POST /recommend` contract
|
||||
- [ ] `apps/web` — three pages (sign-in, connect, tip); PWA manifest; offline reaction queue
|
||||
- [ ] ToS + Privacy Policy + consent capture on first sign-in
|
||||
- [ ] Account-deletion endpoint: revokes providers, purges credentials, soft-deletes profile
|
||||
- [ ] Metrics baseline: activation, first-tip reaction rate, dwell, retention (see `docs/architecture/metrics.md`)
|
||||
- [ ] Deploy modular monolith + `ml/serving` stub to a single VM via docker-compose + Caddy
|
||||
|
||||
### Phase 1 — Real signal *(M1)*
|
||||
Goal: the tip is picked, not drawn from a hat. Still Todoist-only.
|
||||
- [ ] Event bus (NATS) + ingestion from Todoist sync API
|
||||
- [ ] Feature store skeleton (Feast or homegrown) and the first five features (time-of-day, overdue count, task age, priority, project)
|
||||
- [ ] `ml/serving` FastAPI scoring endpoint; `recommender` calls it
|
||||
- [ ] `ContextualBanditPolicy` v1 (LinUCB) replacing `RandomPolicy`
|
||||
- [ ] Tip feedback loop: user reactions (done / snooze / dismiss) become rewards
|
||||
### Phase 1 — Real signal + in-the-moment delivery *(M1)*
|
||||
Goal: tips are picked, not drawn from a hat — and they arrive at the right moment on the web.
|
||||
- [ ] Event bus (NATS JetStream) with protobuf schemas (ADR-0005) + schema-registry CI gate
|
||||
- [ ] Todoist event-driven sync (emit `signals.task.*`)
|
||||
- [ ] Feature store skeleton + first five features (hour-of-day, overdue count, task age, priority, project)
|
||||
- [ ] `ml/serving` FastAPI scorer; `RemotePolicy` wrapper in recommender
|
||||
- [ ] **Global-then-personalize bandit**: pooled LinUCB over shared features, per-user residual when data allows
|
||||
- [ ] Shadow-deploy infra: every new policy logs what it *would* have picked; promotion requires reward-parity
|
||||
- [ ] Feedback loop: reactions → rewards; delayed rewards for tasks completed in Todoist directly
|
||||
- [ ] **Web Push notifications** (VAPID) so the "magic" shows up without opening the app
|
||||
- [ ] `notifier` (lite): web-push delivery, quiet-hours honoured, dedupe
|
||||
- [ ] Apple OAuth added (deferred from M0)
|
||||
|
||||
### Phase 2 — Multi-source user profile *(M2)*
|
||||
Goal: oO knows more than tasks.
|
||||
- [ ] Integrations: Google Calendar, Apple Health (web import), generic webhook
|
||||
### Phase 2 — Multi-source profile & trust *(M2)*
|
||||
Goal: oO knows more than tasks, and users can see/control what we know.
|
||||
- [ ] Integrations: Google Calendar, Apple Health (web import), generic webhook ingress
|
||||
- [ ] Unified `Profile` model (identity, preferences, contexts, consents)
|
||||
- [ ] Timing signals (location, idle, focus windows) via client-side probes
|
||||
- [ ] Advice library (curated tips, not only todos) + mixing policy
|
||||
- [ ] Timing signals (Page Visibility, Idle Detection, coarse location) — opt-in, transparent
|
||||
- [ ] Advice library + mixing policy (todo vs advice vs ambient)
|
||||
- [ ] User-facing data dashboard: what's stored, what's computed, export, delete-by-category
|
||||
- [ ] Cost/usage observability
|
||||
|
||||
### Phase 3 — Mobile & notifications *(M3)*
|
||||
### Phase 3 — Native mobile *(M3)*
|
||||
- [ ] iOS app (SwiftUI) with APNs push
|
||||
- [ ] Android app (Compose) with FCM push
|
||||
- [ ] `notifier` service with quiet-hours + per-channel rate limits
|
||||
- [ ] Rich notifications that deep-link to the tip page
|
||||
- [ ] `notifier` gains APNs + FCM channels, per-device rate limits
|
||||
- [ ] Migrate auth from Auth.js to dedicated OIDC provider (trigger from ADR-0004)
|
||||
- [ ] Decide-and-deliver scheduler: per-user "is this tip worth interrupting now?" threshold
|
||||
|
||||
### Phase 4 — MLOps at scale *(M4)*
|
||||
- [ ] Airflow/Prefect orchestrator for batch retrains
|
||||
- [ ] MLflow model registry + shadow deploys
|
||||
- [ ] Online `experiments` framework: A/B + multi-armed bandits as first-class
|
||||
- [ ] Cohort analysis + cross-user collaborative features (opt-in)
|
||||
- [ ] Model cards, fairness checks, drift monitoring
|
||||
- [ ] Prefect/Airflow for batch feature materialization + retraining
|
||||
- [ ] MLflow registry; shadow → A/B → launch pipeline as first-class
|
||||
- [ ] Online experiments framework: deterministic assignment + bandit policies alongside fixed-split A/B
|
||||
- [ ] Cross-user collaborative features (opt-in only); cohort slicing; fairness checks
|
||||
- [ ] Drift monitoring (feature drift, prediction drift, reward drift); model cards per version
|
||||
|
||||
### Phase 5 — Production hardening *(M5)*
|
||||
- [ ] SOC2-style controls, audit logging, token rotation
|
||||
- [ ] k8s deploy + horizontal autoscaling
|
||||
- [ ] Multi-region failover, PITR backups
|
||||
- [ ] Public integration SDK so third parties can add sources
|
||||
- [ ] Audit logging, rotation of provider tokens + internal signing keys
|
||||
- [ ] **k3s** on existing VM, then k8s + HPA once multi-node justified (no cliff)
|
||||
- [ ] Multi-region failover, Postgres PITR, event-bus mirroring
|
||||
- [ ] Public integration SDK; sandbox tenancy for third-party connectors
|
||||
- [ ] Billing + subscription tiers
|
||||
|
||||
---
|
||||
@@ -123,4 +134,5 @@ Conventions and per-service guidance live in [`CLAUDE.md`](CLAUDE.md).
|
||||
|
||||
## License
|
||||
|
||||
TBD.
|
||||
All rights reserved — 2026. Contact the owner for licensing inquiries.
|
||||
(We'll switch to an OSS license for non-sensitive packages once the public SDK lands in Phase 5.)
|
||||
|
||||
Reference in New Issue
Block a user