Skip to content

feat(companies): resolve and set SIREN via VigieProcure - #11

Merged
franckh-stack merged 3 commits into
releasefrom
feat/company-siren-ui
Sep 5, 2026
Merged

feat(companies): resolve and set SIREN via VigieProcure#11
franckh-stack merged 3 commits into
releasefrom
feat/company-siren-ui

Conversation

@franckh-stack

Copy link
Copy Markdown
Owner

Summary

  • Ajoute deux procedures tRPC (companies.resolveSiren, companies.setSiren) qui appellent GET /api/v1/companies/resolve cote api_v2, avec un JWT de service lu depuis l'environnement (jamais un appel non authentifie -- meme doctrine que vigieProcureBridge()/bridge()).
  • Sur la fiche company (apps/app) : affiche le SIREN existant, ou propose de le resoudre sur clic explicite. Un seul candidat confidence: "exact" ecrit automatiquement -- toujours declenche par une action utilisateur (jamais un effet au chargement ni un backfill de masse), doctrine validee par Franck. Sinon, liste les candidats pour choix manuel.
  • Conflit d'unicite (P2002 sur Company.siren, contrainte scopee archivedAt: null) traduit en erreur utilisateur nommant la fiche en conflit, jamais un 500 nu -- procedure dediee avec son propre catch, ne passe pas par companies.update/translate() (qui aurait mappe le conflit sur le mauvais message, celui du domaine).

Variables d'environnement a provisionner (hors perimetre de cette PR -- Franck)

  • VIGIEPROCURE_API_URL (ex. https://api.vigieproc.fr)
  • VIGIEPROCURE_API_JWT -- jeton de service long-lived mint� cote api_v2 (issue_jwt("service:crm-api", ttl_min=...), voir api_v2/services/auth.py), pas genere par cette branche.

Absentes toutes les deux : la fonctionnalite se degrade proprement (outcome: "not-configured", message explicite dans l'UI), jamais un crash ni un appel non authentifie.

Ecart notable

Le diff inclut la regeneration de apps/api/src/generated/server.ts. Cette regeneration corrige au passage une dette preexistante et sans rapport avec ce chantier : excludeEmail/restoreEmail sont declares dans activities.router.ts depuis le commit 044e350 (branche feat/exclude-email-thread, deja mergee dans release) mais le fichier genere n'avait jamais ete rejoue depuis. Verifie en isolant la regeneration sur origin/release non modifie -- meme diff, avant tout changement de ce chantier.

Test plan

  • bun run check-types (13/13 packages, monorepo entier) -- clean
  • bun run lint:slop (oxlint anti-slop) -- clean
  • bun run lint (biome, via le hook pre-push) -- clean
  • Nouveau fichier apps/api/test/vigieprocure-companies-client.spec.ts (7 tests : env absent -> not-configured, 401 -> unauthorized, corps malforme -> degradation propre, mapping d'un candidat exact) -- ne requiert pas de Postgres
  • Suite complete apps/api + apps/app avec Postgres jetable (docker compose up -d + db:test --reset) -- 445/445 et 169/169 respectivement (verifie aussi que Auth (e2e) > lets the sign-in page read what it may offer, un test sensible a l'ordre de chargement d'env preexistant, echoue identiquement sur origin/release non modifie -- pas une regression de cette PR)
  • Aucun build/deploy Docker execute (instruction explicite -- disque /mnt/hermes-extra sur vigiep1 a 97% plein)

🤖 Generated with Claude Code

https://claude.ai/code/session_01LtJccFqpSuP8tQ3Pwg1dYH

franckh-stack and others added 3 commits September 4, 2026 15:24
Ajoute deux procedures tRPC (companies.resolveSiren, companies.setSiren)
qui appellent GET /api/v1/companies/resolve cote api_v2 avec un JWT de
service (VIGIEPROCURE_API_JWT/VIGIEPROCURE_API_URL, meme doctrine que
VIGIEPROCURE_WEBHOOK_URL/_SECRET -- absent = fonctionnalite degradee,
jamais un appel non authentifie).

Sur la fiche company : affiche le SIREN existant, ou propose de le
resoudre sur clic explicite. Un seul candidat "exact" ecrit
automatiquement (exception ciblee et reversible, validee par Franck --
jamais depuis un effet au chargement ni un backfill de masse). Sinon,
liste les candidats pour choix manuel. Conflit d'unicite (P2002 sur
Company.siren) traduit en erreur utilisateur nommant la fiche en
conflit, jamais un 500 nu.

Inclut la regeneration de apps/api/src/generated/server.ts, qui
corrige au passage une dette preexistante (excludeEmail/restoreEmail
declares dans activities.router.ts depuis le commit 044e350 mais
jamais regeneres).

A provisionner separement (hors perimetre de ce chantier) :
VIGIEPROCURE_API_URL, VIGIEPROCURE_API_JWT sur crm-api en production.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LtJccFqpSuP8tQ3Pwg1dYH
- companySetSirenInput.siren: .length(9) laissait passer 9 caracteres
  non numeriques alors que le message annoncait "9 digits" -- .regex
  le fait respecter reellement.
- companySetSirenOutput (conflict): conflictingCompanyId/Name n'etaient
  consommes nulle part cote frontend (seul `reason` est lu), et le
  fallback `conflicting?.id ?? ""` etait un `z.string()` non-nullable
  rempli d'une chaine vide dans un cas quasi mort (le findFirst est
  scope par la meme contrainte unique partielle que le P2002 qui
  declenche ce chemin). Retire les deux champs plutot que de les
  rendre nullable pour un consommateur qui n'existe pas.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LtJccFqpSuP8tQ3Pwg1dYH
@franckh-stack
franckh-stack merged commit 32b7f2b into release Sep 5, 2026
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.

1 participant