Technique · ProgrammesReprise développeur

Programmes par application

Architecture des programmes et des fonctions — de quoi reprendre chaque application rapidement : point d'entrĂ©e, DI, pipeline, endpoints, services et flux clĂ©s.

Convention. Chaque application = une solution .NET indépendante sous D:\Dev2026\. Toutes exposent leur front via la passerelle (sous-domaine) et lisent l'identité via Identité/Keycloak.

IIQARION Factures (THEIA) — D:\Dev2026\Theia

RÎle : facturation électronique Factur-X, gestion commerciale ventes/achats, stock, PDP. Stack : .NET 10, Razor Pages + API Controllers, EF Core / PostgreSQL.

Structure de la solution

ProjetRĂŽle
Theia.CoreDomaine (entités, enums), Factur-X pur (FacturX/ : GenerateurCii, LecteurCii, AssembleurFacturX PDF/A-3, GenerateurPdf QuestPDF, ValidateurFacturX, MetadataXmp) et moteur de taxes (Taxes/MoteurTaxes). Sans IO.
Theia.StoragePersistance EF (TheiaDbContext) + services métier : ServiceFacturation, ServiceStock, ServiceBonsCommande/Livraison, ServiceRapprochement, ServiceEmail, ServiceSuppression, ServiceEReporting (brouillard de caisse), MigrateurLeger, DonneesInitiales.
Theia.WebUIHÎte web (point d'entrée) : Razor Pages + Controllers API /api/* + middlewares tenant.
Theia.Tenancy / .ControlPlaneRouting multi-base : Shard, Tenant, TenantContext, ControlDbContext, TenantAllocator.
Theia.StockageStockage objet S3/MinIO (lib partagée GED/documents).
Theia.PdpWorkerWorker de synchro PDP dédié (multi-dossier, élection de leader).

Point d'entrée (Theia.WebUI\Program.cs)

  • DI : DbContexts (Control + Theia rĂ©solu par requĂȘte depuis TenantContext), services Storage (scoped), modules partagĂ©s (IArticleCatalog→AdaptateurCatalogueTheia, IStockService, clients HTTP Catalogue/Tiers avec jeton sociĂ©tĂ© signĂ©), PDP (ServicePdpEffinum, ServicePdpAchats, ValidateurSchematron, ServicePollingPdp optionnel), stockage objet (S3/fichier), ServiceRne, ServiceKpi, ContexteSession, IdentiteClient.
  • Auth : cookie (session) + OIDC Keycloak (challenge par dĂ©faut) ; OnTokenValidated→ProvisioningOidc (JIT, réécrit le principal avec l'Id interne). Politiques : Admin + fines Vente/Achat/Reglement.Lire/Ecrire.
  • Pipeline : ForwardedHeaders → StaticFiles → Routing → Authentication → TenantRoutingMiddleware (choisit la base) → TenantMiddleware (fixe SocieteCouranteId) → Authorization → handler d'erreurs JSON /api → RazorPages → Controllers → endpoints minimal-API.
  • Bootstrap : DonneesInitiales, ControlDbContext.AssurerSchema, seed shards, mapping sociĂ©tĂ©s→tenants, MigrateurLeger.Synchroniser sur chaque base physique, backfill des Cle.

Controllers (Theia.WebUI\Controllers\*)

ControllerBaseResponsabilité · endpoints clés
AuthControllerapi/authSession : deconnexion, societe/{id}, societe-dossier (handshake portail, anti-open-redirect)
FacturationControllerapi/facturesVentes/devis/avoirs/rĂšglements/PDP : create, {id}/comptabiliser, calculer, valider-devis, convertir, acompte, solde, avoir, reglement(s-masse), envoyer, relancer, pdp/deposer, pdp/statut, {id}/facturx|apercu|xml
AchatsControllerapi/achatsFactures fournisseur (PDP entrant), catalogue achat, cycle de vie, webhook : synchroniser, {id}/statut/{transition}, {id}/lignes/extraire, catalogue/*, webhook
BonsCommandeControllerapi/bons-commandeBons de commande fournisseur (CRUD, valider, PDF)
BonsLivraisonControllerapi/bons-livraisonBons de livraison (client/fournisseur), facturer, piĂšce jointe
StockControllerapi/stockMouvements & valorisation : entree/sortie/ajustement/inventaire/famille-methode
ReferentielControllerapiRéférentiels : catalogue, clients, articles, unites, vatex
AdministrationControllerapi/adminConfig société : taxes, comptes, journaux, conditions, personnalisation (logo, couleurs, fond de page, filigrane), numérotation, relances, SMTP, PDP, sociétés, users
ModelesController Nouveauapi/modelesModÚles de facture (profils de rÚgles) : liste, upsert, défaut, suppression ; exposés à l'éditeur de facture
ImportController Nouveauapi/importReprise de données : analyser (aperçu, doublons, codes TVA) & executer (CSV/XLSX SAGE/EFAC/CEGID)
ShardsAdminController Nouveauapi/shardsAdmin des shards : liste/charge, création semi-auto, activation (garde plateforme ou clé partagée)
WidgetsControllerapi/widgetsKPI pour le portail : kpi (session), kpi-dossier (machine, clé partagée, résolu cross-shard)
TenantDiagControllerapi/tenantDiagnostic routing multi-tenant (dev)

Module E-reporting (brouillard de caisse) : pages Pages/EReporting/* (Livre de caisse, E-reporting manuel, Caisses) + ServiceEReporting (journées, ventilations TVA/paiement, soldes, validation/snapshot, export comptable, dépÎt PDP).

Services applicatifs (Theia.WebUI\Services\*)

ServiceResponsabilité
TenantRoutingMiddlewareChoisit la connexion base du tenant (cookie dossier) → TenantContext, avant tout accĂšs donnĂ©es
TenantMiddlewareRésout user + société courante, fixe SocieteCouranteId (filtre global)
ContexteSessionContexte requĂȘte : user, sociĂ©tĂ©, rĂŽle, droits par module
ProvisioningOidcProvisioning JIT Ă  la connexion Keycloak (sub→Utilisateur, réécrit le cookie)
IdentiteClientClient HTTP du service Identité (droits fins, cache 5 min)
ServicePdpEffinumDialogue PDP Effinum/Serensia : OAuth2, dépÎt Factur-X, suivi de statut (AFNOR + propriétaire)
ServicePdpAchatsRécupÚre/gÚre les factures fournisseur entrantes, extrait les lignes, propage le cycle de vie
ServicePollingPdp / ServiceSyncMultiTenantSynchro périodique PDP (repli du webhook) / orchestration multi-dossier & élection de leader
ValidateurSchematronValidation EN 16931 (Schematron/Saxon) du XML Factur-X avant envoi
ServiceRneEnrichissement fournisseurs depuis la base RNE (INPI) locale
ServiceImportReferentiel NouveauImport clients/articles : lecture CSV (UTF-8/Latin1, séparateur auto) & XLSX (ClosedXML, gÚre le « CSV encapsulé » SAGE), mapping par nom de colonne, dédoublonnage, purge optionnelle
ServiceKpi / RasteriseurPdf / MessagesErreurKPI tableau de bord / rendu PDF→PNG pour le viewer / traduction des erreurs techniques en messages FR (ErreurUtilisateur dĂ©placĂ© en Theia.Core pour ĂȘtre partagĂ©)

đŸ§Ÿ Flux : crĂ©er & comptabiliser une facture

Route → TenantRouting (base) → TenantMiddleware (SocieteId) → Authorization Vente.Ecrire. POST api/factures crĂ©e le brouillon (contrĂŽle TVA par ligne, MoteurTaxes.CalculerFacture). POST {id}/comptabiliser → validation EN 16931 puis ServiceFacturation.ComptabiliserAsync : n° lĂ©gal (sĂ©quence journal), Ă©chĂ©ance, Ă©tat ComptabilisĂ©e, lettrage, mouvements de stock valorisĂ©s. DĂ©pĂŽt PDP auto si configurĂ©.

đŸ“„ Flux : recevoir une facture d'achat (PDP)

ServicePollingPdp/worker (X-Worker-Secret) → ServiceSyncMultiTenant route le scope vers le bon shard → ServicePdpAchats.SynchroniserEntrantsAsync : jeton OAuth, pagination incrĂ©mentale, upsert FactureAchat par InvoiceId, refresh statuts, dĂ©tection doublons, MAJ fournisseurs, rĂšgles auto. Extraction des lignes & PDF Ă  la demande.

Portail Client — D:\Dev2026\PortailClient

RÎle : point d'entrée unique, GED, control-plane multi-tenant, embarque Factures/POS. Stack : .NET 10, Blazor Server + Fluent UI.

ProjetRĂŽle
PortailClient.WebPortail Blazor + control-plane (PortailDbContext + ControlDbContext) + GED
PortailClient.OcrRunner OCR hors-process (console PortailClient.Ocr <fichier> <tessData>, Tesseract/Paddle)

Point d'entrée (Program.cs)

  • DI : PortailDbContext + ControlDbContext (conn Portail), stockage Theia.Stockage S3/MinIO, clients HTTP (IdentiteClient, TheiaKpiClient:5087, PosKpiClient:5210, CatalogueHttpClient:5130, sonde sante), ContexteSession, ServiceDocuments, ExtracteurContenu, OCR (OcrRunner+OcrQueue+OcrArrierePlan hosted), ProvisioningOidc, TenantAllocator.
  • Auth : cookie PortailClient.Auth (8h) + OIDC "kc" (PKCE, code flow, ResponseMode=query) ; OnTokenValidated→JIT (sub→Utilisateur, aligne Clients↔dossiers, assigne tenant au shard).
  • Pipeline : ForwardedHeaders → (prod) exception/HSTS → StatusCodePages → HttpsRedirect → Authentication → Authorization → ContexteSession.Initialiser → Antiforgery → StaticAssets → RazorComponents (InteractiveServer).

Endpoints minimal-API

RouteBut
GET /auth/loginChallenge Keycloak
POST /auth/entrepriseBascule d'entreprise (réécrit le cookie, validé contre les accÚs)
POST /auth/logoutDéconnexion cookie + session Keycloak
GET /documents/{id}/telecharger|apercuTéléchargement / aperçu (cloisonné)
GET /documents/telecharger-selection?ids=ZIP d'une sĂ©lection (≀200)
POST /api/ingest/documentIngestion externe (X-Api-Key, multipart) → rĂ©sout/crĂ©e le Client
GET /api/control/shards|tenants, POST /api/control/tenants/{code}/assignControl-plane : annuaire & affectation au shard

Pages Blazor (Components/Pages/*)

PageRĂŽle
Home /Accueil : KPI THEIA/POS + tuiles (gated par ADroitApp)
Theia /theia · Pos /posEmbarque Factures / POS en iframe aprÚs handshake SSO top-level
Documents /documentsBase documentaire : recherche plein-texte Ă  facettes
Depot / MesDepots / DepotsRecus / PublierDépÎt (ascendant), mes envois, dépÎts reçus (agent), publication (descendant)
Administration /administrationDistributeurs / dossiers / membres (via Identité)
Outils (Emprunt, FraisKilometriques)Calculatrices

Services (Services/*)

ServiceResponsabilité
ContexteSessionIdentité courante (scoped) ; pilote le filtre global (ClientCourantId, AccesTransversal, ADroitApp)
ServiceDocumentsOrchestration GED : création (stockage+extraction), recherche à facettes, marquage lu, transmission
ServiceStockageObjets S3 content-addressed ged/{clientId}/{sha}
ExtracteurContenu / OcrRunner / OcrArrierePlanExtraction texte native ; OCR hors-process ; file d'attente OCR en tĂąche de fond
TheiaKpiClient / PosKpiClientKPI serveur→serveur (X-Widget-Key), cloisonnĂ©s par dossier
IdentiteClient / ProvisioningOidcSource de vérité droits ; provisioning JIT + cookie applicatif

🔗 Flux : ouvrir Factures embarquĂ©

Garde Identite.EstJoignable. 1á”‰Êł passage : navigation top-level vers {Theia.PublicUrl}/api/auth/societe-dossier?embedded=true&dossier=
&retour=
theia?ok=1 (SSO impossible en iframe cross-origin). Retour ?ok=1 : iframe factures.<domaine> (same-site → cookies OK).

đŸ“€ Flux : dĂ©poser/ingĂ©rer un document

UI ou POST /api/ingest/document → ServiceDocuments.CreerAsync : SHA-256 + PutObject (dĂ©dup), extraction texte (ou OCR si image/PDF scannĂ©), mĂ©tadonnĂ©es + accusĂ©, SaveChanges (regĂ©nĂšre le tsvector GIN), enqueue OCR si requis.

IIQARION POS — D:\Dev2026\THEIAPOS

RĂŽle : point de vente/caisse (offline-first), supervision, tickets NF525. Stack : .NET 8 (API) / .NET 10 (MAUI), Minimal API, EF Core / PostgreSQL, SQLite local (caisse).

ProjetRĂŽle
Theia.Pos.ApiAPI + console de supervision (point d'entrée web)
Theia.Pos.DomainEntités, enums, DTOs, Nf525Chain (chaßnage inaltérable)
Theia.Pos.Caisse / .Caisse.MauiApp caisse (Blazor Server hĂŽte / coque MAUI Windows-Android-iOS)
Theia.Pos.Client / .UiMoteur caisse offline-first (SQLite local, PosService, SyncWorker, impression ESC/POS) / UI partagée

Point d'entrée (Theia.Pos.Api\Program.cs)

  • DI : PostgreSQL obligatoire, routing multi-tenant (PosControlDbContext, PosTenantResolver), PosDbContext rĂ©solu par requĂȘte ; module Catalogue (Embedded ou Hosted via CatalogueHttpClient + jeton), module Tiers (TiersHttpClient, ServicePosSyncTiers) ; EmailWorker (outbox), QuestPDF (tickets/Z).
  • Auth (multi-canal) :
ConsommateurSchéma
Navigateur (console)OIDC Keycloak "kc" + cookie TheiaPos.Auth (client theiapos, ResponseMode=query)
CaissesX-Api-Key = Register.ApiKey
Widgets portailX-Widget-Key (serveur→serveur, match dossier)
Sync TiersX-Sync-Secret
  • Gating middleware : pages HTML protĂ©gĂ©es → challenge Keycloak ; /api/portal/* = cookie SSO obligatoire (jamais une clĂ© de caisse) ; autres /api/* = cookie SSO OU clĂ© caisse. Tenant middleware : lit cookie pos_dossier → rĂ©sout le shard.

Groupes d'endpoints

GroupeEndpoints
Handshake auth/auth/login|logout, GET /api/auth/portail?dossier=&retour= (pose pos_dossier, anti-open-redirect vers Portal:BaseUrl)
Admin portail (SSO)/api/portal/caisses|stores|sellers|customers|products|categories|articles (CRUD, deep-link module Catalogue)
Sync portail→caisseGET /api/catalog (articles actifs filtrĂ©s par assortiment, TTC recomposĂ©), /api/registers/{id}, /api/sellers
Remontée caissePOST /api/sync/tickets (vérif NF525 + ré-ancrage, décrément stock, fidélité, outbox), heartbeat, sessions/close, z.pdf
Clients / e-reporting/api/customers (incrémental + tombstones), /api/ereporting/{date}, POST /api/tickets/{id}/facturer (Factur-X via THEIA)

🔗 Flux : embarquer le POS

Portail → top-level GET /api/auth/portail?dossier=&retour= → (si besoin) challenge Keycloak → pose cookie pos_dossier → retour validĂ© → iframe. Chaque requĂȘte porte pos_dossier : routing base + scope Store.Dossier.

đŸ§Ÿ Flux : vente caisse (offline-first)

Caisse pull catalogue (X-Api-Key). Vente finalisée localement (SQLite), ticket chaßné NF525. SyncWorker pousse vers POST /api/sync/tickets ; le serveur revérifie le hash (inaltérabilité, ré-ancrage si registre vierge), décrémente le stock, crédite la fidélité, met le reçu dématérialisé en outbox.

IdentitĂ© — D:\Dev2026\Identite

RĂŽle : autorisation fine + provisioning Keycloak. Stack : .NET 10 Minimal API, Dapper + Npgsql. Keycloak porte l'authentification & les rĂŽles grossiers ; la base identite porte les droits fins.

Point d'entrée (Program.cs)

  • Bootstrap : EnsureDatabaseAsync → services (SecretProtector, KeycloakAdmin, ResolveurPdp, RafraichisseurPdp hosted) → JWT bearer (realm eportail, NameClaimType=sub) → InitialiserAsync (schĂ©ma+seed).
  • Politiques : ImportApi (client import-api), AdminPlateforme (rĂŽle realm). Helpers de portĂ©e : AutoriserAdminDistrib/Dossier, NiveauxActeur.

Endpoints (préfixe /api/identite)

RouteAuthBut
GET /moi/habilitationsauthentifiéDossiers + droits par module + apps actives (via vue v_habilitations)
POST /distributeurs/{code}/dossiersImportApiImport push d'un dossier + chef (provisionne le chef dans Keycloak)
POST /dossiers/{code}/utilisateurs, PUT 
/habilitations, DELETE 
chef/adminGestion des membres & droits
GET/PUT /dossiers/{code}/apps, POST /provisioningadmin-distribEntitlements applicatifs (THEIA/POS)
POST /admin/distributeurs/*, .../cles-pdpadmin-plateforme / distribDistributeurs, dossiers, clés PDP (secret jamais renvoyé)
POST /pdp/tokentheia/import/adminCourtier de jeton PDP : forge un token OAuth depuis la clé distributeur (secret ne sort jamais)

Services

ServiceResponsabilité
KeycloakAdminProvisionne les users dans le realm eportail (service account import-api) : dĂ©dup email, crĂ©ation, rĂŽle, invitation → renvoie le sub
RealmRolesLit les rĂŽles realm depuis le JWT (realm_access.roles)
SecretProtectorChiffre/déchiffre AES-256-GCM les secrets PDP au repos
ResolveurPdp / RafraichisseurPdpRésout l'identité PDP (organization_id/eas) depuis le SIREN via Serensia, cache-first / rattrapage en tùche de fond
Keycloak vs base locale. Keycloak = identité, credentials, rÎles grossiers (admin-plateforme, admin-distributeur, chef-entreprise, utilisateur). Base identite = quels dossiers (rattachement), quels droits par module (habilitation), quel périmÚtre admin, quels produits (entitlement). Jointure par le sub.

Modules partagés : Catalogue & Tiers

MĂȘme patron : module EF autonome (SQLite/PostgreSQL), cloisonnĂ© par SocieteCode, jeton sociĂ©tĂ© signĂ© HMAC-SHA256 (JetonSociete) requis sur tout /api/*, notification write-through vers les consommateurs.

📚 Catalogue (:5130)

Projets : Core (entités, CatalogueDbContext, ServiceArticles/Stock/Etablissements), Contracts (DTOs, IArticleCatalog/IStockService, JetonSociete), Api (Minimal API + auth jeton), Client (CatalogueHttpClient + JetonSocieteHandler).

Endpoints : /api/articles (CRUD, code-barres), /api/categories, /api/unites, /api/tva, /api/etablissements, /api/stock/{entrer|sortir|ajuster|etat|valeur}. Sync descendante : à chaque écriture, POST /api/admin/sync-catalogue vers THEIA (X-Sync-Secret).

📇 Tiers (:5140)

Projets : Core (Tiers, TiersDbContext, ServiceTiers source de vérité), Contracts (TiersDto, ITiersReferentiel, CleDedup), Api, Client (TiersHttpClient).

Endpoints : /api/tiers (recherche/CRUD), /resoudre, /doublons, /fusionner. Sync bidirectionnelle THEIA ⇄ POS : NotifierAsync → /api/admin/sync-tiers vers chaque consommateur ; garde anti-boucle (notify=false pour les backfills). Enrichissement RNE à l'upsert.

Passerelle, Site vitrine, Ingress PDP

ApplicationProjetProgramme
PasserelleIiqarion.GatewayYARP (LoadFromConfig), routage par hĂŽte (appsettings), HTTPS auto prod (LettuceEncrypt, Tls:Enabled), UseWindowsService, sonde /healthz
Site vitrineIIQARION.Site.WebBlazor SSR marketing ; NavMenu.razor « Se connecter » → PortailUrl (config)
Ingress PDPIiqarion.WebhookIngressService autonome (.NET + PostgreSQL + LettuceEncrypt) : reçoit les webhooks PDP, qu'un worker draine (pull)
DocumentationIiqarion.DocsCe site (hĂŽte statique .NET, wwwroot, :5310)
Document vivant. Mis Ă  jour le 27/09/2026 depuis le code. À rĂ©gĂ©nĂ©rer Ă  chaque Ă©volution (contrĂŽleurs/endpoints/services ajoutĂ©s) — l'idĂ©al Ă©tant de relancer l'extraction sur chaque solution.
IIQARION — Programmes par application · 27/09/2026.