17 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
094c26059f |
test(billing): tests E2E HTTP du tunnel essai 14 j + playbook Stripe test mode
All checks were successful
Build & Deploy API / build-and-deploy (push) Successful in 1m18s
Ajoute 16 tests E2E qui hit les vraies routes `/api/v1/billing/*` à
travers le middleware auth, les validators et la persistance DB.
Complémentaire des 60 tests unitaires sur les services.
Suites couvertes :
- POST /start-trial : 200 happy path, customer Stripe réutilisé,
409 trial déjà consommé (2 garde-fous), 401 sans Bearer
- GET /subscription : expose inTrial + trialEndsAt, garde-fou
trial_ends_at passé
- POST /webhook : checkout.completed, subscription.updated trialing→active,
trial_will_end → enqueue recap (avec spy), payment_failed → past_due,
subscription.deleted → free + trial_ends_at conservé
- Idempotence : 2× le même event = même état final
- Event type inconnu → 200 silencieux (pas de DB write)
- 400 si stripe-signature absent / signature invalide
Helpers de test :
- installFullStripeMock(opts) → mock complet : customers, prices,
checkout, billingPortal, subscriptions, webhooks. Avec
passThroughWebhook qui bypass la vérif signature pour tester
le routing applicatif sans signer manuellement chaque payload.
env.test : STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET dummy +
WEB_URL/LANDING_URL.
Documentation : docs/tech/stripe-trial-e2e-playbook.md — playbook
manuel pour valider en mode Stripe test (5 scénarios : happy path
3DS, carte refusée au prélèvement, annulation Customer Portal,
re-trial bloqué, fallback Free). Utilise Stripe Test Clocks pour
fast-forward sans attendre 14 jours réels.
Total après ce commit : 76 tests sur la chaîne billing (60 unit + 16 E2E).
Les cas Stripe-side (3DS UI réel, prélèvement effectif J+14) restent
à valider manuellement via le playbook avant le go-live.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
f9cba50b5e |
feat(billing,landing): plan Free 2 factures + scaffold preuves sociales/SEO
Suite des chantiers structurants de landing-optimisations.md. #5 — Plan Free : 5 → 2 factures actives (cf. ADR-023) - PLAN_CAPS.free.activeInvoicesLimit dans apps/api/app/services/billing.ts - Tests unitaires alignés (4 → 1, 5 → 2 cap, delta 3 → delta 2) - billing:scenario command : commentaires + valeur par défaut - PlanLimitBanner : copy dynamique via {limit} au lieu de "5" hardcodé - /parametres/abonnement : H1 + tile Free (3 mois → 14 jours, 5 → 2) - billing.test.tsx (fixtures + cas test) - landing copy : hero feature pill, Pricing tile, FinalCTA, CGV §5 - CLAUDE.md pricing table #7 — Scaffold <TrustedBy /> (preuve sociale) - Composant qui render null tant que copy.trustedBy.{logos,testimonials} sont vides — pas de placeholder bidon. - Structure data dans copy.ts avec commentaires sur les prérequis avant d'ajouter une entrée (accord signé, photo, citation chiffrée). - Section insérée juste avant <Pricing /> (cf. doc §4). #8 — Plan articles SEO + brouillon article 1 - docs/marketing/seo-articles.md : 5 articles ciblés, mots-clés, structure type, lead magnet, calendrier 5 semaines. - Article 1 ("Modèle d'email de relance facture impayée") en brouillon complet, prêt à valider via l'admin blog (apps/api). #6 — Plan détaillé migration Stripe trial 14 j (code reporté) - docs/tech/stripe-trial-with-card.md : état actuel vs cible, architecture (Stripe Checkout + trial_period_days), modifs DB (trial_ends_at), API (start-trial + webhook trial_will_end), SPA (onboarding/billing), 3 emails transactionnels avec contenu intégral, risques + mitigations, plan d'exécution 2,5 j. - Implémentation reportée à une session focus avec accès Stripe test mode (cartes 3DS, webhook signing secret). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
cecbddc496 |
refactor(landing): mono-langue FR + quick wins optimisations conversion
All checks were successful
Build & Deploy Landing / build-and-deploy (push) Successful in 1m1s
- Retire le système i18n EN (apps/landing/src/i18n/, pages /en/*) ajouté en 4f3417f. Source unique de copy dans src/copy.ts (FR uniquement). Switcher de langue retiré du header, sitemap nettoyé des hreflang. - Header : micro-baseline « Logiciel de relance de factures impayées » sous le wordmark pour lever l'ambiguïté du nom (§1). - CTA principal : « Lancer Rubis » → « Démarrer mon essai 14 jours » avec sous-texte sur Hero / FinalCTA / Pricing (§5). - Essai 30 j → 14 j sur landing + CGV §6.2 (§3). - Blog promu en nav primaire avec label « Ressources » (§6). Doc d'arbitrage : docs/tech/landing-optimisations.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
e449b708f3 |
docs(invoices): édition native + ADR-025 + roadmap Factur-X (Phase 5)
Documente la feature ajoutée en V1.1 dans toute la doc cadre : - **CLAUDE.md** : "Pure-player relance" nuancé en "La relance reste l'âme du produit", extension douce assumée. Périmètre V1/IN enrichi avec l'éditeur de factures. Glossaire enrichi (facture native, numéro de séquence, snapshot, Factur-X). Stack : ajout @react-pdf/renderer + pointeurs vers pdf-templates et les routes /parametres/facturation et /factures/nouvelle. - **docs/produit.md** : nouvelle section 4.2bis "Édition native des factures" — scope V1.1 minimal, snapshots immuables, numérotation strict séquentielle, roadmap Factur-X V1.5 / PDP V2. - **docs/flow.md** : nouvelle section 11bis (3 sources d'une facture, flow utilisateur de création, génération PDF, numérotation, snapshots, cas limites). Tableau "Ce que Rubis ne fait PAS" mis à jour (édition oui mais pas devis/avoirs/Factur-X V1). - **docs/decisions.md** : ADR-025 "Édition native des factures + roadmap Factur-X" (rationale extension douce, choix techniques notables, alternatives écartées). - **docs/tech/architecture.md** : section 6.1bis (flow technique édition native, points d'attention numérotation atomique + lazy PDF regenerate), ajout @react-pdf à la stack, routes /native + /preview-pdf + /invoice-themes + /invoice-settings documentées. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
51217175ad |
feat(banking): intégration Powens AISP + auto-réconciliation factures
Module banking complet en lecture seule via Powens (ex-Budget Insight)
pour détecter automatiquement les paiements clients et arrêter les
relances dès qu'une facture est payée. Réservé plans Pro / Business,
kill switch global BANKING_ENABLED désactivé en prod tant que le KYC
Powens n'est pas validé (cf. .claude/deploy-memory.md).
Backend (apps/api)
- PowensClient bas niveau : init user, code temporaire 30s, build
webview URL, list/get/delete connections, accounts, transactions,
vérif HMAC SHA-256 timing-safe pour webhook.
- BankingService : ensurePowensUser (chiffrement token via Adonis
encryption / APP_KEY), createWebviewUrl avec state HMAC anti-CSRF
(TTL 10 min), handleCallback (upsert connection + accounts +
fire-and-forget mail + sync 90j + reconcile), disconnect (DELETE
Powens + soft-revoke en DB), setReconciliationMode.
- Réconciliation : match transactions ↔ factures sur montant exact
+ label normalisé (numero ou nom client, NFD strip + alphanum).
Confiance HIGH (label matche) vs LOW (montant seul). Mode auto +
HIGH → invoice.status=paid + bonus rubis + cancel relances +
enqueuePaymentThanks (client) + sendInvoiceAutoPaidNotification
(user). Mode manual ou LOW → match_status='suggested' (UI V2).
- Webhook /webhooks/powens : vérif HMAC, lookup org par
powens_user_id, dispatch CONNECTION_SYNCED / NEW_TRANSACTIONS /
USER_SYNC_ENDED → sync incrémental 7j + reconcile, CONNECTION_ERROR
/ SCA_REQUIRED → update state + last_error. Réponse 200 immédiate
puis processing fire-and-forget pour ne pas timeout côté Powens.
- 4 migrations : bank_connections, bank_accounts, bank_transactions
+ colonnes powens_user_id (chiffré APP_KEY) et reconciliation_mode
sur organizations.
- 2 templates React Email : BankConnectedEmail (post-connection,
récap comptes + lien settings) et InvoiceAutoPaidNotificationEmail
(notif user après match auto, lien direct facture + libellé
bancaire détecté). Toujours en branding Rubis (notif Rubis → user,
jamais marque blanche).
- 2 commandes ace : banking:reconcile (rejoue le reconcile sans
reconnecter la banque) et banking:simulate-payment (injecte une
bank_transaction synthétique qui matche une facture, pour test E2E
sans devoir attendre un vrai virement sandbox).
- Kill switch isBankingEnabled() : flag BANKING_ENABLED + check des
credentials Powens. Endpoint public GET /banking/status renvoie
{ enabled }, /banking/powens/init throw 503 banking_disabled si OFF.
- Fix handler exceptions : UNIQUE violation composite (org, X)
rapporte désormais la vraie colonne en faute (numero/slug/…) avec
message lisible « Le numéro de facture "F2026-0013" existe déjà »,
au lieu d'un message ambigu sur organization_id.
Frontend (apps/web)
- /parametres : nouvelle SettingsSection "Banque" gated par kill
switch + plan Pro/Business. Si Free → upsell card avec CTA vers
/parametres/abonnement. Si Pro/Business sans banque → CTA "Connecter
une banque". Si banque connectée → carte avec accounts (IBAN
masqué FR76 **** **** **** 1234), solde, last sync, bouton
Déconnecter. Toggle Manuel/Auto pour reconciliation_mode.
- /parametres/banque/success : nouvelle route dédiée post-callback
avec badge ✓ animé + halo glow rubis, récap des comptes
synchronisés, 2 CTAs ("Voir mes paramètres" / "Retour dashboard"),
note sécurité "lecture seule, aucun déplacement de fonds".
- Hooks : useBankingStatus, useBankConnections (avec opt-out via
{ enabled }), useInitBanking, useDisconnectBank, useBankingSettings,
useUpdateBankingSettings.
Infrastructure (k3s)
- ConfigMap rubis-api-config : BANKING_ENABLED='false' par défaut,
BANKING_PROVIDER='powens', POWENS_DOMAIN='rubis',
POWENS_API_BASE_URL='https://rubis.biapi.pro/2.0/',
POWENS_REDIRECT_URI='https://app.rubis.pro/api/v1/banking/powens/callback'.
- Secret rubis-app-secrets : 3 nouvelles clés POWENS_CLIENT_ID,
POWENS_CLIENT_SECRET, POWENS_WEBHOOK_SECRET (valeurs sandbox posées
via kubectl patch, à remplacer post-KYC).
Sécurité
- Token Powens chiffré au repos via Adonis encryption (AES-256-GCM,
clé APP_KEY).
- State HMAC SHA-256 signé sur APP_KEY pour le flow webview
(anti-CSRF + porte l'org_id à travers le redirect).
- Webhook HMAC SHA-256 sur header BI-Signature avec
POWENS_WEBHOOK_SECRET, comparaison timing-safe.
- IBAN masqué côté API (transformer).
- Scope par org sur tous les endpoints (anti-IDOR).
- Rate limiting via le middleware Adonis existant.
- Idempotence DB : UNIQUE (org, powens_connection_id), (connection,
powens_account_id), (account, powens_id) → rejouer un event ou un
callback ne pose pas de problème.
Documentation
- /docs/tech/banking-setup.md : procédure complète setup dev avec
Cloudflare Quick Tunnel, compte sandbox Powens, whitelist URLs.
- /.claude/deploy-memory.md : section "Banking (Powens) — activation
prod" avec procédure en 6 étapes (KYC → secrets → ConfigMap →
flip flag → smoke test), snippet kubectl patch pour rotation
ciblée de secrets.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
77d52ea95c |
docs: aligner top-level + produit + technique + decisions sur le changelog
Les commits récents ont introduit le changelog public, le toast SPA, et la convention de release (bump version.ts + ajout du .md dans le même commit). Les docs reflètent maintenant ce qui est en prod : - CLAUDE.md : V1 IN gagne la mention `/changelog` avec le mécanisme MD versionné + toast SPA. Table "Documents associés" gagne 3 lignes (`apps/landing/src/content/changelog/`, `apps/web/src/version.ts`, `.claude/skills/push/`). - produit.md : nouvelle §4.9 "Changelog public et toast de version" qui couvre le ton produit-only, le mécanisme du toast, la première visite silencieuse, le RSS et le SEO. - tech/architecture.md : ajoute `/changelog` à la table de stratégie de rendu (SSG), met à jour l'arbre de fichiers `apps/landing/` avec `content.config.ts` + `content/changelog/` + `pages/changelog/`, et ajoute une sous-section "Mécanique du changelog (release workflow)" qui décrit le couplage `version.ts` ↔ `.md`. Côté SPA, ajoute la sous-section "Versionnage SPA + toast de release" avant la partie auth. - decisions.md : ADR-022 nouvelle entrée — Changelog en Markdown versionné (pas en DB) avec rationale (release-coupled, pas d'admin à maintenir, review en PR, SSG = LCP optimal, schéma Zod). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
9eaac0c7ef |
docs(audit-2/3): aligner doc tech sur le code livré
Audit cross-doc/code, batch tech : architecture, backend, frontend, dev-setup. Corrige les claims qui pouvaient induire un dev en erreur (noms de services K3s, hostnames Traefik, Tuyau, queue wrapper, seeders, env vars, polices). architecture.md - Composants : status « À écrire » → « ✅ Déployé » (apps/web, apps/api, packages/shared) ; ajout Redis Deployment K3s ; OCR = Mistral choisi ; mail = Resend (sortant) + OVH MX (entrant) validés - §7.5 Pods K3s : noms réels (rubis-api / rubis-web / rubis-landing / rubis-redis, pas de *-svc) ; pas d'IngressRoute api.rubis.pro (l'API est servie via app.rubis.pro/api/* proxifié par nginx du pod web) ; PG/MinIO en URL directe dans la ConfigMap, pas de Service ExternalName - §10 Décisions en attente : ADRs 019-024 mises à jour (tranchées / obsolètes), suppression du wording « à venir » pour les choix déjà figés dans le code backend.md - Note de cohérence en tête : pointe vers start/routes.ts comme source de vérité de la surface API (~80 routes — Stripe, Demo, AI, Microsoft SSO, admin blog, posts publics, KPIs timeseries) que cette doc n'inventorie pas exhaustivement - §1 Vue d'ensemble : Tuyau marqué « non utilisé en pratique » (présent en deps mais zéro import côté SPA), partage de types via packages/shared. OCR Mistral choisi. Mail Resend choisi. BullMQ direct (workers inline pod API). Sentry ADR-024. - §2 Stack : queue = BullMQ direct (pas @rlanz/bull-queue, qui n'est pas installé) ; type-sharing = packages/shared - §2 Dépendances : remplacé la todo-list pré-livraison par la liste réelle des packages dans apps/api/package.json - §3 Repo layout : `database/factories/` (dossier) → `factories.ts` (mono-fichier) ; `database/seeders/{default_plans,demo_data}` → inexistants, services à la place - §13.2 Jobs : ProcessOcrJob + RecomputeKpisJob retirés (n'existent pas — OCR synchrone via services/import_batch.ts, KPIs calculés on-the-fly). Liste des jobs réels : send_relance, send_checkin, send_payment_thanks - env vars : MINIO_* → S3_* (cf. .env.example + manifest k3s) ; bucket prod = rubis-prod-invoices frontend.md - Note de cohérence en tête : Tuyau pas utilisé, tokens dans packages/ui (pas inline), polices @fontsource-variable (pas Google Fonts via <link>) - §1 Vue d'ensemble : client API = fetch minimaliste dans apps/web/src/lib/api.ts ; périmètre livré = ~15 routes _app/ - §3 Polices : section Google Fonts → @fontsource-variable (avec note preload woff2 critique sur la landing Astro) - §4 Routes : arbo `_onboarding/` (faux) → `onboarding/` (réel, segment URL) + ajout admin.blog*, clients_.$id, insights, parametres_.abonnement, plans_.nouveau, factures_.import - §6 Tuyau : section marquée « historique, non utilisé en V1 » avec note explicative en tête - §10 env vars : VITE_API_URL=https://api.rubis.pro → vide (proxifié same-origin par nginx) + ajout VITE_USE_MOCKS, VITE_SENTRY_DSN_WEB, VITE_APP_VERSION dev-setup.md - Mailhog → Mailpit (3 occurrences) — c'est ce qui tourne dans docker-compose.dev.yml Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
e5530930b3 |
feat: refactor frontend en stack React unifiée (Astro + packages/ui)
Trois surfaces partagent désormais le même design system, Tailwind v4
et React 19 — au lieu d'avoir landing en HTML vanilla, app en React, et
blog en Adonis SSR :
* packages/ui — design system partagé (tokens Tailwind v4 + composants
TSX) extrait depuis apps/web : Brand, Gem, Button, Card, Chip, Eyebrow,
EmptyState. apps/web migre 41 imports vers @rubis/ui.
* apps/landing — nouvelle app Astro 6 SSR (rubis.pro), remplace l'ancienne
landing nginx vanilla. Embarque :
- Landing complète portée en sections React (Hero, Stats, Promise,
HowItWorks, Gamification, Legal, Pricing, FAQ, FinalCTA, Footnotes)
- Pages légales (mentions, confidentialité, CGV) via LegalLayout.astro
- Blog SSR (/blog, /blog/:slug) qui consomme /api/v1/posts
- sitemap.xml, blog/rss.xml, robots.txt en endpoints Astro
- SEO complet (canonical, hreflang, OG, Twitter Card, JSON-LD
Article/BreadcrumbList/Blog/SoftwareApplication)
* apps/api — BlogController réduit à 2 endpoints JSON (GET /api/v1/posts
+ GET /api/v1/posts/:slug). Suppression des templates SSR Adonis
(apps/api/app/blog/), de l'alias #blog/*, des deps react-dom et
@types/react-dom. PostTransformer + PostSummaryTransformer ajoutés.
Le service blog_renderer + le seeder + les 3 articles fondateurs
restent intacts (réutilisés par futurs admin + cron IA).
* Infra :
- Dockerfile.landing (multi-stage Node 22 + tini, Astro standalone)
- k3s/app/landing.yml (Deployment + Service rubis-landing:4321 +
ConfigMap avec API_URL=http://rubis-api.rubis.svc.cluster.local:3333)
- .gitea/workflows/deploy.yml mis à jour pour build rubis-landing
- .gitea/workflows/deploy-web.yml + Dockerfile.web : prennent en
compte packages/ui/ comme dépendance
- Suppression du Dockerfile nginx legacy + k3s/{deployment,service}.yml
- Suppression de landing/ (assets favicons migrés vers
apps/landing/public/)
* Docs : architecture.md (vue d'ensemble + §4bis apps/landing complet,
§3 endpoints JSON blog, layout monorepo), CLAUDE.md (stack technique,
documents associés, déploiement).
Note infra : l'ancien Deployment "rubis" (nginx) et son Service ne sont
PAS supprimés par la CI — à nettoyer manuellement après validation que
Traefik a été repointé sur rubis-landing:4321 dans le repo proxmox.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
5127cd2c9e |
feat(landing): pages légales + CTAs trial 30 jours
All checks were successful
Build & Deploy Landing / build-and-deploy (push) Successful in 19s
- CGV B2B SaaS (16 sections, conforme avec Stripe en place) - Mentions légales allégées au strict minimum LCEN - Politique de confidentialité resserrée : - retrait des détails infra (Proxmox, K3s, etc.) - sous-traitants par catégorie (Stripe / Resend / Mistral AI) - section sécurité standardisée - cookies simplifiés - Période d'essai harmonisée à 30 jours partout (landing + CGV) - Insistance sur l'hébergement et les données en France |
||
|
|
1acb273c1d |
docs: email infra rubis.pro (Resend sortant + OVH MX entrant)
All checks were successful
Build & Deploy Landing / build-and-deploy (push) Successful in 24s
Documentation post-migration du setup email : - /docs/tech/backend.md §12.5 : architecture des 2 flux (Resend pour le sortant transactionnel via send.rubis.pro, OVH MX Plan pour l'entrant humain via @ rubis.pro) - /CLAUDE.md : tableau récap email infra + maj domaine principal rubis.pro / app.rubis.pro, suppression de la question ouverte "domaine définitif" (résolue) et "endpoint waitlist" (remplacé par CTA app) - /.claude/deploy-memory.md : section migration rubis.pro marquée ✅ avec checklist décommissionnement legacy - /landing/confidentialite.html : remplace privacy@rubis.pro par contact@rubis.pro (alignement avec les boîtes OVH créées) Adresses opérationnelles : - contact@rubis.pro (général + RGPD) - dev@rubis.pro (notifs techniques) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
1c5a58e09a |
chore(domain): migrate rubis.arthurbarre.fr → rubis.pro
Bascule du domaine principal vers rubis.pro / app.rubis.pro : - K3s ConfigMaps (api.yml, web.yml) : APP_URL, WEB_URL, COOKIE_DOMAIN, OAUTH callbacks pointent vers app.rubis.pro - Dockerfile.web : ARG VITE_API_URL et VITE_PUBLIC_LANDING_URL - Workflows Gitea : commentaires + build args web → rubis.pro - Code API (mail_dispatcher, send_test_email, config/mail) : defaults env LANDING_URL et MAIL_FROM_ADDRESS migrés - Templates env (.env.example) idem - Docs (architecture, backend, frontend, brand-identity) idem - AGENTS.md / CLAUDE.md / deploy-memory : pointeurs domaine MAJ Note : MAIL_FROM_ADDRESS dans le secret K3s reste sur rubis@arthurbarre.fr tant que le domaine rubis.pro n'est pas Verified dans Resend. À switcher manuellement après vérif Resend. Compat : un 301 Traefik redirige rubis.arthurbarre.fr → rubis.pro (et app.X aussi) — config Ansible dans le repo proxmox. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
27cfa9ac13 |
docs(bruno): collection complète des routes API + environnement local
Collection Bruno (.bru text files, comme Postman mais file-based versionable) qui couvre l'API V1 actuelle. Open Collection → bruno/ → sélectionner l'environnement "local". Domaines couverts (22 requêtes) : - 00-Auth : Signup, Login, Logout - 01-Account : Get/Update profile - 02-Organizations : Get/Update my org - 03-Clients : List, List+stats, Search, Create, Create duplicate (409), Create without email (422), Get detail, Update - 04-Plans : List, Get by slug, Update (steps remplacés) - 05-Invoices : List, List+filters, Counts, Create, Get detail, Mark paid Environnement local (bruno/environments/local.bru) : - baseUrl, email/password/fullName en dur - token, userId, organizationId, clientId, invoiceId remplis automatiquement par les script:post-response Chaque requête a : - assertions Chai (statut, shape de la réponse) - bloc docs avec sémantique métier + erreurs typiques - inheritance auth Bearer via folder.bru pour ne pas répéter le header Mise à jour de docs/tech/dev-setup.md pour pointer vers la collection. Le parcours recommandé Signup → Update org → Create client → Create invoice → Mark paid couvre le happy path et permet de checker rubisCount qui s'incrémente. |
||
|
|
1d3b6a3f8f |
chore(api): UUID partout pour les PK et FK
Convention dure : tous les identifiants applicatifs sont des UUID v4 générés par PG (default gen_random_uuid()), aucun increments/serial même pour les tables techniques. - CLAUDE.md → "Conventions techniques" : règle énoncée explicitement (anti-énumération, multi-tenant, génération côté client, dumps propres). - docs/tech/backend.md §4.0 : exemple de migration + raisons. - 4 migrations existantes réécrites en uuid (users, auth_access_tokens, organizations, alter users.organization_id). Les access tokens d'Adonis acceptent un tokenable_id uuid sans changement côté provider. - Transformers nettoyés : plus de String(id), les UUID sont déjà des string. - DB régénérée from scratch (migrations sont éditées avant tout déploiement, pas un cas où un autre dev a une DB en prod). |
||
|
|
a8c7ab539a |
chore(dev): swap mailhog → mailpit (multi-arch, maintenu)
mailhog n'est plus maintenu et ne ship qu'en amd64 — sur Apple Silicon ça déclenche un warning Rosetta. Mailpit est le successeur drop-in (mêmes ports SMTP 1025 / UI 8025), multi-arch, activement maintenu. |
||
|
|
4a6c778e7c |
chore(api): docker-compose dev (PG/Redis/MinIO/Mailhog) + bascule sur Postgres
- docker-compose.dev.yml à la racine : PG 16, Redis 7, MinIO + bucket auto, Mailhog. Ports décalés (5433, 6380, 9100…) pour éviter les collisions locales. - apps/api/config/database.ts : Postgres en default, SQLite reste accessible via DB_CONNECTION=sqlite. - start/env.ts : validation des nouvelles vars (PG, Redis, S3, Mail, OCR, refresh tokens). - .env.example complété, scripts pnpm dev:up/down/logs/reset à la racine. - docs/tech/dev-setup.md pour expliquer la stack locale. |
||
|
|
c52f46468f |
docs: guide d'implémentation backend (docs/tech/backend.md)
Miroir de docs/tech/frontend.md, ancré sur : - Le scaffold Adonis 7 déjà en place (apps/api/) - Le contrat exact que le SPA consomme (handlers MSW = source de vérité du shape attendu) - Les types/schemas dans packages/shared - Les ADR 014 (stack), 015 (monorepo), 016 (PG), 017 (auth), 018 (storage) 20 sections : vue d'ensemble, stack interne, repo layout, domain models (Lucid), routes API par domaine, conventions de réponse, auth Bearer + refresh httpOnly custom, Tuyau, validation Vine, storage MinIO, OCR pipeline, email outbound, background jobs (BullMQ), tests Japa, migrations + seeders, variables d'env, Dockerfile + K3s deployment, pointeurs vers l'existant, ADRs encore à trancher (019 à 025), évolutions V2+. Règle d'or rappelée plusieurs fois : avant de coder un endpoint, regarder le handler MSW correspondant — le SPA est déjà branché à cette surface, c'est exactement ce que l'API doit servir. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
8d3bab6a89 |
feat: scaffold frontend monorepo + first /login screen
Monorepo Turborepo (pnpm workspaces) avec 3 packages :
- apps/web : SPA React 19 + Vite 8 + Tailwind v4 (CSS-first)
• TanStack Router (file-based, auto code-splitting), Query, Form
• Radix primitives bruts + CVA + clsx + tailwind-merge
• MSW pour mocker l'API tant qu'Adonis n'est pas branché
• Polices Bricolage Grotesque + Inter self-hostées via fontsource
• Tokens marque (rubis, cream, ink) exposés via @theme
• Primitives maison : Gem, Brand, Eyebrow, Button, Input, Field
• Route /login full flow : TanStack Form + Zod + mutation Query
- apps/api : Adonis 7 (kit api, scaffold via create-adonisjs)
• Auth access tokens (Bearer) — cf. ADR-017
• Tuyau core déjà câblé pour la génération de types
• Routes /api/v1/auth/{signup,login} + /api/v1/account/{profile,logout}
• Minimal — uniquement le pont front ↔ back
- packages/shared : types TS + schemas Zod + constantes
• Source unique de vérité partagée api ↔ web
• Domaines : User, Org, Auth, Client, Invoice, Plan
Tooling racine : Turbo, ESLint v9 flat, Prettier, husky, lint-staged.
CLAUDE.md et docs/decisions.md mis à jour avec ADR-014 à ADR-018
(stack, monorepo, PG existant, Bearer tokens, MinIO existant)
et le pointeur vers docs/tech/architecture.md.
Logo Rubis déplacé de landing/assets/ vers /assets/ (source unique
réutilisée par la landing et l'app).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|