-- ============================================================ -- MODULE 3: Operationele Veiligheid — PtW & MoC -- Phoenix Metals HSEQ VBS — SQL Migration v1.0 -- ============================================================ -- Scope: BRZO Hogedrempelinrichting, ATEX, HF-risico -- Seveso III Bijlage III: Operationele controle & wijzigingsbeheer -- ============================================================ -- ───────────────────────────────────────────── -- 3A. MANAGEMENT OF CHANGE (MoC) -- ───────────────────────────────────────────── -- Flow: Initiatie → Risicobeoordeling → Goedkeuring → Implementatie → PSSR → Close-out -- Goedkeuringschain: Initiator → PSE → HSEQ Manager → Plant Manager -- ───────────────────────────────────────────── -- Stap 1: Renamen bestaande stub naar legacy ALTER TABLE moc_items RENAME TO moc_items_legacy; -- Stap 2: Nieuw volwaardig MoC schema CREATE TABLE moc_requests ( -- ─── Identificatie ─── id INTEGER PRIMARY KEY AUTOINCREMENT, moc_code TEXT NOT NULL UNIQUE, -- Bijv. MOC-2026-001 title TEXT NOT NULL, -- Korte beschrijving wijziging -- ─── Classificatie ─── change_category TEXT NOT NULL CHECK(change_category IN ( 'process', -- Proceswijziging (parameters, flowsheet) 'equipment', -- Apparatuurwijziging (vervanging, upgrade) 'instrumentation',-- Instrumentatie/DCS/SCADA 'materials', -- Materiaalwijziging (leiding, pakking, etc.) 'procedures', -- Procedurewijziging 'organizational', -- Organisatorische wijziging 'facility', -- Gebouwwijziging 'software', -- Software/IT-wijziging 'temporary' -- Tijdelijke afwijking (< 90 dagen) )), change_scope TEXT NOT NULL CHECK(change_scope IN ( 'minor', -- Geringe impact, 1 goedkeurder 'moderate', -- Matige impact, 2 goedkeurders 'major', -- Grote impact, 3 goedkeurders + PSSR 'catastrophic' -- Kritieke veiligheidsimpact, Plant Director )), -- ─── Beschrijving ─── current_situation TEXT NOT NULL, -- Huidige situatie (wat is er nu?) proposed_change TEXT NOT NULL, -- Voorgestelde wijziging (wat wordt er anders?) reason_for_change TEXT NOT NULL, -- Waarom? (business case, veiligheid, efficiëntie) affected_equipment TEXT, -- Equipment tags (bijv. P-101, V-201) affected_area TEXT, -- Locatie/gebied (bijv. Elektrolythal A) affected_processes TEXT, -- Procesunits die beïnvloed worden -- ─── Relaties met Module 1 & 2 ─── related_risk_scenario_id INTEGER, -- FK naar risk_scenarios related_substance_id INTEGER, -- FK naar substance_library related_pbzo_requirement_id INTEGER, -- FK naar pbzo_requirements -- ─── Veiligheidsbeoordeling ─── hazard_identification TEXT, -- Beschrijving geïdentificeerde gevaren risk_assessment_method TEXT CHECK(risk_assessment_method IN ( 'what_if', 'hazop', 'checklist', 'risk_matrix', 'qra', 'none' )), risk_assessment_result TEXT, -- Conclusie beoordeling ipra_completed INTEGER DEFAULT 0, -- 1 = Induvidual Process Risk Assessment afgerond ipra_assessor TEXT, -- Wie voerde IPRA uit ipra_date TEXT, -- ─── Seveso / BRZO specifieke checks ─── safety_report_update_required INTEGER DEFAULT 0, -- Seveso veiligheidsrapport bijwerken? mapi_impact INTEGER DEFAULT 0, -- Maximum Accident scenario beïnvloed? pip_impact INTEGER DEFAULT 0, -- Probability of Failure impact? domino_impact INTEGER DEFAULT 0, -- Domino-effect risico? -- ─── ATEX specifieke checks ─── atex_zone_affected INTEGER DEFAULT 0, -- Wijziging in ATEX-zone? ex_certification_required INTEGER DEFAULT 0, -- EX-certificering vereist? area_classification_review INTEGER DEFAULT 0, -- Zone-indeling herzien? -- ─── Goedkeuringsketen ─── status TEXT DEFAULT 'draft' CHECK(status IN ( 'draft', -- Concept, invullen 'submitted', -- Ingediend bij PSE 'risk_review', -- Risicobeoordeling in uitvoering 'pending_approval', -- Wacht op goedkeuring 'approved', -- Goedgekeurd, mag geïmplementeerd worden 'rejected', -- Afgewezen 'implementation', -- Implementatie bezig 'pssr_pending', -- PSSR moet worden uitgevoerd 'pssr_completed', -- PSSR afgerond 'closed', -- Volledig afgerond 'cancelled' -- Geannuleerd )), priority TEXT DEFAULT 'medium' CHECK(priority IN ('critical','high','medium','low')), -- ─── Rollen ─── initiator TEXT NOT NULL, -- Wie diende de MoC in? initiator_role TEXT, -- Functie initiator pse_reviewer TEXT, -- Process Safety Engineer pse_review_date TEXT, pse_recommendation TEXT, -- PSE advies (approve/conditional/reject) hseq_approver TEXT, -- HSEQ Manager hseq_approval_date TEXT, hseq_recommendation TEXT, plant_approver TEXT, -- Plant Manager (bij major/catastrophic) plant_approval_date TEXT, plant_recommendation TEXT, -- ─── Implementatie ─── implementation_plan TEXT, -- Stappenplan implementatie implementation_start_date TEXT, implementation_due_date TEXT, actual_completion_date TEXT, -- ─── Pre-Startup Safety Review (PSSR) ─── pssr_required INTEGER DEFAULT 0, -- PSSR verplicht? (major/catastrophic = 1) pssr_completed INTEGER DEFAULT 0, pssr_lead TEXT, pssr_date TEXT, pssr_checklist TEXT, -- JSON array van PSSR checklist items pssr_findings TEXT, -- Geconstateerde bevindingen pssr_status TEXT CHECK(pssr_status IN ( 'not_required', 'pending', 'in_progress', 'passed', 'passed_with_conditions', 'failed' )) DEFAULT 'not_required', -- ─── Training & Documentatie ─── training_required INTEGER DEFAULT 0, -- Is bijwerktraining nodig? training_plan TEXT, -- Wie moet wat bijgeleerd krijgen training_completed INTEGER DEFAULT 0, procedures_updated TEXT, -- Lijst bijgewerkte procedures p&id_updated INTEGER DEFAULT 0, -- P&ID bijgewerkt? hysys_updated INTEGER DEFAULT 0, -- HYSYS model bijgewerkt? -- ─── AI Smart Review (Kas) ─── ai_review_enabled INTEGER DEFAULT 1, -- Auto safety review activeren ai_review_status TEXT DEFAULT 'pending' CHECK(ai_review_status IN ( 'pending', 'running', 'completed', 'failed', 'skipped' )), ai_review_result TEXT, -- JSON: warnings, suggestions, required_actions ai_review_date TEXT, ai_review_model TEXT, -- Welk AI model werd gebruikt -- ─── Metadata ─── notes TEXT, attachments TEXT, -- JSON array: bijlage-ID's of paden created_date TEXT DEFAULT CURRENT_TIMESTAMP, updated_date TEXT DEFAULT CURRENT_TIMESTAMP, -- ─── Foreign Keys ─── FOREIGN KEY (related_risk_scenario_id) REFERENCES risk_scenarios(id) ON DELETE SET NULL, FOREIGN KEY (related_substance_id) REFERENCES substance_library(id) ON DELETE SET NULL, FOREIGN KEY (related_pbzo_requirement_id) REFERENCES pbzo_requirements(id) ON DELETE SET NULL ); CREATE INDEX idx_moc_status ON moc_requests(status); CREATE INDEX idx_moc_category ON moc_requests(change_category); CREATE INDEX idx_moc_scope ON moc_requests(change_scope); CREATE INDEX idx_moc_initiator ON moc_requests(initiator); CREATE INDEX idx_moc_priority ON moc_requests(priority); CREATE INDEX idx_moc_substance ON moc_requests(related_substance_id); CREATE INDEX idx_moc_ai_review ON moc_requests(ai_review_status); -- ───────────────────────────────────────────── -- 3B. MoC GOEDKEURINGEN (audit trail) -- ───────────────────────────────────────────── CREATE TABLE moc_approvals ( id INTEGER PRIMARY KEY AUTOINCREMENT, moc_request_id INTEGER NOT NULL, approval_stage TEXT NOT NULL CHECK(approval_stage IN ( 'pse_review', 'hseq_approval', 'plant_approval', 'pssr_signoff' )), approver_name TEXT NOT NULL, approver_role TEXT NOT NULL, decision TEXT NOT NULL CHECK(decision IN ('approved','conditional','rejected','returned')), comments TEXT, conditions TEXT, -- Voorwaarden bij conditional approval signature_data TEXT, -- Digitale handtekening (base64 of hash) signed_at TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (moc_request_id) REFERENCES moc_requests(id) ON DELETE CASCADE ); CREATE INDEX idx_moc_approval_request ON moc_approvals(moc_request_id); CREATE INDEX idx_moc_approval_stage ON moc_approvals(approval_stage); -- ───────────────────────────────────────────── -- 3C. MoC ACTIES (verbonden acties per MoC) -- ───────────────────────────────────────────── CREATE TABLE moc_actions ( id INTEGER PRIMARY KEY AUTOINCREMENT, moc_request_id INTEGER NOT NULL, action_description TEXT NOT NULL, assigned_to TEXT NOT NULL, due_date TEXT, status TEXT DEFAULT 'open' CHECK(status IN ( 'open', 'in_progress', 'completed', 'overdue', 'cancelled' )), completion_date TEXT, verified_by TEXT, verification_date TEXT, notes TEXT, created_date TEXT DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (moc_request_id) REFERENCES moc_requests(id) ON DELETE CASCADE ); CREATE INDEX idx_moc_action_request ON moc_actions(moc_request_id); CREATE INDEX idx_moc_action_status ON moc_actions(status); -- ───────────────────────────────────────────── -- 3D. PERMIT TO WORK (PtW) -- ───────────────────────────────────────────── -- Phoenix Metals specifieke werkvergunning types: -- - Heet werk (brandgevaarlijk) -- - Besloten ruimte (ATEX/HF context) -- - Breaking containment (HF/DMC systemen) -- - Hoogwerk -- - Graafwerk (kabels/leidingen) -- - Elektrisch werk -- ───────────────────────────────────────────── -- Stap 1: Renamen bestaande stub naar legacy ALTER TABLE ptw_items RENAME TO ptw_items_legacy; -- Stap 2: Nieuw volwaardig PtW schema CREATE TABLE ptw_permits ( -- ─── Identificatie ─── id INTEGER PRIMARY KEY AUTOINCREMENT, permit_code TEXT NOT NULL UNIQUE, -- Bijv. PTW-2026-0410-001 title TEXT NOT NULL, -- Omschrijving werkzaamheden -- ─── Classificatie ─── permit_type TEXT NOT NULL CHECK(permit_type IN ( 'hot_work', -- Lassen, slijpen, branden 'confined_space', -- Besloten ruimte 'breaking_containment',-- Openen van procesleiding/-apparaat 'working_at_height', -- Hoogwerk > 2.5m 'excavation', -- Graafwerk 'electrical', -- Elektrisch werk 'radiography', -- NDT/RT 'crane_lift', -- Hijsen/takelen 'general', -- Algemeen onderhoud 'contractor_work' -- Aannemerswerk )), risk_level TEXT NOT NULL CHECK(risk_level IN ( 'standard', -- Standaard protocol 'high_risk', -- Extra controle + gasmeting 'critical' -- Plant Manager goedkeuring + continue bewaking )), -- ─── Locatie & Planning ─── location TEXT NOT NULL, -- Specifieke locatie (bijv. Elektrolythal A, Level +4) area_zone TEXT, -- ATEX-zone indien van toepassing (bijv. Zone 1, Zone 2) equipment_tag TEXT, -- Equipment tag (bijv. V-201, L-305) process_unit TEXT, -- Procesunit work_description TEXT NOT NULL, -- Gedetailleerde werkomschrijving start_datetime TEXT NOT NULL, -- Geplande start end_datetime TEXT NOT NULL, -- Geplande einde actual_start TEXT, actual_end TEXT, extension_requested INTEGER DEFAULT 0, -- Verlenging aangevraagd? extension_reason TEXT, max_extension_hours INTEGER DEFAULT 4, -- Maximale verlengingstijd -- ─── Relaties ─── related_moc_id INTEGER, -- FK naar MoC (indien wijziging) related_risk_scenario_id INTEGER, -- FK naar risk_scenarios related_substance_id INTEGER, -- FK naar substance_library (bijv. HF, DMC) -- ─── Personen ─── requested_by TEXT NOT NULL, -- Aanvrager (operator/contractor) requested_by_role TEXT, issued_by TEXT NOT NULL, -- Vergunningverstrekker (supervisor) issued_by_role TEXT, area_authority TEXT, -- Gebiedsverantwoordelijke performing_contractor TEXT, -- Naam aannemer (indien van toepassing) workers_count INTEGER DEFAULT 1, -- Aantal werknemers worker_names TEXT, -- JSON array met namen -- ─── Gasmetingen (voor BRZO/ATEX/HF context) ─── gas_testing_required INTEGER DEFAULT 0, -- Gasmeting verplicht? gas_test_lel REAL, -- LEL % (Lower Explosive Limit) — < 10% = veilig gas_test_lel_unit TEXT DEFAULT '%LEL', gas_test_toxic REAL, -- Toxische concentratie (bijv. HF ppm) gas_test_toxic_unit TEXT DEFAULT 'ppm', gas_test_o2 REAL, -- O2 % — 19.5-23.5% = veilig gas_test_o2_unit TEXT DEFAULT '%O2', gas_test_h2s REAL, -- H2S ppm — < 10 ppm gas_test_h2s_unit TEXT DEFAULT 'ppm', gas_test_method TEXT, -- Bijv. " Draagbaar multigas detector Dräger X-am 5000" gas_tested_by TEXT, gas_test_timestamp TEXT, continuous_monitoring INTEGER DEFAULT 0, -- Continue bewaking vereist? continuous_monitor_device TEXT, -- Type monitor gas_test_retest_interval INTEGER DEFAULT 60, -- Minuten tussen hermetingen -- ─── LOTO (Lockout / Tagout) ─── loto_required INTEGER DEFAULT 0, -- LOTO verplicht? loto_points_count INTEGER DEFAULT 0, -- Aantal los te koppelen energiepunten loto_description TEXT, -- Beschrijving energiebronnen (elktrisch, pneumatisch, hydraalisch, thermisch, chemisch) loto_verification_by TEXT, -- Wie heeft LOTO geverifieerd? loto_verified_at TEXT, -- ─── Specifieke Veiligheidsmaatregelen ─── isolation_method TEXT, -- Isolatiemethode (dbl block & bleed, spade, spectacle blind) isolation_verified INTEGER DEFAULT 0, -- Isolatie geverifieerd (drain/pressure test)? purging_completed INTEGER DEFAULT 0, -- Leegmaken/spoelen voltooid? purging_medium TEXT, -- Bijv. Stikstof, water, lucht neutralization_completed INTEGER DEFAULT 0, -- Neutralisatie voltooid? (bijv. HF residu) -- ─── Persoonlijke Beschermingsmiddelen ─── ppe_required TEXT, -- JSON: [{type: "Volgelaatsmasker", specification: "..."}] ppe_respiratory TEXT, -- Specifiek: bijv. "SCBA" of "Volgelaatsmasker + HF-filter" ppe_gloves TEXT, -- Bijv. "Viton handschoenen, doorbraaktijd >480 min" ppe_eye TEXT, -- Bijv. "Chemisch veiligheidsbril + face shield" ppe_body TEXT, -- Bijv. "Chemisch bestendige overall + zuurbestendig schort" ppe_footwear TEXT, -- Bijv. "Zuurbestendige laarzen" ppe_other TEXT, -- Bijv. "Hormoon-gevoelige werknemers melden" -- ─── Emergency Voorzieningen ─── emergency_equipment TEXT, -- Bijv. "Calciumgluconate gel binnen 3m bereik, oogdouches, veiligheidsdouches" emergency_response_plan TEXT, -- Specifieke evacuatieroute/actie hf_antidote_available INTEGER DEFAULT 0, -- Calciumgluconate gel beschikbaar? (HF-specifiek) spill_kit_available INTEGER DEFAULT 0, -- Lekkagemiddelen beschikbaar? fire_extinguisher_available INTEGER DEFAULT 0, -- Brandblusser beschikbaar? -- ─── Statussen ─── status TEXT DEFAULT 'draft' CHECK(status IN ( 'draft', -- Concept 'submitted', -- Ingediend 'under_review', -- Beoordeling 'approved', -- Goedgekeurd en afgegeven 'active', -- Werkzaamheden bezig 'suspended', -- Onderbroken (bijv. gasalarm) 'extended', -- Verlengd 'completed', -- Werkzaamheden afgerond, vergunning ingeleverd 'closed', -- Formeel gesloten 'cancelled', -- Geannuleerd 'expired' -- Verlopen zonder afsluiting )), -- ─── Digitale Handtekeningen ─── issuer_signature TEXT, issuer_signed_at TEXT, receiver_signature TEXT, -- Ontvanger/werker receiver_signed_at TEXT, closer_signature TEXT, -- Afsluiter closer_signed_at TEXT, -- ─── Auditting ─── inspection_required INTEGER DEFAULT 0, -- Tussentijdse inspectie? inspection_interval INTEGER DEFAULT 120, -- Minuten last_inspection_at TEXT, last_inspection_by TEXT, inspection_findings TEXT, non_conformances TEXT, -- JSON array: geconstateerde afwijkingen -- ─── AI Safety Check (Kas) ─── ai_safety_check TEXT, -- JSON: generated warnings based on substance + work type ai_check_date TEXT, -- ─── Metadata ─── notes TEXT, attachments TEXT, created_date TEXT DEFAULT CURRENT_TIMESTAMP, updated_date TEXT DEFAULT CURRENT_TIMESTAMP, -- ─── Foreign Keys ─── FOREIGN KEY (related_moc_id) REFERENCES moc_requests(id) ON DELETE SET NULL, FOREIGN KEY (related_risk_scenario_id) REFERENCES risk_scenarios(id) ON DELETE SET NULL, FOREIGN KEY (related_substance_id) REFERENCES substance_library(id) ON DELETE SET NULL ); CREATE INDEX idx_ptw_status ON ptw_permits(status); CREATE INDEX idx_ptw_type ON ptw_permits(permit_type); CREATE INDEX idx_ptw_risk ON ptw_permits(risk_level); CREATE INDEX idx_ptw_location ON ptw_permits(location); CREATE INDEX idx_ptw_dates ON ptw_permits(start_datetime, end_datetime); CREATE INDEX idx_ptw_substance ON ptw_permits(related_substance_id); CREATE INDEX idx_ptw_requested ON ptw_permits(requested_by); -- ───────────────────────────────────────────── -- 3E. PtW GASMETINGEN (meerdere metingen per vergunning) -- ───────────────────────────────────────────── CREATE TABLE ptw_gas_tests ( id INTEGER PRIMARY KEY AUTOINCREMENT, permit_id INTEGER NOT NULL, test_sequence INTEGER NOT NULL, -- Volgorde (1=initial, 2=retest, etc.) test_type TEXT NOT NULL CHECK(test_type IN ( 'initial', 'retest', 'continuous', 'post_work' )), lel_value REAL, lel_unit TEXT DEFAULT '%LEL', toxic_value REAL, toxic_substance TEXT, -- Bijv. "HF", "DMC damp" toxic_unit TEXT DEFAULT 'ppm', o2_value REAL, o2_unit TEXT DEFAULT '%O2', h2s_value REAL, h2s_unit TEXT DEFAULT 'ppm', result TEXT CHECK(result IN ('safe','borderline','unsafe')), tested_by TEXT NOT NULL, tested_at TEXT DEFAULT CURRENT_TIMESTAMP, device_used TEXT, -- Bijv. "Dräger X-am 5000, SN: 12345" notes TEXT, FOREIGN KEY (permit_id) REFERENCES ptw_permits(id) ON DELETE CASCADE ); CREATE INDEX idx_gas_test_permit ON ptw_gas_tests(permit_id); CREATE INDEX idx_gas_test_result ON ptw_gas_tests(result); -- ───────────────────────────────────────────── -- 3F. PtW LOTO ENERGY POINTS (los te koppelen energiepunten) -- ───────────────────────────────────────────── CREATE TABLE ptw_loto_points ( id INTEGER PRIMARY KEY AUTOINCREMENT, permit_id INTEGER NOT NULL, point_number INTEGER NOT NULL, -- LOTO-01, LOTO-02, etc. equipment_tag TEXT NOT NULL, -- Bijv. "P-101A" energy_type TEXT NOT NULL CHECK(energy_type IN ( 'electrical', 'pneumatic', 'hydraulic', 'thermal', 'chemical', 'kinetic', 'gravity', 'other' )), energy_description TEXT, -- Bijv. "440V motor voeding, MCC-3 breaker 12B" isolation_method TEXT, -- Bijv. "Breaker lockout + tag" lock_serial TEXT, -- Slot serienummer tag_number TEXT, -- Tag nummer isolated_by TEXT NOT NULL, isolated_at TEXT, verified_by TEXT, verified_at TEXT, status TEXT DEFAULT 'pending' CHECK(status IN ( 'pending', 'isolated', 'verified', 'released', 'failed' )), FOREIGN KEY (permit_id) REFERENCES ptw_permits(id) ON DELETE CASCADE ); CREATE INDEX idx_loto_permit ON ptw_loto_points(permit_id); CREATE INDEX idx_loto_status ON ptw_loto_points(status); -- ───────────────────────────────────────────── -- 3G. PtW INSPECTIES (tussentijdse controles) -- ───────────────────────────────────────────── CREATE TABLE ptw_inspections ( id INTEGER PRIMARY KEY AUTOINCREMENT, permit_id INTEGER NOT NULL, inspection_sequence INTEGER NOT NULL, inspected_by TEXT NOT NULL, inspected_at TEXT DEFAULT CURRENT_TIMESTAMP, conditions_ok INTEGER DEFAULT 1, -- 1 = OK, 0 = afwijking gas_test_ok INTEGER, -- Hermeting OK? ppe_compliant INTEGER DEFAULT 1, -- PBM naleving workers_present INTEGER, -- Aantal werknemers op locatie findings TEXT, -- Beschrijving bevindingen action_taken TEXT, -- Bijv. "Werk hervat", "Werk opgeschort", "Waarschuwing gegeven" signature_data TEXT, FOREIGN KEY (permit_id) REFERENCES ptw_permits(id) ON DELETE CASCADE ); CREATE INDEX idx_inspection_permit ON ptw_inspections(permit_id); -- ============================================================ -- EINDE MODULE 3 MIGRATIE -- ============================================================