Tenancy & Role Model
Architecture Context: This document defines the multi-tenant access control model for the ESG/GRI platform. For database schema and Laravel implementation details, see Backend Domain Models.
Implementation: For a comprehensive Laravel implementation guide including policies, middleware, code examples, and testing strategies, see Laravel RBAC Implementation Guide. The machine-readable policy specification is available in RBAC Matrix (YAML).
1. Tenancy Model
The platform uses strict hierarchical tenancy with hard data isolation at the tenant (organisation) boundary and soft isolation below that level.
1.1 Tenant (Organisation)
Definition A Tenant represents a legally distinct organisation reporting ESG data.
Examples - A listed company - A holding company - An NGO - A subsidiary operating independently
Key Properties
- tenant_id (UUID, immutable)
- Legal name
- Registration details (country, company number)
- Reporting frameworks enabled (GRI, ISSB, custom)
- Data retention policy
- Timezone & reporting calendar
- Subscription / licence metadata
Isolation Rules - Data must never cross tenant boundaries - Users may belong to multiple tenants, but roles are tenant-scoped - Audit logs are tenant-locked
1.2 Site (Facility / Location)
Definition A physical or operational location under a tenant.
Examples - Factory - Office - Farm - Mine - Warehouse
Key Properties
- site_id
- Parent tenant_id
- Geography (country, region, GPS optional)
- Operational type (manufacturing, admin, logistics)
- Active / inactive status
Usage - Used to scope environmental metrics (energy, water, waste) - Used for workforce and H&S attribution - Used for evidence localisation (photos, meter readings)
1.3 Project (Optional but Recommended)
Definition A logical grouping of ESG activities, initiatives, or data streams.
Examples - "FY2025 Carbon Reduction Programme" - "Supplier Due Diligence Rollout" - "ISO 14001 Certification"
Key Properties
- project_id
- Parent tenant_id
- Optional site_id
- Start/end dates
- Objectives and KPIs
- Status (planned, active, closed)
Usage - Enables cross-cutting initiatives across sites - Supports narrative reporting and improvement tracking - Optional — platform must function without projects
1.4 Reporting Period
Definition A formally defined reporting window against which ESG data is collected, reviewed, and approved.
Examples - FY2024 - Q1 2025 - GRI 2021 Annual Disclosure
Key Properties
- reporting_period_id
- Parent tenant_id
- Period type (annual, quarterly, custom)
- Start/end dates
- Lock status (open, under review, approved, locked)
- Applicable standards (GRI Universal + Topics)
Rules - Data is immutable once a period is locked - Corrections require: - Formal reopening - Full audit trail - Re-approval
2. Role Model
Roles are tenant-scoped, explicit, and non-overlapping by default. A user may hold multiple roles, but conflicting roles should be discouraged or flagged.
2.1 Collector
Purpose Capture raw ESG data and evidence.
Typical Users - Site managers - H&S officers - HR staff - Environmental technicians
Permissions - Create and edit data submissions - Upload evidence (photos, PDFs, meter readings) - View own submissions - View site-level context
Restrictions - Cannot approve or publish data - Cannot modify approved or locked records - Cannot see reviewer or auditor comments unless explicitly shared
2.2 Reviewer
Purpose Validate data completeness, consistency, and plausibility.
Typical Users - ESG officers - Sustainability managers - Internal compliance staff
Permissions - View all submissions within scope - Comment on and request corrections - Reject submissions back to collectors - Attach review notes
Restrictions - Cannot approve final reports - Cannot modify raw data directly - Cannot delete evidence
2.3 Approver
Purpose Formally sign off ESG data and reporting periods.
Typical Users - Executives - Board-delegated signatories - ESG committee members
Permissions - Approve reporting periods - Lock datasets - Add approval statements and declarations - Trigger report generation
Restrictions - Cannot edit underlying data - Cannot approve own submissions (segregation of duties) - Approval actions are irreversible without admin intervention
2.4 Admin
Purpose System and tenant configuration.
Typical Users - Platform administrators - ESG system owners
Permissions - Manage users and role assignments - Configure sites, projects, reporting periods - Configure standards and templates - Reopen reporting periods (with justification) - Access all audit logs
Restrictions - Should not act as approver in production environments - Admin actions are fully auditable and highlighted
2.5 Auditor (Read-Only)
Purpose Independent verification and assurance.
Typical Users - External auditors - Certification bodies - Internal audit teams
Permissions - Read-only access to: - Data - Evidence - Audit logs - Approval records - Export audit packs
Restrictions - No write access - No workflow actions - No configuration access
3. Permission Boundaries & Control Principles
3.1 Segregation of Duties (SoD)
| Activity | Allowed Role |
|---|---|
| Data entry | Collector |
| Data validation | Reviewer |
| Final sign-off | Approver |
| System control | Admin |
| Independent assurance | Auditor |
The platform should warn or block users holding conflicting roles within the same reporting period.
3.2 Audit & Traceability
Every action must record: - User ID - Role at time of action - Timestamp - Object affected - Before/after state (where applicable)
Audit logs are: - Append-only - Tenant-scoped - Non-deletable
3.3 Role Assignment Rules
- Roles are assigned per tenant
- Optional scoping:
- Site-level (e.g. Collector for Site A only)
- Project-level
- Temporary roles supported (expiry date)
4. Recommended Defaults (v1)
For your initial release: - Mandatory roles: Collector, Reviewer, Approver, Admin - Auditor role: Read-only, explicit opt-in - Enforce: - No self-approval - Reporting period locks - Immutable audit logs
5. RBAC Permission Matrix (API-level) — v1
See also: Backend Domain Models - Section 11: Access Control for Laravel implementation details including UserRole model, permission checks, and enforcement patterns.
This matrix assumes: - Tenant-scoped roles (a user can have different roles in different tenants) - Optional scope constraints (site/project) further restrict what the role can access - Reporting Period state gates write actions: OPEN → IN_REVIEW → APPROVED → LOCKED - Segregation of Duties: approvers cannot approve submissions they created; admins should be discouraged from approving in production
Legend: C=Create, R=Read, U=Update, D=Delete, S=State change / workflow action, E=Export
5.1 Core Objects
5.1.1 Tenants / Org Config
| Resource / Endpoint Group | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
Tenant profile (/tenants/{id}) |
R | R | R | CRU | R |
| Tenant settings (standards enabled, retention, timezone) | – | – | – | CRU | R |
| Billing / subscription metadata | – | – | – | R | – |
Notes - Only Admin configures tenant settings - Auditor may read tenant metadata needed for assurance context (optional)
5.1.2 Sites
| Resource | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
Sites (/sites) |
R (scoped) | R | R | CRUD | R |
| Site attributes (location, type, status) | – | – | – | CRUD | R |
Notes - Collectors typically read only sites within their assignment scope
5.1.3 Projects (optional)
| Resource | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
Projects (/projects) |
R (scoped) | R | R | CRUD | R |
5.1.4 Reporting Periods
| Resource | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
Reporting periods (/reporting-periods) |
R | R | R | CRUD | R |
| Change state: open/close for review | – | S (submit for approval / move to review) | R | S (override with justification) | R |
| Approve period | – | – | S | (discouraged; allowed only if explicitly granted) | R |
| Lock/unlock period | – | – | S (lock) | S (unlock/reopen with justification) | R |
| Export period pack | – | R | R | E | E |
Hard gates - LOCKED: no data/evidence edits by anyone; only admin can reopen with justification and audit record - APPROVED: no edits; only admin reopen
5.2 Templates & Standards Mapping (Forms / Indicators)
5.2.1 Data Templates / Indicator Definitions
| Resource | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
Templates (/templates, /indicators) |
R | R | R | CRUD | R |
| Mapping to GRI topics / disclosures | R | R | R | CRUD | R |
Notes - Treat template changes as controlled configuration - Changes should version and not break historical submissions
5.3 Submissions, Evidence, and Review Workflow
5.3.1 Data Submissions (metric entries, narratives, questionnaires)
| Action | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
| Create submission (OPEN only) | C | – | – | C | – |
| Read submissions | R (own + scoped) | R | R | R | R |
| Update submission (OPEN only; before submit) | U (own + scoped) | – | – | U | – |
| Delete draft submission (optional; OPEN only) | D (own) | – | – | D | – |
| Submit for review (OPEN → IN_REVIEW at item-level) | S (own) | – | – | S | – |
| Return to collector (IN_REVIEW → OPEN) | – | S | – | S | – |
| Mark "reviewed/accepted" (IN_REVIEW → READY) | – | S | – | S | – |
| Final approve submission (READY → APPROVED at item-level) | – | – | S | (only if special permission) | – |
Important control rules
- No self-approval: if created_by == approver_user_id then block approval (or require second approver)
- Reviewer never edits raw values; they can only request changes
5.3.2 Evidence (files, photos, invoices, meter readings)
| Action | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
| Upload evidence (OPEN only; or until item submitted) | C | – | – | C | – |
| Read evidence | R (scoped) | R | R | R | R |
| Replace/Update evidence metadata (tags, notes) | U (OPEN only) | U (review notes only) | – | U | – |
| Delete evidence | – (discouraged) | – | – | D (policy-controlled) | – |
| Generate evidence hash / integrity record | – | R | R | S | R |
Recommended v1 policy - Evidence deletion disabled except Admin with "break-glass" permission + mandatory justification - Evidence should be immutable once attached to an IN_REVIEW submission
5.3.3 Comments & Findings (review notes, audit findings)
| Resource | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
Comments (/comments) |
C/R (own threads) | C/R | C/R | C/R | R |
Findings / issues (/findings) |
R (assigned) | CRUD (within scope) | R | CRUD | R |
| Assign corrective actions | – | S | S (if governance wants) | S | – |
5.4 Reporting & Exports
5.4.1 Report Generation
| Action | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
| Preview report (draft) | R (scoped) | R | R | R | R (optional) |
| Generate official report artifact (PDF/Doc) | – | – | S | S | – |
| Publish report to external portal | – | – | S | S | – |
5.4.2 Exports (CSV/XLSX/API extracts)
| Action | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
| Export own/site submissions | R | R | R | E | E |
| Export full tenant dataset | – | – | R | E | E |
| Export "audit pack" (data + evidence + logs) | – | R | R | E | E |
Notes - Auditor export is typically limited to an audit scope (period + sites)
5.5 Identity, Users, and Access Control
5.5.1 Users & Role Assignments
| Resource | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
| User directory (within tenant) | R (limited) | R | R | CRUD | R (optional) |
| Invite users / deactivate | – | – | – | S | – |
| Assign roles & scopes | – | – | – | S | – |
| View access grants | – | R | R | R | R |
Recommended restriction - Only Admin assigns roles - Consider dual-control for granting Approver/Admin roles (optional v2)
5.6 Audit Log (Append-only)
| Action | Collector | Reviewer | Approver | Admin | Auditor |
|---|---|---|---|---|---|
| Read audit log (tenant scoped) | – (optional limited) | R (limited) | R | R | R |
| Export audit log | – | – | R | E | E |
| Write audit events | system | system | system | system | system |
Notes - Audit events are written by the system on every privileged action - Consider limiting Collector audit log access to "my actions only" (optional)
5.7 Permission Evaluation Rules (Implementation)
5.7.1 Required Checks (every request)
- Tenant boundary:
resource.tenant_id == session.tenant_id - Role membership: user has required role in tenant
- Scope constraint (if role grant is scoped):
resource.site_id in allowed_sites,resource.project_id in allowed_projects - Reporting period state: action allowed only if period/item in correct state
- Ownership for collector updates:
created_by == user_id(or assigned collector) - SoD: deny approval if same user created the submission (and optionally if they reviewed it)
5.7.2 "Break-glass" Admin Actions
Certain actions must require:
- Explicit permission flag (e.g., admin.break_glass=true)
- Mandatory justification string
- Extra audit log severity tag
- Optional 2-person approval (v2)
Examples: - Delete evidence - Reopen approved/locked period - Override SoD constraints
5.8 Minimal API Permission Map (Suggested Claims)
If you're implementing JWT/claims (OIDC), a practical set of permission strings:
Tenant & Structure
- tenant.read, tenant.manage
- site.read, site.manage
- project.read, project.manage
Reporting Periods
- period.read, period.manage, period.approve, period.lock, period.reopen
Templates & Standards
- template.read, template.manage
Data & Evidence
- submission.read, submission.create, submission.update, submission.submit, submission.review, submission.approve
- evidence.read, evidence.upload, evidence.tag, evidence.delete
Reporting & Exports
- report.preview, report.generate, report.publish
- export.data, export.auditpack
Audit & Access
- audit.read, audit.export
- user.read, user.manage, role.assign