Aller au contenu

Architecture de données — OLTP, plateforme analytique, isolation

Vous êtes ici : Comprendre — les fondations : où vivent les données de la suite. Comment GS-Apps range, isole et alimente ses données. Lecture 12 min. Audience : devs, data engineers, auditeurs. Date : 2026-10-09 | Version : 1.4 — trajectoire unique ADR-094 (une base GS_Apps, déclencheur charge 80 % / 30 min) ; RLS et médaillon inchangés depuis 1.3

Question Réponse Source de vérité
Où vivent les données des apps ? Un schéma par domaine métier : ug, adm, bil, inv, fbk, ntf, ptl, audit, … (liste ouverte) Base GS_Apps (OLTP)
Où vit l’analytique ? Médaillon sur la même base : bronze (stg_<source>) → dim → (fact direct ou silver) → gold (ordre DAG, ADR-094 règle 5) Base GS_Apps
D’où viennent les données analytiques ? De SOFI aujourd’hui ; puis d’autres sources (Proful, Geotab, Monday, …) — chacune atterrit dans son schéma bronze stg_<source> Sources externes, lecture seule
Les apps utilisent-elles ces données ? Oui — les dimensions conformes (employés, succursales…) servent de données de référence aux apps, en plus de nourrir la BI dim.*
Quand la base change-t-elle ? Un seul déclencheur : charge GS_Apps ≥ 80 % en moyenne sur 30 minutes (alerte alert-gs-apps-charge-de-la-base). Puis question fermée à l’exploitant — pas de scission automatique ADR-094
Comment une compagnie est-elle isolée ? RLS (Row-Level Security) sur les tables tenant — ug.* et les couches silver/gold/dim/fact — prédicat sur company_id Politique RLS en base
Comment une app se connecte ? Convention unique AZURE_SQL_*, un seul pool @gs/config + test de contrat

La bonne image n’est pas « deux murs séparés », mais un flux. Des sources (SOFI aujourd’hui) alimentent une plateforme de données en médaillon, qui sert deux consommateurs : les apps (transactionnel) et la BI (analytique). Les apps tournent autour d’un cœur partagé — le schéma ug (identités, compagnies) que les autres référencent — et réutilisent les données de référence (employés, succursales…) que la plateforme tire des sources.

Carte des données — des sources vers les apps et la BILes sources externes (SOFI aujourd’hui ; Geotab, Proful, Monday à venir) alimentent une plateforme de données en médaillon (bronze — un schéma stg_ par source —, silver, puis la couche servie gold/dim/fact). Cette plateforme sert deux consommateurs : les apps transactionnelles OLTP, organisées autour d’un cœur partagé ug et isolées par RLS, qui réutilisent les données de référence comme les employés et les succursales ; et la BI qui consomme les agrégats et les faits.SOURCESSOFIon-prem · lecture seuleGeotab · Proful · Mondayà venirPLATEFORME DE DONNÉES — médaillonbronze — stg_*brut · 1 schéma par sourcesilvernettoyé · conformégold · dim · factcouche serviedonnées deréférenceagrégats· faitsAPPS (OLTP) — transactionnelug — cœur partagé : identités · compagniesDomaines : bil · inv · fbk · ntf · ptl · adm · auditréutilisent les données de référence · isolés par RLSBI — analytiquetableaux de bordrapports · KPIconsomme gold + fact
La carte des données : les sources alimentent la plateforme en médaillon, qui sert deux consommateurs — les apps (données de référence) et la BI (agrégats et faits).

1. Domaine transactionnel (OLTP) — un schéma par contexte

Section intitulée « 1. Domaine transactionnel (OLTP) — un schéma par contexte »

Chaque domaine métier vit dans son propre schéma, nommé sur 3 lettres minuscules — et la liste est ouverte (ug, adm, bil, inv, fbk, ntf, ptl, audit, … d’autres domaines viendront). Pas de tables métier dans dbo.

Mais tous les domaines ne sont pas au même niveau. ug est le cœur partagé : il détient les identités, les compagnies et les rôles que les autres schémas référencent — une facture bil pointe une compagnie ug, un mouvement de stock inv pointe un utilisateur ug. On lit chez le voisin par clé/jointure explicite, jamais par copie sauvage : un schéma possède sa donnée, les autres la référencent. C’est ce qui empêche la « soupe de tables ».

Schéma Domaine Tables clés
ug Accès (identités, rôles, délégation — Système C) Users, Companies, UserCompanyBcRoles, UserCompanyAccess, RoleTemplates, CompanyBranding(Assets)
adm Administration / ETL (registre d’apps, orchestration des syncs) Apps, Sources, SyncConfigs, SyncLogs, Watermarks, SyncLocks, EtlControl
bil Facturation Clients, Contracts, ContractCodes, BillingPeriods, ExportHistory
inv Inventaire Items, PurchaseOrders(+Lines), Receptions, StockMovements, Suppliers, WeeklyReports
fbk Feedback (tickets internes) Tickets, Messages, Activity, StatusHistory, Attachments
ntf Notifications Notifications, NotificationReads
ptl Palettes (étiquettes / traçabilité) Stickers, StickerBatches, StickerSequence
audit Journal d’accès PII (cible du pool audit) PiiAccessLog

L’analytique suit le patron médaillon (standard data-platform) : des couches de raffinage successives. Chaque source atterrit d’abord telle quelle, puis est nettoyée, puis modélisée. Aujourd’hui la source est SOFI (on-prem, lue en seule lecture via VNet — jamais d’écriture vers SOFI) ; demain d’autres s’ajouteront — Proful, Geotab, Monday, … — toutes par le même patron d’entrée : la couche bronze, incarnée par un schéma stg_<source> par source (stg_sofi aujourd’hui ; stg_geotab, stg_profuel, stg_jpl, stg_saaq, stg_locations déjà réservés). Un schéma par source évite toute collision de noms de tables entre sources — deux sources peuvent avoir une table du même nom sans se marcher dessus.

Le résultat ne part pas que vers la BI. La couche servie a deux consommateurs : la BI lit les agrégats (gold) et les faits (fact) ; les apps réutilisent les dimensions conformes (dim : employés, succursales, véhicules…) comme données de référence — par exemple la liste d’employés à la connexion, ou les succursales dans l’inventaire.

Pipeline médaillon — des sources aux deux consommateursLes sources (SOFI aujourd’hui ; Geotab, Proful, Monday à venir) atterrissent chacune dans son schéma bronze stg_source. Bronze est nettoyé en silver. Silver alimente gold (agrégats) et le modèle dimensionnel dim/fact. La BI consomme gold et les faits ; les apps réutilisent les dimensions conformes comme données de référence. L’orchestration et les watermarks sont gérés par le schéma adm.SOURCESSOFIon-prem · ROGeotab · ProfulMondayà venirbronze — stg_*1 schéma par sourcesilvernettoyé · conformégoldagrégats · KPIdim · factmodèle dimensionnelBItableaux de bordAPPSdonnées de référenceorchestration · watermarks — schéma adm
Le pipeline médaillon : chaque source atterrit dans son schéma bronze, est raffinée en silver, puis sert la BI (gold, faits) et les apps (dimensions conformes). L’orchestration vit dans le schéma adm.
Couche Schéma Rôle Exemple
Bronze stg_<source> — un par source Copie fidèle de la source, sans transformation (rejouable) stg_sofi.PunchParJour ; stg_geotab, stg_profuel… (réservés)
Silver silver Nettoyé, typé, conformé, dédupliqué silver.maintenance_orders, silver.security_rounds
Gold gold Agrégats prêts pour la décision gold.maintenance_cost_per_vehicle_month
Dimensions / faits dim / fact Modèle dimensionnel (étoile) — réutilisé par la BI et les apps dim.vehicles, dim.branches ; fact.invoices, fact.plans

gold vs dim/fact — pourquoi les deux ? dim/fact est le socle réutilisable au grain fin : les dimensions (dim) sont les objets — employés, succursales, véhicules, calendrier ; les faits (fact) sont les événements mesurables — factures, plans, punches. C’est cette couche que les apps réutilisent comme référence. gold, lui, ce sont les réponses pré-calculées construites par-dessus dim/fact — agrégats et KPI taillés pour un tableau de bord précis (ex. coût d’entretien par véhicule par mois), destinés à la BI. En une phrase : dim/fact est le socle commun ; gold est ce qu’on en tire pour décider.

Le multi-tenant se défend en profondeur : au-delà du filtrage applicatif (company_id injecté par middleware), les tables tenant portent une politique RLS (Row-Level Security) dont le prédicat sur company_id borne chaque requête à la compagnie courante — fail-closed (aucun contexte → aucune ligne). Même une requête fautive reste confinée.

Le mécanisme RLS — une seule TVF, une politique par schéma, fail-closedUne requête arrive avec son contexte de compagnie. Une seule fonction table, dbo.fn_company_predicate, est appliquée par une politique CompanyFilter posée sur chaque schéma tenant : elle filtre en lecture et bloque en insertion ou mise à jour. Le résultat ne contient que les lignes de la compagnie courante. Trois cas particuliers : sans contexte, aucune ligne n’est retournée (fail-closed) ; le service ETL dispose d’un bypass contrôlé ; trois tables ug et la couche bronze stg sont exclues par conception.Une requête+ contexte compagniefn_company_predicateune seule TVF · CompanyFilterpar schéma tenantFILTER — lectureBLOCK — écritureLignes deta compagnieAucun contexte → 0 lignefail-closed · prouvé en CI (INV-4)Service ETL → bypass contrôléle seul à écrire pré-tenantExclues par design3 tables ug · bronze stg_* pré-tenantPérimètre actif : ug (5 tables) · silver · gold · dim · fact — un seul mécanisme, jamais un prédicat par tableétat vérifié 2026-07-02 (ADR-056 D6, migrations 113/134/140/141)
Un seul mécanisme d’isolation : la même fonction, posée par schéma, filtre en lecture et bloque en écriture. Sans contexte, la base ne rend rien.

Le périmètre déployé et actif couvre les deux familles (ADR-056 D6) : les tables tenant OLTP (ug.Users, ug.CompanyBranding, ug.UserCompanyBcRoles, ug.CompanyModules, ug.RoleGrantsLog — politique ug.CompanyFilter, migrations 113/134/140) et les couches analytiques tenant-scopées silver / gold / dim / fact. Le mécanisme est unique : une seule TVF dbo.fn_company_predicate (jamais de prédicat dédié par table), une politique CompanyFilter par schéma — en FILTER (lecture) et BLOCK (insert/update) — et un bypass contrôlé pour le service ETL. Trois tables ug sont exclues par design : ug.Companies (registre global des compagnies), ug.UserCompanyAccess (anti-récursion — le prédicat la lit pour résoudre les accès) et ug.CompanyBrandingAssets. La couche bronze (stg_*) n’est pas couverte : c’est un miroir pré-tenant des sources, accessible au seul service ETL.

Une seule famille de variables : AZURE_SQL_SERVER / AZURE_SQL_DATABASE / AZURE_SQL_USER / AZURE_SQL_PASSWORD / AZURE_SQL_PORT, validée par un schéma Zod central (@gs/config). Aucun nom mort SQL_*. La source SOFI a sa propre famille SOFI_SQL_* (système distinct, ne pas mélanger).

Décision Pourquoi (le standard)
Un schéma par domaine (pas de dbo métier) Bounded contexts explicites ; permissions, sauvegardes et évolutions cadrées par domaine.
OLTP et OLAP sur une base (séparation par schéma) L’analytique lourde et l’ETL partagent GS_Apps avec le transactionnel ; les domaines sont isolés par schéma et RLS. Si la charge devient un problème mesuré, ADR-094 impose remesure puis décision humaine — jamais une migration automatique.
Médaillon bronze/silver/gold Standard Databricks/Lakehouse : raffinage par couches, rejouable, lignée claire. Une convention, pas trois.
RLS tenant-scopée, fail-closed Défense en profondeur multi-tenant : la base borne, même si une requête applicative se trompe.
Source unique de config (AZURE_SQL_*) + test de contrat Évite la dérive de nommage infra/code ; un seul vocabulaire, audité automatiquement.
SOFI en lecture seule, isolé (SOFI_SQL_*) La source opérationnelle n’est jamais polluée par l’analytique ; frontière nette.