140 lines
7.1 KiB
Markdown
140 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)* ✓ shipped
|
|
Goal: a single user signs in with Google, connects Todoist, and sees one random Todoist task on a black page. Deletion works.
|
|
- [x] Monorepo scaffold, docker-compose dev env
|
|
- [x] `auth` — Google OAuth2/PKCE via openid-client v6; session cookie; Next.js middleware guard
|
|
- [x] `integrations/todoist` — OAuth2 flow, token stored in DB, disconnect supported
|
|
- [x] `recommender` with `RandomPolicy`; stable `POST /recommend` contract; 30s task cache
|
|
- [x] `apps/web` — sign-in, connect, tip pages; PWA manifest + icons
|
|
- [x] Feedback endpoint (done/dismiss/snooze); marks task complete in Todoist
|
|
- [x] Deploy modular monolith to Agap VM via Caddy at `o.alogins.net`
|
|
- [ ] 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
|
|
|
|
### 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.)
|