# Product DB — Repository Discovery Report

- Date: 2026-08-10
- Scope: /mnt/devel/md/product-db (Laravel + Inertia + React app)
- Method: read-only inspection of manifests, lockfiles, source, routes (`php artisan route:list`), runtime binaries
- Companion repo read: /mnt/devel/md/product-db-react/AGENTS.md (template this app was ported from)

---

## 1. Stack versions

Verified from `composer.lock` / `package-lock.json` (installed), runtime binaries, and `composer.json` / `package.json` (constraints).

| Component | Constraint | Installed (verified) |
|---|---|---|
| Laravel Framework | ^13.17 | **v13.24.0** (`php artisan --version`: "Laravel Framework 13.24.0") |
| PHP | ^8.3 | **8.5.0** (CLI /home/mati/.config/herd-lite/bin/php, built Nov 20 2025, NTS x86_64-linux-musl); CI pins 8.5 |
| inertiajs/inertia-laravel | ^3.0 | v3.3.1 |
| @inertiajs/react | ^3.0.0 | 3.6.1 |
| @inertiajs/vite | ^3.0.0 | 3.6.1 |
| React / react-dom | ^19.2.0 | 19.2.8 |
| Tailwind CSS | ^4.0.0 | 4.3.3 (`@tailwindcss/vite` 4.3.3) |
| Vite | ^8.0.0 | 8.2.1 |
| laravel-vite-plugin | ^3.0.0 | 3.1.3 |
| @vitejs/plugin-react | ^5.2.0 | 5.2.0 |
| TypeScript | ^5.7.2 | 5.9.3 |
| Node (runtime) | — | v24.14.0 (npm 11.9.0); CI pins node 22 |
| ag-grid-community / ag-grid-react | ^36.1.0 | 36.1.0 |
| laravel/fortify | ^1.37.2 | v1.37.3 |
| laravel/passkeys | ^0.2 | v0.2.1; npm @laravel/passkeys 0.2.0 |
| laravel/wayfinder | ^0.1.14 | v0.1.21 (npm side: generated in `resources/js/actions|routes`) |
| pestphp/pest (+plugin-laravel) | ^5.0 | v5.0.4 / v5.0.1 |
| phpunit/phpunit (transitive) | — | 13.2.6 |
| larastan/larastan | ^3.9 | v3.10.0 (PHPStan level 7) |
| laravel/pint | ^1.27 | v1.30.4 (preset: laravel) |
| laravel/boost | ^2.2 | v2.5.3 |
| laravel/chisel | ^0.1.0 | v0.1.1 |
| laravel/pail | ^1.2.5 | v1.2.7 |
| laravel/pao | ^1.0.6 | v1.1.3 |
| laravel/sail | ^1.53 | v1.65.0 |
| laravel/tinker | ^3.0 | v3.0.2 |
| nunomaduro/collision | ^8.9.3 | v8.9.5 |

Tooling summary:
- Testing framework: **Pest 5** (phpunit.xml has Unit + Feature suites; tests use `test()` functions)
- Linting: **ESLint 9** (flat config, `eslint.config.js`, includes react, react-hooks, typescript-eslint, stylistic, import) + **Prettier** (resources/) + **Pint** for PHP
- Static analysis: **PHPStan via Larastan, level 7** (`phpstan.neon`: paths app/, bootstrap/app.php, config/, database/, routes/) + **tsc --noEmit** (`npm run types:check`)
- Build system: **Vite** (Inertia SSR plugin; `config/inertia.php` has `ssr.enabled = true`, url http://127.0.0.1:13714; `npm run build:ssr` exists)
- Package manager: **npm** in this repo (package-lock.json). `pnpm-workspace.yaml` exists (publicHoistPattern @inertiajs/core) but no pnpm lockfile here; the react template repo uses pnpm.

---

## 2. Directory map (concise)

```
app/
  Actions/Fortify/        CreateNewUser.php, ResetUserPassword.php
  Concerns/               PasswordValidationRules.php, ProfileValidationRules.php
  Console/Commands/       (empty)
  Http/Controllers/       Controller.php, Settings/{ProfileController,SecurityController}.php
  Http/Middleware/        HandleAppearance.php, HandleInertiaRequests.php
  Http/Requests/Settings/ PasswordUpdateRequest, ProfileDeleteRequest, ProfileUpdateRequest, TwoFactorAuthenticationRequest
  Models/                 User.php (only model)
  Providers/              AppServiceProvider.php, FortifyServiceProvider.php
bootstrap/app.php         middleware config (encryptCookies except appearance/sidebar_state; web append HandleAppearance, HandleInertiaRequests, AddLinkHeadersForPreloadedAssets)
config/                   13 files — non-default only: fortify.php, inertia.php (see §6)
database/                 migrations (5), factories/UserFactory.php, seeders/DatabaseSeeder.php, database.sqlite (stale file)
resources/js/
  app.tsx                 Inertia app + layout switch
  pages/                  auth/ (7), cockpit/ (8), settings/ (3), dashboard.tsx, welcome.tsx
  components/views/       the real cockpit UI (8 files, 2320 lines)
  components/shared/      9 brand/tab/card/chip components
  components/layout/      cockpit-sidebar.tsx
  components/ui/          shadcn components (~30)
  layouts/                app-layout, auth-layout, cockpit-layout, settings/layout (+ sub-layouts)
  lib/                    data.ts (mock data), ag-grid-theme.ts, utils.ts
  hooks/                  use-appearance, use-clipboard, use-current-url, use-flash-toast, use-initials, use-mobile-navigation, use-mobile, use-two-factor-auth
  types/                  auth.ts, global.d.ts, index.ts, navigation.ts, ui.ts, vite-env.d.ts
  actions/ + routes/ + wayfinder/   Wayfinder-generated TS route helpers
routes/                  web.php, settings.php, console.php
tests/                   Feature/{Auth,Settings,...}, Unit (39 tests)
gauntlet/                goal.md, invariants.md, loop-state.md (round 0, phase DISCOVERY), discovery.md (this file)
```

## 3. Routes inventory

54 registered routes (from `php artisan route:list`). No `routes/auth.php` — Fortify routes come from the package, views wired in FortifyServiceProvider.

Cockpit pages (PUBLIC — no auth middleware):
- `GET /` — home → `cockpit/dashboard`
- `GET /inbox` — inbox → `cockpit/inbox/index`
- `GET /inbox/{messageId}` — inbox.show → closure → `cockpit/inbox/message` (messageId prop)
- `GET /links` — links → `cockpit/links`
- `GET /documents` — documents → `cockpit/documents/index`
- `GET /documents/new` — documents.create → `cockpit/documents/new`
- `GET /compose` — compose → `cockpit/compose`
- `GET /admin` — admin → `cockpit/admin`

Authenticated pages:
- `GET /dashboard` — dashboard (auth + verified) → `dashboard.tsx`
- settings.php (auth): `GET/PATCH /settings/profile` (profile.edit/update), `DELETE /settings/profile` (destroy, verified), `GET /settings/security` (RequirePassword), `PUT /settings/password` (throttle:6,1), `GET /settings/appearance`, `ANY /settings` → redirect to /settings/profile
- `GET .well-known/passkey-endpoints` (well-known.passkeys)

Fortify-provided: login/register (+ POST), logout, forgot-password, reset-password/{token}, email/verify + notification, two-factor-challenge, user/confirm-password + status, user/two-factor-authentication (+ qr-code, recovery-codes, secret-key, confirmed), passkeys (confirm/options, login/options, store, destroy).

Framework/vendor: `GET /up` (health), `storage/{path}` (+upload), `_boost/browser-logs`, `_inertia/devtools/entries`.

## 4. Existing modules

1. **Auth (Fortify + passkeys starter kit)** — fully scaffolded: registration, password reset, email verification, 2FA, passkeys, session-based login. Pages: login, register, forgot-password, reset-password, verify-email, two-factor-challenge, confirm-password. User model implements PasskeyUser. passkeys table migration present.
2. **Settings module** — profile edit, security (2FA/passkeys), appearance (light/dark) under `settings/*`; SettingsLayout nested under AppLayout.
3. **ACE Cockpit dashboard (the ported product UI)** — 8 views under `cockpit/*` (public): Dashboard, Inbox, Message detail, Links, Documents, New document, Compose, Admin. Sidebar nav also lists placeholders without routes: Campaign Portal, Content Management, DIAS, Reporting, Pricelists.
4. **No business/product backend** — no product models, no business tables, no controllers beyond settings/auth. The app is UI-only with mock data.

## 5. Frontend structure

- `app.tsx` layout switch: `welcome` → no layout; `auth/*` → AuthLayout; `cockpit/*` → CockpitLayout; `settings/*` → [AppLayout, SettingsLayout]; default → AppLayout.
- Pages are thin wrappers (e.g. `cockpit/dashboard.tsx` = `<DashboardView />`); all real UI is in `components/views/*` (ported 1:1 from product-db-react template).
- CockpitLayout = flex h-screen + CockpitSidebar (purple, 260px/80px collapse, sections: Dashboard/Inbox/Campaign Portal, Management, Material, System).
- AG Grid: `AllCommunityModule` registered once in `lib/ag-grid-theme.ts`; `astaraGridTheme` (Quartz + Astara params) used by inbox-view and documents-view.
- shadcn/ui (new-york style, radix, lucide icons; components.json) + Tailwind v4 CSS tokens in `resources/css/app.css` (astara-purple/orange/yellow/bg).
- Design system documented in DESIGN.md (47 lines): token table, typography (Montserrat 400–800 via bunny plugin, 10–13px UI text), component patterns, AG Grid theme, brands, DE/FR/IT language convention (DE required).
- Generated TS: `resources/js/actions/` (controller route helpers) and `resources/js/routes/` (named-route helpers) — Wayfinder output, matches routes found above.

## 6. Mock data status

All cockpit views consume **`resources/js/lib/data.ts`** (460 lines) — no API calls anywhere; forms (compose, add-document) are UI-only and not wired to endpoints.

Contents of lib/data.ts:
- `BRANDS` (9): Abarth, Alfa Romeo, Fiat, Fiat Professional, Hyundai, Jeep, KGM, MAXUS, Nissan (+ "System" pseudo-brand) + `BRAND_FILTERS`
- `MESSAGES` (6 inbox rows with German subjects — e.g. "Neue Preisliste Jeep Avenger", "Marketing-Assets Q3", "Rückrufaktion Hyundai"), `INBOX_CATEGORIES` (Sales 693 / Aftersales 890 / Marketing 388)
- `MESSAGE_DETAILS` (2 full message records with attachments)
- `DASHBOARD_INBOX` (5 rows), `LATEST_DOCS` (5), `FREQUENT_LINKS` (5), `PRICELISTS` (8), `VISITS` (3 bar chart points)
- `DOCUMENTS` (7, e.g. "0063.26_Sommerreifen Saison 2026" with Aftersales category), `FOLDER_TREE` (Sales > Fleet > Used cars/Stock list, Aftersales, Marketing, Product with counts)
- `LINKS_TABS` (3 tabs: Aftersales 3, DND 2, Marketing 1), `BRAND_ABBR`

Which views use mock data: dashboard-view, inbox-view, message-detail-view, documents-view, links-view import from `@/lib/data`; add-document-view, compose-view, admin-view import only the `Brand` type.

What the cockpit UI currently shows (per view): Dashboard (greeting, stat cards, DASHBOARD_INBOX feed, LATEST_DOCS, FREQUENT_LINKS, PRICELISTS, VISITS bar chart, brand pills); Inbox (AG Grid of MESSAGES + category tabs + brand filters); Message detail (MESSAGE_DETAILS[messageId], attachments); Documents (AG Grid of DOCUMENTS + FOLDER_TREE + chrome tabs); Links (LINKS_TABS); Compose/New document (DE-required + FR/IT optional lang editor forms); Admin (placeholder panel).

## 7. DB config

- `.env` (local dev, actual values): `DB_CONNECTION=mysql`, `DB_HOST=192.168.200.4`, `DB_PORT=3307`, `DB_DATABASE=product_db`, `DB_USERNAME=developer`, `DB_PASSWORD=DEVEL!now1`
- `.env.example`: same host/port/db, `DB_USERNAME=root`, `DB_PASSWORD=` (empty)
- `config/database.php`: default `sqlite` fallback; mysql connection present (driver mysql, host/port/db via env, options gated on pdo_mysql). Other drivers configured by default (sqlite, mysql, mariadb, pgsql, sqlsrv).
- SESSION_DRIVER=database, CACHE_STORE=database, QUEUE_CONNECTION=database (all DB-backed).
- Migrations (5): 0001_01_01_000000_create_users_table (+ password_reset_tokens, sessions), 0001_01_01_000001_create_cache_table, 0001_01_01_000002_create_jobs_table, 2024_01_01_000000_create_passkeys_table (id, user_id FK, name, credential_id unique, credential json, last_used_at), 2025_08_14_170933_add_two_factor_columns_to_users_table. **No product/business tables.**
- Seeders: DatabaseSeeder creates one User (`Test User` / test@example.com). Factory: UserFactory.
- Known constraint (AGENTS.md): repo lives on a CIFS mount where SQLite locking fails — MySQL on the Windows host (192.168.200.4:3307) is the required DB; `php artisan serve` does not propagate inline env overrides.

## 8. Testing status

- **39 Pest tests in 12 files** (counted `test(` occurrences):
  - Feature/Auth (7 files, 25 tests): AuthenticationTest 6, EmailVerificationTest 6, PasswordResetTest 5, PasswordConfirmationTest 2, RegistrationTest 2, TwoFactorChallengeTest 2, VerificationNotificationTest 2
  - Feature/Settings (10): ProfileUpdateTest 5, SecurityTest 5
  - Feature: DashboardTest 2 (guest redirect + authenticated visit), ExampleTest 1
  - Unit: ExampleTest 1
- phpunit.xml: suites Unit + Feature; env overrides for testing — sqlite `:memory:` DB, array cache/session, sync queue, BCRYPT_ROUNDS 4.
- CI: `.github/workflows/tests.yml` — PHP 8.5 + Node 22, `composer setup`, then `composer ci:check` (npm lint:check → format:check → types:check → phpunit/Pest). No DB services in CI (relies on sqlite :memory:).
- No tests cover the cockpit views (no frontend/component tests present).

## 9. Unknowns

- **State/content of the `product_db` MySQL database** on 192.168.200.4:3307 — not verifiable from files; no DB inspection performed in this pass. `.env` credentials recorded above.
- **welcome.tsx** page exists in resources/js/pages but no route references it (`/` renders cockpit/dashboard); likely unused starter-kit leftover — unverified intent.
- **Parity with product-db-react template**: only its AGENTS.md was read (per scope); per-file parity of views was not diffed — UNKNOWN degree of divergence.
- **Git state**: `/mnt/devel/md/product-db/.git` does not exist (repo is not under git here); `.gitignore`/`.github/` present.
- `database/database.sqlite` file exists but is broken/unusable on this mount (CIFS locking); its contents were not inspected.
- Whether SSR (`ssr.enabled=true`, http://127.0.0.1:13714) is actually exercised in dev — config present, `build:ssr` script exists; runtime behavior UNKNOWN.
- `pnpm-workspace.yaml` presence vs. npm lockfile — package-manager intent ambiguous; npm is what resolves in this repo (package-lock.json + node_modules).
