-- ============================================================ -- 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 -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. -- ============================================================