# P0 Critical: DB Schema & Ownership Model Audit Report **Dátum:** 2026-06-18 **Auditor:** Architect Mode **Cél:** A 404 "Asset not found" hiba kivizsgálása event creation során — a Privát Garázsok (Private Garages) kezelésének DB vs API mismatch-e. --- ## 1. 🔍 SÉMA AUDIT (Tulajdonosi Modell Vizsgálata) ### 1.1 `vehicle.assets` tábla — Tulajdonosi Oszlopok | Oszlop | Típus | Leírás | |--------|-------|--------| | `current_organization_id` | `integer NULL` | Melyik Org-ban van jelenleg a jármű | | `owner_person_id` | `bigint NULL` | **Személy tulajdonos** (Person ID-re mutat, NEM User ID-ra!) | | `owner_org_id` | `integer NULL` | **Szervezeti tulajdonos** (Organization ID) | | `operator_person_id` | `bigint NULL` | **Üzemeltető személy** (Person ID) | | `operator_org_id` | `integer NULL` | **Üzemeltető szervezet** (Organization ID) | | `branch_id` | `uuid NULL` | Fizikai garázs (Branch) ahol áll | | `status` | `varchar NOT NULL` | 'active', 'archived', stb. | | `data_status` | `varchar NULL` | 'draft', 'active', 'enriched' | **Következtetés:** Nincs direkt `owner_id` vagy `user_id` oszlop. A tulajdonjogot a `owner_person_id` (Person) és `owner_org_id` (Organization) kettőse modellezi. Ez a **Dual Entity** (Person vs User) modell része. ### 1.2 `fleet.organizations` tábla — Garázs Attribútumok | Oszlop | Típus | Leírás | |--------|-------|--------| | `id` | `integer PK` | Szervezet azonosító | | `owner_id` | `integer NULL` | Ki a tulajdonos (User ID) | | `org_type` | `orgtype ENUM` | `'individual'`, `'fleet_owner'`, `'business'`, `'service_provider'` | | `status` | `varchar` | `'active'`, `'pending_verification'` | | `is_verified` | `boolean DEFAULT false` | KYC státusz | | `name` | `varchar` | A garázs neve | | `full_name` | `varchar` | Teljes cégnév | **⚠️ KRITIKUS:** NINCS `is_personal`, `is_default` vagy `is_primary` flag az `organizations` táblában. A "Privát Garázs" fogalma **nem létezik külön mezőként** — csak az `org_type = 'individual'` jelzi. ### 1.3 `fleet.organization_members` tábla | Oszlop | Típus | |--------|-------| | `organization_id` | `integer NOT NULL` | | `user_id` | `integer NULL` | | `person_id` | `bigint NULL` | | `role` | `member_role ENUM` (OWNER, ADMIN, MEMBER, stb.) | | `is_verified` | `boolean` | | `status` | `varchar` ('active', 'pending_verification') | ### 1.4 `fleet.asset_assignments` tábla | Oszlop | Típus | |--------|-------| | `id` | `uuid PK` | | `asset_id` | `uuid NOT NULL` | | `organization_id` | `integer NOT NULL` | | `status` | `varchar NOT NULL` | --- ## 2. 👤 ADATBÁZIS AUDIT — User 28 és Asset rekord vizsgálata ### 2.1 User ID: 28 | Mező | Érték | |------|-------| | `id` | **28** | | `email` | `tester_pro@profibot.hu` | | `role` | `admin` | | `person_id` | **29** ⚠️ (ez a Person ID!) | | `subscription_plan` | `PREMIUM` | | `is_active` | `true` | | `is_deleted` | **`true`** 🛑 (SOFT-DELETED!) | | `deleted_at` | **2026-06-14** (4 nappal ezelőtt) | | `scope_level` | `organization` | | `scope_id` | `null` | ### 2.2 Asset ID: `deb42aea-1f48-4a70-85b5-ba451d005577` | Mező | Érték | |------|-------| | `id` | `deb42aea-...` | | `license_plate` | `QWE123` | | `current_organization_id` | **44** (Profibot Kft.) | | `owner_person_id` | **29** ⚠️ (ez a Person ID, ami User 28-hoz tartozik!) | | `owner_org_id` | **44** (Profibot Kft.) | | `operator_person_id` | `null` | | `operator_org_id` | `null` | | `status` | `active` | | `data_status` | `draft` | | `branch_id` | `3bc1bff7-...` | | `vehicle_class` | `motorcycle` | | `brand` | `APRILIA` | | `model` | `af1` | ### 2.3 Asset Assignment | Mező | Érték | |------|-------| | `asset_id` | `deb42aea-...` | | `organization_id` | **44** | | `status` | `active` | ### 2.4 Organization ID: 44 (Profibot Kft.) | Mező | Érték | |------|-------| | `id` | 44 | | `name` | Profibot Kft. | | `org_type` | `business` | | **`owner_id`** | **86** ❗ (NEM User 28, hanem User 86 a tulajdonos!) | | `legal_owner_id` | 93 (Person ID) | | `status` | `pending_verification` | ### 2.5 User 28 Organization Tagsulatai - **Org 1 (Test Company):** User 28 a `owner_id` (saját cége, `fleet_owner`) - **Org 63 (Aszalós Motorszervíz):** Tag (`ADMIN`, `pending_verification`, `service_provider`) - **Org 44 (Profibot Kft.):** **NEM tag, NEM tulajdonos** ❌ ### 2.6 Person ID 29 (User 28 Person rekordja) User 28 `person_id` = 29. Az asset `owner_person_id` = 29. **Ez a helyes kapcsolat a User és az Asset között.** --- ## 3. 📋 REGISZTRÁCIÓS LOGIKA ELEMZÉSE ### 3.1 `register_lite()` (1. fázis) Forrás: [`backend/app/services/auth_service.py:63`](backend/app/services/auth_service.py:63) - Létrehoz egy `Person` rekordot - Létrehoz egy `User` rekordot (a Person-hoz kapcsolva `person_id` segítségével) - `scope_level = "individual"` (alapértelmezett) - `is_active = False` (email verification szükséges) - **NEM hoz létre Organization-t ebben a fázisban** ### 3.2 `complete_kyc()` (2. fázis — "KYC complete") Forrás: [`backend/app/services/auth_service.py:178`](backend/app/services/auth_service.py:178) - **AUTOMATIKUSAN létrehoz egy Organization rekordot** (`OrgType.individual`) - Org naming template: `"{last_name} Flotta"` (pl. "Tester Flotta") - Org name: `"{last_name} Garázsa"` - Beállítja a `User.scope_id` = `new_org.id` (az új Organization ID-jára) - Létrehoz egy `Branch` (fiók/garázs) rekordot "Home Base" néven - Létrehoz egy `OrganizationMember` rekordot OWNER role-lal - Létrehoz egy `Wallet` rekordot - Aktiválja a usert (`is_active = True`) **Összefoglalva:** Igen, a rendszer létrehoz egy automatikus "Privát Garázst" (Organization) a KYC fázisban. Ennek típusa `individual`. Nincs külön `is_personal` flag, csak az `org_type = 'individual'` jelzi. --- ## 4. 🐛 A 404 HIBA GYÖKERÉNEK AZONOSÍTÁSA ### 4.1 Elsődleges Bug: Person ID vs User ID összehasonlítás A [`backend/app/api/v1/endpoints/assets.py:744`](backend/app/api/v1/endpoints/assets.py:744) sorban a `_check_asset_access()` függvény: ```python Asset.owner_person_id == current_user.id, # ❌ BUG! ``` **Hiba:** Az asset `owner_person_id` mezőjét (`29`) a `current_user.id` (`28`) értékkel hasonlítja össze. **Helyes:** `Asset.owner_person_id == current_user.person_id` (29 == 29 ✓) Az asset-ben `owner_person_id = 29`, és a User 28-hoz tartozó `person_id = 29`. Ez egy valid tulajdonosi kapcsolat, de a kód rossz mezőt használ az összehasonlításra. ### 4.2 Ugyanez a bug TÖBB HELYEN is előfordul | Sor | Hely | Hibás Kód | Javítás | |-----|------|-----------|---------| | [`assets.py:316`](backend/app/api/v1/endpoints/assets.py:316) | `get_asset()` | `Asset.owner_person_id == current_user.id` | `current_user.person_id` | | [`assets.py:468`](backend/app/api/v1/endpoints/assets.py:468) | `update_vehicle()` | `Asset.owner_person_id == current_user.person_id` | ✅ **HELYES** | | [`assets.py:548`](backend/app/api/v1/endpoints/assets.py:548) | `maintenance` GET | `Asset.owner_person_id == current_user.id` | `current_user.person_id` | | [`assets.py:605`](backend/app/api/v1/endpoints/assets.py:605) | `maintenance` POST | `Asset.owner_person_id == current_user.id` | `current_user.person_id` | | [`assets.py:744`](backend/app/api/v1/endpoints/assets.py:744) | `_check_asset_access()` | `Asset.owner_person_id == current_user.id` | `current_user.person_id` | **FONTOS:** A 468. sor már helyes! Ott `current_user.person_id` van. Ez arra utal, hogy a többi helyen figyelmetlenségből maradt `current_user.id`. ### 4.3 Másodlagos Probléma: User 28 Soft-Deleted User 28 (`tester_pro@profibot.hu`) **soft-deletelve** lett 2026-06-14-én (`deleted_at` mező kitöltve, `is_deleted = true`). A [`backend/app/services/auth_service.py:313`](backend/app/services/auth_service.py:313) sorban: ```python User.is_deleted == False ``` Ez azt jelenti, hogy User 28 **nem tud bejelentkezni** (az `authenticate()` függvény kiszűri a törölt usereket). ### 4.4 Harmadlagos Probléma: User 28 nincs az Org 44-ben Az asset (`deb42aea`) `owner_org_id = 44` (Profibot Kft.), de User 28: - Nem tagja az Org 44-nek - Nem tulajdonosa az Org 44-nek (azt User 86 birtokolja) - Csak az Org 1 (Test Company) tulajdonosa Tehát még ha a Person ID bug javításra is kerül, a szervezeti ellenőrzés (`Asset.owner_org_id.in_(user_org_ids)`) akkor sem találna match-et, mert User 28 nincs az Org 44 tagjai között. **De ez nem is szükséges**, mert a személyes tulajdonjog (`owner_person_id = 29` ↔ `User 28 person_id = 29`) önállóan is hozzáférést biztosít. --- ## 5. 📊 ÖSSZEFOGLALÓ JELENTÉS ### Prioritási Sorrend | # | Probléma | Hatás | Javítás Jellege | |---|----------|-------|-----------------| | **P0** | `User 28 soft-deleted` (`deleted_at: 2026-06-14`) | A user nem tud bejelentkezni, minden API hívás sikertelen | **Fiók visszaállítása** (restore OTP) vagy új regisztráció | | **P0** | `owner_person_id == current_user.id` bug (4 helyen) | Még élő user esetén is 404-et kapna event létrehozáskor | `current_user.id` → `current_user.person_id` kijavítása | | **P1** | Asset `data_status = 'draft'` — lehet, hogy még nincs teljesen aktiválva | Bizonyos műveletek korlátozva lehetnek | Admin felületen aktiválás vagy API javítás | | **P2** | Nincs `is_personal` / `is_default` flag az organizations táblában | A "Privát Garázs" detektálása csak `org_type = 'individual'` alapján lehetséges | Opcionális séma kiegészítés | ### Ajánlott Következő Lépések 1. **User 28 restore** — Mivel a soft-delete 4 napja történt (30 napos ablakon belül), a `/restore/verify` végponton keresztül visszaállítható 2. **Comparison bug javítása** — Mind a 4 helyen (`assets.py:316, 548, 605, 744`) `current_user.id` → `current_user.person_id` 3. **Ellenőrzés** — Jelenleg `update_vehicle()` (468. sor) már helyes `current_user.person_id`-t használ; a többi endpoint inkonzisztens **Megjegyzés:** A regisztrációs logika automatikusan létrehoz egy `individual` típusú Organization-t a KYC fázisban ("Privát Garázs"), ami a `scope_id`-n keresztül kapcsolódik a userhez. Ez a modell konzisztens, a hiba kizárólag a **comparison logic-ben** van.