Files
service-finder/docs/db_schema_ownership_audit_2026-06-18.md

10 KiB

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

  • 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

  • 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 sorban a _check_asset_access() függvény:

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 get_asset() Asset.owner_person_id == current_user.id current_user.person_id
assets.py:468 update_vehicle() Asset.owner_person_id == current_user.person_id HELYES
assets.py:548 maintenance GET Asset.owner_person_id == current_user.id current_user.person_id
assets.py:605 maintenance POST Asset.owner_person_id == current_user.id current_user.person_id
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 sorban:

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 = 29User 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.idcurrent_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.idcurrent_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.