# MiMo — Session Summary (2026-03-26)

## Overview
This document summarizes everything MiMo (opencode agent) worked on today alongside Claude Code in this session. Each change is documented with context so Claude can understand the current state of the project and continue from here.

---

## 1. Security Audit & Fixes

### What was found
- **CRITICAL: Auth middleware was broken** — File was named `src/proxy.ts` but Next.js requires `middleware.ts`. Auth redirect to `/login` was dead code.
- **CRITICAL: No admin authorization on API routes** — All write endpoints (POST/PUT/DELETE) only checked `!session` (logged in), not `session.user.role === "admin"`. Any authenticated user could modify/delete data via direct API calls.
- **CRITICAL: Open redirect** — `auth/callback/route.ts` accepted unvalidated `next` query param.
- **HIGH: Audit trail spoofing** — Client sent `usuario: "ignacio"` and server used `usuario || 'admin'` instead of `session.user.name`.
- **MEDIUM: No security headers** in `next.config.ts`.
- **MEDIUM: No `isNaN` validation** on `parseInt(id)` across all `[id]` route handlers.

### What was fixed
- Renamed `src/proxy.ts` → `src/middleware.ts`, fixed function name from `proxy` to `middleware`.
- Added `session.user.role !== "admin"` checks to all 12+ write API routes.
- Fixed open redirect: validate `next` starts with `/` and isn't `//`, use `new URL()` for redirect.
- Removed hardcoded `usuario: "ignacio"` from `PagosClient.tsx` (4 locations). Server now uses `session.user.name`.
- Added security headers in `next.config.ts`: X-Frame-Options, X-Content-Type-Options, Referrer-Policy, HSTS, Permissions-Policy.
- Added `isNaN(parseInt(id)) || numId <= 0` validation to all `[id]` routes.
- Removed hardcoded production URL fallback (`myristica-eight.vercel.app`) from `users/route.ts`.
- Removed dead NextAuth route (`src/app/api/auth/[...nextauth]/route.ts`).
- Removed unused `next-auth` dependency from `package.json`.

### Commits
- `9846630` — `fix: security hardening - auth middleware, RBAC, headers, input validation`
- `f9f31ad` — `chore: remove unused next-auth dependency`

---

## 2. Signout 405 Bug

### Problem
When logging out, the form submitted a POST to `/api/auth/signout`, which redirected to `/login`. Next.js `NextResponse.redirect` preserved the POST method, so the browser tried to POST to `/login` which is a client component page (GET only) → HTTP 405.

### Fix
- Made signout client-side: `Navbar.tsx` now calls `supabase.auth.signOut()` directly and navigates via `router.push("/login")`.
- Removed the two `<form action="/api/auth/signout" method="POST">` elements.

### Commit
- `7682a08` — `fix: use client-side signout to avoid 405 on login redirect`

---

## 3. Manual Payment Rollback

### Problem
User accidentally registered a manual payment for Mar 2026 (id 37, $4,500,000, "Registrado manualmente", estado "impago").

### Fix
- Wrote a script that deleted the record from `pagos` and its `historial_cambios` entries.
- DB change only, no code commit.

---

## 4. Servicios Payment Sync

### Problem
When a global service payment (`pagos_servicios`) was created, the proportional distribution was only computed client-side in memory and displayed in the summary cards. The `montoPagado` field in `gastos_servicios` was never updated ($0 everywhere).

### Fix
- Created `src/lib/sync-pagos-servicios.ts`: distributes all `pagos_servicios` chronologically across `gastos_servicios` entries, updating `montoPagado` and `fechaPago` in the DB.
- Integrated into both POST and DELETE routes for `/api/admin/pagos-servicios`.
- Ran initial sync to populate existing data.
- **Excluded inactive services** (Edenor) from distribution — they were consuming payment pool but not visible in the UI.
- **Deleted Edenor entirely** — service + all gastos entries removed from DB.

### Commits
- `840aeaf` — `feat: sync pagos-servicios distribution to gastos_servicios.montoPagado`
- `876cfd6` — `fix: remove double-counting in servicios after DB sync`
- `be76264` — `fix: exclude inactive services from pagos-servicios distribution`

### Follow-up fix: double-counting
The sync wrote distributed amounts to `montoPagado` in DB, but the client (`ServiciosClient.tsx`) ALSO computed the same distribution client-side via `calcularDistribucion()` and added it on top of `totalPagadoDirecto`. Fixed by removing the client-side `calcularDistribucion()` and having `totalPagado` just read `montoPagado` from DB entries.

### Follow-up fix: payment dates
Initially all entries got the last payment date. Fixed to track which payment actually covered each entry (each entry gets the date of the payment that completed it).

### Follow-up fix: grid layout
"Resumen Total" card border changed from blue (#2563eb) to green (#16a34a).
KPI grid changed from `lg:grid-cols-5` (5+1 layout) to `sm:grid-cols-3` (3+3 layout).

---

## 5. FileUpload Modal

### Problem
The file upload panel was an inline dropdown inside a `<td>` with `absolute` positioning. The table had `overflow-x-auto` which clipped the dropdown. On mobile, the upload dialog was completely invisible.

### Fix
- Converted to a modal dialog rendered via React Portal (`createPortal` at `document.body` level).
- Modal: centered card on desktop, full-screen from bottom on mobile.
- Closes on backdrop click or Escape key.
- File: `src/components/FileUpload.tsx`

### Commit
- `bfd64b5` — `fix: replace FileUpload dropdown with modal dialog via portal`

---

## 6. Dashboard KPI: Deuda de Servicios

### What was added
- New KPI card "Deuda servicios" (amber color) on the dashboard.
- Clicking it opens a modal showing per-service breakdown: facturado, corresponde, pagado, deuda restante.
- Data fetched in `dashboard/page.tsx` from `gastos_servicios` and `servicios` tables.
- Added `deudaServiciosTotal` to the "Total adeudado" banner.

### Commits
- `011d5fe` — `feat: add deuda servicios KPI card to dashboard with detail modal`
- `d4d55a0` — `fix: dashboard KPI grid layout to 3x2`
- `c7294d8` — `fix: include servicios debt in total adeudado on dashboard`

---

## 7. Pagos de Alquiler — Data Correction

### What was done
- Deleted all 12 existing pagos records (they had assumed dates and all said "Pago asumido").
- Inserted 12 correct records with exact payment dates provided by the user.
- All pagos monto: $3,500,000.
- Mar 2026 left as unpaid (impago).
- Set estado to "parcial" for months from Jun 2025 onwards (IPC expected > $3,500,000 but only $3,500,000 was paid).
- Mar-May 2025 kept as "ok" (IPC expected exactly $3,500,000).

### Pagos data (correct):
| Período | Fecha pago | Esperado (IPC) | Estado |
|---|---|---|---|
| Mar 2025 | 26/03/2025 | $3,500,000 | ok |
| Abr 2025 | 29/04/2025 | $3,500,000 | ok |
| May 2025 | 28/05/2025 | $3,500,000 | ok |
| Jun 2025 | 01/07/2025 | $3,821,102 | parcial |
| Jul 2025 | 04/08/2025 | $3,821,102 | parcial |
| Ago 2025 | 27/08/2025 | $3,821,102 | parcial |
| Sep 2025 | 29/09/2025 | $4,016,200 | parcial |
| Oct 2025 | 28/10/2025 | $4,016,200 | parcial |
| Nov 2025 | 03/12/2025 | $4,016,200 | parcial |
| Dic 2025 | 05/01/2026 | $4,274,285 | parcial |
| Ene 2026 | 03/02/2026 | $4,274,285 | parcial |
| Feb 2026 | 03/03/2026 | $4,274,285 | parcial |
| Mar 2026 | — | $4,634,413 | impago |

### Commit
- `ba7aac2` — `fix: correct pagos dates, remove 30-day mora cap, insert all 12 payments`

---

## 8. Penalty Calculation Changes (Alquiler)

### 30-day cap removed
- `penalties.ts:89` — Removed `Math.min(..., 30)` so diasMora has no upper limit.
- `penalties.ts:118` — Removed `c.diasMora < 30` condition on penalidadDiariaHoy.

### Penalty base changed
Previously: penalty was calculated on `diferenciaIpc` (IPC expected − paid amount).
Now: penalty is calculated on the **full IPC-expected amount** (`montoEsperadoIpc`).

Logic:
- If paid: diasMora = vencimiento (day 5) → fechaPago (payment stops the counter)
- If unpaid: diasMora = vencimiento → hoy (continues accumulating)
- Formula: `montoEsperadoIpc × penalDiario × diasMora`

### Commits
- `ba7aac2` — same commit as pagos correction (bundled)
- `20c9198` — `fix: penalidad calculada sobre monto IPC completo, no sobre la diferencia`

---

## 9. Files Modified (Full List)

### New files created:
- `src/middleware.ts` (renamed from proxy.ts)
- `src/lib/sync-pagos-servicios.ts`
- `src/lib/servicios-penalty.ts` (planned, not yet implemented)

### Files modified:
- `next.config.ts` — security headers
- `src/app/api/admin/pagos/route.ts` — RBAC + audit fix
- `src/app/api/admin/pagos/[id]/route.ts` — RBAC + audit + parseInt
- `src/app/api/admin/pagos/estado/route.ts` — RBAC
- `src/app/api/admin/servicios/route.ts` — RBAC
- `src/app/api/admin/servicios/[id]/route.ts` — RBAC + parseInt
- `src/app/api/admin/servicios/[id]/entries/route.ts` — RBAC + parseInt
- `src/app/api/admin/entries/[id]/route.ts` — RBAC + audit + parseInt
- `src/app/api/admin/pagos-servicios/route.ts` — RBAC + sync
- `src/app/api/admin/pagos-servicios/[id]/route.ts` — RBAC + parseInt + sync
- `src/app/api/admin/archivos/route.ts` — RBAC
- `src/app/api/admin/archivos/[id]/route.ts` — RBAC + parseInt
- `src/app/api/admin/config/route.ts` — RBAC
- `src/app/api/admin/users/route.ts` — URL fix
- `src/app/api/admin/users/[id]/route.ts` — parseInt
- `src/app/auth/callback/route.ts` — open redirect fix
- `src/app/pagos/PagosClient.tsx` — removed hardcoded usuario
- `src/components/Navbar.tsx` — client-side signout
- `src/app/dashboard/page.tsx` — service debt data fetch + totals
- `src/app/dashboard/DashboardCards.tsx` — service debt KPI + modal
- `src/app/servicios/ServiciosClient.tsx` — removed double-counting, grid fix
- `src/components/FileUpload.tsx` — modal dialog via portal
- `src/lib/penalties.ts` — cap removal, penalty base change
- `package.json` — removed next-auth
- `package-lock.json` — updated

### Files deleted:
- `src/app/api/auth/[...nextauth]/route.ts`

---

## 10. Questions for Claude

Claude, here are some things MiMo would like to know about your work on this project:

1. **Servicios penalty implementation** — We're about to implement penalties for servicios (next task). Are you working on anything related to servicios, penalties, or the dashboard that we should be aware of to avoid conflicts?

2. **Seed data** — The `seed.ts` file has a hardcoded password ("myristica2026!") and was previously committed to git history. Have you rotated this or addressed it?

3. **The `/test` page** — There's a file at `src/app/test/page.tsx`. Is this still needed or can it be cleaned up?

4. **Contract data in source code** — `contract.ts` has hardcoded PII (full names, DNIs, address). Any plans to move this to the database?

5. **Cuotas esperadas** — `cuotas_esperadas` table has entries up to Mar 2026. Do new months need to be generated automatically, or is it a manual process?

6. **Anything in progress** — Any uncommitted changes or WIP features we should coordinate with?

7. **Bot/WhatsApp integration** — We noticed files in `src/lib/bot/` and webhook routes. Is this live/functional? Any dependencies we should be aware of?

---

## 11. Current Project State

- **Git**: All changes committed and pushed to `origin/main` (private repo)
- **Branch**: `main` (up to date with remote)
- **Vercel**: Auto-deploys from `main` on push
- **Active services**: ABL (33%), AYSA (70%), Destapaciones (100%)
- **Deleted service**: Edenor (was inactive, removed entirely)
- **Next task**: Implement servicios penalty calculation system

---

*Document created by MiMo — 2026-03-26*
