Skip to content

ESG Backend Domain Models (v1)

Laravel-Oriented Architecture Specification

1. Design Principles

  • Audit-first: all ESG data is immutable once submitted
  • Evidence-driven: no metric exists without traceable evidence
  • GRI-aligned but extensible: GRI standards are first-class, custom KPIs supported
  • Offline-compatible ingestion: UUID-based, idempotent submissions
  • Separation of concerns:
  • Collection ≠ Review ≠ Approval ≠ Reporting

2. Entity Relationship Diagram

The following diagram shows the relationships between all domain entities:

erDiagram
    Organisation ||--o{ BusinessUnit : "has many"
    Organisation ||--o{ ReportingPeriod : "has many"
    Organisation ||--o{ MaterialTopic : "has many"
    Organisation ||--o{ MetricSubmission : "has many"
    Organisation ||--o| Organisation : "parent of"

    BusinessUnit ||--o{ Site : "has many"
    BusinessUnit }o--|| Organisation : "belongs to"
    BusinessUnit ||--o{ MetricSubmission : "has many"

    Site }o--|| BusinessUnit : "belongs to"
    Site ||--o{ MetricSubmission : "has many"

    GriStandard ||--o{ GriDisclosure : "has many"
    GriStandard ||--o{ MaterialTopic : "referenced by"

    GriDisclosure }o--|| GriStandard : "belongs to"
    GriDisclosure ||--o{ MetricDefinition : "has many"

    MetricDefinition }o--o| GriDisclosure : "optionally mapped to"
    MetricDefinition ||--o{ MetricSubmission : "has many"

    MetricSubmission }o--|| MetricDefinition : "belongs to"
    MetricSubmission }o--|| Organisation : "belongs to"
    MetricSubmission }o--o| BusinessUnit : "optionally belongs to"
    MetricSubmission }o--o| Site : "optionally belongs to"
    MetricSubmission }o--|| ReportingPeriod : "belongs to"
    MetricSubmission ||--o{ MetricEvidence : "has many"
    MetricSubmission ||--o{ ReviewAction : "has many"

    Evidence ||--o{ MetricEvidence : "has many"

    MetricEvidence }o--|| MetricSubmission : "belongs to"
    MetricEvidence }o--|| Evidence : "belongs to"

    ReportingPeriod }o--|| Organisation : "belongs to"

    MaterialTopic }o--|| Organisation : "belongs to"
    MaterialTopic }o--o| GriStandard : "optionally references"

    ReviewAction }o--|| MetricSubmission : "belongs to"

    AuditLog }o--o| Organisation : "tracks"
    AuditLog }o--o| MetricSubmission : "tracks"
    AuditLog }o--o| Evidence : "tracks"

    Organisation {
        uuid id PK
        string name
        string registration_number
        string reporting_currency
        string country
        uuid parent_organisation_id FK
        timestamp created_at
        timestamp updated_at
    }

    BusinessUnit {
        uuid id PK
        uuid organisation_id FK
        string name
        enum type
        text description
        timestamp created_at
        timestamp updated_at
    }

    Site {
        uuid id PK
        uuid business_unit_id FK
        string name
        string location
        decimal latitude
        decimal longitude
        string operational_status
        timestamp created_at
        timestamp updated_at
    }

    GriStandard {
        uuid id PK
        string code
        string title
        enum category
        integer effective_year
    }

    GriDisclosure {
        uuid id PK
        uuid gri_standard_id FK
        string disclosure_code
        string title
        text description
        boolean quantitative
    }

    MetricDefinition {
        uuid id PK
        string code
        string name
        string unit
        enum data_type
        uuid gri_disclosure_id FK
        boolean custom
        text description
    }

    MetricSubmission {
        uuid id PK
        uuid metric_definition_id FK
        uuid organisation_id FK
        uuid business_unit_id FK
        uuid site_id FK
        uuid reporting_period_id FK
        string value
        uuid submitted_by
        timestamp submitted_at
        enum status
    }

    Evidence {
        uuid id PK
        string file_path
        string file_type
        string mime_type
        string checksum
        enum source_type
        uuid uploaded_by
        timestamp uploaded_at
    }

    MetricEvidence {
        uuid metric_submission_id FK
        uuid evidence_id FK
    }

    ReportingPeriod {
        uuid id PK
        uuid organisation_id FK
        string label
        date start_date
        date end_date
        boolean locked
    }

    MaterialTopic {
        uuid id PK
        uuid organisation_id FK
        string name
        text description
        uuid gri_standard_id FK
        text rationale
    }

    ReviewAction {
        uuid id PK
        uuid metric_submission_id FK
        uuid reviewer_id
        enum action
        text comments
        timestamp created_at
    }

    AuditLog {
        uuid id PK
        uuid actor_id
        string action
        string entity_type
        uuid entity_id
        json payload
        timestamp created_at
    }

3. Core Aggregate Roots

3.1 Organisation

Represents the reporting entity (group or subsidiary).

Organisation
- id (uuid)
- name
- registration_number
- reporting_currency
- country
- parent_organisation_id (nullable)
- created_at
- updated_at

Relationships:
  • hasMany BusinessUnits
  • hasMany ReportingPeriods
  • hasMany MaterialTopics

3.2 BusinessUnit

Used to separate mining vs agribusiness operations.

BusinessUnit
- id (uuid)
- organisation_id
- name
- type (mining | agribusiness | corporate)
- description
- created_at
- updated_at

Relationships:
  • belongsTo Organisation
  • hasMany Sites
  • hasMany Metrics

3.3 Site

Physical reporting locations (mine, farm, processing facility).

Site
- id (uuid)
- business_unit_id
- name
- location
- latitude
- longitude
- operational_status
- created_at
- updated_at

Relationships:
  • belongsTo BusinessUnit
  • hasMany MetricSubmissions

4. GRI Standards Model

4.1 GriStandard

GriStandard
- id (uuid)
- code (e.g. "GRI 302")
- title
- category (universal | topic)
- effective_year

4.2 GriDisclosure

Individual disclosures within a standard.

GriDisclosure
- id (uuid)
- gri_standard_id
- disclosure_code (e.g. "302-1")
- title
- description
- quantitative (boolean)

Relationships:
  • belongsTo GriStandard
  • hasMany Metrics

5. Metrics & KPIs

5.1 MetricDefinition

Defines what is being measured.

MetricDefinition
- id (uuid)
- code
- name
- unit
- data_type (number | percentage | text | boolean)
- gri_disclosure_id (nullable)
- custom (boolean)
- description

Examples: • Total energy consumed (GJ) • Lost Time Injury Frequency Rate • Total water withdrawn (m³)


5.2 MetricSubmission

Actual reported values (append-only).

MetricSubmission
- id (uuid)
- metric_definition_id
- organisation_id
- business_unit_id (nullable)
- site_id (nullable)
- reporting_period_id
- value
- submitted_by
- submitted_at
- status (submitted | reviewed | approved | rejected)

Rules: • Never updated after submission • Corrections are new submissions with references


6. Evidence Management

6.1 Evidence

Central to auditability.

Evidence
- id (uuid)
- file_path
- file_type
- mime_type
- checksum (sha256)
- source_type (invoice | photo | report | log | policy)
- uploaded_by
- uploaded_at

6.2 MetricEvidence (Pivot)

MetricEvidence
- metric_submission_id
- evidence_id

Rules: • At least one Evidence record per MetricSubmission • Evidence is immutable


7. Reporting Periods

ReportingPeriod
- id (uuid)
- organisation_id
- label (e.g. "FY2024")
- start_date
- end_date
- locked (boolean)

Rules: • Locked periods are read-only • Locking happens after final approval


8. Material Topics

8.1 MaterialTopic

MaterialTopic
- id (uuid)
- organisation_id
- name
- description
- gri_standard_id
- rationale

Scope v1: • Materiality assumed (no scoring) • Rationale stored as narrative text


9. Workflow & Review

9.1 ReviewAction

ReviewAction
- id (uuid)
- metric_submission_id
- reviewer_id
- action (reviewed | approved | rejected)
- comments
- created_at

Rules: • Supports multi-step review • Immutable history


10. Audit Log (Mandatory)

AuditLog
- id (uuid)
- actor_id
- action
- entity_type
- entity_id
- payload (json)
- created_at

Tracked events: • Submission • Evidence upload • Review decision • Period lock


11. Access Control (RBAC)

See: Tenancy & Role Model for comprehensive RBAC specification including permission matrices, workflow states, and API-level access control patterns.

Implementation Resources: - RBAC Matrix (YAML) - Machine-readable policy-as-code specification - Laravel RBAC Implementation Guide - Complete Laravel implementation with policies, middleware, and code examples

11.1 Role Summary

Recommended roles: • Collector (mobile / field) • ReviewerApproverAdmin (ESG system owner) • Auditor (read-only)

11.2 Enforcement Points

Access control enforced at: • MetricSubmission (CRUD operations) • Evidence access (upload, read, delete) • Period locking (state transitions) • ReviewAction (workflow state changes)

11.3 Implementation Notes

User-Role Assignment

// Tenant-scoped role assignment
UserRole
- id (uuid)
- user_id
- tenant_id (organisation_id)
- role (collector | reviewer | approver | admin | auditor)
- scope_type (nullable: site | project | business_unit)
- scope_id (nullable: uuid)
- expires_at (nullable)
- created_at
- updated_at

Permission Checks - All MetricSubmission operations must verify tenant boundary - Collectors can only CRUD their own submissions (until submitted) - Reviewers can transition submissions: submitted → reviewed - Approvers can transition submissions: reviewed → approved - No self-approval: submitted_by ≠ approver_id

Reporting Period State Gates - locked = false: Collectors can create/update submissions - locked = true: All write operations blocked except Admin with justification

See Section 5: RBAC Permission Matrix for detailed permission mappings.


12. API Boundary Notes

Collector API

• Create MetricSubmission • Upload Evidence • Offline-safe UUIDs

Admin API

• Define Metrics • Manage GRI mappings • Review & approve submissions • Generate reports


13. Explicit Non-Goals (v1)

• No deletions • No inline edits • No computed carbon factors • No real-time sensors


14. Forward-Compatible Extensions

Planned additions: • Targets & baselines • Materiality scoring • Assurance workflows • ISSB / IFRS S2 mapping • Sector standards


Status: Ready for Laravel implementation Alignment: GRI / ESG Scope v1 & Client Annual Report