System Diagram

The Exploration Programme Assurance data model, mapped — 26 models, 45 relationships

🔍 For serious exploration, open the Interactive Diagram Viewer — pan, mouse-wheel zoom, fit-to-screen, full-screen, per-module tabs, the full 45-relationship ERD, and a focus mode that draws one model and its neighbours at a chosen depth. ExplorationProject (24 links) and ExplorationTarget (6) are hub parents that fan out to most of the model, 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

Five 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 OV["📊 Overview"]
        ExplorationProject --> InvestorUpdate
    end

    subgraph PROG["🛠️ Programme"]
        WorkProgramme --> ProgrammeActivity
        WorkProgramme --> ProgrammeMilestone
        WorkProgramme --> ExplorationCampaign
        ExplorationCampaign --> CampaignProgress
        ExplorationCampaign --> AssayBatch
    end

    subgraph EVID["🔬 Evidence & learning"]
        ExplorationTarget --> ExplorationHypothesis
        ExplorationTarget --> EvidenceItem
        ExplorationHypothesis --> HypothesisEvidence
        EvidenceItem --> HypothesisEvidence
        ExplorationTarget --> UncertaintyDimension
        UncertaintyDimension --> UncertaintyAssessment
    end

    subgraph CAP["💰 Decisions & capital"]
        DecisionGate --> GateCriterion
        DecisionGate --> Decision
        FundingFacility --> CapitalCall
        BudgetPeriod --> BudgetLine
        BudgetLine --> Expenditure
    end

    subgraph ASSR["🛡️ Assurance"]
        ProjectRisk
        ProjectIssue
        Tenement
        KpiSnapshot
    end

    ExplorationProject --> Tenement
    ExplorationProject --> WorkProgramme
    ExplorationProject --> ExplorationTarget
    ExplorationProject --> FundingFacility
    ExplorationProject --> BudgetPeriod
    ExplorationProject --> DecisionGate
    ExplorationProject --> ProjectRisk
    ExplorationProject --> KpiSnapshot
    ExplorationTarget --> ExplorationCampaign
    ExplorationTarget --> Decision
    EvidenceItem --> UncertaintyAssessment
    ExplorationCampaign --> ProjectIssue

(ExplorationProject is the root of the model — 24 of the 45 relationships hang off it. ExplorationTarget is the second hub: evidence, hypotheses, uncertainty dimensions and target-level decisions all reference it. That is the pack's design intent — the project is the unit of capital governance, the target is the unit of learning.)


Overview

Everything begins and ends at the project. InvestorUpdate and KpiSnapshot are the two outward views of the same project reality — narrative and numeric.

erDiagram
    ExplorationProject ||--o{ InvestorUpdate : "project_id"
    ExplorationProject ||--o{ KpiSnapshot : "project_id"
    ExplorationProject ||--o{ Tenement : "project_id"

Programme Execution

The plan at three altitudes — the annual work programme, its activities and milestones, and the field campaigns that deliver it with their period progress reports and lab assay batches.

erDiagram
    ExplorationProject ||--o{ WorkProgramme : "project_id"
    WorkProgramme ||--o{ ProgrammeActivity : "work_programme_id"
    WorkProgramme ||--o{ ProgrammeMilestone : "work_programme_id"
    WorkProgramme ||--o{ ExplorationCampaign : "work_programme_id"
    ExplorationTarget ||--o{ ExplorationCampaign : "exploration_target_id"
    ExplorationCampaign ||--o{ CampaignProgress : "campaign_id"
    ExplorationCampaign ||--o{ AssayBatch : "campaign_id"

(A campaign carries both work_programme_id and exploration_target_id — it is the point where the plan (programme) and the purpose (target) meet on the ground.)


Evidence & Learning

What the money buys. A target carries hypotheses and evidence; the hypothesis-evidence join is the audit surface that records how each fact moved each claim's confidence. Uncertainty dimensions and their dated assessments measure how much doubt each spend bought down.

erDiagram
    ExplorationProject ||--o{ ExplorationTarget : "project_id"
    ExplorationTarget ||--o{ ExplorationHypothesis : "exploration_target_id"
    ExplorationTarget ||--o{ EvidenceItem : "exploration_target_id"
    ExplorationHypothesis ||--o{ HypothesisEvidence : "hypothesis_id"
    EvidenceItem ||--o{ HypothesisEvidence : "evidence_item_id"
    ExplorationTarget ||--o{ UncertaintyDimension : "exploration_target_id"
    UncertaintyDimension ||--o{ UncertaintyAssessment : "uncertainty_dimension_id"
    EvidenceItem ||--o{ UncertaintyAssessment : "evidence_item_id"

(HypothesisEvidence carries confidence_before and confidence_after, and UncertaintyAssessment carries reduction_per_million — the two places where the app stores learning per dollar as an explicit, reviewable number rather than inferring it.)


Decisions & Capital

The two halves of governance. Capital enters through funding facilities and capital calls and is allocated through budget periods, lines and expenditure. Decisions are gated by criteria and recorded as investor-material calls.

erDiagram
    ExplorationProject ||--o{ FundingFacility : "project_id"
    FundingFacility ||--o{ CapitalCall : "funding_facility_id"
    ExplorationProject ||--o{ BudgetPeriod : "project_id"
    BudgetPeriod ||--o{ BudgetLine : "budget_period_id"
    BudgetLine ||--o{ Expenditure : "budget_line_id"
    ExplorationProject ||--o{ DecisionGate : "project_id"
    DecisionGate ||--o{ GateCriterion : "decision_gate_id"
    DecisionGate ||--o{ Decision : "decision_gate_id"
    ExplorationTarget ||--o{ Decision : "exploration_target_id"

(CapitalCall also carries project_id directly, and Expenditure carries a campaign_code string — so a spend can be tied back to the campaign that incurred it even though the FK runs through the budget line.)


Assurance

The keep-everyone-sighted layer. Risks are forward-looking and scored; issues are live and raised against a campaign; tenements carry the licence assurance signal; KPI snapshots trend the whole programme.

erDiagram
    ExplorationProject ||--o{ ProjectRisk : "project_id"
    ExplorationTarget ||--o{ ProjectRisk : "exploration_target_id"
    ExplorationProject ||--o{ ProjectIssue : "project_id"
    ExplorationCampaign ||--o{ ProjectIssue : "campaign_id"
    ExplorationProject ||--o{ Tenement : "project_id"
    ExplorationProject ||--o{ KpiSnapshot : "project_id"

Application Flow — Capital to the Next Decision

The loop the app exists to run: committed capital pays for work, work produces evidence, evidence reduces uncertainty, and a gate turns that into the next funding call.

flowchart TD
    A["💰 Funding facility<br/><i>capital committed after the eis go decision</i>"] --> B["📄 Capital call<br/><i>drawn in tranches, required-by date</i>"]
    B --> C["📊 Budget period → lines → expenditure<br/><i>allocated and spent by category</i>"]
    C --> D["🛠️ Work programme → activities<br/><i>the plan at plan and line altitude</i>"]
    D --> E["⛏️ Exploration campaign<br/><i>field delivery, contractor, metres</i>"]
    E --> F["🧪 Assay batch<br/><i>samples to the lab</i>"]
    F --> G{"QA/QC pass<br/>and returned?"}
    G -->|"pending / overdue"| G2["⏳ Milestone → AtRisk<br/>schedule risk monitored"]
    G2 --> F
    G -->|yes| H["🔬 Evidence item<br/><i>a new fact</i>"]
    H --> I["🔗 Hypothesis-evidence link<br/><i>Supports / Weakens · confidence before→after</i>"]
    I --> J["📉 Uncertainty assessment<br/><i>score before→after · reduction per $M</i>"]
    J --> K{"Gate criteria met?<br/><i>mandatory ones especially</i>"}
    K -->|"a mandatory criterion NotAssessed / Fail"| K2["🚪 Decision gate stays Preparing"]
    K2 --> D
    K -->|yes| L["⚖️ Decision gate → Decision<br/><i>Proceed / Redirect / Stop — investor-material</i>"]
    L --> M["📣 Investor update + KPI snapshot<br/><i>next funding requirement</i>"]
    M --> A

Application Flow — Why a Hypothesis's Confidence Can Only Move Through Evidence

The single most important rule in the learning half of the model, drawn out.

flowchart TD
    S(["ExplorationHypothesis at initial_confidence"]) --> R["🔬 A new EvidenceItem is captured"]
    R --> Q{"Is it linked to the<br/>hypothesis?"}
    Q -->|"no link yet"| K1["Confidence unchanged<br/><i>an unlinked fact moves nothing</i>"]
    K1 --> K2["🔗 HypothesisEvidence written<br/><i>relationship · strength · before → after</i>"]
    K2 --> K3{"Supports / Weakens /<br/>Contradicts?"}
    K3 -->|Supports| U1["current_confidence rises<br/><i>0.45 → 0.55 → 0.62</i>"]
    K3 -->|Weakens / Contradicts| U2["current_confidence falls<br/><i>status → PartiallySupported / Contradicted</i>"]
    U1 --> T["confidence_trend follows<br/><i>Strengthening / Weakening / Unresolved</i>"]
    U2 --> T
    Q -->|"grade unresolved"| P["📉 Linked uncertainty stays Open<br/><i>UNC-CF-GRADE — assays not back</i>"]
    P --> R

Reading the Diagrams

  • A ||--o{ B means 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 two hub parents that appear on nearly every model (ExplorationProject via project_id, ExplorationTarget via exploration_target_id) are shown selectively for readability. The interactive viewer's Full ERD shows all 45, with the project/target hub links toggleable.
  • ExplorationProject has the most links (24) because it is the root of capital, programme, evidence, decisions and assurance alike. ExplorationTarget (6) is the second hub — the unit of learning that evidence, hypotheses, uncertainty and target-level decisions reference.
  • No FK was dropped and there are no cycles. Every one of the 26 models' references points at an already-defined table (see the header of apps/epa/schema/epa.dsl). Enum values are verbatim from the pack.
  • Some links are carried as denormalised code strings rather than foreign keys: Expenditure.campaign_code, CapitalCall.linked_decision_code, ProgrammeMilestone.completion_evidence_ref and the various evidence_ref fields are business-key references, not edges, so they do not appear in the ERD.

Diagrams are derived from the generated schema metadata (apps/epa/generated/json/epa_relationship_metadata.json). If the DSL schema changes, regenerate the metadata (python -m codegen.cli all epa), rebuild the viewer (python apps/epa/scripts/build_diagram_viewer.py) and update this page.