System Diagram
The Emergency Preparedness and Exercises data model, mapped — 47 models, 125 relationships
🔍 For serious exploration, open the Interactive Diagram Viewer — pan, mouse-wheel zoom, fit-to-screen, full-screen, per-module tabs, the full 125-relationship ERD, and a focus mode that draws one model and its neighbours at a chosen depth. Person (41 links), MineSite (13) and Document (13) are role/ownership columns that fan out to nearly everything, so the viewer hides those links by default — a toggle brings them back. The diagrams below are the readable, static summary of the principal links only.
Architecture Overview
Ten areas mirror the sidebar menu. Every arrow means "one row of the left model is referenced by many rows of the right model".
flowchart LR
subgraph REQ["📜 Requirements"]
SourceAuthority --> SourceDocument --> Requirement
end
subgraph PLAN["📕 Plans & command"]
EmergencyPlan --> EmergencyProcedure
EmergencyPlan --> CommandStructure --> CommandRoleAssignment
EmergencyControlLocation --> CommandStructure
EmergencyPlan --> PlanReview
end
subgraph SCEN["⚠️ Scenarios"]
EmergencyScenario --> ScenarioControl
end
subgraph RES["🧰 Resources & readiness"]
EmergencyResource --> ResourceInspection
ReadinessAssessment --> ReadinessAssessmentItem
end
subgraph COMP["🎓 Competency"]
Competency --> EmergencyRoleCompetency
Competency --> PersonCompetency
end
subgraph PROG["📅 Exercise program"]
EmergencyExercise --> ExerciseObjective
EmergencyExercise --> ExerciseHazardAssessment
EmergencyExercise --> ExerciseParticipant
EmergencyExercise --> ExerciseLocation
end
subgraph COND["🚨 Exercise conduct"]
ExerciseInject --> ExerciseEventLog
ExerciseMuster --> MusterPerson
ExerciseCommunication
SimulatedCasualty
ResourceDeployment
end
subgraph IMPR["🔧 Improvement"]
ExerciseObservation
ExerciseDebrief
ExerciseFinding --> CorrectiveAction
ExerciseReport
end
Requirement --> PlanRequirementLink
EmergencyPlan --> PlanRequirementLink
EmergencyScenario --> ScenarioPlanLink
EmergencyPlan --> ScenarioPlanLink
EmergencyResource --> ResourceScenarioLink
EmergencyScenario --> ResourceScenarioLink
EmergencyScenario --> ReadinessAssessment
EmergencyScenario --> EmergencyExercise
EmergencyPlan --> EmergencyExercise
EmergencyExercise --> ExerciseInject
EmergencyExercise --> ExerciseMuster
EmergencyExercise --> ExerciseCommunication
EmergencyExercise --> SimulatedCasualty
EmergencyExercise --> ResourceDeployment
EmergencyResource --> ResourceDeployment
EmergencyExercise --> ExerciseObservation
ExerciseObjective --> ExerciseObservation
EmergencyExercise --> ExerciseDebrief
EmergencyExercise --> ExerciseFinding
EmergencyExercise --> ExerciseReport
ExerciseFinding --> PlanReview
(The ExerciseFinding → PlanReview arrow is the conceptual loop, not a
foreign key — a finding triggers a review via PlanReview.review_trigger =
EXERCISE and trigger_reference, which is a deliberate soft link so a review
can also be triggered by an incident, a legislative change or the calendar.)
Requirements and Plan Coverage
Where the obligations come from, and how a plan demonstrates it meets them.
erDiagram
SourceAuthority ||--o{ SourceDocument : "source_authority_id"
SourceDocument ||--o{ SourceDocument : "superseded_by_id"
SourceDocument ||--o{ Requirement : "source_document_id"
Requirement ||--o{ PlanRequirementLink : "requirement_id"
EmergencyPlan ||--o{ PlanRequirementLink : "emergency_plan_id"
Document ||--o{ SourceDocument : "local_document_id"
Document ||--o{ PlanRequirementLink : "evidence_document_id"
Plans, Procedures and Command
The plan spine. A plan revision supersedes the previous one rather than overwriting it, and a command structure names both a primary and an alternate control location, and both a primary and an alternate position per role.
erDiagram
EmergencyPlan ||--o{ EmergencyPlan : "supersedes_plan_id"
EmergencyPlan ||--o{ EmergencyProcedure : "emergency_plan_id"
EmergencyPlan ||--o{ CommandStructure : "emergency_plan_id"
EmergencyPlan ||--o{ PlanReview : "emergency_plan_id"
EmergencyControlLocation ||--o{ CommandStructure : "primary_control_location_id"
EmergencyControlLocation ||--o{ CommandStructure : "alternate_control_location_id"
CommandStructure ||--o{ CommandRoleAssignment : "command_structure_id"
Position ||--o{ CommandRoleAssignment : "primary_position_id"
Position ||--o{ CommandRoleAssignment : "alternate_position_id"
Position ||--o{ EmergencyProcedure : "responsible_position_id"
OperatingArea ||--o{ EmergencyControlLocation : "operating_area_id"
Scenarios, Controls and Resources
Credible scenarios drive everything downstream: the controls that must hold, the plans that address them, the resources that must be available, and the readiness assessments that rate the whole picture.
erDiagram
EmergencyScenario ||--o{ ScenarioControl : "emergency_scenario_id"
EmergencyScenario ||--o{ ScenarioPlanLink : "emergency_scenario_id"
EmergencyPlan ||--o{ ScenarioPlanLink : "emergency_plan_id"
EmergencyScenario ||--o{ ResourceScenarioLink : "emergency_scenario_id"
EmergencyResource ||--o{ ResourceScenarioLink : "emergency_resource_id"
EmergencyResource ||--o{ ResourceInspection : "emergency_resource_id"
EmergencyScenario ||--o{ ReadinessAssessment : "emergency_scenario_id"
ReadinessAssessment ||--o{ ReadinessAssessmentItem : "readiness_assessment_id"
Position ||--o{ ScenarioControl : "responsible_position_id"
Position ||--o{ EmergencyResource : "responsible_position_id"
OperatingArea ||--o{ EmergencyScenario : "operating_area_id"
OperatingArea ||--o{ EmergencyResource : "operating_area_id"
Competency Coverage
EmergencyRoleCompetency is the requirement side (what a command role needs,
and how many people must hold it); PersonCompetency is the evidence side.
Note that neither joins to CommandRoleAssignment directly — the link is the
command_role enum value, so coverage is computed rather than navigated.
erDiagram
Competency ||--o{ EmergencyRoleCompetency : "competency_id"
Competency ||--o{ PersonCompetency : "competency_id"
Person ||--o{ PersonCompetency : "person_id"
Person ||--o{ PersonCompetency : "verified_by_person_id"
Person ||--o{ PersonPosition : "person_id"
Position ||--o{ PersonPosition : "position_id"
The Exercise Spine
Everything about an exercise hangs off EmergencyExercise — twenty-one
relationships, the most of any model except Person.
erDiagram
EmergencyScenario ||--o{ EmergencyExercise : "emergency_scenario_id"
EmergencyPlan ||--o{ EmergencyExercise : "emergency_plan_id"
EmergencyExercise ||--o{ ExerciseObjective : "emergency_exercise_id"
EmergencyExercise ||--o{ ExerciseHazardAssessment : "emergency_exercise_id"
EmergencyExercise ||--o{ ExerciseParticipant : "emergency_exercise_id"
EmergencyExercise ||--o{ ExerciseLocation : "emergency_exercise_id"
EmergencyControlLocation ||--o{ ExerciseLocation : "emergency_control_location_id"
OperatingArea ||--o{ ExerciseLocation : "operating_area_id"
Exercise Conduct
The timed record of what actually happened. ExerciseEventLog.related_inject_id
is what ties a controller's inject to the response it provoked.
erDiagram
EmergencyExercise ||--o{ ExerciseInject : "emergency_exercise_id"
EmergencyExercise ||--o{ ExerciseEventLog : "emergency_exercise_id"
ExerciseInject ||--o{ ExerciseEventLog : "related_inject_id"
EmergencyExercise ||--o{ ExerciseCommunication : "emergency_exercise_id"
EmergencyContact ||--o{ ExerciseCommunication : "recipient_contact_id"
EmergencyExercise ||--o{ ExerciseMuster : "emergency_exercise_id"
ExerciseMuster ||--o{ MusterPerson : "exercise_muster_id"
EmergencyExercise ||--o{ SimulatedCasualty : "emergency_exercise_id"
EmergencyExercise ||--o{ ResourceDeployment : "emergency_exercise_id"
EmergencyResource ||--o{ ResourceDeployment : "emergency_resource_id"
Evaluation and Improvement
The closing loop. A finding points at whatever it implicates — the objective, the plan, the procedure, the resource — so improvement is traceable to the thing that failed.
erDiagram
EmergencyExercise ||--o{ ExerciseObservation : "emergency_exercise_id"
ExerciseObjective ||--o{ ExerciseObservation : "exercise_objective_id"
EmergencyExercise ||--o{ ExerciseDebrief : "emergency_exercise_id"
EmergencyExercise ||--o{ ExerciseFinding : "emergency_exercise_id"
ExerciseObjective ||--o{ ExerciseFinding : "related_objective_id"
EmergencyPlan ||--o{ ExerciseFinding : "related_plan_id"
EmergencyProcedure ||--o{ ExerciseFinding : "related_procedure_id"
EmergencyResource ||--o{ ExerciseFinding : "related_resource_id"
ExerciseFinding ||--o{ CorrectiveAction : "exercise_finding_id"
Position ||--o{ CorrectiveAction : "assigned_position_id"
EmergencyExercise ||--o{ ExerciseReport : "emergency_exercise_id"
Application Flow — Preparedness to Improvement
The order in which the system is actually used, and what gates each step.
flowchart TD
A["📜 Register source documents<br/>and extract requirements"] --> B["📕 Write / revise the emergency plan<br/><i>PlanRequirementLink shows coverage</i>"]
B --> C["⚠️ Register credible scenarios<br/>and their controls"]
C --> D["🔗 Link scenarios to plans<br/>and to required resources"]
D --> E["🧰 Inspect resources<br/><i>available · functional · in date · accessible</i>"]
D --> F["🎓 Verify role competency coverage<br/><i>minimum people current per role</i>"]
E --> G{"📊 Readiness assessment<br/>item by item"}
F --> G
G -->|"gap rated NOT_TESTED<br/>or NOT_READY"| H["📅 Schedule an exercise<br/>against the untested control"]
G -->|"defect or shortfall"| P["🔧 Corrective action"]
H --> I["🎯 Write weighted objectives<br/>with success measures"]
I --> J{"⛔ Hazard assessment<br/>APPROVED?<br/><i>stop criteria + real-emergency protocol</i>"}
J -->|no| I
J -->|yes| K["▶️ Run the exercise<br/><i>injects · event log · comms · muster ·<br/>casualties · deployments</i>"]
K --> L["👁️ Evaluator observations<br/>rated per objective"]
L --> M["🗣️ Hot debrief, then formal debrief"]
M --> N["📋 Classify findings<br/><i>OBSERVATION → NONCONFORMANCE_CRITICAL</i>"]
N --> O["📄 Exercise report<br/>prepared → reviewed → approved"]
N --> P
P --> Q{"✅ Verified by someone<br/>other than the owner?"}
Q -->|no| P
Q -->|yes| R{"All major / critical<br/>actions verified?"}
O --> R
R -->|no| S["Exercise stays<br/>ACTIONS_OPEN"]
S --> P
R -->|yes| T["🔁 Plan review<br/><i>trigger = EXERCISE</i>"]
T --> U["📕 New plan revision<br/><i>old revision → SUPERSEDED</i>"]
U --> B
T --> V["🔒 Exercise CLOSED"]
Application Flow — Running an Exercise
The conduct phase in detail, including the two things that make an exercise safe: the real-emergency override and the simulation markers.
flowchart TD
S(["Exercise SCHEDULED"]) --> B["Safety brief<br/><i>or no-notice controls</i>"]
B --> ST["▶️ IN_PROGRESS<br/>start authorised"]
ST --> IN{"Controller releases<br/>the next inject"}
IN --> AK["Inject acknowledged<br/>→ ACTED_ON / SKIPPED"]
AK --> EV["📝 Event log entry<br/><i>real_event = false</i>"]
EV --> RESP{"What did it provoke?"}
RESP --> C1["📞 Communication<br/><i>simulated = true, prefixed EXERCISE</i>"]
RESP --> C2["👥 Muster + MusterPerson<br/><i>accounted · missing · offsite · exempt</i>"]
RESP --> C3["🩹 Simulated casualty<br/><i>LOCATED → TRIAGED → TREATED →<br/>EXTRACTED → TRANSFERRED</i>"]
RESP --> C4["🚚 Resource deployment<br/><i>requested → mobilised → arrived →<br/>deployed → stood down</i>"]
C1 --> OBS["👁️ Evaluator observation<br/>rated against an objective"]
C2 --> OBS
C3 --> OBS
C4 --> OBS
OBS --> MORE{"More injects?"}
MORE -->|yes| IN
MORE -->|no| END["⏹️ Stand down<br/>participants + resources accounted"]
END --> DONE(["COMPLETED → DEBRIEFING"])
ST -.->|"any stop criterion met"| STOP["⛔ PAUSED / ABORTED"]
ST -.->|"REAL EMERGENCY ×3"| REAL["🚨 Exercise abandoned<br/>site emergency plan takes over<br/><i>logged with real_event = true</i>"]
STOP -.-> ST
Reading the Diagrams
A ||--o{ Bmeans one row of A is referenced by many rows of B (the label is the foreign-key column on B).- These static diagrams show principal links only — the role columns that
appear on nearly every model (
*_person_id,mine_site_id,*_document_id) are omitted for readability. The interactive viewer's Full ERD shows all 125, with the person/site/document noise toggleable. EmergencyExerciseis the hub of the domain — the viewer's Focus mode defaults to it, with 21 links.Personhas the most (41) because every assurance act records who did it: owned, accountable, approved, prepared, reviewed, verified, inspected, assessed, observed, facilitated, directed, controlled, evaluated, completed.- No FK was dropped in translation — the proforma graph was acyclic, so
every relationship in the source model is present.
EmergencyControlLocationwas hoisted aboveCommandStructure(the pack declares it after first use).OperatingArea.parent_area_id,EmergencyPlan.supersedes_plan_idandSourceDocument.superseded_by_idare self-references. - One pointer is deliberately not a foreign key:
ReadinessAssessmentItem.item_reference_keyis a polymorphic reference — an item can address a plan, a procedure, a resource, a control, a contact or a competency — so it is a string, not an edge. - Competency coverage is likewise computed, not navigated:
EmergencyRoleCompetencyandCommandRoleAssignmentboth carry thecommand_roleenum rather than joining, so "does this role have enough current holders?" is a query across two enum matches.
Diagrams are derived from the generated schema metadata
(apps/emergprep/generated/json/emergprep_relationship_metadata.json).
If the DSL schema changes, regenerate the metadata (python -m codegen.cli all
emergprep) and update this page and the viewer's embedded data.