Files
oO/PLAN.md

72 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Implementation plan
Step-by-step build order for Phase 0 (prototype) and the seams that make Phases 15 cheap.
The principle: **build the contracts first, stub the internals.** Every service should exist with a `/health` endpoint and a minimal real implementation of its interface before any service is "finished". This gives us an end-to-end walking skeleton from week one.
---
## Stage 0 — Foundations (days 13)
1. **Monorepo tooling.** pnpm workspaces for JS/TS; uv or poetry for Python; turbo or nx for build graph; pre-commit (lint, typecheck, format).
2. **Docker Compose dev env.** Postgres, NATS, MinIO (S3), Mailhog, all services wired with hot-reload.
3. **CI skeleton** (Gitea Actions): lint → typecheck → unit test → build → publish images.
4. **Secrets convention.** `.env.example` per service; prod secrets injected by orchestrator.
5. **Shared types package.** OpenAPI source → generated TS + Python clients.
Deliverable: `docker compose up` brings a green dashboard of `/health` endpoints.
## Stage 1 — Identity & session (days 47)
1. `services/auth`: Google OAuth2 (PKCE), session cookies, short-lived JWTs, refresh rotation. Library-backed (Auth.js or Ory Kratos + Hydra) — we do not roll our own.
2. `services/profile`: minimal `User` record; created on first sign-in.
3. `apps/web` sign-in page; gateway verifies JWT.
Exit check: a user can sign in and fetch their own profile.
## Stage 2 — Integrations framework (days 812)
1. `services/integrations` with a **Connector** interface:
- `begin_oauth(user) → redirect_url`
- `finish_oauth(code, state) → StoredCredential`
- `fetch_signals(user, since) → Event[]`
2. **Token vault**: column-level encryption (libsodium), key from env or KMS.
3. **Todoist connector** as the first concrete implementation.
4. Web "Connect" page: list of connectors, button per connector, callback handling.
Exit check: a user taps "Connect Todoist", completes the OAuth dance, and the integrations service can fetch their tasks on demand.
## Stage 3 — Recommender contract (days 1316)
1. `services/recommender` exposes `POST /recommend {user_id, context} → {tip}`.
2. Policy interface (`Policy.pick(user, candidates, context) → tip`).
3. **`RandomPolicy` v0** — fetches candidates from `integrations` (Todoist tasks), returns one uniformly at random.
4. Tip shape is provider-agnostic: `{id, kind: "todo"|"advice", title, body, source, deep_link, meta}`.
5. `apps/web` tip page: full black, one tip centered, tap = mark done → callback fires to integrations (complete Todoist task) + emits a feedback event.
Exit check: three-page prototype works end-to-end for one user.
## Stage 4 — Hardening the prototype (days 1720)
1. Error surfaces (Sentry), structured logs (pino / structlog), trace IDs across services.
2. Rate limits + retries on outbound API calls.
3. Integration tests: Playwright for the web flow, pact-style contract tests between services.
4. Deploy to a single VM via docker-compose + Caddy.
Exit check: Phase 0 milestone closed.
---
## Seams prepared for later phases (do not implement yet, but do not foreclose)
- **Event bus.** From day one, `integrations` and `recommender` speak through an async fn that today is an in-process call but will be NATS tomorrow. Keep the signature `(event: NormalizedEvent) → void`.
- **Feature store.** The recommender accepts a `context` blob; later, a feature service fills it. Do not inline feature lookups inside the policy.
- **Policy registry.** `PolicyFactory.get(name)` so A/B and bandit policies slot in without code changes to the gateway.
- **Python boundary.** Recommender is TS today, but its scoring function is isolated — moving to FastAPI in Phase 1 is a file move, not a refactor.
---
## Staffing assumption
Work is parallelizable across ~3 streams: **infra/platform**, **backend services**, **web app**. Each Gitea issue notes which stream and which phase (milestone) it belongs to.