# ECOLE ECOIN Security Baseline

Date: 2026-05-21

Purpose: minimum security bar for every new route, Livewire component, file flow, automation, and integration.

## Route Baseline

### Admin

- Every `/admin/*` route requires `auth`.
- Every operational admin route should declare an explicit permission or policy middleware at the route level.
- Admin group middleware is not a substitute for a domain permission when the page owns sensitive data or actions.
- Routes that intentionally rely on `EnsureUserIsAdmin` only must be documented and reviewed.

### Student portal

- Student routes require student portal middleware and must only query the authenticated student's own records unless an explicit policy says otherwise.
- Enrollment, payment, material, attendance, profile, and certificate access must resist direct ID guessing.

### Teacher/Instructor portal

- Teacher/instructor routes require teacher portal middleware.
- Teacher-scoped queries may only expose assigned cohorts, assigned sessions, allowed materials, and allowed attendance targets.

### Organization portal

- Org routes require `auth`, `org_portal`, and `tenancy`.
- Selected organization state must come from an active membership and an active organization.
- Every org report, invoice, receipt, cohort summary, employee record, and enrollment query must match the selected organization or policy scope.

### Webhooks and public APIs

- Verify signatures/tokens where providers support them.
- Use rate limits.
- Store idempotency identifiers for provider events.
- Respond quickly and queue expensive processing.

## Authorization Baseline

- Route middleware protects entry.
- Policies protect model-level access and sensitive files.
- Livewire sensitive actions call `authorize()` or `Gate::authorize()` before mutation.
- Do not rely on hidden buttons or sidebar visibility.
- Do not rely on a query filter alone when a policy should decide access.

## IDOR Baseline

For every route model parameter ask:

- Can a student open another student's ID?
- Can a teacher open another teacher's cohort/session?
- Can an org member open another organization's invoice/report/payment/receipt?
- Can support perform finance approval/allocation without explicit permission?

Required tests for sensitive modules:

- Allowed owner path.
- Same-role foreign ID path returns 403 or 404 by policy.
- Direct download foreign ID path is rejected.

## Tenant Scoping

- `Organization` is the canonical corporate tenant.
- Do not introduce `companies`, `users.company_id`, or `agreement_path` into new features.
- Tenant scoping belongs in policies, tenancy middleware, and reusable query services.
- A selected organization ID stored in session is not sufficient unless membership is revalidated.

## Private File Baseline

Sensitive files include:

- Student receipts.
- Payment review attachments.
- Course materials with access control.
- Proposal, agreement, signed agreement, report, invoice, credit note, and corporate receipt PDFs.
- Imports and exports containing personal or financial data.

Rules:

- Store sensitive files on a private disk.
- Download via controller plus policy.
- Never expose a private disk path as a public URL.
- Prefer signed routes only when the authorization design explicitly supports them.
- Log download/audit activity for financial, signed, and corporate delivery files where required.
- Do not leave direct `Storage::download()` behavior inside UI components for new sensitive flows.

## Financial Safety

- Every money-changing action needs an explicit permission.
- Financial transactions are append-oriented; do not silently delete audit-relevant history.
- Confirmed payment, allocation, credit note, reversal, void, approval, and refund-like actions require audit/activity logging.
- Idempotency is mandatory for provider callbacks and allocation-derived transaction creation.
- Amount calculations live in domain services/calculators and have unit tests.

## Audit Logging

Audit or activity records are mandatory for:

- Role and permission changes.
- Enrollment approval/confirmation/cancellation paths.
- Payment approval/rejection/receipt review.
- Corporate proposal/agreement/invoice/payment lifecycle actions.
- Credit notes and allocation reversals.
- Sensitive settings and provider credential changes.
- Attendance changes where policy or finance depends on them.

Audit payload rule:

- Store IDs and safe diffs.
- Avoid plaintext secrets.
- Avoid unnecessary full PII copies.

## Secrets And Provider Settings

- API tokens, verify tokens, app secrets, and access tokens must be encrypted at rest when persisted.
- Never log provider secrets.
- Mask tokens in UI after save.
- Keep webhook errors useful without dumping raw secret-bearing request state.

## PII Rules

- Show phone/email only where the role and workflow need them.
- Prefer masking helpers outside owner/profile/admin-need contexts.
- Exports and PDFs must have explicit PII review.
- Messaging templates should receive only the variables they need.

## Livewire Review Rules

For every Livewire page:

- Page mount or route middleware proves page access.
- Every mutating method proves action access.
- Every route model mutation re-scopes to the parent or tenant where possible.
- Reusable workflow logic moves to an Action/Service.

## Minimum Security Tests

Per sensitive module add:

- Route permission feature tests.
- Policy tests.
- IDOR tests.
- File privacy/download tests.
- Tenant membership tests when organization scope exists.
- Financial idempotency tests when money is involved.

## Current Audit Notes

The repository already contains strong examples:

- Corporate downloads use policy middleware.
- Organization routes are grouped behind portal and tenancy middleware.
- WhatsApp webhook routes are rate-limited.

The baseline exists to make those patterns universal, not exceptional.
