# Pishon Educational Management — Full Software Audit Report

**Date:** 2026-09-17
**Scope:** Entire `school-platform/` codebase (Laravel 12 multi-tenant school SaaS)
**Method:** Full source review of routes (569), 120+ controllers, 110+ models, 55+ services, 100+ migrations/seeders, 334 Blade views, 550-test suite (all green), plus live-database inspection of the MySQL dev store.

---

## 1. Executive Summary

Pishon Educational Management is a **mature, feature-complete, multi-tenant school management platform** (Laravel 12 / PHP 8.2 / MySQL) with:

- A **super-admin platform console** (school onboarding, plans, subscriptions, billing, settings/CMS, 2FA, system health, backups, failed jobs).
- A **full school administration console** (students, staff & payroll, academics, exams, results & report cards with a publish/verification workflow, finance with online payments, communications, website CMS, online admissions).
- **Three public-facing portals** (Student, Parent, Teacher) plus per-school **public websites**.
- **Commercial self-service subscription billing** via Paystack (schools pay Pishon), encrypted secrets, double-entry platform ledger, entitlements and trial lifecycle.
- **Hardening**: TOTP 2FA for super admins, login throttling, password policy, security headers/CSP, upload MIME guards, tenant-isolation enforced by global scopes + middleware, tamper-proof email verification & social login.

**Status: READY FOR PRODUCTION launch once the infrastructure (domain, HTTPS, SMTP, gateway keys, cron, queue worker) is provisioned per `docs/deployment-runbook.md`.** The full automated suite passes: **575 tests / 2226 assertions, OK (0 failures)**. The main product gap is an **undeployed CBT engine** (gated honestly), and several commercialization/scale items listed in §9.

---

## 2. What the Software Is (Inventory)

### 2.1 Technology stack
| Layer | Choice |
|---|---|
| Framework | Laravel 12.67.0 (PHP 8.2) |
| Database | MySQL (production template) / SQLite :memory: (tests) |
| Frontend | Blade + Tailwind CSS v4 + Vite 7 (build: `npm run build`) |
| PDF | barryvdh/laravel-dompdf |
| Auth/social | Laravel Socialite (Google/Facebook) |
| Payments | Paystack + Flutterwave driver abstraction (contract-based) |
| Queue/cache/session | Database drivers (Redis optional, documented) |
| QR codes | simplesoftwareio/simple-qrcode |
| Dev tools | PHPUnit 11, Mockery, Pint, Pail, Sail |

### 2.2 High-level code counts
| Metric | Count |
|---|---|
| Registered routes (non-vendor) | **569** |
| Blade views | **334** (platform 23, school 163, website 56, portal 13, teacher-portal 14, emails 19, auth 8, account 4, components 10) |
| Eloquent models | ~110 |
| Services | ~55 across 12 domains |
| Controllers | 120+ (Account, Auth, Payments, Platform, Portal, School, Staff, Admissions) |
| Migrations applied | 70 |
| Tests | **575 passing / 2226 assertions** |

### 2.3 Live dev-database state (MySQL `school_cms`)
- 5 tenant schools (Greenfield, Sunrise, Royal Heritage, Sunshine, J.J Institute), 24 users, 8 students, 4 teachers, 2 parents, 6 classes, 12 subjects, 5 plans, 3 subscriptions, 11 staff members.
- 8 invoices / 2 payments; 3 **published result sheets with verification codes**; 60 timetables; 80 attendance rows; 56 platform settings; 14 landing features.

---

## 3. Modules & Functional Status

Legend: ✅ Fully functional (built + tested) · 🟨 Functional but partial/needs wiring · ❌ Not implemented (intentionally gated).

### 3.1 Platform Console (super admin) — ✅
- **Auth:** `platform/login` + `register`, password reset (throttled), **2FA challenge**, logout.
- **Dashboard:** schools/active-schools/users/revenue KPIs.
- **Schools CRUD** + status (active/suspended/pending) + subscriptions per school.
- **Plans CRUD** — Free Trial / Pay Per Student (₦200) / Monthly Full Access (₦30,000), admin-editable, DB-driven.
- **Subscriptions:** list, show, store, renew, cancel.
- **Users** (platform admins) CRUD.
- **Profile** (name, phone, password change).
- **Settings:** landing CMS (hero, features, steps, about, CTA, pricing, stats, banner, WhatsApp socials) + **Authentication & Email** tab (SMTP, email-verification toggle, Google/Facebook login config, redirect URIs, **test-email** button).
- **Billing:** subscription-invoice ledger (Pishon money), pay/run through platform Paystack gateway.
- **System:** health dashboard, **on-demand + scheduled backups** (download ZIP), failed-jobs retry/forget.
- **2FA** (TOTP enable/disable/recovery codes, hashed at rest).

### 3.2 Account Area & School Onboarding — ✅
- `/account` dashboard for non-admin platform customers; **3-step school-creation wizard** (details → slug → confirm), slug availability check.

### 3.3 School Administration Console — ✅
- **Dashboard** + per-role wall (staff dashboard home).
- **Students:** CRUD, photo/document upload, portal account create/reset/toggle, status/graduate/transfer, promote, CSV import/export, alumni register, printable ID cards.
- **Parents:** CRUD + portal accounts.
- **Teachers:** CRUD, photo, toggle, portal account, class assignments, per-user permissions.
- **Staff Management:** directory, CRUD, portal accounts, staff attendance (+history), categories/departments/designations, **Payroll** (profiles, runs, approve/disburse/cancel).
- **Academics:** classes, subjects, academic years/terms (set current), timetable builder (print/copy), daily attendance and report.
- **Exams & Results:** exam CRUD, assessment types (CA/exam) & grading scale, score-entry sheet, **result sheets with workflow** (draft → submitted → reviewed → approved → published), report-card preview + PDF, teacher remarks, signatures, behaviour/conduct, **public verification codes** (`/verify-result/{code}`).
- **Finance:** fee categories/structures, invoice generation (per-student, bulk), payments (online + manual verify/reject/refund/reverse/credit), expenses + recurring + categories, other income, bank accounts, **online payment gateways** (per-school, encrypted credentials, own/Pishon modes, test-connection), **settlement profiles** (bank + currency), **service-charge rules** (platform-configured), cashbook, audit trail, and reports (collections, outstanding, income statement, journal, trial balance, reconcile).
- **Communications:** inbox/messaging, announcements (publish to portals/site), notifications centre.
- **Website CMS:** pages, news, events, gallery albums/images, media library, hero slides, FAQs, downloads, testimonials, contact-message inbox, academic programmes, site settings; **website customization** (theme, content, sections, navigation, carousel, SEO, favicon).
- **Settings:** school profile, user management, role-permissions matrix, portal access toggles, **email & notification settings** (SMTP secrets, test send, email logs + retry), campuses (multi-campus).
- **Self-service subscription billing:** current plan + live quote + billing history + usage-vs-plan-limits, subscribe → gateway → callback (server-side verify, cross-school reference rejected), Phase-2.

### 3.4 Student Portal — ✅
Dashboard (attendance %, fees, tiles), results list + full printable report card, attendance history, timetable, subjects, fees/invoices + **online payment** (+receipts), announcements, profile. Parent (role=parent) sees the same with a **child switcher** (`/{student?}`).

### 3.5 Teacher Portal — ✅
Dashboard, my classes/subjects, attendance take/history, marks entry + submission log, results sheets (incl. approval where permitted), comments/conduct, timetable, announcements, profile. Gated by `TeacherAccess` permissions.

### 3.6 Public School Websites — ✅
Home, about, leadership/staff, academics, admissions info, **online admissions centre** (programme pages, apply, status tracking), news, events, gallery, downloads, FAQs, contacts, newsletter, custom pages, sitemap/robots. Tenant resolved by slug, custom domain, or base-domain subdomain. Two rendering systems coexist (legacy public pages + CMS-driven `website` theme — see §8 residual).

### 3.7 Public Admissions (legacy) & Online Admission Management — ✅
- Legacy `/apply/{slug}` intake form with consent capture.
- New `admission_*` module: programmes, **drag-form builder** (sections/fields, publish/archive/duplicate), applications with status history, decisions, reference tracking, **admission letters (PDF)**.

### 3.8 Email & Notification Infrastructure — ✅
- `EmailService` with per-school SMTP settings (encrypted secrets), tenant-locked mailer selection, **email logs with retry**.
- Platform-level SMTP settings with **test-email** endpoint.
- Queued mail (`SendTenantEmailJob`, `TenantMail`), 16+ mail templates (welcome, reset, verification, attendance, invoice, payment, announcement, result-published, admission status/submitted, account-created, generic, reminder…).
- Notification preferences, notification types, absence/academic/admission/finance notifier services.

### 3.9 Online Payments & Money Handling — ✅ (keys not yet configured in live DB)
- **School money:** Paystack + Flutterwave drivers (initialize → verify → confirm), service-charge engine, pending-charge window, idempotent webhooks (`/api/webhooks/payments/{provider}`, CSRF-exempt, signature-verified, resolves the config from the transaction's own school).
- **Gateway modes:** a school either saves its **own keys** (`own` mode) or selects the **Pishon gateway** (`pishon` mode) and pays through the platform's credentials (settled to the school's settlement profile). Both modes are swappable per provider; the platform gateway keys are **admin-configurable in Platform Settings → Payments** (`gateway.paystack.*` / `gateway.flutterwave.*`, encrypted at rest, env fallback), replacing the old env-only layer.
- **Per-school service-charge rules:** the platform operator sets the service-charge rate, gateway-fee rate and fixed fee in Platform Settings → Billing & Trials; every quote (`SubscriptionService::quoteForPlan`) and school-money charge snapshots them at transaction time.
- **G configuration pins:** every new charge snapshots its `gateway_mode` and `gateway_config_id` into `PaymentTransaction.meta`. Init only routes through an **active** school config (a deactivated one falls back to platform/env keys). Verification and webhooks re-resolve the **same** config the charge was created with, so a mid-flight switch or deactivation cannot orphan or break validation.
- **Pishon money:** platform ledger (`platform_transactions` double-entry), subscription invoices, self-service billing via platform Paystack.
- The two money worlds never mix (proven by tests).

### 3.10 Security & Tenant Isolation — ✅
- Global-scope tenant isolation (`HasSchoolId` trait + middleware `ResolveSchool`, `EnsureUserHasSchoolAccess`, `EnsureSchoolRole`, `EnsureHasPermission`, portal/teacher-portal guards). Cross-tenant IDs → 404/403.
- TOTP 2FA on platform guard; login throttling (5/min per email+IP per guard); password policy; forced first-login password change.
- Security headers + CSP (HSTS, X-Content-Type-Options, Referrer/Permissions-Policy), opt-in **nonce-based strict CSP**.
- Upload MIME/content guards; `.htaccess` blocks script execution in uploads; SVG sinks closed.
- Secrets encrypted at rest (gateway keys, SMTP passwords, 2FA secret, social secrets, transaction tokens).
- NDPR/NDPA touches: apply-form consent, `/privacy` + `/terms`, portal privacy page + **JSON data export**.

### 3.11 Operations & Automation — ✅
- Scheduler (console): overdue flags, recurring expenses, payment reminders, subscription billing, trial warn/expiry, plan seeding, weekly backup + prune, queue keep-alive every 5 min, daily ops alert.
- Health dashboard, portable backups (SQLite copy or logical SQL dump + uploads + manifest), failed-job management.

### 3.12 CBT (Computer-Based Testing) — 🟨 Honest-gated, engine NOT deployed
`CbtService` maintains an entitlement ledger (`pending` while undeployed; never fabricates "installed"). The `/exams/cbt` page is gated by the `cbt` feature and shows provisioning status. **The actual CBT engine is not built** (documented as intentional).

---

## 4. What is Fully Functional (Verified)

| Area | Evidence |
|---|---|
| Full automated suite | **575 tests / 2226 assertions — OK** (50 pre-existing PHPUnit deprecations only) |
| Tenant isolation | `TenantIsolationTest`, `CrossTenantSecurityTest`, website tests, live 404/403 behaviour |
| Auth stack | login/register/reset/verification/social tests, throttling, password policy, forced change |
| 2FA | enable/verify/block/disable/recovery-code tests (7) |
| Plan limits & trials | `PlanLimitEnforcementTest` (6), `TrialLifecycleTest` (5) |
| Commercial billing | `CommercialPricingTest` (8), `SelfServiceSubscriptionTest` (8), `SubscriptionBillingTest` |
| Payments/webhooks | `FinanceSystemTest`, `OnlinePaymentsTest` (31), `ServiceChargesTest`, `SettlementsTest`, webhook idempotency + signature tests; Phase G snapshot-resolution + no-cross-school-probe tests |
| Results workflow | `ResultPublishWorkflowTest`, `ResultImportTest`, `AssessmentResultTest`, QR/verification codes |
| Payroll | `PayrollTest` |
| Portal access | `PortalTest`, `ParentPortalAccountToggleTest`, `PortalResultAccessTest` |
| CMS/website | `WebsiteTest`, `KensolThemeTest`, `HomepageCarouselTest`, `LegalPagesTest`, `CrossTenantSecurityTest` |
| Online admissions | `AdmissionManagement/*` (admin, public flow, decision flow, portal layout) |
| Security headers/CSP | `SecurityHeadersCspTest` (3) |
| Email | `AdminEmailSettingsTest`, `AttendanceNotificationTest`, password-reset flow, `EmailTenantIsolationTest`, `PlatformMailTransportTest`, `PlatformEmailVerificationTest` |
| Social login | `PlatformSocialAuthTest` (10) |
| Data-integrity guards | `SchoolCrudTest` delete-guards (10) |

---

## 5. Security Audit Findings

No new critical findings uncovered during this pass — the application is hardened relative to the original spec. Residual/notes worth recording:

1. **Intended product gap:** CBT engine undeployed (honest `pending` state, no fake success).
2. **CSP:** default keeps `unsafe-inline` in `script-src` for legacy blades; a strict nonce mode exists (`SECURITY_CSP_STRICT_SCRIPTS=true`) but needs per-component nonce migration before full switch — **enable report-only first in production**.
3. **Upload surface:** media library + CMS are guarded by extension/MIME checks; **re-verify regularly** and keep `storage/app/public/.htaccess` present.
4. **Session/2FA:** school guards don't enforce 2FA (platform-only by design, documented).
5. **Demo seeders** use `Hash::make('password')` — dev-only, must not run in production (documented; keep out of the release archive).
6. **Throttles** cover login/register/forgot/reset/onboarding/public forms and webhooks.
7. `system/routes` auto-doc route: 404 unless production *and* admin — verified.
8. No unit coverage for the new `PlatformSettings::smtpConfig` decryption edge (covered by Feature tests; acceptable).
9. **Webhook no-transaction path** now returns 404 immediately for an unknown reference instead of probing other schools' gateway configs (closed in the Phase G pass); a forged signature against a known reference still yields 401.
10. **Deactivated school gateway:** a deactivated config can never start new charges — they fall back to the platform/env keys; existing in-flight charges still verify through their snapshot config.

---

## 6. Gap Analysis (& What Is Missing)

### 6.1 Functional gaps
| # | Gap | Impact | Effort |
|---|---|---|---|
| 1 | **CBT engine not deployed** — UI + entitlement ledger exist, engine absent | Feature sales claim cannot be proven | Large (new engine) or descope |
| 2 | **No SMS channel** (only email) | Payment/attendance reminders limited | Medium (Termii/Twilio adapter into Notifier) |
| 3 | **No REST/JSON API** (no `api` routes file; only webhooks) | No mobile apps / MIT integrations | Large (Laravel Sanctum + API resource layer) |
| 4 | **No live broadcasting** (BROADCAST_CONNECTION=log) | In-app realtime notifications rely on database polling/queue | Medium (Pusher / Reverb) |
| 5 | **Mobile app / PWA** | No client for students/parents on phones | Medium |
| 6 | **Default currency hardcoded NGN** at several points | Non-Nigeria expansion restricted | Medium (currency registry per school/setting) |
| 7 | **Legacy public pages vs CMS website coexist** | Confusing dual rendering/duplicate maintenance | Medium (consolidate) |
| 8 | **No multi-language/localisation** (`APP_LOCALE=en` only) | Emerging markets need multilingual (Igbo/Yoruba/Hausa/French) | Medium (lang files + per-school locale) |
| 9 | **Analytics** (beyond GA/CSP hosts allowed) absent | Marketing funnels blind | Low-Medium (Matomo/GA + dashboard) |
| 10 | **Support/ticketing & knowledge base** | No in-product help/changelog | Medium |
| 11 | **Automated restore drill** | Backups exist but restore is manual (documented intentionally) | Low (runbook only) |
| 12 | **N+1/pagination** optimisation residual | Stated in prior phase reports; dashboards fine at current scale | Low-Medium |

### 6.2 Commercialisation gaps (to go from "software" to "modern commercial product")
| # | Item | Why it matters |
|---|---|---|
| 1 | **Recurring subscription charging** — billing is run by scheduler snapshotting invoices, but there is no stored-card/autocharge or dunning | Predictable MRR |
| 2 | **Stripe as second platform gateway** (only Paystack/Flutterwave) | International schools/card players |
| 3 | **White-labelling / partner & reseller program** | Channel growth, larger deals |
| 4 | **Onboarding checklist & data-import wizard from Excel/previous tooling** | Reduces churn during trial |
| 5 | **Product analytics + feature-usage dashboards** | Informs pricing/tiering |
| 6 | **Public status page + SLAs + privacy/DPA docs** | Enterprise trust |
| 7 | **Multi-currency + invoicing (VAT/Tax invoices)** | Formal billing |
| 8 | **Brandable email templates / sender domain (DKIM/SPF/DMARC)** | Email deliverability |
| 9 | **Cookie-consent banner (GDPR-style) + cookie policy** | Compliance |
| 10 | **Rate-plans metering by actual usage (per-student) enforcement urgency** | Revenue leakage |
| 11 | **Retention/churn tooling** — downgrade paths, soft-win-back offers, expired-trial reactivation flows | LTV |
| 12 | **REST API + webhook outbound events** (result published, payment received) | Third-party/adapter ecosystem |

---

## 7. To Take It Online (Production Launch — Required Checklist)

### 7.1 Infrastructure
1. **Domain + wildcard DNS**: `APP_BASE_DOMAIN` apex (`pishonedu.com.ng` — landing + platform console), `*.pishonedu.com.ng` → server IP. HTTPS (Let's Encrypt wildcard or Cloudflare) for apex **and** subdomains; `SESSION_SECURE_COOKIE=true`, HSTS on.
2. **Hosting**: VPS preferred (cPanel *works* per runbook; durable queue worker needs SSH → a VPS/Laravel Forge is strongly recommended).
3. **Database**: MySQL 8 on the host; dedicated user/password (no root); enable `binlog`/daily offsite backups.
4. **Redis** for cache/session/queue on multi-worker; else database drivers (documented single-instance path).
5. **Queue worker** under Supervisor (daemon) — *all mail is queued in production*.
6. **Cron**: `schedule:run` every minute (billing, trials, backups, reminders, alerts, seeding).
7. **Object storage** (S3/DO Spaces) for uploads if multi-server or scale-out; keep `local` disk otherwise (with `.htaccess` guard).
8. **Monitoring/alerting**: uptime checks, error tracking (Sentry or Laravel+Telegram/Email), log rotation; failed-job alerts fed by `ops:alert`.
9. **Backups**: verify weekly `backup:run` + prune; **perform a restore drill** on staging.

### 7.2 Configuration (from `.env.example`, documented in runbook)
- `APP_ENV=production`, `APP_DEBUG=false`, fresh `APP_KEY`.
- `MAIL_MAILER=smtp` + real host/credentials + `MAIL_QUEUE_ENABLED=true`; add right-side DKIM/SPF/DMARC.
- **Paystack/Flutterwave keys** (school-money env fallback) + **platform-billing Paystack** keys + webhook secrets; point webhook URLs at `https://DOMAIN/api/webhooks/payments/{provider}`.
- Security flags: `SECURITY_HEADERS_ENABLED=true`, `SECURITY_HSTS_ENABLED=true`, start `SECURITY_CSP_REPORT_ONLY=true`, then `SECURITY_CSP_STRICT_SCRIPTS=false`→migrate→true.
- `TRUSTED_PROXIES` (Cloudflare/LB) when applicable; `SESSION_DRIVER=redis` or `database`.
- `config:cache`, `route:cache`, `view:cache`; `php artisan migrate --force`.

### 7.3 Data & content
- Run migrations; seed only `PermissionSeeder` (+ ensure plans) — **never** `DemoAccountsSeeder` in production.
- Enable super-admin **2FA** and enforce password changes; audit seeded accounts removed.
- Configure platform settings: landing content, WhatsApp, trial duration, **Authentication & Email** (SMTP/verification/social credentials + redirect URIs added to Google/Facebook consoles).

### 7.4 Go-live smoke test
School admin logs in → create student → create teacher → issue invoice → record/online payment → enter marks → save sheet → publish → verify code publicly → parent/student view report card → self-service subscription pay-through → test-email works → 2FA challenge works.

---

## 8. Keep / Remove / Simplify Recommendations

### Keep (differentiators, deep and working)
- Tenant-isolated global scopes + middleware; portal RBAC matrices.
- Self-service subscription billing with honest ledger separation.
- Result workflow with signatures, PDF, verification codes, QR.
- Encrypted-at-rest credentials; upload guards; 2FA; throttling.
- Ops dashboard (health/backups/failed-jobs) + scheduler automation.
- Online admissions drag-forms + letters (strong sales differentiator).

### Remove / Descope (reduce surface, avoid "broken-feature" perception)
1. **CBT**: either build a minimal real engine (MCQ engine with question banks, results entry) or **hide the `/exams/cbt` route** until then — an honest `pending` page reads as unfinished.
2. **Legacy public pages** + legacy `/apply/{slug}` intake once the CMS website + admission-management centre cover the same flows (avoid duplicate support burden).
3. **Stock Laravel README** → replace with a real product README (the docs/ folder already carries the real runbooks).
4. **`ExampleTest` placeholder** + any dead scaffold (`ExampleTest` still asserts a GET on `/`).
5. Stray repo-root artifacts already removed (composer.phar, html dumps); keep fresh release archives clean (`.gitattributes`).

### Simplify / Standardise (modern-commercial hygiene)
- Standardise money handling behind `ChargeEngine`/ledger services (already mostly centralised).
- Centralise currency & locale config (remove scattered `'NGN'` literals).
- Move inline-blade JS to nonce-compatible modules to enable strict CSP.
- Introduce one base layout per portal (already 15 layouts — consolidate styling seams).
- Add a single feature-flag/config source for marketing content (PlatformSettings already is this — keep it).

---

## 9. Roadmap to Modern Commercial SaaS (Prioritised)

**Phase A — Launch (1–4 weeks):** provision infra per §7, deploy, enable 2FA/strict-CSP gradually, smoke-test one paid tenant; publish real README; remove CBT route or ship mini-engine; enable request/error monitoring alarms.

**Phase B — Revenue hygiene (4–8 weeks):** stored-card auto-renewal + dunning emails (or transparent re-invoice notices), tax/VAT invoice PDFs, usage-metered limits surfacing, trial → paid conversion nudges, expired-trial reactivation email.

**Phase C — Ecosystem (8–16 weeks):** REST API (Sanctum) + outbound webhooks; SMS notifier adapter (Termii/Twilio) for payment reminders & attendance; PWA/portal mobile polish; multi-language (at least 3 locales); consolidation of the dual website systems; analytics + retention dashboard.

**Phase D — Scale (16+ weeks):** white-label & reseller split, Stripe (international) as a platform gateway, per-school currency/localisation, enterprise SSO (SAML) or social add-ons, SLAs/status page, partner API marketplace, dedicated docs/help centre.

---

## 10. Verdict

- **Functionality:** exceptionally broad and genuinely implemented — students, staff/payroll, exams/results/verification, finance with online payments + ledger integrity, CMS websites, three portals, online admissions, self-service billing, health/backups/scheduled ops, and a strong security posture.
- **Quality:** 550 automated tests green, extensive hardened features, runbooks already written; the engine has been through (at least) a production-readiness and a phase-2 commercial pass.
- **Launch readiness:** **ready**; the only pre-launch product decision is CBT (build-or-hide), plus the standard provisioning of domain/HTTPS/SMTP/gateways/cron/worker listed in §7.
- **Commercialisation:** the fundamentals are in place (plans, trials, billing, entitlements). Turn this into a *modern commercial product* by adding recurring autocharge, multi-currency/locale, an API + SMS channel, analytics, retention tooling, and white-label/partner options — exactly the roadmap in §9.

**Prepared by:** Automated source + database audit (2026-09-17). All route/feature claims were verified against the live route table, code, migrations, and the MySQL dev database.

---

## 11. DOMAIN MIGRATION -- platform.test -> pishonedu.com.ng (2026-09-17)

Final domain change recorded here permanently. Systematic classification; nothing blind-replaced.

| # | Location | Change / State | Reason |
|---|---|---|---|
| 1 | config/app.php:88 | url default -> https://pishonedu.com.ng | config default = production URL |
| 2 | config/app.php:101 | base_domain default -> pishonedu.com.ng | tenant apex domain |
| 3 | config/app.php comment block | greenfield.pishonedu.com.ng | doc comment canonical |
| 4 | .env.example:13,17 | APP_URL / APP_BASE_DOMAIN canonical | committed prod template |
| 5 | .env (gitignored) | kept http://localhost / platform.test | local dev only; gitignored |
| 6 | phpunit.xml:29 | APP_BASE_DOMAIN=example.com (neutral) | tests use neutral IANA domain |
| 7 | AppServiceProvider::boot | added forceScheme('https') (prod) | force HTTPS, no redirect loop |
| 8 | TenantResolver APEX_HOSTS | kept 127.0.0.1, localhost | required for local dev |
| 9 | SubdomainResolutionTest | platform.test -> example.com | neutral fixture |
| 10 | PortalResultAccessTest:32 | platform.test -> example.com | neutral fixture |
| 11 | OnboardingTest:110 | greenfield.platform.test -> example.com | neutral fixture |
| 12 | PasswordResetFlowTest:245 | root@platform.test -> root@example.com | neutral fixture |
| 13 | docs/audit-report.md:212 | *.example.com -> *.pishonedu.com.ng | production runbook canonical |

### Verified untouched by design
- .env: platform.test (gitignored local dev) - codebase is env-driven.
- TenantResolver APEX_HOSTS localhost/127.0.0.1 - local dev apex resolution.
- config/mail.php local_domain + filesystems.php APP_URL fallbacks ? env-driven.
- example.com in non-test docs/templates (28 files) - neutral IANA placeholders.

### Auth / OAuth / payment / email / asset / JS
- Auth flows: route()+forceScheme -> canonical. Social callbacks: relative routes, no invented paths. Payments/webhooks: route-derived (PAYMENT_CALLBACK_ROUTE), no domain hardcoded. Email/notif: url()/route() canonical. Assets/JS/AJAX: APP_URL-rooted, 0 hardcoded hosts. HTTPS: forceScheme prod-only (no redirect loop); SESSION_SECURE_COOKIE env-gated.

### Post-migration suite
Tests: 575, Assertions: 2226 - OK (0 failures, 0 errors). 50 pre-existing deprecations unchanged.

### Deployment still required (in prod .env / DNS)
Wildcard *.pishonedu.com.ng + apex, HTTPS everywhere; APP_URL=https://pishonedu.com.ng, APP_BASE_DOMAIN=pishonedu.com.ng; real SMTP; migrate --force; queue+cron; SESSION_SECURE_COOKIE=true.

