120 lines
7.6 KiB
Markdown
120 lines
7.6 KiB
Markdown
# ordinarthur-os — Plan d'implémentation
|
||
|
||
> **Status** : planning terminé 2026-04-15. À implémenter via Claude Code (Sonnet).
|
||
|
||
## Vision produit
|
||
|
||
Un assistant personnel qui aide Arthur à s'organiser **sans le déresponsabiliser**.
|
||
|
||
- Dashboard clair de ce qu'il fait / veut faire
|
||
- Aucune action automatique invasive : l'IA propose, Arthur confirme d'un clic
|
||
- Pas de "weekly review" automatique, pas de nudges
|
||
- Une fonctionnalité signature : le **bouton "Parler"** — enregistrement vocal → Groq Whisper → Mistral function calling → création/enrichissement de todos, idées ou étapes projet, avec validation explicite avant écriture en base. **C'est le cœur du produit.** Les formulaires manuels sont intentionnellement minimalistes.
|
||
|
||
## Principes directeurs
|
||
|
||
1. **Self-hosted, open-source**. Pas de Vercel, pas de Next.js. Tout tourne sur le k3s d'Arthur.
|
||
2. **Single-user**. Pas de multi-tenant, pas d'invitations, pas de partage. Bearer token unique pour protéger l'API.
|
||
3. **PWA installable iOS**. Vite + React, pas de SSR. Service worker + mutation queue pour l'offline.
|
||
4. **BFF unique**. La PWA ne parle qu'au NestJS. Le Nest parle à Postgres, Mistral, Groq, Google Calendar, Telegram.
|
||
5. **Design éditorial / Swiss-brutalist** — mirror du portfolio arthurbarre.fr (cream, ink, orange, borders, mono labels).
|
||
|
||
## Stack verrouillée
|
||
|
||
| Couche | Choix |
|
||
| --- | --- |
|
||
| Monorepo | pnpm workspaces + Turborepo |
|
||
| Frontend | Vite + React 18 + TanStack Router + TanStack Query + Tailwind + shadcn/ui |
|
||
| Backend | NestJS + Drizzle ORM (driver `postgres`) |
|
||
| DB | Postgres 16 standalone (k3s StatefulSet + PVC), schéma dédié `ordinarthur_os` |
|
||
| Auth | Bearer token statique (single-user), middleware Nest |
|
||
| IA LLM | Mistral `mistral-small-latest` (low-cost) via API |
|
||
| STT | Groq `whisper-large-v3-turbo` |
|
||
| Bot | Telegram Bot API (webhook) |
|
||
| Calendar | Google Calendar API (Apple souscrit au calendar Google via webcal) |
|
||
| Langue IA | FR only |
|
||
| Déploiement | Images Docker → Gitea Container Registry → pipeline Gitea Actions → k3s (Traefik + cert-manager supposés présents) |
|
||
| Backups | CronJob k8s `pg_dump --schema=ordinarthur_os` quotidien → stockage S3-compatible (à confirmer avec Arthur) |
|
||
|
||
## Roadmap — ordre d'implémentation
|
||
|
||
### Phase 0 — Scaffold (prio immédiate)
|
||
- Monorepo `pnpm-workspace.yaml`, `turbo.json`
|
||
- `apps/pwa` : Vite + React + Tailwind + shadcn + manifest PWA + service worker placeholder + routing TanStack
|
||
- `apps/api` : NestJS + module `health` + middleware bearer + client Drizzle initialisé
|
||
- `packages/shared` : types et zod schemas partagés
|
||
- `packages/db` : schéma Drizzle + premières migrations SQL (`0000_init` crée le schéma `ordinarthur_os`)
|
||
- `deploy/k8s` : manifests génériques (à adapter ensuite à la conf Gitea/Traefik d'Arthur)
|
||
- Design system : composants primitifs (`<Label>`, `<SectionHeader>`, `<GridFrame>`, `<DataChip>`, `<MetaRow>`) qui reproduisent le style arthurbarre.fr
|
||
- Routes `GET /health` et `POST /auth/verify`
|
||
|
||
### Phase 1 — Jobs (prio haute, remontée)
|
||
- Migration : tables `jobs`, `job_search_criteria`
|
||
- API : `POST /jobs/ingest` (bearer), `GET /jobs`, `PATCH /jobs/:id`, `GET/PUT /jobs/criteria`
|
||
- PWA : route `/jobs` avec filtres (toutes / remote / hybrid / marseille), rendu éditorial façon portfolio (lignes tableau, pas des cards violettes)
|
||
- PWA : route `/settings/jobs` pour éditer les critères (titres, localisations, stack[], remote_types[], salary_min, active)
|
||
- Dedup : clé unique `source_url`, update `last_seen_at` si déjà vu
|
||
- Rétention : jobs >30j auto-archivés (soft delete via `archived=true`)
|
||
- Le scheduled task Claude Code (hors repo) lit `/jobs/criteria?active=true` et push les résultats via `/jobs/ingest` quotidiennement à 7h
|
||
|
||
### Phase 2 — Todos (capture rapide)
|
||
- Migration : table `todos`
|
||
- API : CRUD complet (schéma riche pour que la Phase 5 puisse tout remplir via function calling)
|
||
- PWA : **UI volontairement minimale** — textarea de capture + liste plate (checkbox done / delete). Pas de filtres, pas de formulaire de métadonnées. La priorité, le contexte, les tags seront remplis par le **magic button vocal (Phase 5)**.
|
||
- Les champs riches (priority, context, tags, due_at, checklist…) restent dans le schéma DB et l'API pour la Phase 5.
|
||
|
||
### Phase 3 — Projets + Kanban
|
||
- Migrations : `projects`, `project_steps`, `project_ideas`
|
||
- API : CRUD projets, CRUD steps, reorder, CRUD ideas
|
||
- PWA : route `/projects`, détail projet avec kanban (colonnes backlog/todo/doing/review/done), zone idées
|
||
|
||
### Phase 4 — Agenda + Google Calendar sync
|
||
- Migration : `calendar_events`
|
||
- API : OAuth Google (scope calendar), CRUD events avec sync bi-directionnelle, endpoint `/agenda/ical/:secret.ics` pour souscription Apple
|
||
- PWA : route `/agenda` vue semaine + jour
|
||
|
||
### Phase 5 — IA : bouton texte + voice magic button
|
||
- Migration : `ai_actions` (log d'audit)
|
||
- API : `POST /ai/command` (texte → function calling Mistral → plan), `POST /ai/voice` (audio → Groq Whisper → texte → Mistral → plan), `POST /ai/command/confirm` (applique après clic user)
|
||
- Fonctions exposées au LLM : `create_todo`, `add_project_idea`, `add_project_step`, `create_calendar_event`, `toggle_daily_checkin`
|
||
- PWA : bouton "🎤 Parler" sur le dashboard, `Cmd-K` pour la barre de commande texte, modal de confirmation avant exécution
|
||
|
||
### Phase 6 — Telegram bot
|
||
- Webhook Nest `/telegram/webhook` signé (header `X-Telegram-Bot-Api-Secret-Token`)
|
||
- Commandes : `/today` (events + todos du jour), `/todo <texte>` (crée une todo), messages vocaux traités comme le voice magic button
|
||
- Rappel quotidien optionnel à une heure configurable (simple message, pas d'action auto)
|
||
|
||
### Phase 7 — Health tab
|
||
- Migration : `daily_checkins (day date PK, meds_taken boolean, note text?)`
|
||
- API : `GET /health/today`, `POST /health/today/toggle`
|
||
- PWA : slider/toggle simple "médocs pris aujourd'hui" + historique 30j minimaliste
|
||
|
||
### Phase 8 — Finance (reporté)
|
||
- Revolut perso n'a pas d'API → passer par GoCardless Bank Account Data (ex-Nordigen)
|
||
- À traiter uniquement quand les phases 0–7 sont stables
|
||
|
||
## Handoff Claude Code
|
||
|
||
Pour reprendre ce projet avec Claude Code (Sonnet) :
|
||
|
||
1. Lire `README.md`, `PLAN.md`, `ARCHITECTURE.md` dans cet ordre
|
||
2. Pointer `CLAUDE.md` du repo vers ces docs
|
||
3. Respecter les règles de collaboration d'Arthur :
|
||
- Pas de Next.js, pas de Vercel
|
||
- L'IA ne mute jamais la DB sans clic de confirmation
|
||
- Design = portfolio arthurbarre.fr (pas le violet/cyan du HTML jobs)
|
||
4. Avant de scaffolder, récupérer de l'utilisateur :
|
||
- Le dossier `/Users/arthurbarre/dev/perso/proxmox` (conf k3s) pour aligner les manifests
|
||
- Le skill `/deploy` ou `/create-deployment` qu'Arthur utilise pour ses autres déploiements Gitea
|
||
- Les secrets nécessaires : `MISTRAL_API_KEY`, `GROQ_API_KEY`, `TELEGRAM_BOT_TOKEN`, `GOOGLE_OAUTH_CLIENT_ID/SECRET`, `DATABASE_URL` (+ `POSTGRES_USER`/`POSTGRES_PASSWORD`/`POSTGRES_DB` côté StatefulSet), `API_BEARER_TOKEN`
|
||
- Le choix du stockage backup S3-compatible (B2 / Scaleway / autre)
|
||
5. Attaquer par la Phase 0 (scaffold), puis Phase 1 (jobs) — c'est explicitement prioritaire dans la tête d'Arthur.
|
||
|
||
## Points ouverts à trancher avec Arthur
|
||
|
||
- Stockage backups (quel bucket S3-compatible ?)
|
||
- Gitea Container Registry vs GHCR (défaut proposé : Gitea CR, déjà présent dans sa stack)
|
||
- STT Groq → clé à créer côté Arthur
|
||
- Google OAuth → app Google Cloud à créer, redirect URI `https://api.os.arthurbarre.fr/agenda/google/oauth/callback`
|
||
- Bot Telegram → @BotFather → récupérer le token, configurer le webhook vers `https://api.os.arthurbarre.fr/telegram/webhook`
|