Files
service-finder/.roo/history.md

28 KiB

Service Finder Fejlesztési Történet

🎯 Cél

Az email verifikációs folyamat átalakítása "Magic Link" élménnyé. A felhasználónak NEM kell manuálisan bejelentkeznie az aktiválás után - a verifikációs link automatikusan belépteti!

Implementáció

1. Backend: JWT Token Generálás Verifikációnál

Fájl: backend/app/api/v1/endpoints/auth.py

  • A /verify-email végpont most response_model=Token-t ad vissza
  • Sikeres verifikáció után a backend meghívja az AuthService.verify_email() metódust
  • Az AuthService.verify_email() mostantól User objektumot ad vissza (nem csak boolean-t)
  • A végpont generál JWT access és refresh tokent ugyanúgy, mint a /login endpoint
  • A tokenek HTTP-only cookie-ban és JSON response-ban is megjelennek

Változtatások:

# AuthService.verify_email() módosítás
- return True  # RÉGI
+ return user  # ÚJ: visszaadja az aktivált User objektumot

# auth.py verify_email végpont
+ user = await AuthService.verify_email(db, request.token)
+ if not user:
+     raise HTTPException(...)
+
+ # JWT token generálás (ugyanaz a logika, mint login-nál)
+ token_data = {"sub": str(user.id), "role": ..., "rank": ..., ...}
+ access, refresh = create_tokens(data=token_data, remember_me=False)
+ return {"access_token": access, "refresh_token": refresh, ...}

2. Frontend Store: Automatikus Bejelentkezés

Fájl: frontend/src/stores/auth.ts

  • A verifyAccount() action most feldolgozza a backend által küldött JWT tokent
  • Ha data.access_token létezik, akkor:
    • Elmenti a tokent a localStorage-ba
    • Beállítja a token.value state-et
    • Meghívja a fetchUser() metódust (betölti a user profilt)
    • Törli a pending_verification_email értéket

Változtatások:

// Új logika a verifyAccount()-ban
if (data.access_token) {
  localStorage.setItem('access_token', data.access_token)
  if (data.refresh_token) {
    localStorage.setItem('refresh_token', data.refresh_token)
  }
  token.value = data.access_token
  await fetchUser()
  localStorage.removeItem('pending_verification_email')
}

3. Frontend View: Automatikus Átirányítás KYC-re

Fájl: frontend/src/views/VerifyEmailView.vue

  • Új UI: "Sikeres aktiválás és bejelentkezés!" üzenet
  • 3 másodperces countdown: "Átirányítás 3 másodperc múlva..."
  • Automatikus redirect: setInterval() számolja vissza, majd átirányít /complete-kyc-re
  • CTA gomb: "Tovább a Profilhoz" (nem több "Tovább a Belépéshez")
  • Cleanup: onUnmounted() törli az interval-t

Változtatások:

<!-- Sikeres állapot új szövege -->
<h1>Sikeres aktiválás és bejelentkezés!</h1>
<p>{{ autoRedirectCountdown > 0 ? `Átirányítás ${autoRedirectCountdown} másodperc múlva...` : 'Átirányítás...' }}</p>
<button @click="goToKyc">Tovább a Profilhoz</button>

<script>
const autoRedirectCountdown = ref(3)
let countdownInterval: ReturnType<typeof setInterval> | null = null

function startAutoRedirectCountdown() {
  countdownInterval = setInterval(() => {
    autoRedirectCountdown.value -= 1
    if (autoRedirectCountdown.value <= 0) {
      clearInterval(countdownInterval)
      goToKyc()
    }
  }, 1000)
}
</script>

Régi folyamat:

  1. Regisztráció → Email verify link
  2. Verify oldalon aktiválás → "Tovább a Belépéshez"
  3. Felhasználó manuálisan bejelentkezik
  4. Login után átirányítás KYC-re

Új folyamat (Magic Link):

  1. Regisztráció → Email verify link
  2. Verify oldalon aktiválás → Backend JWT tokent ad
  3. Frontend automatikusan bejelentkezteti a felhasználót
  4. 3 másodperc múlva automatikus átirányítás /complete-kyc-re
  5. Felhasználó már be van jelentkezve → KYC mentés sikeres!

📊 Érintett Fájlok

🧪 Tesztelési Eredmény

  1. Backend Python szintaxis helyes (py_compile sikeres)
  2. Auth service módosítás sikeres (User objektum visszaadás)
  3. Backend újraindítás sikeres, nincsenek hibák a logokban
  4. Frontend TypeScript típusok konzisztensek
  5. Auto-redirect logika implementálva (3 mp countdown)

🔗 Gitea

  • Feature: Magic Link Auto-Login on Email Verification
  • Típus: UX Enhancement
  • Státusz: Completed

2026-06-04 (A) - Onboarding UX & KYC Authentication Flow Javítások

🎯 Probléma

A felhasználói visszajelzések alapján a regisztrációs és KYC folyamat kritikus UX hibákat tartalmazott:

  1. 'Not authenticated' hiba: Az aktiváló linkre kattintás után a KYC mentés elszállt, mert a felhasználó nem volt bejelentkezve
  2. Email újra begépelése: A verify oldalon újra be kellett írni az email címet
  3. Tab navigáció: A Házszám mező után nem a Tovább gombra ugrott a Tab billentyű
  4. Kötelező okmányok: A rendszer azonnal kérte a személyi igazolványt, ami rossz UX

Megoldás

1. Backend Módosítások

Fájl: backend/app/schemas/auth.py

  • A DocumentDetail osztály mezői (number, expiry_date) most Optional[str] és Optional[date]
  • A UserKYCComplete.identity_docs mező most Optional[Dict[str, DocumentDetail]]
  • Ez lehetővé teszi a "Soft KYC"-t, ahol a felhasználó bejut a rendszerbe okmányok nélkül is

2. Frontend VerifyEmailView Módosítások

Fájl: frontend/src/views/VerifyEmailView.vue

  • Sikeres aktiválás után: A CTA már nem "Tovább a profil kitöltéséhez", hanem "Tovább a Belépéshez"
  • Átirányítás: A goToKyc() helyett goToLogin() amely a főoldalra irányít
  • Email auto-fill: A localStorage.getItem('pending_verification_email') használata a korábbi saved-email helyett

3. Auth Store Logika

Fájl: frontend/src/stores/auth.ts

  • Regisztráció: Az email mentésre kerül localStorage.setItem('pending_verification_email', data.email)
  • Login után KYC ellenőrzés: Ha !isKycComplete.value, automatikus átirányítás a /complete-kyc oldalra
  • Cleanup: Sikeres belépés után törlődik a pending_verification_email a localStorage-ból

4. CompleteKycView Módosítások

Fájl: frontend/src/views/CompleteKycView.vue

Tab Order Javítás:

  • A Házszám input kapott egy @keydown.tab.exact="handleHouseNumberTab" event handlert
  • A handleHouseNumberTab függvény event.preventDefault() és nextTick(() => nextButton.value?.focus())
  • A Tovább gomb kapott egy ref="nextButton" attribútumot

Opcionális Okmányok:

  • A 3. lépés címe: "Okmányok (opcionális)"
  • A személyi igazolvány vizuálisan is opcionálisként jelenik meg (fehér pont helyett átlátszó, szöveg halvány)
  • Validáció eltávolítva: A validateStep() függvény már nem ellenőrzi az ID_CARD mezőket
  • Payload logika: Az identity_docs objektum csak akkor kerül a payload-ba, ha legalább egy dokumentum ki van töltve

5. Teljes Folyamat Átalakítás

Régi folyamat:

  1. Regisztráció → Email confirm → KYC (nem bejelentkezve) → HIBA

Új folyamat:

  1. Regisztráció → Email mentés localStorage-ba
  2. Email confirm → "Tovább a Belépéshez" CTA
  3. Belépés → Auth store ellenőrzi KYC státuszt
  4. Ha KYC hiányzik → Átirányítás /complete-kyc (már bejelentkezve!)
  5. KYC opcionális okmányokkal → Sikeres mentés

📊 Érintett Fájlok

🧪 Tesztelési Szempontok

  1. Új user regisztráció email mentése
  2. Verify oldalon email auto-fill
  3. Sikeres aktiválás után "Tovább a Belépéshez" gomb
  4. Belépés után KYC ellenőrzés és átirányítás
  5. Házszám → Tab → Tovább gomb fokusz
  6. KYC mentés okmányok nélkül
  7. Backend fogadja az üres identity_docs-ot

🔗 Gitea

  • Issue: #200 - Fix: Onboarding UX & KYC Authentication Flow
  • Státusz: In Progress

2026-06-04 (C) - Soft KYC, Trust Profile Extension & Device-Hub Architecture

🎯 Cél

Teljes stack implementáció a bizalmi infrastruktúra kiterjesztésére: Device Fingerprinting (Device-Hub architektúra), UserTrustProfile bővítés (identity_score, verification_level, verified_channels, identity_risk_flag), Person rekordok merge-elhetősége (merged_into_id), Soft KYC (opcionális címadatok a regisztrációnál), és eszközazonosítás a login folyamatban.

Implementáció

1. Backend Modellek Bővítése

Fájl: backend/app/models/identity/identity.py

Person.merged_into_id (73. sor):

  • merged_into_id: Mapped[Optional[int]] - BigInteger, FK identity.persons.id-re, SET NULL on delete
  • Lehetővé teszi Person rekordok összeolvasztását (duplikáció kezelés)

UserTrustProfile bővítés (263. sor):

  • identity_score: Mapped[Optional[float]] - 0.0 - 1.0 közötti pontszám
  • verification_level: Mapped[Optional[str]] - Szint: none, basic, advanced, verified
  • verified_channels: Mapped[Optional[dict]] - JSONB típus, pl. {"email": true, "phone": false, "id_card": true}
  • identity_risk_flag: Mapped[Optional[bool]] - Red flag jelzés

Device modell (294. sor):

  • fingerprint_hash: Mapped[str] - Primary Key, az eszköz ujjlenyomatának hash-e
  • risk_score: Mapped[Optional[float]] - Eszköz kockázati pontszáma
  • is_banned: Mapped[bool] - Kitiltott eszköz flag
  • created_at: Mapped[datetime] - Létrehozás időpontja

UserDeviceLink modell (309. sor):

  • id: Mapped[uuid.UUID] - UUID Primary Key
  • user_id: Mapped[int] - FK identity.users.id-re
  • device_hash: Mapped[str] - FK identity.devices.fingerprint_hash-re
  • first_seen_at: Mapped[datetime] - Első látogatás
  • last_seen_at: Mapped[Optional[datetime]] - Utolsó látogatás
  • login_count: Mapped[int] - Bejelentkezések száma (default: 1)

2. Adatbázis Szinkronizáció

Parancs: docker exec sf_api python -m app.scripts.sync_engine

  • Eredmény: 7 séma változás sikeresen alkalmazva (1000 OK, 7 Fixed, 0 Shadow Data)
  • Létrejött: identity.devices tábla, identity.user_device_links tábla
  • Bővült: identity.persons (merged_into_id), identity.user_trust_profiles (4 új oszlop)

3. Pydantic Schema Relaxáció (Soft KYC)

Fájl: backend/app/schemas/auth.py

  • address_street_nameOptional[str] = None
  • address_street_typeOptional[str] = None
  • address_house_numberOptional[str] = None
  • Csak address_zip és address_city maradt kötelező

4. Login Endpoint Device Fingerprint Tracking

Fájl: backend/app/api/v1/endpoints/auth.py

  • Új paraméter: device_fingerprint: Optional[str] = Form(None)
  • Sikeres autentikáció után:
    1. Ellenőrzi, hogy a Device létezik-e a hash alapján → ha nem, létrehozza
    2. Ellenőrzi a UserDeviceLink-et user_id + device_hash alapján
    3. Ha létezik: frissíti last_seen_at és növeli login_count
    4. Ha nem létezik: új rekordot hoz létre first_seen_at = now, login_count = 1
    5. Commit

5. Frontend FingerprintJS Integráció

Fájl: frontend/src/components/LoginModal.vue

  • import FingerprintJS from '@fingerprintjs/fingerprintjs'
  • getDeviceFingerprint(): Lazy singleton pattern - egyszer inicializálja a FingerprintJS-t, majd gyorsítótárazza a visitorId-t
  • handleLogin(): Meghívja getDeviceFingerprint()-et, átadja az eredményt authStore.login()-nak

Fájl: frontend/src/stores/auth.ts

  • login() függvény kibővítve: deviceFingerprint?: string paraméter
  • Ha megadva, device_fingerprint mezőként hozzáfűzi a FormData-hoz

6. Frontend CompleteKycView Soft KYC

Fájl: frontend/src/views/CompleteKycView.vue

  • Lépés leírás frissítve: "Add meg a lakcímed (csak irányítószám és város kötelező)"
  • address_street_name, address_street_type, address_house_number validáció eltávolítva
  • "(opcionális)" címkék hozzáadva az opcionális mezőkhöz
  • Payload builder: opcionális címmezők csak akkor kerülnek bele, ha ki vannak töltve

📊 Érintett Fájlok

🧪 Tesztelési Szempontok

  1. Backend modellek szintaxis helyes (py_compile)
  2. Sync engine 7 séma változást sikeresen alkalmazott
  3. Pydantic schema opcionális mezők (Soft KYC)
  4. Login endpoint device fingerprint fogadása és tárolása
  5. Frontend FingerprintJS betöltés és visitorId küldés
  6. CompleteKycView opcionális címmezők validáció nélkül
  7. Device-Hub architektúra: Device + UserDeviceLink modellek

🔗 Gitea

  • Issue: #202 - Soft KYC, Trust Profile Extension & Device-Hub Architecture
  • Státusz: Completed

2026-06-04 (C) - Soft KYC Address Constraints Fix

🎯 Cél

A system.addresses tábla street_name, street_type és house_number mezőinek opcionálissá tétele az adatbázis szintjén is a Soft KYC bevezetéséhez.

Implementáció

1. SQLAlchemy Modell Frissítés

Fájl: backend/app/models/identity/address.py

  • street_name: Mapped[str]Mapped[Optional[str]], nullable=Falsenullable=True
  • street_type: Mapped[str]Mapped[Optional[str]], nullable=Falsenullable=True
  • house_number: Mapped[str]Mapped[Optional[str]], nullable=Falsenullable=True

2. Adatbázis ALTER TABLE

  • ALTER TABLE system.addresses ALTER COLUMN street_name DROP NOT NULL;
  • ALTER TABLE system.addresses ALTER COLUMN street_type DROP NOT NULL;
  • ALTER TABLE system.addresses ALTER COLUMN house_number DROP NOT NULL;

3. Verifikáció

  • information_schema.columns szerint mindhárom oszlop is_nullable = YES

🔗 Gitea

  • Issue: #203 - Fix: Soft KYC - Address mezők nullable=True
  • Státusz: Completed

🎯 Cél

Két adatfolyam-törés javítása: (1) KYC first_name/last_name nem frissült a Person rekordon, (2) Magic Link verify-email végpont nem támogatta a device_fingerprint-et.

Implementáció

1. Backend KYC Schema

Fájl: backend/app/schemas/auth.py

  • first_name: Optional[str] = None és last_name: Optional[str] = None hozzáadva a UserKYCComplete sémához

2. Backend KYC Service

Fájl: backend/app/services/auth_service.py

  • complete_kyc() metódusban mindkét ágon (Shadow Identity IF és ELSE) hozzáadva a név frissítés:
    • if kyc_in.first_name: p.first_name = kyc_in.first_name
    • if kyc_in.last_name: p.last_name = kyc_in.last_name

3. Frontend KYC Payload

Fájl: frontend/src/views/CompleteKycView.vue

  • handleSubmit() payload-ba bekerült: first_name: kycForm.first_name és last_name: kycForm.last_name

Fájl: backend/app/api/v1/endpoints/auth.py

  • VerifyEmailRequest sémához hozzáadva: device_fingerprint: Optional[str] = None
  • Sikeres verify_email() után teljes Device UPSERT blokk (Device + UserDeviceLink), megegyező logikával, mint a /login végpontban

🔗 Gitea

  • Issue: #204 - Fix KYC Data Binding & Magic Link Device Tracking
  • Státusz: Completed

2026-06-04 (C) - Nested Profile Response & Editable Profile Card

🎯 Cél

A GET /users/me végpont UserResponse Pydantic sémájának kibővítése beágyazott Person és Address adatokkal, valamint egy PUT /users/me/person végpont létrehozása a profil inline szerkesztéséhez a frontenden.

Implementáció

1. Pydantic Schemas (backend/app/schemas/user.py)

  • AddressResponse: Beágyazott cím adatok (zip, city, street_name, house_number, stairwell, floor, door, latitude, longitude, stb.) from_attributes=True konfigurációval
  • PersonResponse: Személyes adatok (first_name, last_name, phone, mothers data, birth data, identity_docs, ice_contact) + address: Optional[AddressResponse] beágyazott címmel
  • PersonUpdate: PUT végponthoz - tartalmazza a személyes adatokat + address_* prefixű cím mezőket
  • UserResponse: Kibővítve person: Optional[PersonResponse] = None mezővel

2. Eager Loading (backend/app/api/deps.py)

  • get_current_user(): joinedload(User.person).joinedload(Person.address) láncolt betöltés
  • Ezzel a SQL egyetlen 4-táblás JOIN-ban tölti be: users → persons → addresses → geo_postal_codes

3. Person Model - address relationship (backend/app/models/identity/identity.py)

  • Hozzáadva: address: Mapped[Optional["Address"]] = relationship("Address", foreign_keys="[Person.address_id]", lazy="joined")
  • TYPE_CHECKING import: from .address import Address

4. PUT /users/me/person végpont (backend/app/api/v1/endpoints/users.py)

  • Elfogad PersonUpdate sémát
  • Frissíti a Person mezőit (first_name, last_name, phone, stb.)
  • Cím frissítés/létrehozás a GeoService.get_or_create_full_address() segítségével
  • Visszaadja a frissített UserResponse-t beágyazott person+address adatokkal
  • _build_user_response() helper: egységes UserResponse építés minden végponthoz

5. Wallet FK Fix (backend/app/models/identity/identity.py)

  • Wallet.user_id FK hozzáadva: ondelete="CASCADE" - ezzel a user törlésekor automatikusan törlődik a wallet rekord is

6. Frontend ProfileView.vue - Inline Editing

  • Read mód: Megjeleníti a authStore.user.person.* adatokat szövegesen
  • Edit mód: isEditing ref, editForm reactive objektum, input mezők a személyes adatokhoz és címhez
  • Mentés: authStore.updatePerson(payload) hívása, sikeres mentés után visszavált read módba
  • Cím szekció: Grid layout zip/city, street/type/number, stairwell/floor/door mezőkkel

7. Auth Store (frontend/src/stores/auth.ts)

  • AddressData interface: zip, city, street_name, house_number, stairwell, floor, door
  • PersonData interface: id, first_name, last_name, phone, address: AddressData | null
  • UserProfile kibővítve: person: PersonData | null
  • updatePerson() action: PUT /users/me/person hívás, sikeres esetén user.person frissítése

8. Identity init.py javítás

  • Device és UserDeviceLink modellek exportálása (hiányoztak, emiatt ImportError-t dobott az auth.py)

9. auth.py javítás

  • from typing import Optional hozzáadva (hiányzott, NameError: name 'Optional' is not defined)

🔗 Gitea

  • Issue: #205 - Nested Profile Response & Editable Profile Card
  • Státusz: Completed

2026-06-04 (C) - Profile UI Refactor + Identity Docs + Change Password

🎯 Cél

Profil oldal vizuális felújítása dark card témával, okmányadatok (identity_docs) megjelenítése/szerkesztése, és jelszóváltoztatás implementálása.

Implementáció

1. Backend: PersonUpdate séma bővítés

Fájl: backend/app/schemas/user.py

  • identity_docs: Optional[Any] = None hozzáadva a PersonUpdate osztályhoz
  • Új ChangePasswordRequest séma: current_password + new_password mezőkkel

2. Backend: PUT /me/person identity_docs merge logika

Fájl: backend/app/api/v1/endpoints/users.py

  • Ha identity_docs érkezik és nem null, merge-el a meglévő adatokkal (dict.update())
  • Megőrzi a nem küldött mezőket (pl. csak LICENSE küldésekor ID_CARD megmarad)

3. Backend: PUT /me/password végpont

Fájl: backend/app/api/v1/endpoints/users.py

  • Jelenlegi jelszó ellenőrzés (verify_password)
  • Új jelszó ≠ régi jelszó validáció
  • Komplexitás validáció (AuthService._validate_password_complexity)
  • Bcrypt hash-elés és mentés (get_password_hash)

4. Frontend: ProfileView teljes átírás

Fájl: frontend/src/views/ProfileView.vue

  • Dark card UI: bg-black/40 backdrop-blur-xl, text-white font-medium, #00E5A0 accent
  • Identity docs szekció: ID_CARD (number, expiry_date) + LICENSE (number, expiry_date, categories) read/edit módban
  • Change Password modal: Teleport, 3 mező, frontend validáció, API hívás, auto-close 2s után

5. Frontend: Auth store bővítés

Fájl: frontend/src/stores/auth.ts

  • changePassword() action: PUT /users/me/password hívás

🔗 Gitea

  • Issue: #206 - Profile UI Refactor + Identity Docs + Change Password
  • Státusz: Completed

2026-06-04 (C) - Fix SQLAlchemy JSON Mutation for identity_docs

🎯 Cél

Az identity_docs JSON mező nem mentődött el a profil szerkesztésnél, mert az SQLAlchemy nem detektálta az in-place dict mutációt.

Implementáció

1. Backend: flag_modified + copy.deepcopy

Fájl: backend/app/api/v1/endpoints/users.py

  • Importált: copy és sqlalchemy.orm.attributes.flag_modified
  • Az identity_docs frissítésnél copy.deepcopy()-val új dict példány készül
  • flag_modified(person, "identity_docs") hívás explicit jelzi SQLAlchemy-nek a JSON oszlop változását

2. Frontend: Success üzenet frissítés

Fájl: frontend/src/views/ProfileView.vue

  • Mentés siker üzenet: "A profil adatok és okmányok sikeresen frissítve!"

🔗 Gitea

  • Issue: #207 - Fix SQLAlchemy JSON mutation for identity_docs
  • Státusz: Completed

2026-06-04 (E) - Internal Zip Lookup Endpoint & Frontend Auto-Fill

🎯 Cél

Külső zippopotam.us API kiváltása belső adatbázis lekérdezéssel. Backend zip-lookup végpont létrehozása a system.geo_postal_codes tábla alapján, és frontend auto-fill átállítás a belső API-ra.

Implementáció

1. Backend: Zip-Lookup Endpoint

Fájl: backend/app/api/v1/endpoints/system_parameters.py

  • Új GET /zip-lookup végpont a system parameters routerben
  • Paraméterek: country_code (default: "HU") és zip_code (kötelező)
  • Lekérdezi a system.geo_postal_codes táblát country_code + zip_code alapján
  • Visszaadja: {"city": "Budapest"} (200) vagy 404 ha nem található
  • Kritikus: A /zip-lookup route a /{key} catch-all route ELŐTT van regisztrálva, hogy ne a catch-all nyelje el
@router.get("/zip-lookup", response_model=Dict[str, Any])
async def zip_lookup(
    country_code: str = Query("HU", description="Országkód (pl. HU, AT, DE)"),
    zip_code: str = Query(..., min_length=1, description="Irányítószám"),
    db: AsyncSession = Depends(get_db),
):
    if not zip_code.strip():
        raise HTTPException(status_code=400, detail="zip_code is required")
    stmt = select(GeoPostalCode).where(
        and_(
            GeoPostalCode.country_code == country_code,
            GeoPostalCode.zip_code == zip_code.strip(),
        )
    ).limit(1)
    result = await db.execute(stmt)
    postal_code = result.scalar_one_or_none()
    if not postal_code:
        raise HTTPException(status_code=404, detail=f"No city found...")
    return {"city": postal_code.city}

Teljes URL: GET /api/v1/system/parameters/zip-lookup?country_code=HU&zip_code=1111

2. Frontend: CompleteKycView.vue - Internal API

Fájl: frontend/src/views/CompleteKycView.vue

  • Külső https://api.zippopotam.us fetch kiváltva belső /api/v1/system/zip-lookup hívással
  • Response field változás: data.places[0]['place name']data.city

3. Frontend: ProfileView.vue - Debounced Zip Lookup

Fájl: frontend/src/views/ProfileView.vue

  • watch() a editForm.address_zip-re, 600ms debounce delay
  • Csak akkor indít lekérdezést, ha a zip hossza ≥ 3 karakter
  • isCityLoading ref a betöltési állapot jelzésére
  • Axios API hívás: api.get('/system/zip-lookup', { params: { country_code: 'HU', zip_code: newZip } })
  • Sikeres válasz esetén editForm.address_city auto-fill

4. identity_docs Payload Verifikáció

  • Frontend ProfileView.vue: buildIdentityDocsPayload() (636-663. sor) helyesen építi az ID_CARD + LICENSE struktúrát
  • savePerson() (665-701. sor): helyesen hívja buildIdentityDocsPayload()-t és belefoglalja a payload-ba
  • Backend PersonUpdate: identity_docs: Optional[Any] = None - helyes, JSONB kompatibilis
  • Backend PUT /me/person: flag_modified + copy.deepcopy már implementálva (#207)
  • Read mód display: identityDocs?.ID_CARD?.number pattern helyes

📊 Érintett Fájlok

🧪 Tesztelési Eredmény

  1. Backend zip-lookup endpoint működik: 1111{"city": "Budapest"} (200)
  2. Ismeretlen irányítószám: 404 hibakód megfelelő üzenettel
  3. Frontend CompleteKycView belső API-t használ
  4. Frontend ProfileView debounced zip lookup implementálva
  5. identity_docs payload már helyesen működik (nem kellett javítás)

🔗 Gitea

  • Issue: #208 - Internal Zip Lookup & Identity Docs Payload Fix
  • Státusz: Completed