# Architecture — CMMSchool CI4

## High-level picture

```mermaid
flowchart LR
  subgraph clients [Clients]
    Browser[Browser]
    StripeWH[Stripe webhooks]
  end
  subgraph public [public]
    FC[index.php]
    Assets[CSS / JS / PDFs]
  end
  subgraph app [Application]
    Routes[Routes.php]
    C[Controllers]
    M[Models]
    V[Views]
    Lib[Libraries / Helpers]
  end
  subgraph data [Data]
    DB[(MySQL)]
  end
  Browser --> FC
  StripeWH --> FC
  FC --> Routes --> C
  C --> M
  C --> V
  C --> Lib
  M --> DB
```

- **Front controller:** `public/index.php` bootstraps CodeIgniter 4 (`CodeIgniter\Boot::bootWeb`).
- **Routing:** Explicit routes in `app/Config/Routes.php` (no reliance on auto-routing for main features).
- **State:** PHP sessions (`writable/session`); flash data for forms and messages.
- **Persistence:** Shared **MySQL** schema with the legacy CI3 app during migration.

---

## Folder layout (important paths)

| Path | Role |
|------|------|
| `app/Controllers/` | HTTP controllers (`Tp\`, `Admin\`, `Webhook\`, root) |
| `app/Models/` | Active Record–style models per table / domain |
| `app/Views/` | PHP views (`admin/`, `tp/`, `pp/`, …) |
| `app/Libraries/` | Shared logic (e.g. `EnrollmentStripeHelper`) |
| `app/Config/` | `Routes`, `App`, `Database`, `Stripe`, `Filters`, … |
| `public/` | Web root: `index.php`, static assets, `registration_paper_form/*.pdf` |
| `writable/` | Logs, sessions, cache, uploads (as configured) |
| `tests/` | PHPUnit (`feature/`, `unit/`, `_support/`) |
| `vendor/` | Composer dependencies |

---

## URL namespaces (logical)

| Prefix | Audience | Notes |
|--------|----------|--------|
| `/` | Public | `Home` → redirect into teacher portal login |
| `tp/…` | Teachers & parents | “Third party” portal: `te`, `ur`, `pa`, `pp`, `studentEnrollment`, `payment`, `quests`, `rosters`, … |
| `admin/…` | School admins / franchise | `home`, `schools`, `students`, `enrollment`, `prospects`, … |
| `POST /webhook/stripe` | Stripe | Raw body + signature header; **not** behind CSRF |
| `GET /registration_paper_form/(:any)` | Public | Serves PDFs from `public/registration_paper_form/` |

---

## Controllers and layers

- **`BaseController`** — shared helpers (`form`, `url`).
- **`Admin\AdminController`** — common admin auth / layout hooks for admin modules.
- **Business logic** often lives in **models** (legacy style) and **libraries**; controllers orchestrate requests, validation, and responses.

### Stripe payments

- Parent flow: `Tp\Payment` + Stripe Checkout.
- Server confirmation: `Webhook\StripeWebhook` (`checkout.session.completed`) + `EnrollmentStripeHelper::finalizeFromCheckoutSession`.
- Details: [payment-gateway.md](payment-gateway.md).

### Paper registration PDFs

- `RegistrationPaperForm::pdf` — validates path under `public/registration_paper_form/`, serves `application/pdf`.

---

## Security notes

- **CSRF:** Global CSRF filter may be disabled in `Filters.php`; treat forms and APIs accordingly when hardening.
- **Stripe webhook:** Must use signing secret verification (`Stripe\Webhook::constructEvent`); route excluded from CSRF so the raw body is preserved.
- **PDF route:** Uses `realpath` + prefix check to avoid path traversal.

---

## Filters (overview)

`app/Config/Filters.php` defines global/required filters (e.g. `forcehttps`, `pagecache`, `toolbar` in development). Adjust per environment.

---

## Autoloading

- **Composer PSR-4:** `App\` → `app/`, `Config\` → `app/Config/`.
- **Tests:** `Tests\Support\` → `tests/_support/`.

---

## Related reading

- [README.md](README.md) — documentation index  
- [MIGRATION.md](MIGRATION.md) — CI3 parity and remaining work  
- [payment-gateway.md](payment-gateway.md) — payments  
