# 01 — Discovery Report

**Project:** Godsfavour Okpara — Portfolio Website + CMS (Laravel + Filament)
**Phase:** 1 — Discovery (read-only)
**Date:** 2026-10-03
**Governing documents:** `docs/implementation/MASTER-PROMPT.md`, PRD at `docs/prd/portfolio-prd.md` (converted from `docs/Godsfavour-Okpara-Portfolio-PRD.docx`; the original is unmodified)

---

## 1. Headline finding

**There is no Laravel application in this repository, and it is not a git repository.**

The master prompt assumes "an EXISTING Laravel repository". It does not exist. `/Users/secureview/Documents/Projects/gf-portfolio` contains only:

```
gf-portfolio/
├── .DS_Store
└── docs/
    ├── .DS_Store
    ├── COMPANION-PROMPTS.md
    ├── Godsfavour-Okpara-Portfolio-PRD.docx      (original PRD, untouched)
    ├── implementation/
    │   └── MASTER-PROMPT.md
    └── prd/
        └── portfolio-prd.md                      (created in this phase: Markdown conversion)
```

There is no `composer.json`, `package.json`, `artisan`, `.env`, `app/`, `routes/`, `database/`, `resources/` or `tests/`, and no `.git/` directory.

The prompt says: *"If the repository is effectively a fresh Laravel install, say so explicitly."* This is one step earlier than that. The project is **greenfield** and the application must be scaffolded. So most of the discovery checklist (routes, models, controllers, Filament panels, auth, tests) has the answer **"none exists"**, and there is nothing existing to preserve, reuse, or stay backward-compatible with. The rest of this report concentrates on the **environment** the app will be built and run in, and on **current package compatibility**.

## 2. Discovery checklist (Master Prompt §2)

| # | Item | Finding |
|---|---|---|
| 1 | Repository structure | Docs only (see §1). No non-standard directories. |
| 2 | Laravel version | **None installed.** Latest stable on Packagist: `laravel/framework` **v13.34.0**; skeleton `laravel/laravel` v13.10.1 (requires PHP ^8.3). |
| 3 | PHP version and extensions | The default `php` on PATH is **8.1.30** (`/opt/homebrew/opt/php@8.1`), which is **too old** (see §4). Also installed: 8.2.25, 8.3.13 (`/opt/homebrew/opt/php`), and **8.4.21** (`/opt/homebrew/opt/php@8.4`). PHP 8.4 extensions present: bcmath, exif, fileinfo, gd, intl, mbstring, pdo_mysql, pdo_sqlite, sodium, zip. **Missing: imagick, redis (phpredis).** GD is enough for WebP. AVIF depends on the GD build (to verify in Phase 3). |
| 4 | composer.json | None. Composer 2.8.2 is installed. |
| 5 | package.json / Vite / Tailwind / Alpine / Livewire | None. Node v22.17.0 and npm 11.11.0 are installed. Laravel 13 skeleton defaults: Vite ^8, `laravel-vite-plugin` ^3.1, **Tailwind CSS ^4** via `@tailwindcss/vite`. |
| 6 | Database | No app config. Local **MySQL 9.7.1** is running (Homebrew service) and reachable as `root` on localhost. Existing schemas belong to unrelated projects (`caresync_test`, `crowdstack`, `emwa_platform`, `kvlc`); no portfolio schema exists. `migrate:status` is not applicable. |
| 7 | Routes | None. No collision risk with the required public URLs. |
| 8 | Models / migrations / factories / seeders | None. |
| 9 | Controllers, requests, policies, services, actions, events, jobs, notifications | None. |
| 10 | Views, components, CSS/JS | None. |
| 11 | Filament | Not installed. Latest stable: **Filament v5.9.0** (requires PHP ^8.2, Laravel ^11.28/^12/^13, **Livewire ^4.4.2**). |
| 12 | Authentication | None. |
| 13 | Admin outside Filament | None. |
| 14 | Storage | None. `storage:link` not applicable yet. No S3 configuration. |
| 15 | Queue / cache / session / mail drivers | No `.env`. Local **Redis is running** (`PONG`), but the PHP `redis` extension is not installed, so Laravel would need `predis/predis` (pure PHP) or `pecl install redis`. |
| 16 | Tests | None. **Baseline: no test suite.** |
| 17 | Code quality tooling | None (no Pint, Larastan, Rector, or CI). |
| 18 | Deployment hints | None (no Docker, Forge/Ploi, GitHub Actions, Procfile, or Supervisor). Hosting target unknown. |
| 19 | Reusable code | None in this repository. Sibling projects in `~/Documents/Projects` (`lv_front-end`, `lv_new_app`, `donacschools`) are unrelated and are **not** used as sources. |
| 20 | Conflicts with the target architecture | No code conflicts (greenfield). Environment and process conflicts are listed in §5. |

Other tooling: `pandoc` is **not installed**. The PRD was converted with a small standard-library script (headings, lists, bold, and tables kept; the one embedded image, the §21.4 palette swatch, was extracted to `docs/prd/assets/palette-swatch.jpeg`). Homebrew Python 3.14's `pyexpat` is broken, so the system Python 3.9 was used. This doesn't matter to the app, but it affects any doc tooling that relies on Homebrew Python.

## 3. Version matrix (proposed target)

All compatibility was verified against Packagist metadata on 2026-10-03. Phase 3 confirms it again with `composer require --dry-run` / `composer why-not` before each install.

| Component | Target version | Constraint evidence |
|---|---|---|
| PHP | **8.4.x** (8.4.21 local) | Required by `spatie/laravel-medialibrary` 11.23 (^8.4), `spatie/laravel-activitylog` 5.1 (^8.4), `spatie/laravel-sitemap` 8.2 (^8.4), `symfony/html-sanitizer` 8.x (>=8.4.1), Pest 5 (^8.4) |
| Laravel | **13.x** (13.34.0) | Skeleton requires PHP ^8.3 |
| Filament | **5.x** (5.9.0) | PHP ^8.2, illuminate ^13 supported |
| Livewire | 4.x (pulled in by Filament) | ^4.4.2 |
| spatie/laravel-medialibrary | 11.23.x | illuminate ^12/^13 |
| filament/spatie-laravel-media-library-plugin | 5.9.x | medialibrary ^11 |
| spatie/laravel-settings | 3.9.x | illuminate ^11/^12/^13 |
| filament/spatie-laravel-settings-plugin | 5.9.x | settings ^3 |
| spatie/laravel-permission | 8.3.x | PHP ^8.3, illuminate ^12/^13 |
| spatie/laravel-activitylog | 5.1.x | PHP ^8.4 |
| spatie/laravel-sitemap | 8.2.x | PHP ^8.4 |
| spatie/laravel-honeypot | 4.7.x | illuminate ^11/^12/^13 |
| symfony/html-sanitizer | 8.1.x | Already a Filament dependency (^7/^8), so reusing it adds no new dependency |
| blade-ui-kit/blade-heroicons | 2.7.x | Already a Filament dependency; reused for the public icon set |
| Pest | 5.x (PHPUnit 13) | Pest 5 requires phpunit ^13.3.6. `laravel/framework` 13 allows PHPUnit 11.5/12.5/13. The skeleton pins PHPUnit ^12.5, so it is raised to ^13. Fallback: Pest 4 on PHPUnit 12. |
| Larastan | 3.12.x | illuminate ^13 |
| Tailwind CSS | 4.x | Skeleton default |
| Vite | 8.x | Skeleton default |
| Alpine.js | 3.x | Public site only. Filament bundles its own copy for the admin. |
| MySQL | 9.7 local; 8.0+ in production | Laravel 13 supports MySQL 8.0+ |
| Redis | Local service running | Client: `predis/predis` or phpredis (decision D-06) |

**Not proposed:** `bezhansalleh/filament-shield` 4.3 supports Filament ^4/^5 but is deliberately not used (see ADR-008 in `DECISIONS.md`).

## 4. Environment risks

| # | Risk | Severity | Mitigation |
|---|---|---|---|
| E1 | The default CLI `php` is 8.1, which **cannot** run Laravel 13 or the spatie packages above. Running `composer` with it would fail or resolve to old versions. | **High** | Run every project command with PHP 8.4. Option A (recommended): `brew link --overwrite --force php@8.4` or put `/opt/homebrew/opt/php@8.4/bin` first on PATH. Option B: always call `/opt/homebrew/opt/php@8.4/bin/php` explicitly. Pin `"config.platform.php": "8.4"` in `composer.json` and add `.php-version`. **Needs your choice, because it changes your machine's PATH.** |
| E2 | Not a git repository. The workflow (phase commits, `git status`/`git log` in the resume prompt, rollback safety) depends on git. | **High** | `git init -b main` in Phase 3, then commit the docs as the first commit before scaffolding. |
| E3 | `composer create-project` refuses a non-empty directory, and `docs/` already exists. | Medium | Scaffold into a scratch directory, then move the files into the repository root without touching `docs/`. |
| E4 | No phpredis extension. | Low | Use `predis/predis` (no compilation) or `pecl install redis`. Tagged cache works with either. |
| E5 | No `imagick`. AVIF support in GD is unverified. | Low | Use GD for WebP. Generate AVIF only if `imageavif()` exists; otherwise document it. |
| E6 | Hosting target is unknown, which affects queue, cache, and CSP-at-edge decisions. | Medium | Write `DEPLOYMENT.md` for a generic VPS/Forge-style host and keep everything configurable through `.env`. **Open question for the owner.** |
| E7 | MySQL `root` has no password locally. | Low (local only) | Create a dedicated `gf_portfolio` user and `gf_portfolio` + `gf_portfolio_testing` schemas instead of using root in `.env`. |
| E8 | Filament 5 is recent, and its APIs differ from v3 in several places (schemas, actions namespace, MFA). | Medium | Treat vendor source as the authority. Never mix v3 syntax. Check `vendor/filament/*` whenever unsure. |

## 5. Conflicts with the master prompt (process level)

| # | Conflict | Severity | Resolution proposed |
|---|---|---|---|
| C1 | The prompt assumes an existing Laravel repository; the project is greenfield. | High (process) | Scaffold a fresh Laravel 13 app as the first step of Phase 3 (recorded as ADR-002). Rules about preserving existing code and backward compatibility have nothing to apply to. |
| C2 | The PRD sits at `docs/` root; `COMPANION-PROMPTS.md` expects it in `docs/prd/`. | Low | `docs/prd/portfolio-prd.md` was created as the converted Markdown. The `.docx` stays where it is. |
| C3 | The PRD (§23.2, §32) recommends a headless CMS. The prompt overrides this. | Recorded | ADR-001 in `DECISIONS.md`. |
| C4 | PRD §20.1 reads "first viewed in a new **icon**". | Low | Read as "new **tab**", matching master prompt §0.4. Recorded in DECISIONS. |
| C5 | PRD §6.1 lists `/404` as a sitemap entry. | Low | Unknown URLs render the CMS-driven 404 with HTTP 404. `/404` is reserved and also renders the not-found page with status 404. It is excluded from `sitemap.xml`. |

## 6. Current architecture summary

None: the project is greenfield. The target architecture is in `docs/architecture/ARCHITECTURE.md`.

## 7. Dependency inventory

None present. The proposed inventory is in the version matrix (§3) and `ARCHITECTURE.md` §15.

## 8. Existing frontend summary

None. The plan uses the Tailwind 4 + Vite 8 skeleton defaults, plus Alpine.js for the public site, self-hosted fonts, and Heroicons through Blade Icons.

## 9. Filament status

Not installed. Plan: Filament 5.9 with a single panel (`admin`, path set by `ADMIN_PATH`) and the official Spatie Media Library and Spatie Settings plugins.

## 10. Database status

Local MySQL 9.7.1 is reachable. No project schema exists. Plan: create `gf_portfolio` (development) and `gf_portfolio_testing` (tests) with a dedicated user (decision D-04).

## 11. Auth status

None. Plan: Filament's panel authentication (login, password reset, built-in MFA, rate-limited login) for admin users. There is no public user registration and no Breeze/Jetstream/Fortify, because the public site has no accounts.

## 12. Reusable assets

None in the repository. Reused from the dependency tree rather than added: `symfony/html-sanitizer` and `blade-ui-kit/blade-heroicons`, both already required by Filament.

## 13. Recommended implementation strategy

1. **Environment** (with your approval): make PHP 8.4 the project PHP (E1), run `git init` (E2), and create the database and user (E7).
2. **Scaffold** Laravel 13 into a scratch directory, move it into the root next to `docs/`, then make the first commits: docs, then the skeleton.
3. **Phase 3 foundation** in the order set out in master prompt §20. Install each package only after a dry-run compatibility check, in this order: Filament 5 → permission → settings (+ plugin) → medialibrary (+ plugin) → activitylog → honeypot → sitemap → Pest 5 / Larastan.
4. Nothing existing is **kept, extended, or replaced**, because nothing exists. All Laravel skeleton defaults (the `users` table, the jobs/cache/sessions tables, the welcome route) are kept and extended. The welcome route is removed in favour of the homepage route.
5. Then follow Phases 4–8 as in the master prompt, with an audit after each phase (Companion Prompt 3).
