# Fermenty — Project Overview

> **Technical reference**: what Fermenty is, its stack, routing and architecture.
> For orientation and reading order, **start at `docs/INDEX.md`** — that is the front
> door; this file is the room it leads to for the technical detail.
> §5 (current state) last reconciled against the code: **2026-07-25**.

---

## 1. What it is

Fermenty is a fermentation companion (kombucha, kefir, chucrut, kimchi, …). It
guides users through a ferment step by step, tracks batches/logs/measurements,
and offers a Premium tier with per-step expert hints. Owner: **ZYMOLAB ESPAÑA,
S.L.** UI language: Spanish (`locale = es`).

There are **three surfaces**, all served from one Laravel codebase:

| Surface | Term | Host (prod / local) | Audience |
|---|---|---|---|
| ERP web app | `web` | `erp.fermenty.es` / `fermenty.local` | End users + admin panel |
| Mobile simulation (browser) | `app` | `app.fermenty.es` / `app.fermenty.local` | Dev tool to design mobile UX/flows |
| Mobile API | `api` | `api.fermenty.es` / `api.fermenty.local` | The `app` sim and (later) native apps |
| Native mobile | `android app` | — | Final Flutter/Dart app (future) |

Development path: build the **API** → build the **app** simulation that consumes
the API → port the validated flows to **Flutter**. (See `APP_DEVELOPMENT_PROCESS.md`.)

---

## 2. Tech stack

- **Laravel 13** (PHP **8.4**), MySQL, Apache. Local PHP 8.4 served separately on **port 8084**.
- Auth: **Laravel Breeze** (web session) + **Socialite** (Google) + **Sanctum** (API tokens).
- Mail: **Mailpit** locally (SMTP :1025, UI :8025); **Resend** planned for prod.
- Frontend: Blade + Vite. Images via `intervention/image`.
- Repo shared via GitHub between a Windows machine and an Ubuntu machine.

---

## 3. Routing architecture (host-based)

All host dispatch lives in **`bootstrap/app.php`** (`withRouting(using: …)`):

```
api.fermenty.*  -> routes/api.php     (middleware: api  — stateless, Sanctum, no session/CSRF)
app.fermenty.*  -> routes/mobile.php  (middleware: web)
everything else -> routes/web.php -> routes/erp.php  (middleware: web)
```

- The API is versioned under **`/v1`** (e.g. `api.fermenty.es/v1/login`). The
  subdomain *is* the API, so there is **no `/api` URL prefix**.
- ⚠️ **Do not run `route:cache`** — routing depends on the request host, so a
  cached route table would freeze one host's routes. As a side effect,
  `php artisan route:list` (console host = `localhost`) shows **only the ERP
  routes**; this is expected, not a bug.

---

## 4. Directory map (the parts that matter)

```
routes/
  web.php        host dispatch entry (-> erp.php for the ERP host)
  erp.php        ERP web app routes (users + /acp admin area)
  mobile.php     app.* simulation routes (Blade prototype)
  api.php        /v1 mobile API routes
  auth.php       Breeze auth routes
app/
  Http/Controllers/        ERP controllers (Batch, Community, Profile, Dashboard, …)
  Http/Controllers/Admin/  admin panel controllers
  Http/Controllers/Mobile/ app.* simulation controllers (Welcome/Login/Register/Home/Onboarding)
  Http/Controllers/Api/V1/ API controllers (AuthController, DashboardController)
  Http/Requests/Api/V1/    API form requests (RegisterRequest, LoginRequest)
  Http/Resources/          API JSON resources (UserResource, BatchResource)
  Services/                BatchService, NotificationService (core domain logic)
  Models/                  25 models (Batch, BatchStep, DailyLog, Measurement, …)
  Policies/                BatchPolicy, CommunityPostPolicy
config/                    + cors.php, sanctum.php (added for the API)
resources/views/
  welcome.blade.php, dashboard, batches/, comunidad/, perfil/, notificaciones/,
  fermentos/, pages/, admin/, auth/, emails/, layouts/, components/, partials/
  mobile/                  the app.* simulation views
```

---

## 5. Current state

> Reconciled against the code on 2026-07-25. The headline since 2026-07: the **motor
> and the incorporated mentor** were built end to end. What was a guided-steps app is
> now a mentor that formulates, accompanies and closes the loop.

### The Mentor / Motor — ✅ built & tested (the big arc)
Pure calculation engine in **`App\Mentor`**, no coefficients ever crossing to the
client. Model-driven (`Modelos\ModeloFicha` interface; today one model,
`solucion_azucarada`, resolved via `Registro::deFicha`). Pieces:

- **Motor** (`Motor::calcular`) assembles the public output (cantidades, ventanas,
  lo_que_pasa, avisos, trueques) from the model; **ficha** (coefficients) lives in
  `fermentation_guides.ficha` and freezes into `batches.formulacion` at formulation.
- **Formular** — the draft cycle: `formular()` ≠ `arrancar()` (a batch is formulated
  first, activated later). `Inversor` derives a recipe's `perfil_defecto` from the
  obrador's known point; `Cartas` are the profile presets; `ProxyTemperatura` turns
  "where + how it feels" into temperature + confidence (which sets the window width).
- **Corte F1→2F** — `reformular()`: at cut, the 2F is formulated with the **real**
  residual (level-2, from the actual cut day; level-3 if pH measured). Preview
  (`reformulaExpuesta`, no writes) + confirm share one calculation. Cutting advances
  the F1 steps and activates the 2F step.
- **Cierre del lazo** — `cerrarLazo()`: on review, crosses **cut × rating** (seven
  voices) into an `insight` ("Cómo salió"). Arithmetic with voice, not calibration.
- **Bucle 1** — `acompanar()`: any `daily_log` wakes the mentor. The **cata** (a
  `daily_log`, model-declared responses) moves the window by criterion; pH/temp
  correct; the window lives in `batches.forecast`. A per-model **ritmo de cata**
  drives a tasting reminder relative to the predicted window.
- **Voz** (`Voz::render` + `lang/es/motor.php`) centralises the mentor's words; all
  numbers speak in what the person weighs (grams/days/bubble, decimal comma).

**Tested:** ~167 tests — the golden table (`MotorSolucionAzucaradaTest`), `CierreLazo`,
`BucleUno`, `Reformular`, `Acompanar`, `AvisoCata`, `VozMotor`, backtest. Reference:
`docs/Matematica_Motor.md`, `docs/Lexico.md`, `docs/Cierre_del_lazo.md`, `docs/Backtest.md`.

### Mobile PWA (`app.*`) — ✅ the mentor experience, not a shell
Blade+Alpine screens consuming `/v1` over HTTP exactly like Flutter will (`fmApi` +
`public/mobile/api.js`; Bearer token, guest-first, 401 → login sheet, 403 → premium;
service worker `public/sw.js`, bump `CACHE_NAME` on static JS/CSS edits). Beyond the
catalogue/community/profile shell, the live mentor: recipe-first catalogue → **formular**
→ **asistente** (live prediction + window, cata, bitácora, step collapse) → **cortar**
(2F preview) → **evaluar** → **resumen** (with the cierre insight). Key views:
`fermentos`, `formular`, `asistente`, `lote-cortar`, `lote-bitacora`, `lote-evaluar`,
`lote-resumen`.

### ERP web app — ✅ mature
Full batch lifecycle, daily logs, measurements, events, reviews, community, profile
(+ avatar, GDPR deletion), notifications, admin panel (`/acp`: guides & steps, ficha
editor, ingredients, recipes wizard, users, notification rules, API analytics). Domain
logic in `BatchService` / `NotificationService`. Google login + transactional mail working.

### Mobile API — ✅ mentor endpoints on `/v1`
Auth, profile, dashboard, tracker, notifications, community, catalogue/recipes, and the
full batch + mentor surface: `formular`, `arrancar`, `cortar/preview`, `cortar`, `cata`,
`quick-log`, `review`, `advance/skip/pause/resume/discard`, `saborizantes`, `recordatorio`
(POST/DELETE — «avísame para catar», 2026-08-29). `BatchResource` exposes `forecast`,
`en_f1`, `plan_2f`, `catas`, `cierre`, `daily_logs` (measurements with `at`), `recipe`,
`started_at`, `es_rapido`, `recordatorio`; `store`/`arrancar` accept `start_at` (exact
start instant). See `UX_Revision_2026-08.md`. **Still missing**
(see `MOBILE_API_PLANNING.md`): push/FCM tokens, password reset, native Google auth.

### Pending (the honest queue)
Bucle 2 / calibration (the §3 decision of `Cierre_del_lazo.md` first), the cultivo/starter
flow, order ≠ batch (per-vessel scaling), the producer board, and porting the validated
flows to **Flutter**. The live queue lives in project memory and the `*_Deuda.md` briefings.

---

## 6. Known issues / things to watch

1. ~~`mobile.php` references missing controllers~~ — resolved: `mobile.php` is
   now pure `Route::view`/closures; data arrives via the API.
2. ~~Sim doesn't use the API yet~~ — resolved 2026-06/07: all screens consume
   `/v1` over HTTP (see §5).
3. **PHP 8.4 CLI is misconfigured on the Windows machine**: `D:\xampp\php84\php.ini`
   points `extension_dir` at the 8.2 ext folder, so extensions fail to load.
   Run artisan/composer with an override (do **not** edit the shared ini):
   ```
   "D:/xampp/php84/php.exe" -d extension_dir="D:\xampp\php84\ext" artisan <cmd>
   ```
   `php artisan serve` does not inherit this; start the built-in server directly
   when testing the API (see §7).
4. **Vhosts/hosts not confirmed** for `api.fermenty.local` / `app.fermenty.local`
   on Apache:8084 — until set up, test the API with a `Host` header (see §7).
5. **Prod mail not finished** — Resend + DNS (SPF/DKIM/DMARC) pending (`MAIL_SERVER_SETUP.md`).
6. **Legal**: NIF/CIF still missing in `privacidad`/`terminos` blades (`GOOGLE_PLAY_LEGAL_CHECKLIST.md`).

---

## 7. Local development quick reference

```bash
# Artisan / composer (PHP 8.4 with the extension_dir fix)
"D:/xampp/php84/php.exe" -d extension_dir="D:\xampp\php84\ext" artisan migrate

# Dev server for API testing (artisan serve won't inherit the ext fix)
"D:/xampp/php84/php.exe" -d extension_dir="D:\xampp\php84\ext" -S 127.0.0.1:8099 -t public public/index.php

# Hit the API by sending the api host header
curl -H "Host: api.fermenty.local" -H "Accept: application/json" http://127.0.0.1:8099/v1/me

# Mail: run Mailpit (SMTP :1025, UI http://localhost:8025)
```

---

## 8. Documentation index

The documentation map — what each doc is, the reading order, and the project status —
lives in **`docs/INDEX.md`** (the front door). This file no longer keeps its own index,
so the two don't drift apart (a single owner for "what should I read").
