Aller au contenu

app.appareil

Téléphone enrôlé pour un agent. Une installation est enrôlée pour une seule organisation à la fois.

Name Type Default Nullable Children Parents Comment
id uuid app.uuid_v7() false app.code_enrolement app.fichier sync.commande sync.commande_resultat app.appel_administration Identifiant de l’appareil (UUID v7).
organisation_id uuid false app.code_enrolement app.fichier sync.commande sync.commande_resultat app.appel_administration app.utilisateur Organisation propriétaire de la ligne. Sert à l’isolation par RLS (EC-032) et au filtrage de la synchronisation.
code text false Code court unique de l’appareil, utilisé dans les références provisoires (EC-009).
utilisateur_id uuid false app.utilisateur Agent titulaire de l’appareil.
modele text true Modèle du téléphone.
gnss_bifrequence boolean true Vrai si le téléphone dispose d’un récepteur GNSS bifréquence (GPS-03, GPS-05).
version_application text true Dernière version de l’application terrain connue.
statut text ‘actif’::text false Statut : actif, revoque ou remplace.
enrole_le timestamp with time zone now() false Date d’enrôlement.
revoque_le timestamp with time zone true Date de révocation. Nulle si l’appareil n’est pas révoqué.
revoque_par uuid true app.utilisateur Utilisateur qui a révoqué l’appareil.
motif_revocation text true Motif de la révocation, obligatoire dès qu’elle a lieu.
derniere_sequence bigint 0 false Dernière séquence de commande traitée pour cet appareil. Ne diminue jamais.
derniere_synchro timestamp with time zone true Date de la dernière synchronisation.
cree_le timestamp with time zone now() false Date de création de la ligne.
modifie_le timestamp with time zone now() false Date de la dernière modification, tenue par un déclencheur.
Name Type Definition
appareil_check CHECK CHECK (((statut = ‘revoque’::text) = (revoque_le IS NOT NULL)))
appareil_check1 CHECK CHECK (((revoque_le IS NULL) OR (motif_revocation IS NOT NULL)))
appareil_code_check CHECK CHECK ((code ~ ‘^[A-Z0-9]{4,6}$’::text))
appareil_derniere_sequence_check CHECK CHECK ((derniere_sequence >= 0))
appareil_statut_check CHECK CHECK ((statut = ANY (ARRAY[‘actif’::text, ‘revoque’::text, ‘remplace’::text])))
appareil_organisation_id_revoque_par_fkey FOREIGN KEY FOREIGN KEY (organisation_id, revoque_par) REFERENCES app.utilisateur(organisation_id, id)
appareil_organisation_id_utilisateur_id_fkey FOREIGN KEY FOREIGN KEY (organisation_id, utilisateur_id) REFERENCES app.utilisateur(organisation_id, id)
appareil_pkey PRIMARY KEY PRIMARY KEY (id)
appareil_code_key UNIQUE UNIQUE (code)
appareil_organisation_id_id_key UNIQUE UNIQUE (organisation_id, id)
Name Definition
appareil_pkey CREATE UNIQUE INDEX appareil_pkey ON app.appareil USING btree (id)
appareil_code_key CREATE UNIQUE INDEX appareil_code_key ON app.appareil USING btree (code)
appareil_organisation_id_id_key CREATE UNIQUE INDEX appareil_organisation_id_id_key ON app.appareil USING btree (organisation_id, id)
Name Definition
journal CREATE TRIGGER journal AFTER INSERT OR DELETE OR UPDATE ON app.appareil FOR EACH ROW EXECUTE FUNCTION journal.tg_journaliser()
modifie_le CREATE TRIGGER modifie_le BEFORE UPDATE ON app.appareil FOR EACH ROW EXECUTE FUNCTION app.tg_modifie_le()
erDiagram

"app.code_enrolement" }o--|| "app.appareil" : "FOREIGN KEY (organisation_id, appareil_id) REFERENCES app.appareil(organisation_id, id)"
"app.fichier" }o--|| "app.appareil" : "FOREIGN KEY (organisation_id, appareil_id) REFERENCES app.appareil(organisation_id, id)"
"sync.commande" }o--|| "app.appareil" : "FOREIGN KEY (organisation_id, appareil_id) REFERENCES app.appareil(organisation_id, id)"
"sync.commande_resultat" }o--|| "app.appareil" : "FOREIGN KEY (organisation_id, appareil_id) REFERENCES app.appareil(organisation_id, id)"
"app.appel_administration" }o--|| "app.appareil" : "FOREIGN KEY (organisation_id, cible_appareil_id) REFERENCES app.appareil(organisation_id, id)"
"app.appareil" }o--|| "app.utilisateur" : "FOREIGN KEY (organisation_id, revoque_par) REFERENCES app.utilisateur(organisation_id, id)"
"app.appareil" }o--|| "app.utilisateur" : "FOREIGN KEY (organisation_id, utilisateur_id) REFERENCES app.utilisateur(organisation_id, id)"

"app.appareil" {
  uuid id "Identifiant de l'appareil (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
  text code "Code court unique de l'appareil, utilisé dans les références provisoires (EC-009)."
  uuid utilisateur_id FK "Agent titulaire de l'appareil."
  text modele "Modèle du téléphone."
  boolean gnss_bifrequence "Vrai si le téléphone dispose d'un récepteur GNSS bifréquence (GPS-03, GPS-05)."
  text version_application "Dernière version de l'application terrain connue."
  text statut "Statut : actif, revoque ou remplace."
  timestamp_with_time_zone enrole_le "Date d'enrôlement."
  timestamp_with_time_zone revoque_le "Date de révocation. Nulle si l'appareil n'est pas révoqué."
  uuid revoque_par FK "Utilisateur qui a révoqué l'appareil."
  text motif_revocation "Motif de la révocation, obligatoire dès qu'elle a lieu."
  bigint derniere_sequence "Dernière séquence de commande traitée pour cet appareil. Ne diminue jamais."
  timestamp_with_time_zone derniere_synchro "Date de la dernière synchronisation."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
  timestamp_with_time_zone modifie_le "Date de la dernière modification, tenue par un déclencheur."
}
"app.code_enrolement" {
  uuid id "Identifiant du code (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
  uuid utilisateur_id FK "Agent pour lequel le code a été généré."
  text empreinte_code "Empreinte SHA-256 du code, en hexadécimal."
  timestamp_with_time_zone expire_le "Date d'expiration du code (24 heures)."
  timestamp_with_time_zone utilise_le "Date d'utilisation. Nulle tant que le code n'a pas servi."
  uuid appareil_id FK "Appareil enrôlé avec ce code."
  uuid cree_par FK "Administrateur qui a généré le code. Différent de l'agent."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
  timestamp_with_time_zone modifie_le "Date de la dernière modification, tenue par un déclencheur."
}
"app.fichier" {
  uuid id "Identifiant du fichier (UUID v7, généré sur l'appareil ou par l'API)."
  uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
  text cle_objet "Clé de l'objet dans le stockage."
  text type_mime "Type MIME du contenu."
  bigint taille_octets "Taille en octets."
  text sha256 "Empreinte SHA-256 du contenu, en hexadécimal."
  text statut "Statut : attendu, recu ou empreinte_invalide. Un fichier reçu n'est plus modifiable."
  uuid appareil_id FK "Appareil d'origine du dépôt."
  uuid depose_par FK "Utilisateur qui a déposé le fichier."
  timestamp_with_time_zone depose_le "Date de réception du contenu par le stockage."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
  timestamp_with_time_zone modifie_le "Date de la dernière modification, tenue par un déclencheur."
}
"sync.commande" {
  uuid id "Identifiant de la commande (UUID v7 généré sur l'appareil). Clé d'idempotence."
  uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
  uuid appareil_id FK "Appareil émetteur."
  uuid utilisateur_id FK "Agent auteur."
  bigint sequence "Séquence locale de l'appareil, à partir de 1. Unique par appareil."
  text type "Type de commande (ex. collecte.enregistrer)."
  integer version_schema "Version du JSON Schema de la charge utile."
  timestamp_with_time_zone cree_le_appareil "Heure du téléphone à la saisie."
  timestamp_with_time_zone date_operation "Date d'opération retenue par le serveur, jamais postérieure à la réception (protocole §6.4)."
  timestamp_with_time_zone recue_le "Heure de réception par le serveur."
  text reference_provisoire "Référence provisoire du document de terrain (EC-009)."
  text empreinte "Empreinte SHA-256 de la commande canonique."
  jsonb enveloppe "Commande complète en JSON, telle que reçue."
}
"sync.commande_resultat" {
  uuid id FK "Identifiant de la commande concernée (PowerSync exige une colonne id)."
  uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
  uuid appareil_id FK "Appareil destinataire."
  text issue "Issue : acceptee, acceptee_controle ou rejetee."
  text__ motifs "Motifs de contrôle ou de rejet. Vide si la commande est acceptée."
  text__ alertes "Alertes non bloquantes."
  text numero_officiel "Numéro officiel attribué par le serveur."
  jsonb entites "Entités créées, par identifiant, en JSON."
  timestamp_with_time_zone date_operation "Date d'opération retenue."
  timestamp_with_time_zone traitee_le "Date de traitement par le serveur."
}
"app.appel_administration" {
  uuid id "Identifiant de l'appel (UUID v7)."
  uuid organisation_id FK "Organisation concernée : l'organisation active, ou celle qui vient d'être créée. Sert à l'isolation par RLS (EC-032)."
  uuid auteur_sub "Identifiant Keycloak de l'auteur de l'appel."
  uuid auteur_id FK "Ligne app.utilisateur de l'auteur dans l'organisation. Nul pour un membre de l'équipe BioTrace qui crée une organisation."
  text action "Action demandée, ex. utilisateur.creer, utilisateur.desactiver, appareil.revoquer, organisation.creer."
  uuid cible_utilisateur_id FK "Utilisateur visé, de la même organisation."
  uuid cible_keycloak_sub "Identifiant Keycloak du compte visé, conservé même si la ligne app.utilisateur n'existe pas ou plus."
  uuid cible_appareil_id FK "Appareil visé, de la même organisation."
  text resultat "`reussi`, `refuse` (droit manquant, cible d'une autre organisation) ou `echec` (Keycloak ou base indisponible)."
  jsonb details "Éléments utiles à l'audit : motif, code d'erreur, ensemble de permissions. Jamais de mot de passe ni de jeton."
  timestamp_with_time_zone cree_le "Date de l'appel."
}
"app.utilisateur" {
  uuid id "Identifiant de l'utilisateur (UUID v7)."
  uuid organisation_id FK "Organisation propriétaire de la ligne. Sert à l'isolation par RLS (EC-032) et au filtrage de la synchronisation."
  uuid keycloak_sub "Identifiant du compte Keycloak (revendication sub). Identique d'une organisation à l'autre pour un compte externe."
  text identifiant "Identifiant local de connexion, sans le code de l'organisation : 3 à 32 caractères parmi a-z, 0-9, _ et -. Unique dans l'organisation."
  text nom_affiche "Nom affiché dans l'application."
  text telephone "Numéro de téléphone. Attribut du compte, jamais son identifiant."
  text statut "Statut du compte : actif, suspendu ou desactive."
  timestamp_with_time_zone cree_le "Date de création de la ligne."
  timestamp_with_time_zone modifie_le "Date de la dernière modification, tenue par un déclencheur."
}

Generated by tbls