Files
Omika/infra/postgresql/011_diagnostics_reference.sql
2026-10-23 18:46:50 +02:00

141 lines
8.9 KiB
SQL

-- ============================================================
-- Omika Diagnostic Center -- 011_diagnostics_reference.sql
-- T24-A : référentiel administrable ScreenCode / FeatureCode.
-- ============================================================
-- TO RUN ON SRV-OMIKA as PostgreSQL superuser (e.g. psql -U postgres -d <base> -f 011_...),
-- AFTER 010 (diagnostics_users). Order: 001 -> ... -> 010 -> 011.
--
-- Guarantees :
-- - PostgreSQL 18 compatible.
-- - Idempotent : re-running is a no-op (CREATE ... IF NOT EXISTS + GRANT idempotent
-- + seed ON CONFLICT DO NOTHING).
-- - Non destructive : NO DROP, NO DELETE/TRUNCATE, no data removal.
-- - NO password, NO secret.
--
-- PURPOSE :
-- diagnostic_event reste la VÉRITÉ sur ce qui a réellement été observé. Ce
-- référentiel est un ENRICHISSEMENT administrable (libellé / description /
-- ordre / état) depuis Diagnostics.Web. Il ne détermine JAMAIS quels événements
-- sont acceptés : un nouveau code observé reste visible même non référencé.
--
-- reference_type : 'SCREEN_CODE' ou 'FEATURE_CODE' (V1). Extensible plus tard.
-- code : code technique, normalisé TRIM + UPPER (unique par type).
-- label : libellé métier français.
-- description : documentation métier (nullable).
-- enabled : FALSE => archivé (aucun DELETE physique en V1).
-- sort_order : ordre d'affichage.
-- created_at_utc / updated_at_utc : TIMESTAMPTZ (comme 005/007/008/010).
--
-- Ownership : omika_diagnostics_owner (comme 003/008/009/010).
-- ============================================================
CREATE TABLE IF NOT EXISTS diagnostics_reference (
id BIGSERIAL PRIMARY KEY,
reference_type TEXT NOT NULL,
code TEXT NOT NULL,
label TEXT NOT NULL,
description TEXT,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
sort_order INTEGER NOT NULL DEFAULT 0,
created_at_utc TIMESTAMPTZ NOT NULL,
updated_at_utc TIMESTAMPTZ NOT NULL
);
-- Unicité d'un code POUR SON TYPE, insensible à la casse (T24-A §20) : l'index
-- porte sur UPPER(code), donc 'agenda' / 'AGENDA' / 'Agenda' sont le même code.
CREATE UNIQUE INDEX IF NOT EXISTS ux_diagnostics_reference_type_code
ON diagnostics_reference (reference_type, UPPER(code));
-- ------------------------------------------------------------
-- Ownership : omika_diagnostics_owner.
-- ------------------------------------------------------------
ALTER TABLE diagnostics_reference OWNER TO omika_diagnostics_owner;
ALTER SEQUENCE diagnostics_reference_id_seq OWNER TO omika_diagnostics_owner;
-- ------------------------------------------------------------
-- Défense PUBLIC (ceinture + bretelles, idempotent).
-- ------------------------------------------------------------
REVOKE ALL ON TABLE diagnostics_reference FROM PUBLIC;
-- ------------------------------------------------------------
-- Connexion explicite + schéma pour omika_diagnostics_web
-- (déjà accordés par 003 ; ré-affirmé idempotent).
-- ------------------------------------------------------------
DO $$
BEGIN
EXECUTE format('GRANT CONNECT ON DATABASE %I TO omika_diagnostics_web', current_database());
END
$$;
GRANT USAGE ON SCHEMA public TO omika_diagnostics_web;
-- ------------------------------------------------------------
-- Web (Omika.Diagnostics.Web, admin /Referentiel/Admin) : SELECT + INSERT +
-- UPDATE colonne-ciblé (moindre privilège) + USAGE séquence.
-- - INSERT : création d'une entrée (id BIGSERIAL).
-- - UPDATE (label, description, enabled, sort_order, updated_at_utc) :
-- modification + archivage (enabled=false). Le CODE est immuable.
-- - AUCUN DELETE (aucune suppression physique en V1, §24).
-- ------------------------------------------------------------
GRANT SELECT ON TABLE diagnostics_reference TO omika_diagnostics_web;
GRANT INSERT ON TABLE diagnostics_reference TO omika_diagnostics_web;
GRANT UPDATE (label, description, enabled, sort_order, updated_at_utc)
ON TABLE diagnostics_reference TO omika_diagnostics_web;
GRANT USAGE ON SEQUENCE diagnostics_reference_id_seq TO omika_diagnostics_web;
-- ------------------------------------------------------------
-- API (omika_diagnostics_api) : AUCUN droit sur diagnostics_reference.
-- Worker (omika_diagnostics_worker) : AUCUN droit sur diagnostics_reference.
-- Aucun GRANT accordé ; les rôles n'ont aucun privilège par défaut.
-- (Testé négativement : SELECT référentiel REFUSÉ pour api et worker.)
-- ------------------------------------------------------------
-- ------------------------------------------------------------
-- INITIALISATION IDEMPOTENTE (T24-A §36) : les 29 ScreenCode et 3 FeatureCode
-- du catalogue applicatif. ON CONFLICT DO NOTHING => un libellé modifié par un
-- Admin n'est JAMAIS écrasé au redémarrage. Les libellés correspondent EXACTEMENT
-- à DiagnosticScreenCodeCatalog / DiagnosticFeatureCodeCatalog.
-- ------------------------------------------------------------
INSERT INTO diagnostics_reference
(reference_type, code, label, description, enabled, sort_order, created_at_utc, updated_at_utc)
VALUES
('SCREEN_CODE', 'AGENDA', 'Agenda', NULL, TRUE, 10, now(), now()),
('SCREEN_CODE', 'INTERVENTION_SEARCH', 'Recherche d''interventions', NULL, TRUE, 20, now(), now()),
('SCREEN_CODE', 'DOSSIER_LIST', 'Dossiers', NULL, TRUE, 30, now(), now()),
('SCREEN_CODE', 'TEAM', 'Équipe', NULL, TRUE, 40, now(), now()),
('SCREEN_CODE', 'TEAM_DETAIL', 'Détail d''équipe', NULL, TRUE, 50, now(), now()),
('SCREEN_CODE', 'CLIENT_LIST', 'Clients', NULL, TRUE, 60, now(), now()),
('SCREEN_CODE', 'SITE_LIST', 'Sites', NULL, TRUE, 70, now(), now()),
('SCREEN_CODE', 'SETTINGS', 'Paramètres', NULL, TRUE, 80, now(), now()),
('SCREEN_CODE', 'RENDEZVOUS_DETAIL', 'Détail de rendez-vous', NULL, TRUE, 90, now(), now()),
('SCREEN_CODE', 'AGENDA_TEAM', 'Agenda d''équipe', NULL, TRUE, 100, now(), now()),
('SCREEN_CODE', 'INTERVENTION_DETAIL', 'Détail d''intervention', NULL, TRUE, 110, now(), now()),
('SCREEN_CODE', 'INTERVENTION_DOCUMENTS', 'Documents d''intervention', NULL, TRUE, 120, now(), now()),
('SCREEN_CODE', 'INTERVENTION_NOTES', 'Notes d''intervention', NULL, TRUE, 130, now(), now()),
('SCREEN_CODE', 'INTERVENTION_NOTES_ADMIN', 'Notes administratives', NULL, TRUE, 140, now(), now()),
('SCREEN_CODE', 'INTERVENTION_EMAILS', 'Courriels d''intervention', NULL, TRUE, 150, now(), now()),
('SCREEN_CODE', 'EMAIL', 'Nouveau courriel', NULL, TRUE, 160, now(), now()),
('SCREEN_CODE', 'RAPPORT', 'Rapport', NULL, TRUE, 170, now(), now()),
('SCREEN_CODE', 'INTERVENTION_RESOURCES', 'Contenus d''intervention', NULL, TRUE, 180, now(), now()),
('SCREEN_CODE', 'PHOTO_VIEWER', 'Visionneuse photo', NULL, TRUE, 190, now(), now()),
('SCREEN_CODE', 'IMAGE_EDITOR', 'Éditeur d''image', NULL, TRUE, 200, now(), now()),
('SCREEN_CODE', 'INTERVENTION_CONTACTS', 'Contacts d''intervention', NULL, TRUE, 210, now(), now()),
('SCREEN_CODE', 'CONTACT_DETAIL', 'Détail de contact', NULL, TRUE, 220, now(), now()),
('SCREEN_CODE', 'DOSSIER_DETAIL', 'Détail de dossier', NULL, TRUE, 230, now(), now()),
('SCREEN_CODE', 'CLIENT_DETAIL', 'Détail de client', NULL, TRUE, 240, now(), now()),
('SCREEN_CODE', 'SITE_DETAIL', 'Détail de site', NULL, TRUE, 250, now(), now()),
('SCREEN_CODE', 'COLLABORATEUR_DETAIL', 'Détail de collaborateur', NULL, TRUE, 260, now(), now()),
('SCREEN_CODE', 'INTERVENTION_EDIT', 'Formulaire intervention', NULL, TRUE, 270, now(), now()),
('SCREEN_CODE', 'SUIVI_TEMPS_CREATE', 'Saisie de temps', NULL, TRUE, 280, now(), now()),
('SCREEN_CODE', 'COMPTE_RENDU_CREATE', 'Compte rendu', NULL, TRUE, 290, now(), now()),
('FEATURE_CODE', 'INTERVENTION_SEARCH_RUN', 'Recherche d''intervention', NULL, TRUE, 10, now(), now()),
('FEATURE_CODE', 'REPORT_GENERATE', 'Génération de rapport', NULL, TRUE, 20, now(), now()),
('FEATURE_CODE', 'EMAIL_SEND', 'Envoi de courriel', NULL, TRUE, 30, now(), now())
ON CONFLICT DO NOTHING;
-- ============================================================
-- END 011. Ordre serveur : 001 -> 002 -> 003 -> 004 -> 005 -> 006
-- -> 007 -> 008 -> 009 -> 010 -> 011. Aucun DELETE, aucune donnée écrasée.
-- ============================================================