Files
service-finder/.roo/history.md
2026-06-24 11:29:45 +00:00

429 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Service Finder Fejlesztési Történet
## 2026-06-21 - P0 Deep Audit: Database Consistency & Zombie API Hunt
### 🎯 Cél
Teljes körű adatbázis konzisztencia ellenőrzés és zombie API végpontok felderítése a `vehicle`, `finance`, `fleet_finance` sémákban, mielőtt a frontend fejlesztés elkezdődik.
### 🔧 Eredmények
**1. ADATBÁZIS TISZTASÁG:** ✅ PASS
- API modul import: ✅ Sikeres (2 route: GET, POST)
- Sync Engine: ✅ 1210 OK, 0 Fixed, 0 Extra
- E2E test: ⚠️ Pre-existing conftest hiba (verification token timeout - nem kapcsolódó)
## 2026-06-23 - Cost Entry Wizard (CostEntryWizard.vue) - 4-lépéses Számla Űrlap
### 🎯 Cél
4-lépéses stepper wizard építése részletes számla/invoice költségek rögzítésére a CostsActionsCard-ból indíthatóan.
### 🔧 Módosított fájlok
- **`frontend/src/components/cost/CostEntryWizard.vue`** (ÚJ) - 4-step stepper wizard komponens
- **`frontend/src/components/dashboard/CostsActionsCard.vue`** - "🧾 Részletes Számla" gomb hozzáadva, CostEntryWizard import és modal state
- **`frontend/src/i18n/en.ts`** - costWizard i18n szekció hozzáadva
- **`frontend/src/i18n/hu.ts`** - costWizard i18n szekció hozzáadva
### 🧩 CostEntryWizard lépések
1. **Alapadatok**: Jármű (read-only), kategória cascade (fő+alkategória), dátum
2. **Pénzügyek**: Nettó összeg, ÁFA kulcs (0/5/10/20/27%), Bruttó összeg (GROSS-FIRST), Pénznem
3. **Admin & Szállító**: Dinamikus vendor autocomplete (GET /organizations?org_type=SERVICE_PROVIDER) szabad szöveges fallbackkel, számlaszám, számla dátuma, fizetési határidő
4. **Fájlok**: Drag & drop fájl feltöltő UI (csak UI szintű file picker)
### 🔌 API Integráció
- POST `/expenses/` a `costStore.addExpense()`-on keresztül AssetCostBase payload-dal
- Payload tartalmazza: amount_gross (GROSS-FIRST), category_id, currency, date, data JSONB (net_amount, vat_rate, invoice_number, invoice_date, payment_deadline, vendor_id, vendor_name, file_names)
### ✅ Verifikáció
- Vite build: ✅ Sikeres (253 modules, 6.94s)
- Gitea kártya: #277
## 2026-06-23 - Dashboard Cost Card Navigation Fix & Dedicated Costs Page
### 🎯 Cél
A dashboard költség kártya üres területére kattintva és a "További költségek" gombbal is a költségek oldalra navigálás. Dedikált CostsView oldal létrehozása vissza gombbal és garázs háttérrel.
### 🔧 Módosított fájlok
- **`frontend/src/views/costs/CostsView.vue`** (ÚJ) - Teljes költség oldal garázs háttérrel, vissza gombbal, költség táblázattal és paginációval
- **`frontend/src/router/index.ts`** - `/dashboard/costs` route hozzáadva a CostsView-hoz
- **`frontend/src/components/dashboard/CostsActionsCard.vue`** - Header bar kattinthatóvá téve + "További költségek" gomb átirányítva a `/dashboard/costs` oldalra
- **`frontend/src/layouts/PrivateLayout.vue`** - Hamburger menü "Költségek" navigáció `/dashboard/costs`-ra módosítva
- **`frontend/src/i18n/hu.ts`** - `costs.backToDashboard` kulcs hozzáadva
- **`frontend/src/i18n/en.ts`** - `costs.backToDashboard` kulcs hozzáadva
### ✅ Verifikáció
- Vite build: ✅ Sikeres (CostsView-DaFsqPnD.js chunk generálva)
## 2026-06-23 - Hotfix: Backend Expenses GET / endpoint & AssetCost.organization FK fix
### 🎯 Cél
Két kritikus backend hiba javítása:
1. A `GET /api/v1/expenses/` hívás 404-et adott (nem létezett `GET /` végpont), amit a reverse proxy 307-es HTTPS→HTTP átirányítással válaszolt, ami Mixed Content blokkolást okozott a böngészőben.
2. A backend indításkor `InvalidRequestError`-ral összeomlott az `AssetCost.organization` relationship hibás konfigurációja miatt (két FK ugyanarra a táblára, de a `foreign_keys` paraméter hiányzott).
### 🔧 Módosított fájlok
- **`backend/app/api/v1/endpoints/expenses.py`** - `GET /` végpont hozzáadva: list_all_expenses() - szervezet összes költségének listázása paginációval, Asset, CostCategory, Organization JOIN-okkal
- **`backend/app/models/fleet_finance/models.py`** - `AssetCost.organization` relationship javítva: `foreign_keys=[organization_id]` paraméter hozzáadva a kétértelmű FK kapcsolat feloldásához
### 🔧 Eredmények
- Backend konténer: ✅ Tisztán indul, nincs SQLAlchemy hiba
- Login: ✅ Működik (nem omlik össze)
- `GET /api/v1/expenses/`: ✅ Végpont elérhető, paginált költség listát ad vissza
## 2026-06-23 - Hotfix #2: Expenses API 307 redirect / Mixed Content - trailing slash fix
### 🎯 Cél
A `GET /api/v1/expenses` hívás 307-es HTTPS→HTTP átirányítást kapott, mert a backend route `@router.get("/")` (perjellel) volt definiálva, de a frontend `/expenses` (perjel nélkül) hívta. A Starlette automatikus 307 redirect-je a külső openresty proxy miatt `http://` címmé alakult → Mixed Content blokk.
### 🔧 Módosított fájlok
- **`backend/app/api/v1/endpoints/expenses.py`** - `@router.get("/")``@router.get("")` (perjel eltávolítva a route-ból)
### 🔧 Eredmények
- Backend konténer: ✅ Tisztán indul
- `GET /api/v1/expenses` most direkt egyezik a route-tal → nincs 307 redirect → nincs Mixed Content
## 2026-06-23 - Hotfix #3: Expenses API 500 Internal Server Error - AssetCost.cost_date → AssetCost.date
### 🎯 Cél
A `GET /api/v1/expenses` végpont 500-as hibát dobott: `AttributeError: type object 'AssetCost' has no attribute 'cost_date'`. Az `AssetCost` modellben a mező neve `date` (110. sor), de a kód `cost_date`-t használt.
### 🔧 Módosított fájlok
- **`backend/app/api/v1/endpoints/expenses.py`** - 2 helyen javítva:
- 157. sor: `AssetCost.cost_date``AssetCost.date`
- 193. sor: `cost.cost_date.isoformat()``cost.date.isoformat()`
### 🔧 Eredmények
- Backend konténer: ✅ Tisztán indul
- `GET /api/v1/expenses`: ✅ Várhatóan 200 OK (nem 500)
---
## 2026-06-23: Dashboard üres AdPlacementWidget elrejtése
### 🎯 Cél
A felhasználó kérésére: a dashboardon a "PRO" feliratú `SubscriptionStatusWidget` mellett egy üres csempe volt látható (`AdPlacementWidget`), mert nincs hirdetés beállítva a rendszerben. A kérés az volt, hogy rejtsük el ezt az üres csempét.
### 🔧 Módosított fájlok
- **`frontend/src/components/dashboard/AdPlacementWidget.vue`** - `defineEmits` hozzáadva: `ads-loaded` esemény, amely jelzi a szülőnek, hogy van-e hirdetés (`hasAds: boolean`). Az esemény a `fetchAds` siker és hiba ágában is meghívásra kerül.
- **`frontend/src/views/DashboardView.vue`** - `adWidgetHasAds` ref hozzáadva (alapértelmezett: `false`). A hirdetési csempe wrapper `<div>`-je `v-if="adWidgetHasAds"` feltételt kapott, így csak akkor jelenik meg, ha az API ténylegesen adott vissza hirdetéseket. Az `@ads-loaded` esemény frissíti a ref értékét.
### ✅ Verifikáció
- Frontend build: ✅ Sikeres (Vite build, 0 hiba)
## 2026-06-23 - P0 Fix: cost_date vs date mezőnév mismatch + CostsView.vue upgrade
### 🎯 Cél
Két produkciós hiba javítása a cost rögzítésben:
1. **P0 - 500 Internal Server Error** POST `/api/v1/expenses/` végponton: négyrétegű mezőnév-eltérés (`cost_date` vs `date`) a frontend, Pydantic séma, endpoint és SQLAlchemy model között.
2. **P1 - `/dashboard/costs` oldal** nem mutatott semmilyen információt és nem volt költség hozzáadási lehetőség.
### 🔧 Módosított fájlok
**Fix 1a - Backend endpoint** (`backend/app/api/v1/endpoints/expenses.py:464`):
- `cost_date=expense.cost_date``date=expense.cost_date` (SQLAlchemy model mezőneve `date`)
**Fix 1b - Backend Pydantic schema** (`backend/app/schemas/asset_cost.py:37`):
- `validation_alias="date"` hozzáadva a `cost_date` mezőhöz, hogy mind a `date`, mind a `cost_date` kulcsot elfogadja
**Fix 2 - Frontend CostsView.vue** (`frontend/src/views/costs/CostsView.vue`):
- Vezérlősáv hozzáadva járműszűrő dropdown-nal
- " Új Költség" gomb hozzáadva
- CostEntryWizard integráció (modal formában)
- Mezőnevek javítva: `cost_type``category_name`, `amount``amount_gross`, `vehicle_label``vehicle_name`
- `useVehicleStore` importálva a járművek listájához
### ✅ Verifikáció
- Python szintaxis: ✅ asset_cost.py OK, expenses.py OK
- Backend indítás: ✅ Uvicorn fut, nincs hiba
- Frontend build: ✅ Sikeres (Vite build 6.77s, 0 hiba)
- Gitea kártyák: #278 (P0) és #279 (P1) lezárva
## 2026-06-23 - #280 Vizsgálat: Miért nem jelennek meg költségek?
### 🎯 Cél
Annak kivizsgálása, hogy az admin@profibot.hu teszt felhasználó miért nem lát költségeket.
### 🔍 Vizsgálat
- `fleet_finance.asset_costs` táblában összesen **1 rekord** van (org_id=43, asset=PTB162 Mazda 2, 18118 HUF, "Finanszírozás")
- admin@profibot.hu (user_id=2) tagja: org 1 (Test Company), 57, 58, 62, 67
- admin **NEM tagja** org 43-nak ("Accipe garage"), ahova az egyetlen költség tartozik
- admin szervezeteiben (1, 57, 58, 62, 67) összesen **0 db költség** van
### ✅ Következtetés
**NINCS backend/frontend hiba.** A probléma egyszerű **adathiány**:
1. Nincs rögzítve költség admin egyetlen járművéhez sem
2. Az egyetlen DB-ben lévő költség egy másik szervezethez tartozik
3. A #278 és #279 javítások után most már lehetővé vált a költségrögzítés
- Dokumentáció: `/opt/docker/docs/cost_visibility_investigation_280.md`
## 2026-06-23 - #281 Hotfix: Hiányos #278 javítás - expenses.py:533 new_cost.cost_date → new_cost.date
### 🎯 Cél
A #278-as javítás hiányos volt: a konstruktor paramétert kijavítottuk (expenses.py:464: cost_date= → date=), de a response dict-ben (expenses.py:533) továbbra is `new_cost.cost_date`-et használtunk az SQLAlchemy AssetCost modellen, aminek a mezőneve `date`. Ez `AttributeError: 'AssetCost' object has no attribute 'cost_date'` hibát okozott minden POST /api/v1/expenses/ híváskor.
### 🔧 Módosított fájlok
- **`backend/app/api/v1/endpoints/expenses.py:533`** - `new_cost.cost_date.isoformat()``new_cost.date.isoformat()`
### ✅ Verifikáció
- Python szintaxis: ✅ OK
- Backend újraindítás: ✅ OK (Application startup complete)
- POST /api/v1/expenses/ teszt: ✅ **201 Created** - sikeres költség rögzítés a QWE432 járműre
- Response tartalmazza: `"date":"2026-06-23T13:07:34.785065+00:00"` (helyes)
- Gitea kártya: #281 lezárva
## 2026-06-23 - P0 Fix: User 28 Data Anomaly Resolution
### 🎯 Cél
User 28 (tester_pro@profibot.hu) adat-anomália javítása ORM szkript segítségével.
### 🔧 Végrehajtott műveletek
**A) Org 1 javítása:** `fleet.organizations` ID=1 org_type átállítva `fleet_owner``individual`
**B) Tag hozzáadása:** `fleet.organization_members` rekord létrehozva: org=1, user=28, role=OWNER, status=active. Org 1 owner_id=28 beállítva.
**C) Scope törlése:** User 28 `scope_level` visszaállítva `individual`-ra (NOT NULL constraint miatt), `scope_id` None-ra.
**D) Fantom garázs törlése:** Org 68 ("Tester Garázsa") és hozzá tartozó OrganizationMember rekordok törlése.
### ✅ Verifikáció
- Org 1: org_type=individual, owner_id=28
- Org 1 Member: role=OWNER, status=active, is_verified=True
- User 28: scope_level=individual, scope_id=None
- Org 68: nem létezik (deleted)
- Ideiglenes szkript törölve: `backend/scripts/fix_user_28.py`
## 2026-06-23 - P0 Cost Pipeline Visibility Audit (#282)
### 🔍 Felfedezés
A `/dashboard/costs` oldal üres User 28 számára, annak ellenére, hogy Org 1-ben 5 db asset_cost rekord van (BMW123, QWE432).
### 🐛 Gyökér Ok
A `GET /expenses/` endpoint (`backend/app/api/v1/endpoints/expenses.py:130-139`) a user első aktív tagságát használja org feloldáshoz (`.limit(1)` ORDER BY nélkül). User 28-nak 3 tagsága van: org 63 (ADMIN, nincs költség), org 21 (OWNER), org 1 (OWNER, 5 költség). Az első tagság org 63-ra mutat, ami üres.
### 📄 Dokumentáció
`docs/cost_pipeline_audit.md` - Teljes pipeline audit a frontendtől a DB-ig.
## 2026-06-23 - P0 Architecture Audit Fixes: Vendor Leak & Expense Priority
### 🎯 Cél
Az Architect által auditált P0 hibák kijavítása: vendor org szivárgás megszüntetése, expense organization_id prioritás javítása, frontend payload kiegészítése vendor_organization_id-val.
### 🔧 Módosított fájlok
- **`backend/app/services/provider_service.py`** (632-651. sor) - `quick_add_provider`: Eltávolítva az OrganizationMember létrehozás. A létrehozó user NEM lesz tagja a beszállító szervezetének. Owner_id=None marad.
- **`backend/app/api/v1/endpoints/expenses.py`** (398-429. sor) - `create_expense`: Átírva az organization_id feloldási prioritás: 1) asset.current_organization_id, 2) asset.owner_org_id, 3) user active org membership fallback.
- **`frontend/src/components/cost/CostEntryWizard.vue`** (690-714. sor) - `vendor_organization_id` és `external_vendor_name` root szintű payload mezők hozzáadva.
- **`frontend/src/stores/cost.ts`** - `AddExpensePayload` interface kiegészítve `vendor_organization_id` és `external_vendor_name` mezőkkel; `addExpense()` body-ba is átadva.
### 🗄️ Adatbázis Cleanup
- **`backend/scripts/fix_vendor_leak.py`** (ideiglenes, futás után törölve)
- A) Törölve `fleet.organization_members` rekord (org_id=63, user_id=28) - phantom ADMIN jog megvonva
- B) Javítva `fleet_finance.asset_costs` rekord: organization_id=63 → 21, vendor_organization_id=63 beállítva
### ✅ Verifikáció
- Backend restart: ✅ Sikeres
- Python syntax check: ✅ provider_service.py OK, expenses.py OK
- Vite build: ✅ Sikeres (255 modules, 6.97s)
## 2026-06-23 - P0 Tenant Isolation & Vehicle Mapping Audit
### Scope
Full-stack audit of vehicle dropdown tenant isolation failure in CostsView.vue
### Elemzett fájlok
- `backend/app/api/v1/endpoints/assets.py` - GET /assets/vehicles (229-318)
- `frontend/src/views/costs/CostsView.vue` - Vehicle dropdown & org switch (330-565)
- `frontend/src/stores/vehicle.ts` - fetchVehicles() (141-158)
- `frontend/src/stores/auth.ts` - switchOrganization() & active_organization_id (687-717)
- `frontend/src/stores/cost.ts` - defense-in-depth org injection (71)
### Adatbázis: tester_pro (User ID: 28)
- 2 organization: Test Company (ID:1, 19 vehicles) + Private_28 (ID:21, 6 vehicles) = 25 total
- Schema: identity.users, fleet.organization_members, fleet.organizations, vehicle.assets
### Root Cause
Frontend cache staleness: vehicles load once in onMounted(), never refresh on org switch. The watch on active_organization_id only re-fetches costs, not vehicles.
### Verdict
Backend filtering is correct (JWT scope_id). Database schema is correct. Fix requires adding `vehicleStore.fetchVehicles()` to the org switch watch in CostsView.vue:549.
### Report
`docs/p0_tenant_isolation_vehicle_mapping_audit_report.md`
## 2026-06-23 - P0 Tenant Isolation Fix: CostsView.vue org switch watcher
### 🎯 Cél
Frontend tenant isolation fix: garázsváltáskor a CostsView.vue watch blokkja most már reseteli a jármű szűrőt (`selectedVehicleFilter.value = null`), újratölti a járműveket az új garázs scope-jával (`vehicleStore.fetchVehicles()`), és frissíti a költségeket.
### 🔧 Módosított fájlok
- `frontend/src/views/costs/CostsView.vue` — watch blokk kiegészítése: jármű szűrő reset + vehicleStore.fetchVehicles() hívás
### ✅ Verifikáció
- Vite build: ✅ Sikeres (0 hiba)
- `vehicleStore.fetchVehicles()` mindig küld GET kérést (nincs belső cache guard)
## 2026-06-23 - P0 EXECUTION: UI Switcher, Subscription Widget & Menu Alignment
### 🎯 Cél
A P0 audit riportban azonosított hibák kijavítása: garázsválasztó szűrés, előfizetés widget jármű limit megjelenítés, mobil menü igazítás, backend admin jogosultság javítás.
### 🔧 Változtatások
**1. HeaderCompanySwitcher.vue — Garázsválasztó javítás**
- Eltávolítva az `org_type !== 'individual'` szűrő a `companyOrganizations` computed property-ből
- Létrehozva új `individualOrganizations` computed property a privát garázsokhoz
- Dropdown most két csoportra van osztva: "👤 Saját garázsok" (individual) és "🏢 Céges garázsok" (business)
- Privát garázsokra kattintva `switchOrganization()` hívódik, majd `/dashboard` navigáció
- Eltávolítva a keménykódolt "Private Garage" gomb — helyette dinamikus lista
**2. SubscriptionStatusWidget.vue — Jármű limit megjelenítés**
- Hozzáadva `useVehicleStore` import és `vehicleCount` computed property
- Hozzáadva `maxVehicles` computed property (org vagy user szintről)
- Második progress bar a jármű telítettséghez (🚗 Járművek: X / Y)
- Színkódolt sáv: zöld (<75%), sárga (75-90%), piros (>90%)
- Ha nincs limit (0 vagy null): "Korlátlan" felirat
- Dátum formázás és lejárati információ hozzáadva
**3. PrivateLayout.vue — Mobil menü igazítás**
- "Költségek" gombhoz hozzáadva `justify-end` és `text-right` osztályok
- A gomb ikonja és szövege jobbra igazítva
**4. organizations.py — Backend admin jogosultság javítás**
- `PUT /{org_id}/subscription` végpontról eltávolítva a `RequireSystemCapability(Capability.CAN_MANAGE_SUBSCRIPTIONS)` függőség
- Helyette `_check_org_admin_access(org_id, current_user.id, db)` hívás — így org ADMIN/OWNER is kezelheti a saját előfizetését
**5. organization.ts — TypeScript típus javítás**
- `org_type` mező kötelezővé téve (eltávolítva a `?` optional flag)
### ✅ Verifikáció
- Vite build: ✅ Sikeres (6.75s, 0 hiba)
- Backend Python szintaxis: ✅ Sikeres
- API konténer újraindítás: ✅ Sikeres
## 2026-06-23 - P0 HOTFIX: Cost Wizard Edit Mode Bug (POST vs PUT)
### 🎯 Cél
A CostEntryWizard szerkesztés módban POST helyett PUT hívást indítson, hogy ne hozzon létre duplikátumot.
### 🔧 Módosított fájlok
1. **`backend/app/schemas/asset_cost.py`** - Új `AssetCostUpdate` Pydantic schema (minden mező opcionális)
2. **`backend/app/api/v1/endpoints/expenses.py`** - Új `PUT /expenses/{expense_id}` végpont a meglévő költségrekordok módosítására
3. **`frontend/src/stores/cost.ts`** - Új `updateExpense(id, payload)` action a store-ban, ami `PUT /expenses/{id}`-t hív
4. **`frontend/src/components/cost/CostEntryWizard.vue`** - `handleSubmit()` logika javítva: ha `props.editCost.id` létezik, `updateExpense()`-t hív, egyébként `addExpense()`-t
### 🗑️ Adatbázis cleanup
- Duplikált rekord törölve: `55214098-74be-4261-a101-7fd9159e10d8` (asset_id=`deb42aea-1f48-4a70-85b5-ba451d005577`, amount_gross=5500.00)
### ✅ Verifikáció
- Vite build: ✅ Sikeres (7.09s, 255 module, 0 hiba)
- Backend Python AST parse: ✅ Sikeres (expenses.py, asset_cost.py)
- `AssetCostUpdate` schema import: ✅ Sikeres (14 field)
- Duplikátum törlés: ✅ Sikeres
## 2026-06-23 - P0 Final Polish: Wizard UX & Menu Alignment
### 🎯 Cél
Három kritikus UI hiba javítása: dátum hydratáció Edit módban, Fizetési Mód logika és UI átrendezés, mobil menü jobbra igazítás.
### 🔧 Módosított fájlok
1. **`frontend/src/components/cost/CostEntryWizard.vue`**
- **Date Hydration Fix (watch block):** `form.invoiceDate` és `form.paymentDeadline` most már mindig érvényes `YYYY-MM-DD` stringet kap (vagy `''` ha null). Két forrást is ellenőriz: `data.invoice_date` (JSONB) és `editData.invoice_date` (top-level). Használ `rawDate.split('T')[0] || rawDate.slice(0, 10) || ''` fallback láncot.
- **Payment Method UI áthelyezés:** A `<select>` a STEP 3 blokkban a Számla kelte és Fizetési határidő ELÉ került (Invoice Number után, Invoice Date előtt).
- **Payment Deadline dinamikus rejtés:** `v-if="form.paymentMethod === 'TRANSFER'"` a Payment Deadline inputon — CASH/CARD esetén eltűnik.
- **Mentési automatizmus:** `handleSubmit()`-ben, ha `form.paymentMethod === 'CASH' || 'CARD'`, a `form.paymentDeadline` automatikusan `form.invoiceDate || form.date` értékre áll.
2. **`frontend/src/layouts/PrivateLayout.vue`**
- **Mobile Menu "Költségek" jobbra igazítás:** `flex-row-reverse` osztály hozzáadva, hogy az ikon a jobb szélre tapadjon. Megtartva `justify-end` és `text-right`.
3. **`frontend/src/layouts/OrganizationLayout.vue`**
- **"Költségek" gomb hozzáadva** a hamburger menübe (hiányzott). Jobbra igazított `flex-row-reverse` stílussal, a `navigateToCosts()` függvény az `/organization/:id/costs` oldalra navigál.
### ✅ Verifikáció
- Vite build: ✅ Sikeres (7.31s, 255 modules, 0 hiba)
## 2026-06-24 — P0 3D Capability Matrix Audit (Issue #283)
**Architect:** Completed read-only audit of all SQLAlchemy models for 3D RBAC readiness.
**Findings:**
- **D1 (Global Roles):** `UserRole` enum with 6 values (SUPERADMIN, ADMIN, MODERATOR, SALES_REP, SERVICE_MGR, USER) — ✅ sufficient
- **D2 (Tenant Roles):** `OrgUserRole` enum (OWNER, ADMIN, ACCOUNTANT, DRIVER, VIEWER) + `OrgRole.permissions` JSONB + `OrganizationMember.permissions` JSON — ✅ sufficient
- **D3 (Subscription Capabilities):** ⚠️ Partial — `SubscriptionTier.rules` JSONB exists but no standardized feature capability format. **Missing:** `custom_features` JSONB on Organization model
- **D4 (Cost Category Gating):** ⚠️ Partial — `CostCategory.min_tier` exists but no `required_feature` column
**Report:** `docs/p0_3d_capability_matrix_audit_report.md`
**Proposed migrations:** 3 ALTER TABLE statements (SubscriptionTier.feature_capabilities, Organization.custom_features, CostCategory.required_feature) + optional FeatureCapability enum
## 2026-06-24 — P0 3D Capability Matrix Implementation (Code)
### 🎯 Cél
A 3D Capability Matrix teljes implementációja: modellek bővítése, adatbázis migráció, Capability Resolver Service, és a /categories API végpont capability-alapú védelme.
### 🔧 Módosított fájlok
- `backend/app/models/core_logic.py` — SubscriptionTier.feature_capabilities (JSONB)
- `backend/app/models/marketplace/organization.py` — Organization.custom_features (JSONB) + subscription_tier reláció
- `backend/app/models/fleet_finance/models.py` — CostCategory.required_feature (String(50))
- `backend/app/services/capability_service.py` — Új Capability Resolver Service (Superadmin Fast-Pass)
- `backend/app/api/v1/endpoints/dictionaries.py` — /cost-categories endpoint capability filtering
### ✅ Verifikáció
- Sync Engine: 1213 OK, 0 Fixed, 0 Extra — teljes szinkron
- Python import/attribute check: minden modelloszlop és reláció jelen van
- resolve_org_capabilities() callable, Fast-Pass működik
## 2026-06-24 — P0 EXECUTION: Backoffice SSO & Staff Guards
### 🎯 Cél
Cross-subdomain SSO cookie fix, backend staff role dependencies, frontend admin routing guard expansion, and dead link cleanup in AdminLayout.
### 🔧 Módosított fájlok
**Phase 1 — Cross-Subdomain Cookies (Backend)**
- `backend/app/core/config.py` — Added `COOKIE_DOMAIN: str = ".servicefinder.hu"` setting
- `backend/app/api/v1/endpoints/auth.py` — Added `domain=settings.COOKIE_DOMAIN` to both `set_cookie()` calls (login:127, verify-email:221)
**Phase 2 — Scalable Backend Dependencies**
- `backend/app/api/deps.py` — Added `STAFF_ROLES` set (SUPERADMIN, ADMIN, MODERATOR, SALES_REP, SERVICE_MGR)
- `backend/app/api/deps.py` — Added `get_current_staff` dependency (admits all staff roles)
- `backend/app/api/deps.py` — Added `RequireRole(allowed_roles: List[UserRole])` flexible dependency factory
**Phase 3 — Frontend Guards & Store**
- `frontend/src/stores/auth.ts` — Expanded `isAdmin` getter to include SALES_REP and SERVICE_MGR
- `frontend/src/router/index.ts` — Expanded `requiresAdmin` guard to admit all 5 staff roles
**Phase 4 — Admin UI Cleanup**
- `frontend/src/layouts/AdminLayout.vue` — Removed dead sidebar links: /admin/vehicles, /admin/translations, /admin/system, /admin/audit
### ✅ Verifikáció
- Vite build: ✅ Sikeres (255 modules, 7.13s, 0 hiba)
- Python AST parse: ✅ config.py, auth.py, deps.py — all syntax OK
- Python import test: ✅ `settings.COOKIE_DOMAIN` = `.servicefinder.hu`
- Python import test: ✅ `STAFF_ROLES` contains all 5 roles, `get_current_staff` and `RequireRole` are callable
## 2026-06-24 - P0 READ & PLAN: Admin Container Separation Audit
### 🎯 Cél
Architecture audit for strictly isolated Admin container. Read docker-compose.yml, NPM proxy configs, and directory structure.
### 🔧 Eredmények
**1. DOCKER ARCHITECTURE:** ✅ 3 admin-related containers exist
- `sf_admin_ui` (Streamlit, port 8501) — Active HITL panel
- `sf_admin_frontend` (Nuxt 3, port 8502) — Placeholder only
- `sf_public_frontend` (Vite/Vue, port 8503) — Contains embedded admin views
**2. CRITICAL FINDING:** Admin views are split across two codebases
- Full admin views (Dashboard, Users, Packages, Services, Login) exist in `frontend/src/views/admin/`
- Separate Nuxt 3 container at `frontend/admin/` is provisioned but empty (placeholder app.vue only)
- NPM routing already correct: `admin.servicefinder.hu``sf_admin_frontend:8502`
**3. GITEA CARDS CREATED:**
- #284 — Main audit card (FINISHED)
- #285 — Build Nuxt 3 Admin App
- #286 — Remove Admin Views from Public Frontend
- #287 — Production Dockerfile for Admin
- #288 — Deprecate Streamlit Admin
**4. REPORT:** `plans/admin_container_separation_audit.md`