Correctifs veille RSS, notifications, agents IA et catégories#96
Merged
Conversation
Les flux RSS français (marchesonline.com, BOAMP...) sont souvent publiés en ISO-8859-1/Windows-1252. Le sondeur les récupérait avec responseType 'text', ce qui forçait un décodage UTF-8 et corrompait les caractères accentués (ex. "déchèterie" -> "d�ch�terie"). Le flux est maintenant récupéré en octets bruts puis décodé avec l'encodage réellement déclaré (en-tête HTTP ou prologue XML) via iconv-lite. Corrige aussi l'affichage "Invalid Date" dans la liste et la fiche détail des appels d'offres lorsque la date limite de soumission est vide (cas d'une annonce RSS convertie en appel d'offre sans date structurée). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DT2bkCp3f7xKaNfsxC4Kb
…les activités "Marquer tout comme lu" écrivait notifications_last_seen sur team_members, filtré par auth_user_id + tenant_id. team_members est un roster séparé qui n'a pas forcément de ligne pour chaque utilisateur authentifié, donc l'UPDATE ne touchait parfois aucune ligne : le prochain rafraîchissement du fil (30s) recalculait "non lu" à partir d'une valeur jamais mise à jour. Ce suivi est déplacé vers profiles, qui a garantiment une ligne par utilisateur (clé primaire = auth.users.id). Le nom de l'élément créé/modifié dans "Notifications & Flux d'activité" est maintenant un lien vers l'élément quand sa page existe (projet, appel d'offres, CCTP...), ou vers la liste correspondante sinon. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DT2bkCp3f7xKaNfsxC4Kb
…vé par défaut Nouvelle capacité distincte de action_scopes (qui ne couvre que les ressources CRUD internes) : un toggle par agent, dans sa page de configuration, autorise l'outil Gemini fetch_url à récupérer le contenu texte d'une page web publique. Off par défaut, jamais hérité d'un template, avec un avertissement de sécurité explicite dans l'UI. La récupération (packages/archioffice-agents/src/server/webFetch.ts) résout le nom d'hôte et rejette les adresses privées/loopback/lien-local (dont les endpoints de métadonnées cloud), à chaque saut de redirection, avant toute requête sortante — limite le risque SSRF d'un outil qui, contrairement aux autres, fait un vrai appel réseau externe plutôt que de boucler sur l'API interne de l'app. Le contenu récupéré est explicitement présenté au modèle comme une donnée à analyser, jamais comme des instructions à suivre. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DT2bkCp3f7xKaNfsxC4Kb
…jets) contact_categories et project_categories portaient une contrainte UNIQUE (name) globale, reliquat d'avant le multi-tenant : dès qu'un tenant créait une catégorie dont le nom était déjà pris par un AUTRE tenant (ex. "Fournisseur", "Client"), l'insertion échouait en base avec "duplicate key value violates unique constraint" et l'API renvoyait 500 sans détail (confirmé via les logs Postgres). La contrainte est maintenant scopée par tenant : UNIQUE (tenant_id, name). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DT2bkCp3f7xKaNfsxC4Kb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Suite de correctifs et une nouvelle fonctionnalité opt-in, en continuation de la veille RSS des appels d'offres (PR #95, déjà mergée) :
Encodage RSS + date manquante (
server/tenderRssPoller.ts,src/pages/Tenders.tsx,src/pages/TenderDetail.tsx) — les flux RSS français souvent publiés en ISO-8859-1/Windows-1252 étaient mal décodés (caractères accentués corrompus). Le flux est maintenant récupéré en octets bruts puis décodé avec l'encodage réellement déclaré (en-tête HTTP ou prologue XML) viaiconv-lite. Corrige aussi l'affichage "Invalid Date" quand la date limite de soumission est vide."Marquer tout comme lu" qui ne persiste pas + liens sur les activités (
server.ts,src/pages/Notifications.tsx) — le suivi de lecture était écrit surteam_members(roster séparé sans ligne garantie par utilisateur), donc la mise à jour ne persistait pas toujours. Déplacé versprofiles(une ligne garantie par utilisateur authentifié). Le nom de l'élément créé/modifié dans le fil d'activité est maintenant un lien cliquable vers l'élément (ou sa liste).Accès web optionnel pour les agents IA (
packages/archioffice-agents/) — nouvel outilfetch_urlgated par un toggle par agent (web_fetch_enabled, off par défaut, jamais hérité d'un template), avec avertissement de sécurité explicite dans l'UI de configuration. Protections anti-SSRF danswebFetch.ts: résolution DNS + rejet des adresses privées/loopback/lien-local à chaque saut de redirection, timeout, plafond de taille de réponse, et instruction explicite au modèle de traiter le contenu récupéré comme une donnée, pas des instructions.Contrainte unique globale sur les catégories (
supabase/migrate_fix_categories_unique_per_tenant.sql) —contact_categoriesetproject_categoriesavaient une contrainteUNIQUE (name)globale (reliquat d'avant le multi-tenant), causant un 500 dès qu'un tenant utilisait un nom de catégorie déjà pris par un autre tenant. Corrigé enUNIQUE (tenant_id, name).Toutes les migrations Supabase associées ont déjà été appliquées manuellement sur le projet de production pendant le développement.
Test plan
npm run lint(tsc --noEmit) passe sans erreurhttps://claude.ai/code/session_013DT2bkCp3f7xKaNfsxC4Kb
Generated by Claude Code