Commit Graph

774 Commits

Author SHA1 Message Date
Colin Maudry 03afb8347c feat(mcp): instructions OAuth Claude.ai/ChatGPT sur /compte/mcp (#114)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 14:43:01 +02:00
Colin Maudry 34a8470792 feat(mcp): migrations OAuth/usage + câblage app.py (#114)
Ajoute les migrations 0008-0011 (oauth_clients, oauth_codes,
oauth_tokens, mcp_usage) et câble le serveur d'autorisation OAuth 2.1
dans le bloc DASH_MCP_ENABLED de app.py : init des schémas oauth/usage,
purge périodique, enregistrement des routes /oauth et /.well-known, et
exemption CSRF de ces routes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 14:38:33 +02:00
Colin Maudry 8258b92f98 feat(mcp): garde /_mcp unifié statique+OAuth, audience & usage (#114)
Le garde before_request de /_mcp accepte désormais les jetons OAuth
opaques (store.get_token_by_access) en plus des jetons statiques
colibre_*, avec vérification d'audience (resource == mcp_resource)
et d'expiration. Le 401 porte resource_metadata pour le découverte
RFC 9728. Sur succès, incrémente le compteur du bon store et
journalise dans mcp_usage (best-effort).

Corrige aussi une régression d'assertion stricte sur le header
WWW-Authenticate dans test_app_wiring.py, cassée par le nouveau
suffixe resource_metadata.
2026-07-13 14:32:49 +02:00
Colin Maudry 4e3c8517ad feat(mcp): flux OAuth authorize+token avec gate abonnement (#114)
Remplace le stub 501 de src/mcp/oauth/authorize.py par le flux réel
authlib (GET consentement, POST émission de code, échange de token),
avec gate d'abonnement avant tout affichage du consentement.

Deux ajustements de compatibilité authlib 1.7.2 dans server.py,
découverts en exécutant le flux bout-en-bout pour la première fois :
AUTHLIB_INSECURE_TRANSPORT en mode DEVELOPMENT (le client de test
Flask ne sert pas en HTTPS) et OAUTH2_REFRESH_TOKEN_GENERATOR (off
par défaut côté Flask, requis pour émettre les refresh_token du scope
offline_access). Détails dans .superpowers/sdd/task-9-report.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 14:27:58 +02:00
Colin Maudry 633462f18b feat(mcp): routes découverte + DCR + révocation OAuth (#114) 2026-07-13 14:19:49 +02:00
Colin Maudry ca2f6746f8 fix(mcp): refresh renvoie invalid_grant si abonnement perdu (#114) 2026-07-13 14:17:23 +02:00
Colin Maudry 0970803e5e feat(mcp): configuration authlib (grants + PKCE + DCR, #114)
- AuthorizationCodeGrant avec PKCE requis (CodeChallenge), RefreshTokenGrant
  avec rotation + re-vérification d'abonnement, DCR (ClientRegistrationEndpoint)
  et révocation (RevocationEndpoint) câblés sur le store sqlite (Tasks 1-3),
  metadata (Task 5) et consent.subscription_ok (Task 6).
- _Token (dict + check_client/get_scope) fait le pont entre les rows sqlite
  bruts et le protocole TokenMixin qu'authlib 1.7.2 attend pour le refresh
  et la révocation.
2026-07-13 14:12:03 +02:00
Colin Maudry 7dea07a30f feat(mcp): gate abonnement + écrans de consentement OAuth (#114)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 14:04:22 +02:00
Colin Maudry c693992041 feat(mcp): documents de découverte OAuth (RFC 9728/8414, #114)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 14:00:30 +02:00
Colin Maudry db0550a170 feat(mcp): journal d'usage mcp_usage (détection niveau 1, #114)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 13:56:08 +02:00
Colin Maudry 13538a4f41 feat(mcp): store OAuth — tokens access/refresh + usage (#114)
Implements OAuth token management functions for Task 3:
- save_token: persists access/refresh tokens with hashing
- get_token_by_access/refresh: retrieves tokens by their hashes
- increment_usage: tracks token usage count and last_used_at
- revoke_token: sets revoked_at timestamp

All 3 tests passing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 13:51:55 +02:00
Colin Maudry adbaffe545 feat(mcp): store OAuth — codes d'autorisation (#114)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 13:48:42 +02:00
Colin Maudry f6132d41a2 feat(mcp): store OAuth — schéma + clients DCR (#114)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 13:45:12 +02:00
Colin Maudry 8b3e72d20a MCP uniquemnet pour les clients CLI 2026-07-13 12:53:14 +02:00
Colin Maudry 7d413ccda4 feat(titulaire): migration du tableau des marchés vers AG Grid (#41) 2026-07-13 12:03:37 +02:00
Colin Maudry 639c2eb986 feat(acheteur): migration du tableau des marchés vers AG Grid (#41) 2026-07-13 12:03:37 +02:00
Colin Maudry 0d2ad33d6c fix(entity_grid): allow_duplicate sur le store columnState partagé (collision acheteur/titulaire) (#41)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 12:03:37 +02:00
Colin Maudry 2454c8109f feat(entity_grid): register_entity_grid_callbacks (datasource/reset/export/meta) (#41) 2026-07-13 12:03:37 +02:00
Colin Maudry 76c1096f4c feat(entity_grid): fonctions pures de grille scopée acheteur/titulaire (#41) 2026-07-13 12:03:37 +02:00
Colin Maudry 94addf7fae feat(figures): get_top_org_ag_grid (top 10 en AG Grid client-side) (#41) 2026-07-13 12:03:37 +02:00
Colin Maudry 0c22138e19 feat(figures): ag_grid() paramétrable (id dict + persisted_props) (#41)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 12:03:37 +02:00
Colin Maudry 495fe153b1 feat(grid): export_dataframe scopable par base_where_sql/base_params (#41) 2026-07-13 12:03:37 +02:00
Colin Maudry 10c1e45d71 Update version de Dash dans CLAUDE.md 2026-07-13 12:01:00 +02:00
Colin Maudry f2810640ba %àj instructions clients MCP 2026-07-13 09:25:39 +02:00
Colin Maudry 04125f91f8 Ajout du tool schema_donnees 2026-07-13 09:23:33 +02:00
Colin Maudry b4e778ab8c Mode d'emploi tableau 2026-07-13 07:50:34 +02:00
Colin Maudry 445c8666cf Valeurs possibles dans la description des champs 2026-07-13 07:36:54 +02:00
Colin Maudry 26de687ece Améliorations sur le style de l'ag grid, ajout nb marchés uniques #47 2026-07-13 06:38:58 +02:00
Colin Maudry 6e9b451734 feat(tableau): réserver l'espace de la barre de défilement horizontale AG Grid
alwaysShowHorizontalScroll force la piste de scroll à rester visible
en permanence (comportement déjà natif sous Chrome). Sans effet sur
Firefox, dont le curseur en overlay est géré par l'OS/le navigateur
et non contrôlable côté appli (#41).
2026-07-12 20:45:23 +02:00
Colin Maudry 6dd7dca271 Améliorations sur le style de l'ag grid, ajout nb marchés uniques #47 2026-07-12 20:44:43 +02:00
Colin Maudry f580459bd5 Améliorations sur le style de l'ag grid #47 2026-07-11 16:58:36 +02:00
Colin Maudry 117ce9a4ab fix(tableau): filtres à conditions multiples ignorés + tri non réinitialisé (#41)
Deux bugs découverts en usage réel sur /tableau :

1. filtermodel_to_ast lisait condition1/condition2 pour un filtre à
   deux conditions (ET/OU) sur une colonne — mais AG Grid >=29.2 (la
   version 35.2.0 utilisée ici) encode ça via une liste `conditions`,
   confirmé par la doc Dash AG Grid "Filter Model & Dash Callbacks" >
   "Filter Model Multiple Conditions". Le filtre était donc
   silencieusement ignoré (colonne exclue du AST, comme si aucun
   filtre n'était posé), d'où des résultats sans rapport avec les
   valeurs saisies. Corrigé : filtermodel_to_ast lit désormais
   `conditions` (N éléments) en priorité, avec repli sur
   condition1/condition2 (forme dépréciée mais "still accepted" selon
   AG Grid). L'inverse (ast_to_filtermodel, utilisé au rappel d'une
   vue sauvegardée) produit aussi la forme `conditions`.

2. Le bouton "Réinitialiser" ("Supprime tous les filtres et les tris")
   ne réinitialisait que filterModel, jamais le tri. Corrigé via
   resetColumnState (remet les colonnes à l'état de columnDefs, qui
   reflète déjà la visibilité choisie via le sélecteur de colonnes —
   seul le tri est donc affecté).

Reproduit et corrigé en TDD (tests/test_query_ast.py,
tests/test_grid.py), vérifié manuellement en navigateur par l'auteur
du rapport de bug.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 20:21:53 +02:00
Colin Maudry 4e07c69a85 feat(tableau): traduire les libellés de filtre AG Grid en français (#41)
Menu de filtre de colonne (Contient, Égal à, Vide, ET/OU, etc.) traduit
via l'option native AG Grid localeText, exposée par dashGridOptions.
N'affecte pas l'apparence de base conservée au Lot 1 (aucun thème/CSS
custom) — uniquement le texte des libellés.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 19:43:13 +02:00
Colin Maudry 34e5065550 Merge branch 'worktree-111-mcp-connecteur' into dev (connecteur MCP, scope B #111) 2026-07-10 16:13:06 +02:00
Colin Maudry 71ad4dd1ca fix(mcp): apply_pending tolère l'absence de api_tokens (migration 0007, scope B #111) 2026-07-10 15:19:58 +02:00
Colin Maudry ff78b86ad0 feat(mcp): page compte Connecteur MCP + instructions clients (scope B #111)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 15:16:36 +02:00
Colin Maudry 4dbe986310 feat(mcp): blueprint création/révocation de jetons MCP (scope B #111) 2026-07-10 15:08:24 +02:00
Colin Maudry ec45dc05ec feat(mcp): l'API REST refuse les jetons kind=mcp (scope B #111) 2026-07-10 15:04:46 +02:00
Colin Maudry 4f18cc07f2 feat(mcp): câble le garde /_mcp + exemption CSRF dans l'app (scope B #111) 2026-07-10 15:00:53 +02:00
Colin Maudry 697711f676 feat(mcp): garde d'abonnement sur /_mcp (scope B #111) 2026-07-10 14:46:50 +02:00
Colin Maudry 4f36022443 fix(tableau): vues sauvegardées en AST canonique, cache du comptage, synchro visibilité colonnes (#41) 2026-07-10 14:44:14 +02:00
Colin Maudry 2318702e29 feat(mcp): migration 0007 kind + init schema jetons au démarrage (scope B #111) 2026-07-10 14:43:43 +02:00
Colin Maudry 647d7a7759 feat(mcp): colonne kind + fonctions jetons par utilisateur (scope B #111) 2026-07-10 14:39:02 +02:00
Colin Maudry 0bfac680a5 fix(tableau): vues sauvegardées pré-migration + double comptage track_search (#41)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 14:34:47 +02:00
Colin Maudry 055b0edc7e docs(tableau): mode d'emploi réécrit pour AG Grid (#41)
Décrit les filtres de colonne AG Grid (flottant/entonnoir, texte/numérique/
date, combinaison ET/OU), le tri multi-colonne (Maj+clic) et le défilement
infini, à la place de l'ancienne syntaxe icontains/i</i> et des liens
d'exemple ?filtres=... (mécanisme retiré à la tâche 10). Retire la ligne
"Partager la vue" de la légende des boutons (bouton supprimé).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 13:53:19 +02:00
Colin Maudry 8efd8db07e feat(tableau): vues sauvegardées en JSON AST, retrait URL riche (#41)
Les vues stockent désormais {filterModel, columnState} en JSON dans
saved_views.query au lieu d'une query string DSL. Le rappel d'une vue
applique filterModel + columnState à la grille AG Grid via un nouveau
callback apply_saved_view, déclenché par pattern-matching sur les items
du menu "Mes vues" (désormais cliquables au lieu de liens href).

Retire restore_view_from_url, sync_url_and_reset_button,
show_confirmation, le bouton "Partager la vue" et le clientside
clean_filters de tableau.py - la migration AG Grid retire le mécanisme
d'URL riche sans rétrocompatibilité.

Le lien "Ouvrir" de compte/vues.py pointe maintenant vers /tableau nu
(limitation connue documentée, le rappel cross-page reste à faire).
2026-07-10 08:35:31 +02:00
Colin Maudry fbea2ebd53 feat(tableau): export Excel via DuckDB (AST->SQL) (#41)
Rewrite download_data to read filterModel/columnState from the AG Grid
component and add export_dataframe (compiles filterModel to SQL via
filtermodel_to_ast/ast_to_sql, builds ORDER BY, excludes hidden columns,
queries DuckDB via query_marches). Replaces the old Polars filter_query
pipeline tied to the removed DataTable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 08:26:10 +02:00
Colin Maudry 436906911b feat(tableau): sélecteur de colonnes piloté par columnDefs (#41)
apply_hidden_columns régénère columnDefs (via grid_column_defs) sur
tableau_grid quand le Store tableau-hidden-columns change, remplaçant
store_hidden_columns qui ciblait l'ancienne prop hidden_columns de la
DataTable (supprimée en tâche 7). update_checkboxes_from_hidden_columns
lit désormais directement le Store plutôt que la prop de la DataTable
disparue, pour que la synchronisation cases à cocher <-> colonnes
masquées continue de fonctionner.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 08:17:44 +02:00
Colin Maudry 4c1c1cc987 feat(tableau): grille AG Grid + datasource getRows server-side (#41)
Remplace le composant DataTable et le callback update_table de tableau.py
par la grille dash-ag-grid (mode ligne infini) et un callback get_rows_tableau
piloté par getRowsRequest/getRowsResponse, plus un callback update_meta qui
synchronise nb_rows/btn-download-data/download-hint via un dcc.Store du total.

Les autres callbacks de la page (sélecteur de colonnes, vues sauvegardées,
export, restauration URL, aide) référencent encore les anciens
id/props (tableau_datatable, hidden_columns, filter_query, sort_by) et seront
mis à jour dans les tâches suivantes (8-11) du plan de migration #41.
2026-07-10 08:11:06 +02:00
Colin Maudry 97e1d0b5de feat(grid): columnDefs + fabrique ag_grid (#41) 2026-07-10 08:05:19 +02:00