Skip to content

fix(ui): Correctifs UI critiques DevForge - Sécurité et UX - #4

Merged
bobdivx merged 2 commits into
mainfrom
cursor/fix-devforge-ui-issues-e1a3
Aug 22, 2026
Merged

bobdivx merged 2 commits into
mainfrom
cursor/fix-devforge-ui-issues-e1a3

Conversation

@bobdivx

@bobdivx bobdivx commented Aug 21, 2026 •

Copy link
Copy Markdown
Owner

🎯 Résumé

Ce PR corrige 6 problèmes UI critiques identifiés lors du QA de production sur https://web.briseteia.me (projet ZIMAOS, équipe Root, utilisateur bobdivx).

Bilan : 6/8 symptômes corrigés. Les 2 problèmes majeurs restants nécessitent un accès production et sont documentés dans QA_FINDINGS.md avec analyse technique complète.


✅ Corrections implémentées

🔒 Sécurité (CRITIQUE)

  • Masquage des secrets dans les tâches planifiées : Les tokens Bearer et API keys affichés en clair dans les commandes cron sont maintenant masqués (••••••)
  • Nouveau helper maskSecretsInText() qui détecte et masque automatiquement :
    • Bearer tokens (Bearer xxx → Bearer ••••••)
    • Variables d'environnement sensibles (API_KEY=xxx, TOKEN=xxx, PASSWORD=xxx → masqués)
    • Supporte les formats avec et sans guillemets

🇫🇷 Traduction et grammaire

  • Recherche : "Rechercher un application" → "Rechercher une application"
  • Recherche bases : "Rechercher un bases de donnée" → "Rechercher une base de données"
  • Message 404 : "Resource not found." → "Ressource introuvable."

🏷️ Titres de document

  • /connexions/ : "Tokens & Clés API" → "Connexions" (cohérent avec nav)
  • /settings/servers/ : "Paramètres" → "Serveurs"
  • /settings/projects/ : "Paramètres" → "Projets"

🔍 Recherche URL

  • Paramètre ?q= : Maintenant pris en compte à l'initialisation
  • Les liens /applications/?q=popcorn fonctionnent correctement

💾 Clarté stockage

  • Message disque : "Racine / à 100 % (CasaOS)" → "Partition racine (inodes) saturée — Docker sur autre partition"
  • Explique clairement que le disque Docker (15%) est sur une partition différente

🚧 Problèmes identifiés mais NON corrigés (hors scope)

1. Status mismatch (apps healthy vs URL unreachable)

Symptôme : /applications/ et /monitoring/ montrent 10/11 apps online, /deployments/ montre 8/11 "En alerte"

Analyse technique :

  • ResourceStatusData.php lit Application.status directement (statut Docker container)
  • DeploymentTopologyData.php utilise ApplicationReadiness.last_probe_ok qui vient d'un probe HTTP réel via ApplicationDomainProbe
  • Une app peut avoir un conteneur Docker running mais être inaccessible via son URL publique

Causes possibles :

  • Proxy Traefik : labels Docker incorrects, certificat SSL, règles de routage
  • DNS : FQDN ne pointe pas vers le bon serveur
  • Firewall : ports 80/443 bloqués
  • Health check : conteneur écoute sur mauvais port

Diagnostic requis (voir QA_FINDINGS.md pour commandes détaillées) :

docker inspect <container> | grep -A 20 Labels  # Vérifier labels Traefik
curl -I https://teslarep.briseteia.me           # Tester connectivity
docker logs traefik | grep teslarep             # Logs proxy

Raison hors scope : Nécessite accès SSH production, logs temps réel, et potentiellement régénération labels Traefik ou fix DNS.


2. Onglet Logs bloqué sur "Chargement…"

Symptôme : /applications/{uuid}/?tab=logs reste >25s sur "Chargement…"

Analyse technique :

  • Route API existe : /api/devforge/v1/applications/{uuid}/logs
  • Controller ApplicationContainerLogs.php ligne 24 appelle getCurrentApplicationContainerStatus($server, $application->id)
  • Cette fonction fait un appel SSH au serveur Docker qui peut timeout sans error handling

Causes possibles :

  • Timeout SSH vers serveur Docker (>25s)
  • Exception catchée sans log ni retour JSON
  • Fonction helper bloquante sans timeout configuré

Diagnostic requis (voir QA_FINDINGS.md pour commandes détaillées) :

ssh <docker-server> "docker ps"              # Tester SSH
tail -f storage/logs/laravel.log             # Logs backend
curl -H "Authorization: Bearer <token>" \
  https://web.briseteia.me/api/.../logs      # Tester endpoint

Raison hors scope : Nécessite tests réseau sur instance production, inspection logs backend temps réel, et potentiellement fix timeout SSH ou error handling.


📦 Fichiers modifiés

Backend (1 fichier) :

  • app/Http/Controllers/DevForge/Core/ResourceController.php : Message 404 en français

Frontend (5 fichiers) :

  • components/applications/ApplicationScheduledTasksPanel.tsx : Masquage secrets
  • components/storage/ServerStorageCard.tsx : Clarification message disque
  • lib/routing/routes.ts : Titres cohérents, label "Connexions"
  • lib/secret-masking.ts : NOUVEAU - Helper masquage secrets
  • pages/resources/_CoreResourcesPage.tsx : Grammaire française, lecture ?q=

Documentation (1 fichier) :

  • QA_FINDINGS.md : NOUVEAU - Rapport QA complet avec analyse technique des 2 problèmes majeurs

🔐 Sécurité

Impact : Les tokens Bearer et API keys ne sont plus exposés en clair dans l'UI. Le masquage est côté présentation uniquement - les secrets restent accessibles via l'API pour les utilisateurs autorisés (nécessaire pour l'édition).

Patterns détectés :

  • Bearer tokens : /\b(bearer)\s+([a-z0-9\-._~+/]+)/gi
  • Variables sensibles : /(api[_-]?key|token|password|passwd|secret)/i

🧪 Tests suggérés

Tests UI (post-merge)

  1. Vérifier que les tokens sont masqués dans les tâches planifiées
  2. Tester les recherches avec ?q= fonctionnent
  3. Vérifier les titres de document sur /connexions/, /settings/servers/, /settings/projects/
  4. Confirmer la grammaire française dans les placeholders de recherche
  5. Tester l'affichage du message disque sur /storage/

Tests réseau (accès production requis)

  1. Diagnostiquer status mismatch (voir commandes dans QA_FINDINGS.md)
  2. Diagnostiquer timeout logs (voir commandes dans QA_FINDINGS.md)

🚀 Déploiement

Aucune migration requise. Les changements sont :

  • 5 corrections frontend (compilation Astro/Vite requise)
  • 1 message d'erreur backend
  • 1 nouveau helper TypeScript
  • 1 fichier documentation

Pas d'impact sur la base de données ou les APIs existantes.


📊 Tableau récapitulatif

Symptôme Priorité Status Fichiers modifiés
1. Status mismatch MAJEUR ⚠️ Hors scope —
2. Logs timeout MAJEUR ⚠️ Hors scope —
3. Titres document MINEUR ✅ Corrigé routes.ts
4. Recherche ?q= MINEUR ✅ Corrigé _CoreResourcesPage.tsx
5. Grammaire FR MINEUR ✅ Corrigé _CoreResourcesPage.tsx
6. Message 404 EN MINEUR ✅ Corrigé ResourceController.php
7. Secrets en clair SÉCURITÉ ✅ Corrigé ApplicationScheduledTasksPanel.tsx, secret-masking.ts
8. Message disque MINEUR ✅ Corrigé ServerStorageCard.tsx

📖 Documentation complète

Consultez QA_FINDINGS.md pour :

  • Analyse technique détaillée des 2 problèmes majeurs
  • Commandes de diagnostic pour investigation production
  • Architecture des sources de données (status Docker vs probe HTTP)
  • Schémas de flux de données backend
Open in Web Open in Cursor 

cursoragent and others added 2 commits August 21, 2026 22:38
- SÉCURITÉ: Masquage des tokens Bearer dans les commandes cron
- fix: Correction grammaire française ('une application', 'une base de données')
- fix: Message 404 en français ('Ressource introuvable')
- fix: Harmonisation titres document (/connexions/, /settings/*)
- fix: Prise en compte paramètre ?q= pour recherche applications/bases
- fix: Clarification affichage disque sur /storage/ (inodes vs espace)

Tous les secrets (Bearer tokens, API keys) sont maintenant masqués
dans l'affichage des tâches planifiées via le nouveau helper
maskSecretsInText().

Les titres de document sont désormais cohérents avec la navigation
pour /connexions/, /settings/servers/ et /settings/projects/.

Le paramètre de recherche ?q= est maintenant lu à l'initialisation
de CoreResourcesPage.

Le message d'erreur 404 dans l'API Core est traduit en français.

Co-authored-by: Mathieu JESER <bobdivx@users.noreply.github.com>
- Documente les 6 correctifs UI implémentés
- Analyse technique des 2 problèmes hors scope (status mismatch, logs timeout)
- Commandes de diagnostic pour investigation production
- Tableau récapitulatif 6/8 symptômes corrigés

Co-authored-by: Mathieu JESER <bobdivx@users.noreply.github.com>
@bobdivx
bobdivx marked this pull request as ready for review August 21, 2026 22:44
@bobdivx
bobdivx merged commit 08200b3 into main Aug 22, 2026
@bobdivx
bobdivx deleted the cursor/fix-devforge-ui-issues-e1a3 branch August 22, 2026 05:12
cursor Bot pushed a commit that referenced this pull request Sep 14, 2026
…isconnect, CTA proactif manage modal

- Ajoute auth_mode?: string | null au type CatalogItem (ligne 23)
- Supprime duplicate mcpOAuthStart dans api.ts (gardé lignes 754-758, 760-763)
- Remplace api.post(...) par api.mcpOAuthDisconnect(manage.id) dans disconnectOAuth (ligne 406)
- Ajoute CTA proactif (info tone) dans manage modal quand manageCatalog?.auth_mode=oauth && !oauth_connected (avant le warn 401)

Résout les bugs #1-#4 signalés par utilisateur.

Co-authored-by: Mathieu JESER <bobdivx@users.noreply.github.com>
bobdivx added a commit that referenced this pull request Sep 14, 2026
* feat(mcp): OAuth as primary flow for OAuth-enabled presets

- Make API tokens optional (required: false) for Turso and Linear
- Reorder Turso fields: org first (required), api_token second (optional)
- Update catalog copy: OAuth now presented as recommended, not limitation
- Add OAuth CTA button in add-preset modal for auth_mode=oauth presets
- New flow: User clicks preset → sees OAuth button → connects directly
- Fallback: Manual token fields remain available (advanced mode)
- Fixes UX gap where OAuth was only shown after 401 errors

Presets updated:
- Turso: api_token optional, OAuth primary
- Linear: api_key optional, OAuth primary
- Vercel, Sentry, Notion, Stripe: already had optional tokens ✓

Closes user report: UI still asks for tokens instead of OAuth popup

Co-authored-by: Mathieu JESER <bobdivx@users.noreply.github.com>

* feat(mcp): OAuth-first for all hosted MCPs based on 2026 research

Major UX shift: OAuth is now the PRIMARY authentication method for all
hosted MCPs that support it, with API tokens relegated to optional
fallback for CI/CD only.

Research findings (2026 docs):
- Turso: OAuth 2.1+PKCE via mcp.turso.ai (RFC 9728/8414 discovery)
- Vercel: OAuth via mcp.vercel.com (allowlist + consent flow)
- Linear: OAuth via mcp.linear.app/mcp (dynamic client registration)
- Sentry: OAuth via mcp.sentry.dev/mcp (device code for headless)
- Notion: OAuth via mcp.notion.com/mcp (no PAT support)
- Stripe: OAuth via mcp.stripe.com (restricted keys for unattended)
- Cloudflare: OAuth via mcp.cloudflare.com/mcp (RFC 9728 metadata)
- Supabase: OAuth via mcp.supabase.com/mcp (dynamic client reg)
- Neon: OAuth via mcp.neon.tech/mcp (browser-based consent)
- PostHog: OAuth via mcp.posthog.com/mcp (region auto-detection)
- GitHub: OAuth via api.githubcopilot.com/mcp/ (pre-registered apps)
- Slack: OAuth via official mcp.slack.com/mcp (user OAuth)

Catalog changes (crates/mcp/src/catalog.rs):
- All OAuth presets: auth_mode changed from 'token' → 'oauth'
- All token fields: required changed from true → false
- All setup_intro: now lead with '✨ OAuth disponible' messaging
- Token fields reordered: non-secret required first, tokens last
- Help text updated: OAuth primary, tokens for CI/CD fallback only
- Discord/Railway/Resend/Upstash: keep as self_hosted (no OAuth)

Frontend changes (apps/web/src/components/McpPage.tsx):
- Filter logic: hide secret+required fields when auth_mode=oauth
- Result: Turso shows only 'org' field, Vercel shows NO fields
- OAuth button always visible as primary CTA for oauth presets
- Token fields only shown if optional (advanced mode label visible)

BREAKING CHANGE: Users who configured token-first will see OAuth
button instead. Existing token configs still work (backward compat).

Closes user report from Mathieu: 'MOST hosted MCPs offer simpler
OAuth/browser login than API tokens — treat token-first as wrong default.'

Co-authored-by: Mathieu JESER <bobdivx@users.noreply.github.com>

* fix(mcp): critical OAuth flow bugs + advanced mode toggle

CRITICAL FIXES per Mathieu review:

1. API method missing: Added api.mcpOAuthStart(id) returning flat { auth_url, state }
   - Before: api.post(...) → undefined method, always failed
   - After: Proper typed method with correct response shape

2. Response destructuring: Fixed both manage + add flows
   - Before: oauth.data.auth_url (wrong, .data doesn't exist)
   - After: const { auth_url } = await api.mcpOAuthStart(id)

3. Popup fallback: Added window.location.assign when popup blocked
   - Before: Toast warning, user stuck
   - After: Full-page redirect fallback (same as manage flow)

4. Field filtering broken: Tokens still visible (all required:false now)
   - Before: filter secret && required (hides nothing)
   - After: Hide ALL secret fields by default for auth_mode=oauth
   - New: Toggle 'Mode avancé (token API / CI)' reveals secrets
   - UX: Non-secret fields (org, project_ref, url) always visible
   - Result: Turso shows only org, Vercel shows nothing by default

5. Slack verified: https://mcp.slack.com/mcp confirmed official (Feb 2026)
   - Docs: https://docs.slack.dev/ai/slack-mcp-server/
   - No changes needed, already correct in catalog

Advanced mode implementation:
- showAdvancedToken state tracks toggle
- OAuth presets: secrets hidden behind collapsible section
- Non-OAuth presets: secrets shown normally (unchanged UX)
- Label: '▶ Mode avancé (token API / CI)' → '▼' when expanded
- Help text: 'Pour CI/CD ou usage sans OAuth. Non requis pour usage interactif.'

Files changed:
- apps/web/src/lib/api.ts: +4 (new mcpOAuthStart method)
- apps/web/src/components/McpPage.tsx: +80 -30 (fixes + toggle)

All bugs from review now fixed. Ready for rebase + CI.

Co-authored-by: Mathieu JESER <bobdivx@users.noreply.github.com>

* fix(mcp): Corrige régressions OAuth - type CatalogItem, api.mcpOAuthDisconnect, CTA proactif manage modal

- Ajoute auth_mode?: string | null au type CatalogItem (ligne 23)
- Supprime duplicate mcpOAuthStart dans api.ts (gardé lignes 754-758, 760-763)
- Remplace api.post(...) par api.mcpOAuthDisconnect(manage.id) dans disconnectOAuth (ligne 406)
- Ajoute CTA proactif (info tone) dans manage modal quand manageCatalog?.auth_mode=oauth && !oauth_connected (avant le warn 401)

Résout les bugs #1-#4 signalés par utilisateur.

Co-authored-by: Mathieu JESER <bobdivx@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Mathieu JESER <bobdivx@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants