Files
oO/README.md
alvis 7f173f88d3 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)
2026-04-13 14:36:11 +00:00

139 lines
7.1 KiB
Markdown

# oO
> One tip. Right now. Feels like magic.
oO learns who you are from the apps you already use and surfaces **one** perfectly-timed suggestion — an advice or a todo — on a black page. No feed. No dashboard. One tip.
---
## Why
Everyone has too many tasks, too many apps, too much noise. What people actually need is a single, well-chosen nudge at the right moment. oO is that nudge, powered by a recommendation engine that gets smarter the more of your life it sees.
## Product principles
1. **One thing at a time.** The UI is a black page with one tip. That's the product.
2. **We don't own your data, we understand it.** Connect your apps; we read what we need, when we need it.
3. **Magic requires craft.** Precision, timing, and restraint matter more than features.
4. **Private by default.** Tokens are encrypted, models are per-user, deletion is one click.
## Prototype scope (Phase 0)
Three pages. That's it.
| Page | What it does |
|------|--------------|
| **Sign in** | Google / Apple OAuth. No passwords. |
| **Connect** | A list of integrations. Tap "Todoist" → OAuth flow → token stored. |
| **Tip** | Black page. One tip. Tap to dismiss / done / snooze. |
Under the hood the "pick a tip" call already routes through a `recommender` service with a pluggable policy — so v0 is literally "random Todoist task" but every other version slots into the same contract.
---
## Architecture at a glance
```
┌──────────┐ OAuth ┌────────────┐
│ Web / │──────────▶│ auth │
│ Mobile │ └─────┬──────┘
│ client │ │ JWT
│ │ REST/GraphQL ▼
│ │────────▶┌───────────────┐
└──────────┘ │ gateway │──┬──▶ profile
└───────┬───────┘ ├──▶ integrations ──▶ Todoist / Google / ...
│ └──▶ recommender ──▶ ml/serving (Python)
┌───────────────┐
│ events │ ◀── integrations emit normalized events
│ (Kafka/NATS) │ ──▶ ml/pipelines (features, training)
└───────────────┘
```
More detail in [`docs/architecture/`](docs/architecture/) and decisions in [`docs/adr/`](docs/adr/).
## Monorepo layout
See [`CLAUDE.md`](CLAUDE.md) for the full tree and conventions.
```
apps/ web, ios, android
services/ gateway, auth, profile, integrations, recommender, events, notifier
packages/ shared-types, sdk-js, ui
ml/ pipelines, features, registry, experiments, serving
infra/ docker, k8s, terraform, ci
docs/ architecture, adr, api
```
---
## Roadmap
### 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 + 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 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 (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 — Native mobile *(M3)*
- [ ] iOS app (SwiftUI) with APNs push
- [ ] Android app (Compose) with FCM push
- [ ] `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)*
- [ ] 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)*
- [ ] 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
---
## Contributing
This repo is split into independent modules; most tickets belong to exactly one. Pick an issue, check its milestone (= phase), read the service's `README.md`, ship.
Conventions and per-service guidance live in [`CLAUDE.md`](CLAUDE.md).
## License
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.)