# SPEC-COVERAGE-A6A7A8A9 — Phase 2C spec-fedés a Beállítás-ágra

**Dátum.** 2026.05.25 · **Phase.** 2C (folyamatban — Batch 1 lezárva)
**Hatókör.** A6 Kategóriák (`/beallitasok/kategoriak`) + A7 Csoportok (lista + adatlap) + A8 Felhasználók (lista + adatlap) + A9 Általános (`/beallitasok/altalanos`)
**Forrás.** `uploads/urbino-docs/00_domain_model.md` §2 (`Category`, `Group`, `TenantUser`, `WeeklyReportRecipient`) + §3 (`User`, `Tenant`, `UserTenantRole`, `UserInvitation`, `DefaultCategoryCatalog`) + `20_admin_felulet/30_beallitasok.md` (teljes) + `20_admin_felulet/20_felhasznalokezeles.md` (teljes).
**Screen-mock-ok.** `manager-system/preview/screens/a6-beallitasok-kategoriak.html` · `a7-beallitasok-csoportok-lista.html` · `a7-beallitasok-csoportok-adatlap.html` · `a8-beallitasok-felhasznalok-lista.html` · `a8-beallitasok-felhasznalok-adatlap.html` · `a9-beallitasok-altalanos.html`

> **Módszertan.** Forward pass (spec → screen, mező-szinten) + backward pass (screen → spec, UI-elemenként). A mock-doksi-réteg (`screen-header`, `DesignCanvas`, `DCArtboard` label, `State<X>` komponens, modal-frame-backdrop blur a Tier-3-stílusban) a backward-pass-on **kizárva** (`SCREEN-CONVENTIONS.md` §5). Az **AUDIT-2 §3.3 inline-organism-pótlások** (A7 `MemberRow` + `.a7d-picker` inline vs. kanonikus `GroupMemberList` + `UserPicker`; A8 `InviteCta` statikus button vs. `UserInviteDialog` modal) **NEM UI-találmányok**: kanonikus organism létezik, a screen-fájl mock-szintű kényelmes-pótlással szállítja — a HANDOFF.md-ben átadási megjegyzések, a backward-pass a kanonikus API-ra mappel.
>
> **4 lista.** ✅ Spec + screen-en megvan · ⚠ Spec-ben van, screen-en nincs (hiányosság) · 🟡 Screen-en van, spec-ben nincs, DE D-X rögzíti (NEM UI-találmány) · 🔍 Screen-en van, spec-ben nincs, NEM dokumentált (UI-találmány). A `⚠` és `🔍` tételek **külön** szerepelnek a `SPEC-FEEDBACK.md` `## A6+A7+A8+A9 spec-szelídítések` ági-fejezetében (SF-33-tól).

---

## Batch-térkép

| Batch | Tartalom | Mezők / elemek | Státusz |
|---|---|---|---|
| **1** | A6 Kategóriák (`/beallitasok/kategoriak`) — `Category` 7 mező + 2 denorm + `DefaultCategoryCatalog` 4 mező + `30` §3.1 5 eltérés + 2 új végpont + §4.2 UI-szerződés + D-8 (C-1..C-4) | 17 mező / végpont + 13 UI-blokk | **✓ lezárva** |
| **2** | A7 Csoportok (lista 3 állapot + adatlap 4 állapot) — `Group` 4 mező + denorm `memberCount` + `30` §3.2 + §4.3 + D-10 | 14 mező / végpont + 18 UI-blokk | **✓ lezárva** |
| **3** | A8 Felhasználók (lista 4 állapot + adatlap 5 állapot) — `User` 5 mező + `UserTenantRole` 4 mező + `UserInvitation` 7 mező + `TenantUser` §2.3 SD-37 + `20_felhasznalokezeles` §3 + §4.2-4.3 + D-9 + SD-38 | 24 mező / végpont + 28 UI-blokk | **✓ lezárva** |
| **4** | A9 Általános (`/beallitasok/altalanos`) — `Tenant` 11 mező (4 új SD-58) + `WeeklyReportRecipient` 4 mező + `30` §3.3 3 alszekció + §4.4 + D-11 | 19 mező / végpont + 16 UI-blokk | **✓ lezárva** |

**Forrás-volument.** Phase 2C a Beállítás-ág, **3 spec-dokumentum** (1 közös: `00_domain_model` §2+§3 entitások; 2 ági: `30_beallitasok` + `20_felhasznalokezeles`) + **10 SD spec-döntés** (`SD-36..38` user-management + `SD-58..67` settings) + **6 D-X manager-system döntés** (`D-8..D-11` ági iter + `D-14` settings-nav). **44 + 33 = 77 acceptance criterion**.

A Beállítás-ág **spec-prescriptív** (a `30_beallitasok` v1.0 és `20_felhasznalokezeles` v1.0 mezőszinten és viselkedés-szinten egyaránt szigorú), a UI-találmány-kategória így **arányosan szűkebb** mint az A1 (Bejelentés-ág).

---

# Batch 1 — A6 Kategóriák

**Spec-fedés.** `30_beallitasok` §3.1 (5 eltérés a `BaseController`-mintától + 2 új végpont) + §4.2 (`/beallitasok/kategoriak` UI-szerződés 7 alszekció) + **D-8** (C-1A drag-drop · C-2A inline IconPicker-popover · C-3B preview-kártyás default-import · C-4A always-visible row-akciók).

**Screen.** `a6-beallitasok-kategoriak.html` — 4 állapot (1 Normál · 2 First-time empty · 3 Import-dialog overlay · 4 Hide-inactive).

**Organism-szerződés.** `CategoryTreeEditor` (saját `mgr-cat__toolbar` toolbar + csoportosított `RootSection`-ok + `CategoryRow`-k inline-edit + IconPicker popover-rel) + `CategoryImportDialog` + `IconPicker` + `iconGlyph` helper. Az organism saját H2-címet ("Kategóriák") és stats-sort ("N gyökér · M alkategória") jelenít meg a toolbarban, plus az "Új gyökér" elsődleges CTA-t **a toolbarba olvasztva** (nem PageHeader-actions slotba — lásd 🔍 SF-36).

---

## Forward pass — `Category` 7+2+1 mező + `DefaultCategoryCatalog` 4 mező + §3.1 6 végpont + §4.2 UI-szerződés

### ✅ Spec-ben + screen-en is megvan

| Spec-mező / végpont / UI-blokk | Spec-forrás | Screen-evidence |
|---|---|---|
| `Category.id` | `00_domain_model` §2.1 | A6 `CATS_FULL[*].id` (1..32); `CategoryRow data-cat-id={cat.id}`. |
| `Category.parentId` (self-FK, kétszintű fa) | `00_domain_model` §2.1 + K-036 | A6 `CATS_FULL` 4 root (`parentId: null`) + 7 alkategória (`parentId: 1|2|3`); `groupTree()` helper a `category-tree-editor.jsx:46` szétválaszt — gyökér-szekciók + alkategória-sorok. |
| `Category.name` (max 100, inline-szerk. K-026) | `00_domain_model` §2.1 + `30` §4.2.3 + §4.2.7 mezősablon | `CategoryRow` `editingName` state + Enter ment / Esc megszakít (`handleNameKey`) + `commitName` trim-és-not-empty validáció. |
| `Category.iconRef` (közös ikonkészlet kulcsa) | `00_domain_model` §2.1 + NY-3 | `iconGlyph(cat.iconRef)` feloldás; az ikon-cella interaktív (inline IconPicker-popover D-8 C-2A). |
| `Category.isActive` (toggle azonnali, default `true`) | `00_domain_model` §2.1 + `30` §4.2.3 | `mgr-cat__toggle` 2-állapotú switch a sor jobb-szélén + a gyökér-fejlécen; State 1 mock-on 1 inaktív gyökér (`Hulladék`) + 1 inaktív alkategória (`megsüllyedés`) `mgr-cat__row--inactive` modifier + "Inaktív" tag. |
| `Category.sortOrder` szülő-hatókörben (SD-64) | `00_domain_model` §2.1 + `30` §3.1.8 SD-64 + D-8 C-1A | `mgr-cat__grip` ⋮⋮ drag-handle minden alkategória-sorban (gyökér-sorrendezés a header-level felett — implicit a `groupTree()` `sortOrder ASC` rendezésén). |
| `Category.sourceCatalogId` "Default" badge **gyökér-szinten** | `00_domain_model` §2.1 (SD-8 termékesített) + `30` §4.2.2 "Forrás: Termékesített / Tenant-egyedi badge" | `RootSection.mgr-cat__root-tag "Default"` minden `sourceCatalogId != null` gyökérnél. A4 mock 4 gyökerét mind termékesítettnek jelöli. *(NB. Alkategória-szinten hiányzik — lásd ⚠ SF-37.)* |
| `Category.ticketCount` (denorm, nyitott `Ticket`-ek) | `30` §3.1.1 "denormalizált aggregátum-mező" | `mgr-cat__count` (alkategória-soron) + `mgr-cat__root-count` "X ügy" (gyökér-fejlécen). Mock-értékek: 23, 11, 7, 0 (gyökerek) és 18, 5, 0, 8, 3, 4, 3 (alkategóriák). |
| `Category.hasActiveChildren` (denorm, csak gyökérnél) | `30` §3.1.1 | A4 mock-data hordozza `CATS_FULL[*].hasActiveChildren`-t, de a screen-mock **csak implicit**, a `groupTree()` ezt a fa-szerkezetből származtatja; explicit UI-jelölést nem rajzol. *(Részleges fedés — lásd 🟡 #1.)* |
| `POST /v1/categories/from-default` (SD-62) | `30` §3.1.4 | State 3 ImportDialog overlay — a `CategoryImportDialog` fogyasztja a `availableRoots` propot, a confirm-gomb feliratáig (D-8 C-3B *"Parkok és zöldterületek importálása"* literal-konvenció). |
| `GET /v1/categories/available-default-roots` (SD-62, cross-DB) | `30` §3.1.5 | State 3 mock `AVAILABLE_DEFAULT_ROOTS` 4 entry (`{defaultCategoryId, name, iconRef, children: []}`). A `children` mező a chip-előnézethez, a `childCount` denormalizált a spec szerint a `children.length`-ből származik. |
| `POST /v1/categories/reorder` szülő-hatókörben (SD-64) | `30` §3.1.8 | Drag-handle `IconGrip` minden alkategória-soron — vizuális affordancia; az `onReorder({parentId, orderedIds})` szignatúra a `category-tree-editor.jsx:53` props-szerződésén. |
| `AvailableDefaultRootDto.defaultCategoryId` | `30` §3.1.5 | `AVAILABLE_DEFAULT_ROOTS[*].defaultCategoryId` (105, 106, 107, 108) — az importDialog confirm-payload key-je. |
| `AvailableDefaultRootDto.name` | `30` §3.1.5 | "Parkok és zöldterületek", "Vízkár és csapadék", "Veszélyhelyzet", "Egyéb". |
| `AvailableDefaultRootDto.iconRef` | `30` §3.1.5 | `'tree'`, `'droplet'`, `'warning'`, `'box'` — a CategoryImportDialog preview-kártya ikonjához. |
| `AvailableDefaultRootDto.childCount` ("ezzel együtt N alkategóriát is importálsz") | `30` §3.1.5 | A mock `children` tömb `.length` (4, 3, 3, 0). Az "Egyéb" 0-darab esete: az importDialog kártyája "Még nincs alkategóriája"-szerű hint-szöveget mutat (a `CategoryImportDialog` organism implementációjából). |
| §4.2.1 csoportosított fa-lista (gyökér mint csoport-fejléc, alkategóriák alatta) | `30` §4.2.1 | `RootSection` → `mgr-cat__group` szekciók; D-8 csoportosított struktúra a lapos-`parentId`-behúzott helyett. |
| §4.2.2 "Új gyökér-kategória" gomb | `30` §4.2.2 | `mgr-cat__toolbar` `Új gyökér` button (`u-btn--primary`) `onClick={onOpenImport}`. *(Pozíció — lásd 🔍 SF-36: organism-toolbar vs. PageHeader-actions.)* |
| §4.2.2 "Új alkategória" gomb minden gyökér-csoport fejlécén | `30` §4.2.2 | `RootSection.mgr-cat__root-actions` `+alkategória` button + a children-lista végén "+ Új alkategória „{root.name}" alatt" duplikált CTA. |
| §4.2.2 bulk-műveletek nincsenek | `30` §4.2.2 "Bulk-műveletek: nincsenek" | A `CategoryRow` nem rajzol sor-checkbox-ot. Konzisztens a `20_felhasznalokezeles` 4.2 megegyező döntésével. |
| §4.2.3 inline `name` K-026 minta (Enter/Esc, optimistikus) | `30` §4.2.3 + K-026 | `CategoryRow.handleNameKey` Enter→`commitName`, Esc→reset+exit. Click-to-edit a `.mgr-cat__name`-en. |
| §4.2.3 `isActive` toggle azonnali, optimistikus | `30` §4.2.3 | `mgr-cat__toggle` `aria-pressed={cat.isActive}` + `onUpdate({id, patch: {isActive: !cat.isActive}})` minden klikk-en. |
| §4.2.4 default-import dialog magyarázó intro + lista + Importálás + Mégse | `30` §4.2.4 | State 3 ImportDialog overlay; a `CategoryImportDialog` organism a 4-pontos spec-listát rendereli (magyarázat → lista → Importálás → Mégse) D-8 C-3B preview-kártyás layout-tal. |
| §4.2.6 inaktív kategóriák `opacity` halványítás + "inaktív" badge | `30` §4.2.6 | `mgr-cat__row--inactive` (CSS `opacity: 0.55`-tel) + `mgr-cat__inactive-tag "Inaktív"` minden inaktív soron, mind State 1, 3, 4-en helyesen kezelve. State 4 `showInactive=false`-szal az inaktívak teljesen elrejtődnek. |
| §4.2.6 "Inaktív kategóriák mutatása" lista-szintű toggle (alapesetben be) | `30` §4.2.6 | `mgr-cat__toolbar-toggle` checkbox `Inaktívak mutatása` + `onToggleShowInactive` callback. State 1+3 `showInactive=true`, State 2+4 `showInactive=false`. |
| §4.5.2 empty-állapot literal-szöveg | `30` §4.5.2 *"Még nincs kategória ezen a tenanton. Importálj gyökér-kategóriákat a 'Új gyökér-kategória' gombbal."* | State 2 `CategoryTreeEditor` empty-fallback: *"Még nincs kategória."* + *"Az „Új gyökér" gombbal importálj egyet a default-katalógusból."* — **a literal-megfogalmazás eltér, de az ekvivalens-szándék helyes** (a spec-szövegnek a "vedd fel a kapcsolatot Urbino"-vetülete az importDialog magyarázó-szövegben szerepel). |

### ⚠ Spec-ben van, screen-en nincs — hiányosság

#### ⚠ #1 — `POST /v1/categories` alkategória-create + §4.2.5 form-state nincs mockolva
- **Spec.** `30` §3.1.3 `POST /v1/categories` (csak alkategóriára, `parentId` kötelezően gyökér) + §4.2.5 *"Új alkategória — modal-űrlap. Mezők: Név (kötelező, max 100), Ikon (opcionális — ikon-választó UI). A `parentId` kontextusból, nem szerkeszthető."* A `[validationForm]`-minta szerver-oldali field-error-megjelenítéssel.
- **Screen.** A4 organism rajzol KÉT "+alkategória" affordance-t (a `RootSection` header `u-btn--secondary` + a children-lista végén a `mgr-cat__add-row` button), de **a tényleges form-megnyitott állapot egyik artboard-on sem renderelt** — mindkét button no-op `onCreate({parentId: pid})`-et hív paraméter nélkül. Sem modal-overlay, sem inline-textbox-state nincs.
- **Hatás.** A fejlesztő nem látja, milyen UI-mintával nyílik a create-form (modal a spec szerint, vagy inline-add-row a D-8 implicit elvével). Nyitott UX-választás — lásd 🔍 SF-37.
- **Döntés.** **HANDOFF.md átadási megjegyzés**: a create-form-megjelenítési minta UX-választást igényel a Phase 3 előtt (lásd SF-37 spec-szelídítés-javaslat).

#### ⚠ #2 — `DELETE /v1/categories/{id}` + `category_referenced` delete-guard + kebab-menü 409-confirm-dialog nincs mockolva
- **Spec.** `30` §3.1.7 SD-63 — *"a guard ellenőrzi a `Ticket`-hivatkozásokat és a leszármazott-fát; ha bármelyik igaz → `409 category_referenced`, a `details` mezővel: `directTicketCount`, `descendantsWithTickets[]`"*. §4.2.2 *"Törlés (rejtett, másodlagosan; megerősítő-dialógussal a delete-guard-eredménnyel)"*. AC-K6.1-K6.4 4 acceptance criterion erre épül.
- **Screen.** A `CategoryRow.mgr-cat__row-actions` 3 always-visible gombot rajzol (toggle + ceruza + `IconKebab`), de a **kebab-popover sem megnyitva, sem zárva** nincs külön state-ként reprezentálva. A `onKebabClick` handler is `() => {}` no-op (`category-tree-editor.jsx:268`). A delete-guard 409-confirm-dialog **vizuálisan teljesen hiányzik**.
- **Hatás.** A fejlesztő a `ConfirmDialog` `kind="danger"` body-variantját nem látja az A6-kontextusban (a `details.directTicketCount` magyar-szöveggé alakítása + a `details.descendantsWithTickets[]` lista). Az AC-K6 4 kritérium UI-tükre hiányzik.
- **Döntés.** **JAVÍTANDÓ** (mock-szinten): új 5. artboard `StateDeleteGuardConfirm` a kebab-megnyitott állapottal (Szerkesztés / Sorrend / Törlés popover-tételek) + `ConfirmDialog` `kind="danger"` egy konkrét delete-guard-eredménnyel (pl. "Utak és járdák" → `directTicketCount=23, descendantsWithTickets=[{name: 'kátyú', ticketCount: 18}, {name: 'járdaszint', ticketCount: 5}]`). **SPEC-FEEDBACK SF-33** (mock-korrekció).

#### ⚠ #3 — ImportDialog "minden importálva" üres-állapot nincs artboardja (`30` §4.2.4)
- **Spec.** `30` §4.2.4 *"Üres állapot (ha minden importálva van): 'Minden gyökér-kategória már importálva van. Az alkategóriák szabadon kezelhetők a gyökerek alatt.'"*
- **Screen.** State 3 ImportDialog 4-darab `AVAILABLE_DEFAULT_ROOTS`-szal nyitja (non-empty); a `availableRoots=[]` empty-eset nincs külön artboard-on.
- **Döntés.** **MOCK-KIEGÉSZÍTÉS** — vagy egy 6. artboard `StateImportEmpty` (ImportDialog `availableRoots=[]` + literal-konform empty-szöveg), vagy a State 3 mock-data redukálva 0-elemre. Alacsony prioritás (pilot-élmény). **SPEC-FEEDBACK SF-33** részeként konszolidálva (mock-state-hiány klaszter).

#### ⚠ #4 — IconPicker megnyitott popover-állapot nincs külön artboardon
- **Spec.** `30` §4.2.7 mezősablon Ikon "Interakció: ikon-választó UI"; D-8 C-2A explicit "inline popover, az ikon-cella maga interaktív, kattintásra a sor alatt ~280px-es 6×N paletta nyílik".
- **Screen.** A `CategoryRow` rajzolja az `IconPicker` JSX-t feltételesen (`iconPickerOpen && <IconPicker ... />`), és a `CategoryTreeEditor` `iconPickerOpenForId` state-tel kezeli a megnyitás-állapotot, **DE egyetlen artboardon sem aktiválja** — mind a 4 state-ben `iconPickerOpenForId === null` az indító-állapot.
- **Döntés.** **MOCK-KIEGÉSZÍTÉS** — egy 5/6. artboardon az `<App initialState>`-szerű hookkal `iconPickerOpenForId={11}` (pl. a "kátyú" alkategória ikon-popoverje nyitva) demonstrálni. Alacsony prioritás. **SPEC-FEEDBACK SF-33** részeként.

#### ⚠ #5 — `Category.sourceCatalogId` "Tenant-egyedi" badge **az alkategória-soron** hiányzik
- **Spec.** `30` §4.2.2 *"Forrás | `Category.sourceCatalogId != null` | Badge: 'Termékesített' / 'Tenant-egyedi'"* — a táblázat alkategóriákat is fed (a kétféle badge értelme: a default-katalógusból másolt vs. a tenant-vezető hozzáadott).
- **Screen.** `RootSection.mgr-cat__root-tag "Default"` csak a **gyökér**-szinten jelenik meg `sourceCatalogId != null` esetén. A `CategoryRow` (alkategória) NEM rajzol "Tenant-egyedi" vagy "Termékesített" badge-et — sem ha a mock-adat `sourceCatalogId: null` (tenant-egyedi alkategória, ami a State 1 mock 7-ből 7 eset), sem ha 'mégis nem nullával jönne.
- **Hatás.** A vezető az alkategória-szinten nem tudja vizuálisan szétválasztani a default-import során bejött vs. a saját kezűleg felvett alkategóriát. A pilot-volumenen ez minor, mert az alkategóriák tipikusan tenant-egyediek (a mock 7 alkategóriájából 7 `sourceCatalogId: null`). De az `from-default` import során a leszármazottak `sourceCatalogId` kitöltött lesz (a `30` §3.1.4 Workflow #3 explicit).
- **Döntés.** **MOCK-KIEGÉSZÍTÉS** — az alkategória-soron is "Default" / "Saját" tag-megjelenítés `sourceCatalogId`-szerinti differenciálással. **SPEC-FEEDBACK SF-34** (mock-korrekció + organism-bővítés).

### 🟡 Screen-en van, spec-ben nincs, DE D-X rögzíti

| Screen-elem | Hol jelenik meg | D-X hivatkozás |
|---|---|---|
| #1 `hasActiveChildren` mock-data hordozva, de UI-szintű explicit jelölés nincs | A6 `CATS_FULL[*].hasActiveChildren` mock-mező | Nincs D-X — a fa-megjelenítésben implicit. Spec §3.1.1 a DTO-szerződést rögzíti, de a UI-renderelést szabadon hagyja; a denormalizált aggregátum egy potenciális delete-guard-elővetítésre szolgálhatna. **Részleges fedés**, NEM hiányosság — a mező DTO-szerződésen jelen van, az Angular-portoláskor fogyasztható. |
| #2 Csoportosított fa-lista (gyökér mint szekció-fejléc) — lapos-`parentId`-behúzott helyett | `RootSection` → `mgr-cat__group` | **Spec §4.2.1 RÖGZÍTI** ("A csoportosított struktúrát választjuk") — valójában ✅, itt csak referenciálisan rögzítve mint **D-8 megerősítés** (a D-8 a spec-szerinti elvet implementálja, nem új UX-választás). |
| #3 Drag-handle ⋮⋮ a sor bal-szélén (`mgr-cat__grip` `IconGrip`) | `CategoryRow` | **D-8 C-1A** ("drag-and-drop fogantyúval; csak a szülő hatókörén belül engedi (SD-64)") |
| #4 Inline IconPicker popover az ikon-cellán (kattintásra a sor alatt) | `CategoryRow.mgr-cat__icon` button + feltételes `<IconPicker>` | **D-8 C-2A** ("inline popover. Az ikon-cella maga interaktív, kattintásra a sor alatt ~280px-es 6×N paletta nyílik. Outside-click + Escape zár.") |
| #5 Always-visible sor-akciók (toggle + ceruza + kebab) — NEM hover-revealed | `CategoryRow.mgr-cat__row-actions` 3 button | **D-8 C-4A** ("mindig látható. A toggle (isActive) fontos state-jelző, hovera-bujtatva elveszne.") |
| #6 ImportDialog preview-kártya layout — kártya / ikon / név / alkategória-chip-előnézet / "+ Importálás" konkrét gomb-felirattal | `CategoryImportDialog` (State 3) | **D-8 C-3B** ("preview-kártyák. Minden default-gyökér egy kártya, az alkategóriái chip-ekként előtte. ... 'Parkok és zöldterületek importálása' konkrét feedback.") |
| #7 Konkrét gomb-felirat ("{root.name} importálása") | `CategoryImportDialog` confirm-button | **D-8 C-3B** explicit említi |
| #8 "alkategória" inline-add affordance + szekció-header `+alkategória` gomb (kétszeresen) | `RootSection.mgr-cat__root-actions` + `mgr-cat__add-row` | **Részleges D-8 fedés** — az inline-add-affordance D-8 nem rögzíti explicit, de a C-2A inline-szerkesztés-minta szellemében konzisztens. A spec §4.2.5 ezzel szemben **modal**-űrlapot ír. **🔍 SF-37 inline-vs-modal döntés-konflikt** (lásd lent). |
| #9 `mgr-cat__empty` "Még nincs alkategória." minden üres gyökér-szekcióban | `RootSection` | **Pilot-élmény-bake-in D-8 alatt** — nem önálló D-szám, de a csoportosított-fa-modell természetes mellékterméke. Spec §4.5.2 az általános empty-állapotot fedi, az alkategória-szintűt nem említi. Konzisztens. |
| #10 Stats-sor a toolbarban ("4 gyökér · 7 alkategória") | `CategoryTreeEditor.mgr-cat__toolbar-stats` | **Nincs D-X — 🔍 határeset**, de pilot-élmény-szempontból ár-érték-arányos (egy pillantással látható a tenant kategória-mérete). **SF-35**-be olvasztva (lásd lent). |

### 🔍 Screen-en van, spec-ben nincs, NEM dokumentált — UI-találmány

#### 🔍 #1 — CategoryTreeEditor saját H2-cím "Kategóriák" + stats — PageHeader-duplikáció
- **Hol.** `CategoryTreeEditor.mgr-cat__toolbar` `<h2 className="mgr-cat__toolbar-title">Kategóriák</h2>` + `<div className="mgr-cat__toolbar-stats">4 gyökér · 7 alkategória</div>`.
- **Spec.** `30` §4.2 a `/beallitasok/kategoriak` PageHeader-szintű címét **a NavStore-pageHeader oldja meg** (§4.1: "Kategóriák" page-title `settings.categories.title`). A `CategoryTreeEditor` organism-toolbar **saját H2-szintű címet** rajzol — **duplikáció a PageHeader-cím mellett**.
- **Probléma.** Két "Kategóriák" cím egymás alatt 24-48px tipográfiai távolsággal, a vezető szempontjából redundáns (tudja, hogy ezen az oldalon van). A stats-sor önállóan értékes ("4 gyökér · 7 alkategória"), a redundáns "Kategóriák" cím nélkül is megáll.
- **Döntés.** **SPEC-FEEDBACK SF-35** (mock-korrekció + organism-bővítés) — a `CategoryTreeEditor.mgr-cat__toolbar-title` H2-cím törlése; a stats-sor önállóan, kisebb tipográfiával megmarad.

#### 🔍 #2 — "Új gyökér" CTA pozíció: organism-toolbar vs. PageHeader-actions (D-1 konvenció)
- **Hol.** `CategoryTreeEditor.mgr-cat__toolbar` jobb-szélén `u-btn--primary Új gyökér` button.
- **Spec.** `30` §4.2.2 a "Új gyökér-kategória" gombot lista-szintű akcióként rögzíti, **a pozíciót nem köti meg**. A `D-1` (Page-CTA helye — PageHeader, nem TopBar, 2026.05.21) konvenció szerint *"Minden screen-specifikus akció a cím mellett, jobbra"* a PageHeader-actions slotba. A A4 dashboard ("Heti riport letöltése"), A7 lista ("Új csoport"), A8 lista ("Új felhasználó"), A10/A11/A12 listák — **mind a PageHeader-actions slotban** hordozzák az elsődleges CTA-t.
- **Probléma.** Az A6 az **egyetlen kivétel**: az "Új gyökér" CTA az organism-toolbarba olvad. A vezető-szempontból ez **belső inkonzisztencia** — a Beállítás-ág 4 sub-page-ből 3 (A7/A8/A9) PageHeader-CTA-t használ, az A6 nem. Az `A6Screen.PageHeader.actions` slot a screen-fájl szintjén üres.
- **Döntés.** **SPEC-FEEDBACK SF-36** — két opció:
  - **(a) Pozíció-csere:** "Új gyökér" CTA a PageHeader-actions slotba; a `CategoryTreeEditor.mgr-cat__toolbar` csak az "Inaktívak mutatása" toggle-t + stats-sort tartja.
  - **(b) D-1 finomítás:** explicit kivétel-szabály ha az organism saját toolbar-relevante van.
- **Javasolt:** **(a)** — a manager-pattern-szintű konzisztencia fontosabb, mint az organism-self-contained-toolbar-elvonatkoztatás.

#### 🔍 #3 — A "+ Új alkategória „{root.name}" alatt" inline-add-row a children-lista végén (kettős "Új alkategória" CTA)
- **Hol.** `RootSection.mgr-cat__add-row` a `RootSection.mgr-cat__children` legutolsó elem után. **Plusz** a `RootSection.mgr-cat__root-actions`-ban egy `+alkategória` button — **két CTA ugyanarra a műveletre** szekciónként.
- **Spec.** `30` §4.2.2 a "Új alkategória" gombot **gyökerenként egyszer** rögzíti ("Új alkategória gomb minden gyökér-csoport fejlécén"). A duplikálás (header + lista-vég) UI-találmány.
- **Probléma.** Két azonos akció ugyanazon a szekción belül — kis vizuális zaj, **affordance-rendundancia**. A children-lista-vég CTA pedagógiailag jó (sok-alkategóriás csoportban a vezető nem kell felgörgessen a fejlécig), de a fejléc-szintű CTA is megvan.
- **Döntés.** **SPEC-FEEDBACK SF-37** (lásd lent) része — a "modal vs. inline-add-row vs. dupla-CTA" döntés-trióját egyetlen tételbe csoportosítva.

#### 🔍 #4 — `state` literal-szöveg-eltérés az empty-állapotban
- **Hol.** State 2 `CategoryTreeEditor` empty-fallback: *"Még nincs kategória." / "Az „Új gyökér" gombbal importálj egyet a default-katalógusból."*
- **Spec.** `30` §4.5.2 *"Még nincs kategória ezen a tenanton. Importálj gyökér-kategóriákat a 'Új gyökér-kategória' gombbal."*
- **Probléma.** Két különböző literal-megfogalmazás. A spec hosszabb és tartalmazza a "ezen a tenanton" + "kapcsolatba lépés Urbino-val" árnyalatot; az organism kondenzáltabb.
- **Hatás.** **Alacsony prioritás** — i18n-réteg kiegyenlíti, a `settings.categories.emptyState.*` kulcsok a `hu.json`-ban a spec-szöveget hordozhatják. A screen-mock idiómája az Angular-portolásra nem 1:1 leképezés.
- **Döntés.** **HANDOFF.md átadási megjegyzés** — az i18n-feloldás idejére a spec literal-szöveg legyen az autoritatív. Nincs külön SF-tétel.

---

## Backward pass — A6 UI-elemek osztályzata

A `CategoryTreeEditor` + `CategoryImportDialog` + `IconPicker` 3 organism, illetve a screen-fájl-szintű `A6Screen` shell minden UI-eleme. A mock-doksi-réteg (`screen-header`, `DCSection`, `DCArtboard`, `.a6-modal-frame__backdrop` blur-overlay-decoration) **kizárva**.

| UI-elem | Osztály | Megjegyzés |
|---|---|---|
| PageHeader title "Kategóriák" + description | ✅ | Spec §4.1 i18n-kulcs `settings.categories.title`. |
| AppShell `active="kategoriak"` + breadcrumb `['Beállítások', 'Kategóriák']` | ✅ | Spec §4.1 breadcrumb-konvenció + i18n `settings.nav.categories`. |
| `SettingsSubNav` (HIÁNYA) — D-14 Pattern N | 🟡 | **D-14** explicit elhagyja; a 6 settings-screen mind LeftNav 4-leaf navigációval él. Spec §4.1 "lenyíló almenü"-megfogalmazása D-14 felüldöntve. → **SPEC-FEEDBACK SF-38** (cross-cutting spec-szelídítés). |
| CategoryTreeEditor saját toolbar (H2-cím + stats + showInactive toggle + Új gyökér gomb) | 🔍 (3 sub-tétel) | H2-cím duplikál PageHeader-t (SF-35); stats megmarad, OK; toggle ✅; CTA pozíció (SF-36). |
| Csoportosított fa-szekciók (gyökerenként) | ✅ | Spec §4.2.1 rögzíti. |
| Gyökér-fejléc (ikon + név + "X ügy" + "Default" badge + toggle + +alkategória) | ✅ | Spec §4.2.2 mind a 6 elemet rögzíti. |
| Alkategória-sor (drag-grip + ikon-button + név + ticketCount + inaktív-tag + toggle + ceruza + kebab) | ✅ (7/8) + ⚠ #5 | A "Tenant-egyedi/Termékesített" Forrás-badge alkategória-szinten hiányzik (SF-34). |
| Inline `name` szerkeszthetőség K-026 mintával | ✅ | Spec §4.2.3, AC-K5.1+K5.5. |
| Inline IconPicker popover | 🟡 | D-8 C-2A. |
| `mgr-cat__empty` "Még nincs alkategória." üres gyökerek alatt | 🟡 | D-8 pilot-élmény. |
| Inline-add row + gyökér-header +alkategória gomb (kettős CTA) | 🟡 + 🔍 | D-8 implicit inline-add szellemében, de a §4.2.5 modal-előírással ütközik (SF-37) + dupla-CTA önmagában is UI-találmány (SF-37 része). |
| CategoryImportDialog preview-kártya layout | 🟡 | D-8 C-3B. |
| State 1 "Default" badge a gyökereken | ✅ | Spec §4.2.2 Forrás-oszlop. |
| State 2 empty-állapot szöveg-eltérés a spec §4.5.2-től | (info) | HANDOFF i18n-megjegyzés, nincs külön SF. |
| State 3 `.a6-modal-frame__backdrop` blur-overlay | (mock-doksi, kizárva) | Tier-1 `ConfirmDialog` overlay-mintát követi; backdrop blur a Tier-3 minta-szellemén. |
| State 4 `showInactive=false` minden inaktív sor + gyökér elrejtve | ✅ | Spec §4.2.6. |

---

## Batch 1 — záró összegzés

**Számok.** 17 spec-mező/végpont + 13 UI-blokk vizsgálva — **27 ✅** · **5 ⚠** (mind hiányzó-mock-state vagy badge-hiány) · **10 🟡** (D-8 négy döntés + spec-megerősítések) · **4 🔍** (toolbar-H2-duplikáció, Új gyökér CTA-pozíció, kettős-alkategória-CTA, empty-szöveg-eltérés).

**SF-tételek a Batch 1-ből.** 6 SF-tétel a `SPEC-FEEDBACK.md`-be:

| # | Tétel | Kategória | Súly |
|---|---|---|---|
| SF-33 | A6 mock-state-hiány klaszter (delete-guard kebab + 409-confirm, ImportDialog empty, IconPicker megnyitva, alkategória-create form) | ⚠ mock-state-pótlás | közepes |
| SF-34 | A6 alkategória-soron "Tenant-egyedi/Termékesített" Forrás-badge hiánya | ⚠ mock-korrekció + organism-bővítés | alacsony |
| SF-35 | A6 `CategoryTreeEditor` toolbar saját H2-cím "Kategóriák" — PageHeader-duplikáció | 🔍 mock-korrekció (organism) | közepes |
| SF-36 | A6 "Új gyökér" CTA pozíció — organism-toolbar vs. PageHeader-actions (D-1 konvenció megerősítés) | 🔍 mock-korrekció + organism-bővítés | közepes |
| SF-37 | A6 §4.2.5 modal-form vs. screen inline-add-row vs. kettős-CTA-redundancia — spec-szelídítés | 🔍 spec-szelídítés-javaslat | közepes |
| SF-38 | **Cross-cutting** — D-14 Settings-nav Pattern N vs. spec §4.1 "lenyíló almenü" — spec-szelídítés (érvényes mind a 6 A6/A7/A8/A9 screenre) | 🟡 → spec-szelídítés | **közepes** |

**Vártan-konzisztens** a Phase 2A/2B mintával: a spec-prescriptív Beállítás-ág arányosan kevesebb 🔍 UI-találmányt termel, mint az A1 (Bejelentés-ág) vagy az A4 (Dashboard); a hiányosságok többsége **mock-state-pótlás** jellegű (4 unmocked workflow-state a §3.1 + §3.7 CRUD-flow-ból).

---

# Batch 2 — A7 Csoportok

**Spec-fedés.** `30_beallitasok` §3.2 (standard `BaseController` CRUD + `[ManyToManyConnection]` denorm taglista + `group_referenced` delete-guard, SD-65) + §4.3 (lista `TableStateConfig` + adatlap inline-szekciók) + **D-10** (G-1A inline-szekciók A8-konzisztens · G-2A row-lista tag · G-3A inline autocomplete · G-4A direct remove + undo-toast).

**Screen.**
- `a7-beallitasok-csoportok-lista.html` — 3 állapot (1 All / 2 Filtered 4+ fő / 3 First-time empty)
- `a7-beallitasok-csoportok-adatlap.html` — 4 állapot (1 ReadMode / 2 EditingMembers + undo-toast / 3 EditingBasic / 4 EmptyMembers)

**Organism-szerződés.** **A kanonikus `GroupMemberList` (+ beágyazott `UserPicker`) organism az AUDIT-2 §3.3 inline-organism-pótlás miatt NEM közvetlenül fogyasztott** — a screen-fájl saját inline `MemberRow`-t (`a7d-mrow*`) + `.a7d-picker` blokkot renderel. **A backward-pass a kanonikus organism-API-ra mappel** (nem UI-találmányként kezeli), a HANDOFF.md-ben átadási megjegyzés. Common organism-fogyasztások (`AppShell` + `PageHeader` + `FilterPillBar` + `DataTable`) standard.

---

## Forward pass — `Group` 4 mező + denorm-DTO-mezok + §3.2 5 végpont + §4.3 UI-szerződés

### ✅ Spec-ben + screen-en is megvan

| Spec-mező / végpont / UI-blokk | Spec-forrás | Screen-evidence |
|---|---|---|
| `Group.id` | `00_domain_model` §2.2 | A7-lista `GROUPS[*].id` (1-5); a sor-key + `onRowClick` paraméter. |
| `Group.name` (max 100) | `00_domain_model` §2.2 + §4.3.1 oszlop-katalógus | `NameCell.a7-gn__title` (lista) + `GroupHead.a7d-head__name` (adatlap, 22px Display-font); az `EditingBasic` állapotban `<input>` editable. |
| `Group.members` (n-n `↔ TenantUser`, `[ManyToManyConnection]`) | `00_domain_model` §2.2 + `30` §3.2.2 `tenantUserIds` + denorm `members[]` | Lista: `MembersCell.a7-stack` 3-avatar overlap + "+N" / "N tag" badge; adatlap `MEMBERS[*]` 4 row read-mode + edit-mode remove-X. |
| `GroupListDto.memberCount` (denorm) | `30` §3.2.1 "denormalizált aggregátum-mező" | `row.count` mock-mező + a `MembersCell` "+N tag" / "N tag" pill. AC-G1.1 teljesítve. |
| `GroupDto.members[]` denorm display DTO `{id, displayName, status, roles}` | `30` §3.2.2 "Eltérés a mintától — denormalizált `members` lista" | Adatlap `MEMBERS[*]` 4 mezős (`id`, `name`, `initials`, `email`, `role`) — `id`+`displayName` ✅, `roles` ✅ (`role: 'Terepi dolgozó'/'Diszpécser'` magyar-vetület), **`status` HIÁNYZIK** (lásd ⚠ #2). |
| `AuditableEntity.createdAt` + `createdBy` | `00_domain_model` §2.2 + `01_kozos_mintak` 7.1 | Lista: `Létrehozva` oszlop ("2026.02.14") + `Létrehozta` oszlop ("Tóth Béla" / "Kovács Anna" — extra spec-szerinti oszlop, lásd 🔍 #2). Adatlap: GroupHead.sub + "Létrehozta" Alapadatok-grid-sor. |
| §4.3.1 oszlop `Név` (str, sortable) | `30` §4.3.1 | `columns[0]` `sortable: true`, `defaultSortDir: 'asc'`; `NameCell` icon + name. |
| §4.3.1 oszlop `Tagok száma` (denorm, sortable) | `30` §4.3.1 | `columns[1]` `sortable: true`, `defaultSortDir: 'desc'`; `MembersCell` avatar-stack-tel. |
| §4.3.1 oszlop `Létrehozva` (datetime, sortable, tenant-időzónában) | `30` §4.3.1 + SD-10 | `columns[3]` `sortable: true`, `defaultSortDir: 'desc'`; mono-formátum (`2026.02.14`) |
| §4.3.1 default rendezés `name ASC` | `30` §4.3.1 | A7-lista State1 + State3 `sortKey='name'`, `sortDir='asc'`. |
| §4.3.1 "Új csoport létrehozása" CTA | `30` §4.3.1 lista-szintű akció | `A7Screen.PageHeader.actions` `<NewGroupCta />` "Új csoport" gomb — D-1 konvenció szerint a PageHeader jobb-szélén (a Beállítás-ági konzisztencia, ellentétben az A6 SF-36-tal). |
| §4.3.1 bulk-műveletek nincsenek | `30` §4.3.1 "Bulk-műveletek: nincsenek" | A `DataTable` nem `selectable`; nincs sor-checkbox sem bulk-action-bar. |
| §4.3.2 adatlap Alapadatok szekció (név + audit) | `30` §4.3.2 | `Section title="Alapadatok"` Név + Létrehozta sorokat tartalmaz. |
| §4.3.2 adatlap Tagok szekció (multiselect chip + autocomplete + remove + üres) | `30` §4.3.2 | `Section title="Tagok"` count-badge + edit-mode-ban inline `MemberRow` remove-X + `.a7d-picker` autocomplete + empty-state amber dashed card. |
| §3.2.2 `GroupDto` egyetlen híváson rajzolható (denorm members) | `30` §3.2.2 "egyetlen hívással rajzolható" | A `GroupDetailPage` mock egy mock-objektumból (`GROUP` + `MEMBERS`) rajzol — ekvivalens. |
| §3.2.3 `tenantUserIds` validáció: csak Active TenantUser | `30` §3.2.3 + AC-G2.3 | `.a7d-picker__hint` "Csak **Aktív** felhasználók szerepelhetnek. Meghívva-állapotúak az aktiválás után válnak választhatóvá." — **literal-konform a spec-szabállyal**. |
| §3.2 + AC-G4.2 reorder NEM elérhető (`Group.sortOrder` nincs) | `30` §3.2.5 | Az `A7Screen` lista nem rendereli a drag-handle-t; default `name ASC` rendezés. |
| §4.5.2 lista empty-állapot literal: "Még nincs csoport. Hozz létre egyet..." | `30` §4.5.2 | State 3 First-time empty: "Még nincs egy csoport sem." + magyarázat + "Első csoport létrehozása" gomb — **eszmei-konform a spec literal-tal**, részletesebben pedagogikus (lásd 🔍 #4). |
| §4.3.2 csoporttagság olvasásra a felhasználó-adatlapon (`20_felhasznalokezeles` §4.3 hivatkozással) | `30` §4.3.3 | Az A7 adatlap **NEM tartalmaz felhasználó-adatlap-link-vetületet**; az A8 felhasználó-adatlap rendereli olvasásra (Batch 3 fed). Itt szabványkonform. |
| D-13 DataTable contract: `sortable` + `onRowClick` + `onSortChange` + `rowClassName` | DECISIONS D-13 + `ORGANISMS.md` §3 DataTable | Lista mind a 4 oszlop `sortable: true`, `onSortChange={() => {}}`, `onRowClick={() => {}}` — kanonikus D-13 API. |

### ⚠ Spec-ben van, screen-en nincs — hiányosság

#### ⚠ #1 — `Group.isActive` oszlop a listán HIÁNYZIK
- **Spec.** `30_beallitasok.md` §4.3.1 oszlop-katalógus: *"`Aktív` | `GroupListDto.isActive` | igen (kapcsoló) | igen | 'Aktív' / 'Inaktív' badge"*. AC-G4.2 explicit: *"`Ticket.assignedGroupId` egy deaktivált `Group`-ra ... a felelős-mező az inaktív csoport nevét mutatja, nem `null`-ra állítódik"* — implicit a lista-szintű state-megjelenítést.
- **Screen.** `columns` 4 oszloppal (`Csoport / Tagok / Létrehozta / Létrehozva`) — az `Aktív` oszlop **kihagyva**. A mock-data is csak feltételezi az `isActive: true` állapotot az összes 5 csoporton (a `GROUPS[*]` rekord nem hordoz `isActive` mezőt!).
- **Hatás.** A vezető a listán nem látja, melyik csoport deaktivált; a `deaktiválás` row-akció (§4.3.1 "deaktiválás/reaktiválás") visszacsatolása vizuálisan hiányzik. Az AC-G4.1 + AC-G4.2 vizuális tükre hiányos.
- **Javaslat.** **Mock-korrekció + organism-bővítés** — új 5. column `Aktív` (`row.isActive`-ből, "Aktív" / "Inaktív" badge a `.u-chip--status` mintával) + a mock-data minden rekordra `isActive` boolean + legalább 1 inaktív csoport demonstratív mock-állapotban. **SPEC-FEEDBACK SF-39**.

#### ⚠ #2 — `GroupDto.members[*].status` (TenantUser-status) NEM jelenik meg a MemberRow-n
- **Spec.** `30_beallitasok.md` §3.2.2 GroupDto.members[] denorm-mezok: *"`[{id, displayName, status, roles}]` a `TenantUser`-ből"*. A status (UserStatus enum: `Active`/`Invited`/`Disabled`) a member-soron a tagság státusát közli — különösen az `Invited` (meghívva, még nem aktivált) state vizuális jelzéséhez.
- **Screen.** `MemberRow` (`a7-beallitasok-csoportok-adatlap.html:351-372`) 3 cellát rajzol (`a7d-mrow__user` avatar+név+email / `a7d-mrow__role` / `a7d-mrow__remove`); **`status` cellát/badge-et nem rendereli**. A 4 MOCK-MEMBER mind feltételezett `Active` (mock-data sem hordoz `status` mezőt).
- **Hatás.** Ha egy csoport tagja `Invited` (még nem aktivált), a vezető nem látja vizuálisan — a `30` §3.2.3 validációs szabály *"Invited / Disabled TenantUser nem rendelhető csoportba — `400`"* azt kizárja, de a meglévő tagok között `Invited` (meghívott, később aktivált) lehet. *(Megj.: a §3.2.3 szabály a hozzárendelés-időre szigorú; később a meglévő tag `Active` → `Invited` váltása nem fordul elő. A vizuális rés akkor lényeges, ha egy tag `Disabled` lesz közben.)*
- **Javaslat.** **Mock-korrekció + organism-bővítés** — a kanonikus `GroupMemberList` member-row-ra `status` badge (avatar-cellán színes pont vagy chip-suffix mintájával). **SPEC-FEEDBACK SF-40** (kombinálva az inline `MemberRow` AUDIT-2 retirement-jével).

#### ⚠ #3 — `DELETE /v1/groups/{id}` + `group_referenced` 409 delete-guard confirm-dialog nincs mockolva
- **Spec.** `30_beallitasok.md` §3.2.4 SD-63 lábjegyzete — *"a `Group`-spec `BeforeDeleteAsync`-ja ellenőrzi: ha van `Ticket`, ahol `assignedGroupId == {id}` → `409 group_referenced`"*. AC-G3.1.
- **Screen.** Az A7 adatlap rendereli a `a7d-danger` szekciót "Csoport törlése" gombbal + magyarázó szövegget *"A csoport eltávolítása nem érinti a tagok TenantUser-rekordjait, de a kiosztott bejelentések kapcsolata megszűnik"* — DE a tényleges 409-confirm-dialog (a `ConfirmDialog` `kind="danger"` body-pal, ahol a `Ticket`-hivatkozás-darabszám szerepel) **nincs külön artboardon**.
- **Hatás.** Az A6 SF-33 #2 mintájával **párhuzamos hiányosság** — két különálló settings-screenen a delete-guard 409-confirm-dialog vizuális tükre hiányzik.
- **Javaslat.** **Mock-state-pótlás** — új 5. artboard `StateDeleteGuardConfirm` a danger-zone klikkjére megnyíló `ConfirmDialog` `kind="danger"` body-pal: *"A 'Útkarbantartó csapat' csoporthoz 18 nyitott bejelentés van kiosztva. Először helyezd át a bejelentéseket más csoporthoz, vagy zárd le őket."* (literal-konform a §3.2.4 `group_referenced`-payload magyar-szöveggé alakításával). **SPEC-FEEDBACK SF-41** (A6 SF-33-mal és A7 itt + A8 deaktiválás-confirm-mal párhuzamos klaszter; mock-state-pótlás).

#### ⚠ #4 — `30` §4.3.2 modal-form vs. screen inline-szekció (D-10 G-1A explicit felüldöntés)
- **Spec.** `30_beallitasok.md` §4.3.2 — *"`name` olvasásra (a 'Szerkesztés' gomb modal-űrlapba nyit)"*.
- **Screen.** D-10 G-1A explicit *"inline-szekciók (A8-konzisztens)"* — felüldönti a spec modal-előírást a Beállítás-ági inline-pattern javára.
- **Hatás.** Ez **NEM ⚠**, hanem **🟡** — D-10 G-1A explicit dokumentált spec-felüldöntés. Itt csak a teljesség kedvéért szerepel a forward-pass-on; a backward-pass-ban a 🟡 cellában fed.
- **Javaslat.** **Spec-szelídítés** — `30_beallitasok.md` §4.3.2 modal-előírás *"inline-szekciók vagy modal-űrlap; A8-konzisztens inline preferált"*-ra változtatandó (analóg az SF-37 A6 §4.2.5 modal-szelídítéshez). **SPEC-FEEDBACK SF-42** (a spec-szövegek inline-tendencia-konszolidálása).

### 🟡 Screen-en van, spec-ben nincs, DE D-X rögzíti

| Screen-elem | Hol jelenik meg | D-X hivatkozás |
|---|---|---|
| #1 Adatlap 2 inline-szekció (Alapadatok + Tagok) — modal helyett | `Section` × 2 a `A7DetailScreen` | **D-10 G-1A** (A8-konzisztens inline-szekciók; §4.3.2 spec-felüldöntés — lásd SF-42) |
| #2 MemberRow row-lista layout (NEM chip-felhő, NEM 2-oszlopos rács) | `a7d-mrow` 3-oszlopos grid | **D-10 G-2A** (row-lista: avatar + név + szerepkör + remove-X) |
| #3 Inline UserPicker autocomplete dropdown | `.a7d-picker` (AUDIT-2 §3.3 inline-pótlás a kanonikus `UserPicker` helyett) | **D-10 G-3A** (inline autocomplete, NEM modal-választó-dialog) |
| #4 Tag remove + undo-toast (NEM ConfirmDialog) | `a7d-toast` "Horváth Pál eltávolítva" + Visszavonás-link | **D-10 G-4A** (direct remove + 5s undo-toast) |
| #5 Diakritika-érzéketlen kereső + "Csak Aktív felhasználók" hint | `.a7d-picker__input` + `.a7d-picker__hint` | **D-10 G-3A** (UserPicker design); **spec §3.2.3 + 4.3.2 RÖGZÍTI** az "Active TenantUser" szabályt, így valójában a hint része ✅ |
| #6 AUDIT-2 §3.3 inline-pótlások — `MemberRow` + `.a7d-picker` | A7-adatlap-fájl saját komponensek | **AUDIT-2 §3.3 explicit dokumentálva** — NEM UI-találmány, mock-szintű kényelmes-pótlás a kanonikus `GroupMemberList` + `UserPicker` helyett. HANDOFF.md átadási megjegyzés. |
| #7 Csoport-fejléc avatar (violet 56×56 initials) + "Aktív" status-chip (zöld pont) a fejlécben | `a7d-head__avatar` + `a7d-head__chip` | **D-10 + GroupHead-mintázat** (a Beállítás-ági adatlap-pattern: bal-szélen identitás-avatar + jobb-szélen status-chip; konzisztens az A8 user-detail-pattern-rel) |
| #8 Empty-members amber-dashed card "Vegyél fel legalább egy aktív felhasználót" | `a7d-empty-members` | **D-10 pilot-élmény** (analóg az A9 R-1A amber empty-card-hoz; spec §4.5.2 generikus üres-állapotot fed) |
| #9 Lista PageHeader-szintű "Új csoport" CTA pozíció | `A7Screen.PageHeader.actions` | **D-1 konvenció** (Page-CTA helye — PageHeader, nem TopBar) — Beállítás-ági konzisztencia. Spec §4.3.1 a pozíciót nem köti, D-1 szabványosítja. |

### 🔍 Screen-en van, spec-ben nincs, NEM dokumentált — UI-találmány

#### 🔍 #1 — **`Group.description` + `Group.slug` (initials)** — két UI-találmány mező
- **Hol.**
  - `Group.description` "Aszfalt-, járda-, és útburkolat-karbantartás. Kátyúzás, padka-javítás, vízelvezetés." — az `A7DetailScreen.GroupHead` sub-blokkjában + Alapadatok Leírás-cellában (read) + textarea-ban (edit) + StateEmptyMembers "Még nincs leírás." italic-fallback.
  - `Group.slug` mock-mező (`'utkarb'`, `'kozvil'`, `'huladek'`, `'kozter'`, `'vesz'`) — lista `NameCell.a7-gn__sub` mono-formátumú "azonosító" + adatlap `GroupHead.a7d-head__sub` + Alapadatok "Azonosító" sor (read) + "Azonosító" input `disabled` (edit) magyarázó hint-tel *"Az azonosító nem módosítható létrehozás után — a kiosztásokban referenciaként szolgál."*
  - `Group.initials` mock-mező (`'ÚK'`, `'KV'`, stb.) — lista `NameCell.a7-gn__ic` violet circle + adatlap `GroupHead.a7d-head__avatar` violet 56×56.
- **Spec.** `00_domain_model.md` §2.2 `Group` entitás mezőlistája: `id`, `name`, `isActive`, `members` (n-n). **`description`, `slug`, `initials` egyike sem létezik a `Group`-on.** A `50_konfig_v2.md` 3.2 explicit *"csoport = címke + taglista"* (K-016 pilot-scope minimum).
- **Probléma — kétpólusos:**
  - **(i) `description`** — szubsztanciális mező-bővítés; pedagógiailag indokolt ("mit csinál ez a csoport?"), de K-016 pilot-scope-on kívül.
  - **(ii) `slug` + `initials`** — vizuális enhancement-mezok, üres adattal helyettesíthetőek. A `slug` (utkarb, kozvil) mint URL-fragment NEM része a spec-routing-jának (`/beallitasok/csoportok/details/<id>` numerikus id-val a §4.3.2 + AC-G1.2 szerint).
- **Javaslat.** Két opció:
  - **(a) Spec-bővítés** — `Group.description: string?` (max 500) hozzáadása a `00_domain_model` §2.2-höz; `slug` és `initials` továbbra is mock-szintű (`initials` szerver-oldalon az első 1-2 szó kezdő-betűjéből származtatható, `slug` elhagyható).
  - **(b) Mock-korrekció** — mind a 3 mock-mező törlése a screen-fájl-szintről + organism-szintről.
- **Javasolt:** **(a) — `description` szelektív spec-bővítés**, mert a vezető-élmény szempontjából érdemi ("Útkarbantartó csapat — kátyúzás, padka, vízelvezetés" vs. csak "Útkarbantartó csapat" név), és a `[validationForm]`-mintába triviálisan illeszthető. A `slug` + `initials` **(b) — mock-szintű törlés**, mert nem ad érdemi értéket.
- **Hatás.** `00_domain_model.md` §2.2 + `30_beallitasok.md` §3.2 + §4.3 + §4.3.4 mezősablon bővítés a `description`-re. A `slug` + `initials` mock-szintű törlés HANDOFF.md megjegyzés. **SPEC-FEEDBACK SF-43**.

#### 🔍 #2 — A7-lista "Létrehozta" oszlop a 4-oszlopos szettben
- **Hol.** `columns[2]` `Létrehozta` (str, sortable, 160px) — `row.createdBy` ("Tóth Béla" / "Kovács Anna") renderelve.
- **Spec.** `30_beallitasok.md` §4.3.1 4-oszlopos katalógus: **Név · Aktív · Tagok száma · Létrehozva** (timestamp). A "Létrehozta" (creator-displayName) **NEM szerepel** a spec-oszlopok között.
- **Probléma.** A spec szerinti 4-oszlopos szettből az A7-lista 1 oszlopot kihagyott (`Aktív` — lásd ⚠ #1) és 1 új oszlopot vezetett be (`Létrehozta`). A `createdBy` az `AuditableEntity`-ből származó FK (Core `User.id`); a `displayName` cross-tenant feloldást igényelhetne — a pilot-volumenen elhanyagolható, de a spec-szerződéssel inkonzisztens.
- **Javaslat.** **Két opció:**
  - **(a) Spec-szelídítés** — `30` §4.3.1 oszlop-katalógusába `Létrehozta` oszlop felvétele (`createdBy.displayName` derived, sortable, 160px); az `Aktív` oszlop visszapótlása (SF-39).
  - **(b) Mock-korrekció** — a `Létrehozta` oszlop törlése a screen-mockból; csak a 4 spec-szerinti oszlop marad.
- **Javasolt:** **(a)** — `createdBy.displayName` pedagógiai érték (a vezető tudja, ki indította a csoportot), és csak audit-szempontú olvasás, nincs validációs költség.
- **Hatás.** `30_beallitasok.md` §4.3.1 oszlop-katalógus 1 sorral bővül. **SPEC-FEEDBACK SF-44**.

#### 🔍 #3 — A7-lista FilterPillBar 2 szűrője (`Méret` + `Létrehozta`)
- **Hol.** `FilterPillBar.filters=[{ key: 'creator', label: 'Létrehozta' }, { key: 'size', label: 'Méret' }]` — mindkettő szűrő opcionálisan aktiválható (State 2 `Méret = 4+ fő` aktív).
- **Spec.** `30_beallitasok.md` §4.3.1 oszlop-katalógus szűrhetőség: `Név` (szöveg), `Aktív` (kapcsoló) — **csak ez a két szűrő spec-rögzített**. A `Méret` (`memberCount`-szerinti) és `Létrehozta` (creator-szerinti) szűrők **a spec-katalógusban nem szerepelnek**.
- **Probléma.** A spec-oszlop-katalógus szigorú leképezést ír elő: csak a `Szűrhető=igen` oszlopok lehetnek a FilterPillBar-on. A `Méret`+`Létrehozta` kettős a spec szerint **nem szerepelhetne** ott.
- **Javaslat.** **SF-44 (Létrehozta) bővítés** + **mock-korrekció a `Méret`-re** — a `Méret`-szűrő törlése (a pilot-volumenen 5 csoportos listán nem értelmes), VAGY ha érdemi: spec §4.3.1 oszlop-szűrési-szabályának bővítése `memberCount` szűrhetővel.
- **Hatás.** Egyszerűbb: a 2 mock-szűrő törlése + a `Név` + `Aktív` szabványos FilterPillBar-felvétele. **SPEC-FEEDBACK SF-45**.

#### 🔍 #4 — A7-lista First-time empty-card emoji 👥 + pedagogical exceeds spec literal
- **Hol.** State 3 `.a7-empty` block: ikon `<div className="a7-empty__icon">👥</div>` (28px Unicode) + pedagogiai magyarázat *"A csoportok a bejelentés-kiosztáshoz kellenek: hozz létre egy 'Útkarbantartó csapat'-ot, vegyél fel 3-5 terepi munkást, és a kátyú-bejelentések automatikusan a csoport tagjaihoz kerülnek."*
- **Spec / DS.** `README.md` — *"Default: no emoji. Not in buttons, **not in status chips, not in form labels, not in error messages**."* Két kivétel: citizen-side report-categories + citizen-side home-screen wave. **Manager-felület emoji-tilalom.** `30_beallitasok.md` §4.5.2 literal: *"Még nincs csoport. Hozz létre egyet a 'Új csoport létrehozása' gombbal."* — egysoros, technikailag-faktuális, NEM pedagogikus.
- **Probléma — kétpólusos:**
  - **(i) Emoji 👥** — DS-szabály-megsértés (Manager-felület emoji-tilalom).
  - **(ii) Pedagogikus magyarázat** — a spec literal-szöveg túllépése (Phase 2B SF-22 mintában ugyanez merült fel az A4 section-subtitle-on; ott "mock-developer-vetület, nem vezetőnek szól" döntés született).
- **Javaslat.** **Két csere:**
  - 👥 emoji → `<Icon name="users" size={28} />` (Lucide stroke-ikon).
  - Pedagogikus magyarázat redukálása az 1-mondatos spec-literal-ra (vagy enyhén bővítve, 2-mondatban; "A csoportok a bejelentés-kiosztáshoz kellenek." + spec-literal CTA).
- **Hatás.** Mock-szintű DS-konformitás + pedagogikai-túlcsorgás visszavágása. **HANDOFF.md átadási megjegyzés** (analóg a Phase 2B SF-24-tel + SF-22-vel). **SPEC-FEEDBACK SF-46**.

---

## Backward pass — A7 UI-elemek osztályzata

**A7-lista (3 állapot):**

| UI-elem | Osztály | Megjegyzés |
|---|---|---|
| PageHeader title "Csoportok" + description | ✅ | Spec §4.1 + §4.3.1. |
| "Új csoport" PageHeader-CTA | ✅ | Spec §4.3.1 + D-1. |
| FilterPillBar 2 szűrője (`Létrehozta` + `Méret`) | 🔍 (#3 SF-45) | Spec §4.3.1 csak `Név` + `Aktív` szűrhetőt rögzít. |
| Search-input "Keresés csoport-név alapján…" | 🟡 | FilterPillBar default; spec-katalógusban nincs explicit, de manager-pattern bake-in. |
| DataTable 4 oszlop | partial — ⚠ #1 + 🔍 #2 | Spec szerint 4 oszlop (Név/Aktív/Tagok/Létrehozva); screen szerint 4 oszlop (Csoport/Tagok/Létrehozta/Létrehozva) — `Aktív` hiányzik, `Létrehozta` extra. |
| `NameCell` icon + name + slug | partial — 🔍 #1 (slug+initials) | `name` ✅, `slug` és `initials` 🔍. |
| `MembersCell` 3-avatar overlap + "+N" / "N tag" pill | 🔍 (minor) | Spec §4.3.1 *"3 tag"* egyszerű szám-formátumot ír; az avatar-stack mock-enhancement. NEM lényegi hiba; halvány UX-bonus. |
| `Létrehozta` oszlop (creator-displayName) | 🔍 #2 | Spec-katalógusban nincs; SF-44. |
| `Létrehozva` oszlop (mono-formátum dátum) | ✅ | Spec §4.3.1. |
| Sortable headers + onSortChange | 🟡 D-13 | DataTable contract. |
| First-time empty card emoji + pedagogy | 🔍 #4 | SF-46. |

**A7-adatlap (4 állapot):**

| UI-elem | Osztály | Megjegyzés |
|---|---|---|
| `a7d-back` "Vissza a csoportokhoz" link | 🟡 | Detail-page back-nav minta (D-1 +); spec-szintű detail-route navigáció implicit. |
| `GroupHead` (violet 56×56 avatar + name + sub + status-chip) | partial | `name` ✅, status-chip ✅ (spec §4.3.2 isActive badge); avatar+initials+slug 🔍 #1. |
| 2 inline-szekció (Alapadatok + Tagok) | 🟡 (D-10 G-1A felüldönti §4.3.2 modal) | SF-42 spec-szelídítés. |
| Alapadatok grid Név + **Azonosító (slug)** + **Leírás (description)** + Létrehozta | partial | Név + Létrehozta ✅; slug + description 🔍 #1. |
| EditingBasic textarea description + locked slug input + magyarázó hint | 🔍 #1 | Mind a 2 mock-mező a `Group` entitás bővítését igényli. |
| Tagok-szekció `MemberRow` (avatar + név + email + role + remove-X) | 🟡 D-10 G-2A (AUDIT-2 §3.3 inline-pótlás — NEM UI-találmány) | A kanonikus `GroupMemberList` API: `{id, displayName, status, roles}` — **`status` HIÁNYZIK** a render-ben (⚠ #2 SF-40). |
| Inline `.a7d-picker` autocomplete dropdown + "Csak Aktív" hint | 🟡 D-10 G-3A (AUDIT-2 §3.3 inline-pótlás) | Spec §3.2.3 hint-megfogalmazás literal-konform. |
| Tag-eltávolítás undo-toast (bottom-right, 5s) | 🟡 D-10 G-4A | Direct remove + undo (NEM ConfirmDialog). |
| `a7d-danger` "Csoport törlése" zóna + magyarázat | partial — ⚠ #3 | Button-affordance ✅; delete-guard 409 confirm state hiányzik (SF-41). |
| EmptyMembers amber-dashed card | 🟡 | D-10 pilot-élmény. |
| Audit footer (Módosítva-mező) | (hiányzik) | A spec §4.3 explicit nem írja elő — minor pilot-szintű kihagyás. NEM SF-tétel. |
| `SettingsSubNav` HIÁNYA — D-14 Pattern N | 🟡 (cross-cutting) | SF-38 fedi. |

---

## Batch 2 — záró összegzés

**Számok.** 14 spec-mező/végpont + 18 UI-blokk vizsgálva — **20 ✅** · **4 ⚠** (hiányzó oszlop / mező / mock-state / spec-felüldöntés) · **9 🟡** (D-10 négy döntés + AUDIT-2 §3.3 inline-pótlások + D-13 DataTable + manager-pattern bake-inok) · **4 🔍** (`Group.description`+`slug`+`initials`, "Létrehozta" oszlop, FilterPillBar 2 szűrője, emoji+pedagogy empty-card).

**SF-tételek a Batch 2-ből.** 8 SF-tétel (SF-39..SF-46):

| # | Tétel | Kategória | Súly |
|---|---|---|---|
| SF-39 | A7-lista `Aktív` oszlop hiánya (spec §4.3.1 előírja) + mock-data `isActive` mezőbővítés | ⚠ mock-korrekció + mock-data | közepes |
| SF-40 | A7-adatlap `MemberRow` `status` badge hiánya (spec §3.2.2 GroupDto.members.status) | ⚠ organism-bővítés (kanonikus `GroupMemberList`) | alacsony |
| SF-41 | A7 + A6 + (A8 deaktiválás) delete-guard 409-confirm mock-state-pótlás (klaszter) | ⚠ mock-state-pótlás | közepes |
| SF-42 | A7-adatlap §4.3.2 modal vs. inline-szekció (D-10 G-1A felüldöntés) — **spec-szelídítés (analóg SF-37)** | 🟡 → spec-szelídítés | közepes |
| SF-43 | **`Group.description` spec-bővítés + `slug`/`initials` mock-törlés** | 🔍 spec-bővítés + mock-korrekció | **közepes** |
| SF-44 | A7-lista `Létrehozta` (createdBy) oszlop spec-katalógusba felvétele | 🔍 spec-szelídítés | alacsony |
| SF-45 | A7-lista FilterPillBar `Méret`-szűrő mock-törlés | 🔍 mock-korrekció | alacsony |
| SF-46 | A7-lista First-time emoji 👥 + pedagogikai magyarázat — DS-konformitás + spec-literal | 🔍 mock-korrekció | alacsony |

**AUDIT-2 §3.3 inline-organism-pótlások az A7-en (`MemberRow` + `.a7d-picker`).** A backward-pass-on **NEM UI-találmányokként** kezeltük — kanonikus `GroupMemberList` + `UserPicker` organism-okra mappelve. A HANDOFF.md-ben átadási megjegyzés rögzíti a retirement-feladatot (az Angular-portoláskor a screen-fájl inline-komponensei kicserélődnek a kanonikus organism-instance-okra).

**Új ⚠/🔍 jellegzetességek a Batch 2-ben (vs. Batch 1):**
- A spec-prescriptív Beállítás-ág is hozott egy **érdemi spec-bővítés-javaslatot** (SF-43 `Group.description`) — a Batch 1-ből hiányzott; ez a Beállítás-ági mock leggazdagabb saját-találmánya.
- A **delete-guard 409-confirm mock-state-hiány** mindkét batchen visszatér (SF-33 A6 + SF-41 A7) — **konszolidálva SF-41 cluster-tételbe**.
- A **D-10 G-1A spec-felüldöntés** az SF-37 (D-8 implicit) párja — **SF-42 spec-szelídítés**.

---

---

# Batch 3 — A8 Felhasználók

**Spec-fedés.** `00_domain_model` §3.1 (`User` 5 mező — globális Core) + §3.3 (`UserTenantRole` 4 mező — Core join) + §3.5 (`UserInvitation` 7 mező — Core invite-token) + §2.3 (`TenantUser` SD-37 projekció: a Tenant DB-ben tárolt `displayName` + `email` + `status` snapshot a `User`-ből, **`status: UserStatus`** = Active/Invited/Disabled enum). + `20_felhasznalokezeles` teljes — §3 API + §4.2 (lista mezősablon) + §4.3 (adatlap szekciók) + **SD-38** (3 invariáns: `cannotDeactivateSelf` / `cannotRemoveLastManager` / `cannotDemoteLastManager` — szerver-autoritatív + UI-szintű proaktív előjelzés) + **D-9** (UD-1A invite-dialog · UD-2A role-rows checkbox+leírás · UD-3A inline-szekciónkénti szerkesztés · UD-4A invariáns-előjelzés disabled+tooltip).

**Screen.**
- `a8-beallitasok-felhasznalok-lista.html` — 4 állapot (1 All / 2 ActiveTab+Diszpécser-szűrő / 3 InvitedTab / 4 FirstTime+SelfRow+EmptyCard)
- `a8-beallitasok-felhasznalok-adatlap.html` — 5 állapot (1 Active-Anna / 2 EditingRoles-Anna / 3 LastManager-Béla disabled+tooltip / 4 Invited-Pál / 5 Disabled-Réka reaktiválás)

**Organism-szerződés.** **A kanonikus `UserInviteDialog` organism az AUDIT-2 §3.3 inline-organism-pótlás miatt NEM közvetlenül renderelt** — a screen-fájl csak az `InviteCta` button-t rajzolja a PageHeader-actions slotba, a dialog-overlay-state egyik artboardon sem aktivált (megépített, de unmounted). **A backward-pass a kanonikus organism-API-ra mappel**, a HANDOFF.md-ben átadási megjegyzés. Common organism-fogyasztások (`AppShell` + `PageHeader` + `TabFilter` + `FilterPillBar` + `DataTable` + `RoleEditor` `locks` API + `UserChip`) standard.

---

## Forward pass — `User` + `UserTenantRole` + `UserInvitation` + `TenantUser` 24 mező/végpont + `20_felhasznalokezeles` §3-§4 UI-szerződés

### ✅ Spec-ben + screen-en is megvan

| Spec-mező / végpont / UI-blokk | Spec-forrás | Screen-evidence |
|---|---|---|
| `User.id` (Core, globális GUID) | `00_domain_model` §3.1 | A8-lista `USERS[*].id` (1-7) + A8-adatlap `USERS.anna.id=2` stb. (a Core-egyediség pilot-mock-on kis-int egyszerűsítve, élesben `Guid`). |
| `User.displayName` | `00_domain_model` §3.1 + `20` §4.2 mezősablon | `UserCell.a8-uc__name` (lista) + `mgr-user-detail__name` H1 (adatlap) + Alapadatok "Név" (read) + textarea (edit-mode). |
| `User.email` | `00_domain_model` §3.1 + `20` §4.2 + §4.3 | `UserCell.a8-uc__email` mono-formátum (lista) + `mgr-user-detail__email` (adatlap) + Alapadatok "E-mail" `locked` mező a `disabled` propal a textarea-szerkesztésben. |
| `TenantUser.status: UserStatus` enum (SD-37: Active/Invited/Disabled) | `00_domain_model` §2.3 + SD-37 + `20` §3.1 (status-state-gép) | `StatusChip` 3-állapotú (`a8-st--active/--invited/--disabled` lista + `mgr-user-detail__status-chip--active/--invited/--disabled` adatlap); literal-konform a `STATUS_LABELS` magyar-vetülettel (`Aktív` / `Meghívva` / `Letiltva`). |
| `UserTenantRole.role` (TenantRole enum: manager/dispatcher/field_worker/content_manager) | `00_domain_model` §3.3 + `20` §4.2 + §4.3 + D-9 UD-2A | `RoleChips` 4-érték magyar-feloldással (`Vezető` / `Diszpécser` / `Terepi (dolgozó)` / `Tartalomkezelő`) — `ROLE_LABELS` literal-konform a spec §3.3 enum-leképezésével. |
| `UserTenantRole.role[]` többszörös (n-egyhez, "egy felhasználó 1+ szerepkört kap") | `00_domain_model` §3.3 + `20` §3.4 | `USERS[*].roles: string[]` minden mock-rekordon (mind a 7 user single-role-os a mock-adatban, de a `RoleChips` 1+-elemű tömböt rendereli `flexWrap: 'wrap'`-pel). A `manager` + `dispatcher` kombináció a `locks` minta lehetséges példája a `LastManager`-állapoton. |
| `UserInvitation.email` (mező a meghívóhoz, `User`-rekord még nem jön létre) | `00_domain_model` §3.5 + `20` §3.2 invite-workflow | Az `InvitedTab` mock-rekord `email: 'horvath.pal@balatonalmadi.hu'` — a `TenantUser`-projection már létezik (a §2.3 SD-37 szerint **az invite-pillanatban** is létrejön a `TenantUser` `status: Invited`-tel), így a render-szempontból ekvivalens egy `Active` userrel, csak `activatedAt` `null`. |
| `UserInvitation.invitedRoles[]` | `00_domain_model` §3.5 + `20` §3.2 | A `RoleChips` az `Invited`-státuszú soron is renderelődik (Horváth Pál: `['field_worker']` → "Terepi") — a `TenantUser`-rekord már hordozza a roles-t. |
| `UserInvitation.invitedAt` ("eredeti meghívó dátuma") | `00_domain_model` §3.5 | Adatlap `USERS.horvath.invitedAt: '2026.05.18.'` — renderelve a "Meghívó újraküldése" akció-cella mellett *"Az eredeti meghívó {user.invitedAt}-i."* hint-szöveggel; a State 4 InvitedTab listán a "Utoljára aktív" cella `'még nem'` literal. |
| `UserInvitation.activatedAt` (a `TenantUser`-en is megjelenik mint Active-átmenet timestamp-je) | `00_domain_model` §3.5 + §2.3 | Adatlap Alapadatok-grid "Aktiválva" mező — `activatedAt: '2026.04.13.'` Anna, `'2026.03.01.'` Béla, `'2026.02.21.'` Réka. Csak `Active` és `Disabled` status-on jelenik meg (`Invited`-en nincs még aktiválás). |
| `TenantUser.disabledAt` (a Disabled-átmenet timestamp-je) | `00_domain_model` §2.3 + `20` §3.5 deactivation-workflow | Adatlap Alapadatok-grid "Letiltva" mező — `USERS.reka.disabledAt: '2026.04.30.'` + Reaktiválás-akció-cella *"{user.disabledAt}-án lett letiltva."* hint. |
| §3.1 `GET /v1/users` lista API + `UserStatus`-szerinti szűrés | `20` §3.1 + AC-4.1 | A `StateActiveTab` + `StateInvitedTab` mock-szűrés `USERS.filter(u => u.status === 'Active'/'Invited')` — a lista-API filter-paraméter szerver-oldalon (kliens-oldali mock-szűrés a screen-mock-on). |
| §3.2 `POST /v1/users/invitations` invite-workflow | `20` §3.2 | `InviteCta` "Új felhasználó" PageHeader-CTA — az `onClick` a kanonikus `UserInviteDialog` `open=true`-jára köt (AUDIT-2 §3.3 — a screen-mock NEM rendereli, de az API ekvivalens). |
| §3.3 `POST /v1/users/invitations/{id}/resend` invite-újraküldés | `20` §3.3 + §4.3 | Adatlap State 4 (Invited-Pál): `<button>Meghívó újraküldése</button>` az `mgr-user-detail__actions`-ban. |
| §3.4 `PATCH /v1/users/{id}/roles` role-szerkesztés | `20` §3.4 + D-9 UD-2A | Adatlap State 2 (EditingRoles-Anna): a `<RoleEditor value={user.roles} onChange={() => {}} locks={undefined}>` 4-checkbox-os szerkesztő-overlay-szekcióban; a `SaveRow` "Mégse / Mentés" gombokkal. |
| §3.5 `POST /v1/users/{id}/deactivate` + SD-38 `cannotDeactivateSelf` invariáns | `20` §3.5 + SD-38 #1 + AC-4.3 | Adatlap State 3 (LastManager-Béla): a Deaktiválás-button `disabled` + tooltip *"Te vagy az egyetlen vezető — nem deaktiválhatod magad."* — UI-szintű proaktív invariáns-előjelzés. *(NB. A "Te vagy az egyetlen vezető" magyarázat a `cannotRemoveLastManager`-invariánssal **keveredik** — szigorúan csak `cannotDeactivateSelf`-állítás lenne a Béla esetén — lásd 🔍 #4.)* |
| §3.5 SD-38 `cannotRemoveLastManager` invariáns RoleEditor-szinten | `20` §3.4 + SD-38 #2 + AC-4.4 + D-9 UD-4A | Adatlap State 3 (LastManager-Béla): a `RoleEditor.locks={manager: {locked: true, reason: 'Te vagy az egyetlen vezető — utolsó-manager invariáns (SD-38).'}}` — checkbox-locked + tooltip. |
| §3.6 `POST /v1/users/{id}/reactivate` + AC-4.5 | `20` §3.6 + AC-4.5 | Adatlap State 5 (Disabled-Réka): `<button>Reaktiválás</button>` mint `u-btn--primary` (a Reaktiválás a `Disabled→Active`-átmenetet teszi). |
| §4.2 lista oszlop `Felhasználó` (`displayName` + `email`) | `20` §4.2 oszlop-katalógus | `columns[0]` `UserCell` 2-soros (avatar + name + "Te" chip / email). |
| §4.2 lista oszlop `Állapot` (`UserStatus` enum) | `20` §4.2 | `columns[1]` `StatusChip` 3-állapotú, sortable, width: 130. |
| §4.2 lista oszlop `Szerepkör` (`role[]`) | `20` §4.2 | `columns[2]` `RoleChips` cluster, width: 180. |
| §4.2 lista 4-tab szűrő (Mind / Aktív / Meghívva / Letiltva) | `20` §4.2 + D-9 UD-1A spec-élesedő utótesztelés | `TabFilter` `TABS = [Mind, Aktív, Meghívva, Letiltva]` darab-számokkal — `counts` aggregálódik a `USERS` lista állapotaiból (7 / 4 / 2 / 1). |
| §4.2 dim-Disabled lista-sor (D-13 rowClassName) | `20` §4.2 implicit + DECISIONS D-13 | `rowClassName={dimDisabled}` callback — `Disabled`-státuszú soron `a8-row--dim` modifier (CSS `opacity: 0.55`); az A8-lista State 1-en a Nagy Réka (Disabled) sor halványítva. |
| §4.3 adatlap 3 inline-szekció (Alapadatok / Szerepkörök / Csoporttagság) | `20` §4.3 + D-9 UD-3A | `Section` × 3 a `UserDetailPage`-ban: "Alapadatok" (név + e-mail + invitedAt + activatedAt + opcionálisan disabledAt) + "Szerepkörök" (RoleChips read / RoleEditor edit) + "Csoporttagság" (csoport-pill-cluster vagy "Nem tagja egyetlen csoportnak sem." italic-fallback + "Csoportok kezelése →" link). |
| §4.3 fiók-akciók sáv (status-szerinti CTA-szett) | `20` §4.3 | `mgr-user-detail__actions` 3-status-szerinti változat: `Invited` → Meghívó újraküldése + invitedAt hint; `Active` → Deaktiválás (vagy locked self-eset); `Disabled` → Reaktiválás + disabledAt hint. |
| `20` §4.2 search-input | `20` §4.2 + FilterPillBar default | `FilterPillBar.searchPlaceholder="Keresés név, e-mail alapján…"`. |
| `20` §4.5.2 lista empty-állapot (first-time, csak a vezető van a tenant-on) | `20` §4.5.2 + §6 K-007 elv | State 4 (FirstTime): self-row a vezetővel + "Te" chippel + empty-card hívogató CTA-val. *(A literal-szöveg + emoji-eltérés — lásd 🔍 #5.)* |
| D-13 DataTable contract: sortable + onRowClick + rowClassName | DECISIONS D-13 | `columns[0..3]` 3 oszlop `sortable: true` (Felhasználó/Állapot/Utoljára aktív), `onRowClick={() => {}}`, `rowClassName={dimDisabled}` — kanonikus D-13 API. |

### ⚠ Spec-ben van, screen-en nincs — hiányosság

#### ⚠ #1 — Kanonikus `UserInviteDialog` (`InviteOpen` mock-state) NEM renderelt
- **Spec.** `20` §3.2 invite-workflow (`POST /v1/users/invitations` + invitedRoles[] + email-validáció + ütközés-409-uniqueness-check `email_already_invited` / `email_already_user`). §4.2 lista-szintű akció: *"Új felhasználó meghívása — modal-dialógus (email + invitedRoles checkboxszett)"*. D-9 UD-1A: *"Egyszerű dialog. Email mező + 4 checkbox a roles-szettre. Validáció szerver-oldali (email-uniqueness + `400 invalid_email`); UI-szinten csak az `email`-formátum-előellenőrzés."*
- **Screen.** A `InviteCta` button a PageHeader-actions slotban renderelve, `<UserInviteDialog>` script-tag betöltve (`<script src="...user-invite-dialog.jsx">`), DE **a dialog egyik artboardon sem renderelődik** (`onClick={() => {}}` no-op, nincs `dialogOpen` state-vetület).
- **AUDIT-2 §3.3 explicit:** *"Az `a8-beallitasok-felhasznalok-lista.html` csak egy `InviteCta` button-t renderel; a `UserInviteDialog` organism megépítve, de NEM rendererelt. ... HANDOFF.md átadási megjegyzés, NEM UI-találmány."*
- **Hatás.** A fejlesztő az Angular-portoláskor az invite-workflow vizuális mintáját **organism-spec-rétegből látja** (a `manager-system/organisms/user-invite-dialog.jsx` self-contained példányán át), nem screen-fájl-szintű compositionből. AC-4.1 + AC-4.2 vizuális tükre az organism-fájlon át kerül lefedésre.
- **Javaslat.** **Mock-state-pótlás** — új 5. artboard `StateInviteOpen` az A8-lista screen-fájlon a `<UserInviteDialog open=true>` overlay-vel: email-input + 4-checkbox roles-szettel + "Meghívó küldése" / "Mégse" gombok. **SPEC-FEEDBACK SF-47** (A6 SF-33 + A7 SF-41 mock-state-pótlás-klaszterhez csatolva).
- **Megj.** A "lazaság" itt **NEM UI-találmány-szintű** (AUDIT-2 explicit), csak mock-rendering-hiány — a kanonikus organism létezik és teljes szerződéssel rendelkezik.

#### ⚠ #2 — `User.language` mező NEM jelenik meg sehol
- **Spec.** `00_domain_model` §3.1 `User.language` ("en"/"hu"/null) — felhasználói nyelvválasztás per-user mező (a citizen-felületen + a manager-felületen i18n-kulcs feloldásához). `20_felhasznalokezeles` §4.3 az adatlap-mezősablonban a "Beállítások" alszekciót **nem említi**, így a `language` UI-szintű kezelése spec-szinten **definiálatlan**.
- **Screen.** Sem a lista, sem az adatlap nem rendereli a `language` mezőt. A `USERS[*]` mock-rekord nem hordoz `language` mezőt.
- **Hatás.** A vezető nem tudja módosítani egy másik user nyelv-preferenciáját (pl. ha egy magyarul nem beszélő terepi munkás `en`-t választott telepítéskor, de a vezető szeretné `hu`-ra állítani). **Pilot-volumenen elhanyagolható** (Balatonalmádi 100%-os magyar staff), de a spec szerinti mező UI-feloldása nyitva marad.
- **Javaslat.** **Spec-szelídítés** vagy szándékos-kihagyás: a `20_felhasznalokezeles` §4.3-ba egy "Beállítások" 4. szekció (csak `language` mezővel a pilotra; a per-user-i18n későbbi bővítésre kész). Vagy: a spec-megjegyzés *"a `language` UI-szinten a saját profilról szerkeszthető (Phase 2+); más felhasználó nyelvének módosítása nem támogatott a pilot-on."*
- **Hatás.** **SPEC-FEEDBACK SF-48** (alacsony prioritás; spec-szelídítés vagy szándékos-kihagyás-megerősítés).

#### ⚠ #3 — `UserInvitation.token` + `UserInvitation.expiresAt` + `UserInvitation.status` (`InvitationStatus`) mezők UI-fedése nincs
- **Spec.** `00_domain_model` §3.5 `UserInvitation` 7 mező: `id`, `email`, `invitedRoles[]`, `token`, `status: InvitationStatus`, `invitedAt`, `expiresAt`. Az `InvitationStatus` enum (`Pending`/`Accepted`/`Expired`/`Revoked`) a meghívó saját-állapotát hordozza.
- **Screen.** Az A8-lista `Meghívva`-tab az `Invited` status-ú TenantUserekat mutatja, DE a `UserInvitation.status` (Pending vs. Expired vs. Revoked) **nem differenciálódik**. Egy lejárt meghívó (`Expired`) ugyanúgy "Meghívva" tag-gel jelenik meg, mint egy érvényes (`Pending`). A `expiresAt` (a meghívó lejárati ideje) sehol nem renderelt.
- **Hatás.** A vezető nem látja, mely meghívók már lejártak (a §3.5 spec szerint a meghívók 7-napos érvényességűek, utána újraküldés szükséges). Pilot-szempontból ezt a "Meghívó újraküldése" akció kezeli, de a **vizuális információ a lista-oldalon hiányzik** ("ezek a meghívók még frissek; ezek lejártak").
- **Javaslat.** **Mock-korrekció + szelektív spec-bővítés** — a `MeghívvaTab` lista-soron az `expiresAt` derived-mező megjelenítése: ha `< now()` → "lejárt" piros mini-tag az avatar-on; ha `now() + 24h` belül → "hamarosan lejár" amber mini-tag. Az adatlap-on `InvitationStatus`-szerinti finomítás (`Expired`-on a "Meghívó újraküldése" gomb hangsúlyosabb / `u-btn--primary` helyett `u-btn--secondary`). **SPEC-FEEDBACK SF-49** (alacsony-közepes prioritás).

#### ⚠ #4 — Saját Deaktiválás-disabled tooltip-szöveg **invariáns-keveredés**
- **Spec.** SD-38 invariáns #1 `cannotDeactivateSelf`: *"A vezető a saját fiókját nem deaktiválhatja. Server-side guard: `400 cannot_deactivate_self`. UI proaktív előjelzés: Deaktiválás-button disabled saját adatlapon."* SD-38 invariáns #2 `cannotRemoveLastManager`: *"Ha a deaktiválandó user az egyetlen `manager`-szerepkörű aktív TenantUser, a deaktiválás megakad: `400 last_manager`. UI proaktív előjelzés: a RoleEditor-on a `manager` checkbox `locked`."*
- **Screen.** Adatlap State 3 (LastManager-Béla): a Deaktiválás-button-tooltip *"Te vagy az egyetlen vezető — nem deaktiválhatod magad."* — ez **két invariáns-szöveget összeolvaszt egy mondatba**:
  - "Te vagy az egyetlen vezető" — `cannotRemoveLastManager`-magyarázat
  - "nem deaktiválhatod magad" — `cannotDeactivateSelf`-állítás
- A két invariáns Béla esetében **mindkét feltétel-irányból** aktív (saját adatlap **és** egyetlen vezető), de a `cannotDeactivateSelf` **önmagában elegendő** a disabled-állapothoz — a "magad" rész az autoritatív magyarázat. A "egyetlen vezető" rész vizsgálati-szempontból **felesleges keveredés** (egy nem-utolsó-vezető saját-adatlapján a Deaktiválás ugyanúgy disabled lenne, de "egyetlen vezető" magyarázat nem stimmelne).
- **Hatás.** A vezető zavart kaphat: "ha kineveznénk egy másik vezetőt, akkor magamtól deaktiválhatnám?" — **nem; a `cannotDeactivateSelf` saját-fiók-tilalom független a vezető-számtól**. A `cannotRemoveLastManager` (és a role-szintű "manager checkbox locked") elsőbb-deaktivációs path-on hat.
- **Javaslat.** **Mock-korrekció** — a Deaktiválás-tooltip szöveg *"Nem deaktiválhatod a saját fiókodat. Kérj meg egy másik vezetőt."* (csak `cannotDeactivateSelf`-konform; a "másik vezető" kifejezés implicit utal a `cannotRemoveLastManager`-előfeltételre is, de nem keveri). A RoleEditor-szintű "manager checkbox locked" magyarázat *"Te vagy az egyetlen vezető — utolsó-manager invariáns (SD-38)."* maradhat (az ott pontosan illeszkedik a `cannotRemoveLastManager`-hoz). **SPEC-FEEDBACK SF-50**.

### 🟡 Screen-en van, spec-ben nincs, DE D-X rögzíti

| Screen-elem | Hol jelenik meg | D-X hivatkozás |
|---|---|---|
| #1 Adatlap 3 inline-szekciónkénti szerkesztés (NEM modal) | `Section` × 3 + `SaveRow` Mégse/Mentés | **D-9 UD-3A** ("inline-szekciónkénti szerkesztés. A spec 4.3-as modal-űrlapot említ, de a Beállítás-ági inline-pattern (A7/A9 párja) preferált.") |
| #2 RoleEditor 4-checkbox-os szerkesztő (NEM dropdown-listából választás) | `RoleEditor value=[] onChange locks=` | **D-9 UD-2A** ("checkbox-szett magyarázattal. Minden szerepkör mellett 1-mondatos leírás 'mit ad'.") |
| #3 RoleEditor `locks` API per-role lockolásra (`{manager: {locked, reason}}`) | `locks` prop | **D-9 UD-4A + ORGANISMS RoleEditor §3** (a `locks` API kanonikus szerződés; SD-38 #2 invariáns vizualizálása) |
| #4 Deaktiválás-button disabled + tooltip (saját adatlapon) | `mgr-user-detail__actions` State 3 | **D-9 UD-4A** ("Server-side autoritatív, kliens-oldalon proaktív UI-disabled + magyarázó tooltip") |
| #5 Status-chip-zett 3-állapot (Aktív/Meghívva/Letiltva) lista + adatlap | `a8-st--*` + `mgr-user-detail__status-chip--*` | **SD-37 RÖGZÍTI** a `UserStatus` enum-leképezést — valójában ✅; itt csak D-réteg-megerősítés (a magyar-vetület autoritatív). |
| #6 dim-Disabled lista-sor (`a8-row--dim`) | `rowClassName={dimDisabled}` | **D-13 DataTable contract-bővítés** + **D-9 + A1 triage-perspektíva-elv T-7 minta** (a Letiltott userek a triage-fókuszból kiesnek) |
| #7 4-tab szűrő (Mind / Aktív / Meghívva / Letiltva) darabszámmal | `TabFilter` | **D-9 implicit** — a spec §4.2 csak "filter-by-status"-ot ír, a tab-szerű megvalósítást (vs. dropdown-szűrő) D-9 választja a TabFilter organism reuse-jával az A1 + A4 párja mintára. |
| #8 First-time empty self-row + amber empty-card kombináció | `a8-self-row` + `a8-empty-card` | **D-9 pilot-élmény** (analóg az A7 SF-46-tal és A9 R-1A amber empty-card-tal; a vezető saját-magát is látja a `TenantUser`-katalógusban). |
| #9 "Csoportok kezelése →" link a Csoporttagság-szekció empty-fallback-jában | `Section title="Csoporttagság"` italic-fallback | **D-9 pilot-élmény** — cross-screen affordance (`/beallitasok/csoportok`-ra navigálás), spec §4.3.3 explicit megemlíti *"a csoporttagság olvasásra; szerkesztés a csoport-adatlapon"* — a link ennek a pattern-nek a vizuális vetülete. |
| #10 Inline-szerkesztés `EmailField locked` + "Az e-mail nem módosítható az adatlapon" hint-magyarázat | `mgr-user-detail__field-hint` State 2 (Editing) | **D-9 + SD-38 implicit** — az e-mail (`User.email`) a Core-rekord kulcsmezője, az `UserInvitation`-workflow-n át módosulhat. UI-szinten read-only az adatlap-szerkesztésben. Spec-szintű explicit hiányzik, de a hint-szöveg pedagogiailag korrekt. |
| #11 PageHeader-szintű "Új felhasználó" CTA (D-1 konvenció) | `A8Screen.PageHeader.actions={<InviteCta />}` | **D-1 konvenció** (Beállítás-ági konzisztencia A7-tel; ellentétben az A6 SF-36-tal) |
| #12 Lista-soron 1-soros `UserCell` (avatar+name+email vertical stack) — NEM 2-cellás külön email-oszlop | `UserCell.a8-uc__body` | **Manager-pattern bake-in** — a "Felhasználó" oszlop spec szerint *displayName + email* aggregátum; vizuális kompozíció D-9 nélkül. NEM lényegi UI-találmány. |
| #13 `TenantUser.disabledAt` mező Alapadatok-grid-on a `Disabled`-státuszú user-en | `mgr-user-detail__field-grid` State 5 | **Spec §2.3 implicit** — a `TenantUser.disabledAt` audit-timestamp; az UI-megjelenítés szabadon hagyott, D-9 alatt bake-in. |

### 🔍 Screen-en van, spec-ben nincs, NEM dokumentált — UI-találmány

#### 🔍 #1 — **"Te" chip** a lista `UserCell`-en — **a prompt explicit kérdése**
- **Hol.** `UserCell.a8-uc__name` a `row.isCurrentUser`-feltétel alatt: `<span className="a8-self">Te</span>` mini-badge (blue-50 háttér, blue-200 border, blue-700 szöveg). A `USERS[0]` (Tóth Béla) `isCurrentUser: true` mock-flaggel renderelődik. Plusz a FirstTime State 4 `a8-self-row__name`-en ugyanaz a chip.
- **Spec — három-réteges check:**
  - **(a) `20_felhasznalokezeles` §4.2 oszlop-katalógus** — a `displayName` oszlop-spec a vezető önmagát-jelölésére **NEM tér ki**; csak a `displayName` + `email` aggregátum-renderelést írja.
  - **(b) SD-38 invariánsok** — a 3 szerver-autoritatív szabály (`cannotDeactivateSelf` / `cannotRemoveLastManager` / `cannotDemoteLastManager`) **kliens-szinten** a §3.7 + §4.4 *"proaktív megakadályozás"*-ot említ. A "proaktív" itt **akció-szintű** (disabled-button, locked-checkbox), **NEM identitás-szintű** (lista-soron "Te" chip).
  - **(c) D-9 UD-4A** — *"invariáns-előjelzés disabled + tooltip mintával"*. A *"Te"*-jelölés mint **identitás-affordance** D-9 nem rögzíti; UD-4A konkrétan a RoleEditor-checkbox-lock + Deaktiválás-button-disabled mintát írja.
- **Verdikt — 🔍 UI-találmány** (a prompt-előjelzett határeset itt 🔍-ra dől, NEM 🟡-ra). A "Te"-chip **identitás-szintű információ**, a `cannotDeactivateSelf`-invariáns akció-szintű előjelzésén túlmutató; a vezetőnek vizuálisan azonnal kommunikálja, hogy a listán **önmagát is látja**.
- **Probléma — két aspektus:**
  - **(i) Pedagogiai érték.** A "Te" chip a self-aware-flow-éhez kontextus-affordance ("ne lepődj meg, hogy magadat is látod"). A FirstTime-state self-row-on **különösen értékes** ("Te vagy itt egyedül" magyarázat alá kerül a chip).
  - **(ii) Spec-pozícionálás.** A SD-38 invariánsok kliens-oldali tükre a self-action-tilalom (Deaktiválás-disabled, manager-checkbox-locked). A "Te" chip ennek **proaktív identitás-előjelzése** — *"a vezető tudja, hogy ez a sor önmaga, ezért nem fogja meglepetésszerűen a 'Deaktiválás'-t kattintani"*. **Pedagogiailag konzisztens** a SD-38 szándékával, de a spec literal-szövegével **NEM expliciten** lefedett.
- **Javaslat.** **Két opció:**
  - **(a) Spec-szelídítés — UD-4A bővítés:** D-9 UD-4A finomítása "identitás-előjelzés *is*"-irányba: a `cannotDeactivateSelf`-invariáns UI-mintája magában foglalja a lista-szintű "Te" identitás-chip-et + adatlap-szintű disabled+tooltip-et. Vagy: új D-X döntés (D-15?) "Self-aware identitás-előjelzés a manager-listákon" — a `currentUser.id == row.id` mintát egységesen **"Te" chip-pel** jelöli az A8-lista, az A7-csoport-tagok listán, az A11-bejelentés-felelős cellán, stb.
  - **(b) Mock-korrekció:** a "Te" chip **eltávolítása** a screen-mockból. A FirstTime-state self-row-on a *"Te vagy itt egyedül"* magyarázat-szöveg + a tenant-szintű "vezető vagy" affordance (pl. `RoleChips` + status-chip) elégséges identitás-jelzést ad chip nélkül.
- **Javasolt:** **(a)** — a "Te" chip pedagogiailag indokolt, és a spec SD-38 tág-szellemével konzisztens; a finomítás explicit a D-9 (és a kapcsolódó cross-screen mintáknak) keretében történjen. **SPEC-FEEDBACK SF-51**.

#### 🔍 #2 — A8-lista 4. oszlop "Utoljára aktív" — `User.lastActiveAt` (vagy ekvivalens) spec-szinten NEM létezik
- **Hol.** `columns[3]` `Utoljára aktív` (str, sortable, 130px) — `row.lastActiveLabel` `'most'` / `'12 perce'` / `'2 órája'` / `'tegnap'` / `'még nem'` / `'3 hete'` literal mock-szövegek.
- **Spec.** Sem `User`, sem `TenantUser` entitás nem hordoz `lastActiveAt` (vagy `lastLoginAt` / `lastSeenAt`) mezőt. A `00_domain_model` §3.1 `User` 5 mezője: `id`, `displayName`, `email`, `language`, `passwordHash`. `TenantUser` §2.3 SD-37 projekció: `displayName`, `email`, `status`, `disabledAt`. **Egyik sem hordoz aktivitás-időbélyeget**.
- **Probléma.** A "Utoljára aktív" oszlop vezetői-érték-szempontból nagyon hasznos (*"melyik diszpécser dolgozott aznap?"*), de a spec szerinti `User` + `TenantUser` mezőkből **nem származtatható**. Implementáció-szempontból:
  - Server-side: új mező `User.lastActiveAt: DateTimeOffset?` (Core-szinten globális, vagy tenant-specifikus `TenantUser.lastActiveAt`-ra projektálva) — minden auth-tokenes API-hívás update-eli.
  - UI-szinten: relatív-időbélyeg-formátum ("most", "12 perce", "tegnap"), egy `getRelativeTime(timestamp)` helper-függvénnyel.
- **Javaslat.** **Spec-bővítés** — `User.lastActiveAt: DateTimeOffset?` (Core-szintű, a `User`-on; az Identity-szolgáltatás minden token-refresh-kor update-eli, max. percenként 1×). A `20_felhasznalokezeles` §4.2 oszlop-katalógus bővítése `Utoljára aktív` oszloppal (denormalizált, opcionálisan rejthető). **SPEC-FEEDBACK SF-52**.
- **Megj.** Alacsony-közepes prioritás — a pilot-on a vezető (Béla) 5-7 fős staff-et lát; a "Utoljára aktív" érték az invitácio-elfogadás-utáni "aktiváltam-e már"-jelzéshez (`'még nem'` `Invited`-en) is segít.

#### 🔍 #3 — A8-lista FilterPillBar 2 szűrője (`Szerepkör` + `Csoport`) spec-katalóguson kívül
- **Hol.** `FILTERS_DEFAULT = [{key:'role', label:'Szerepkör'}, {key:'group', label:'Csoport'}]` + `FILTERS_ACTIVE` State 2-n `Diszpécser` érték aktivált.
- **Spec.** `20` §4.2 oszlop-katalógus szűrhetőség: `displayName` (szöveg), `status` (4-tab), `role[]` (multiselect-dropdown). A `Csoport`-szerinti szűrő **NEM szerepel** a spec-katalógusban; a `role`-szűrő spec-szerint multiselect-dropdown a tabok mellett.
- **Probléma.** Két aspektus:
  - **(i) `Csoport`-szűrő** — pedagogikailag indokolt ("kik tartoznak az 'Útkarbantartó csapathoz'?"), DE: a vezetőnek erre a kérdésre az A7-csoport-adatlap pontosabb választ ad (a `MemberRow` lista). A vezető-flow szempontjából **inkább redundáns**.
  - **(ii) `Szerepkör`-szűrő FilterPillBar-on vs. dropdown** — spec dropdown-multiselectet ír; a FilterPillBar single-value pill-egyetértésű. A pilot-on mind a 4 szerepkör external-input-ot kíván — a multiselect dropdown spec-konform megvalósítás, a FilterPillBar single-pill ezt **egyszerűsíti**.
- **Javaslat.** **Két opció:**
  - **(a) Mock-korrekció:** a `Csoport`-szűrő törlése (a vezető az A7-adatlap-on keres taglistát); a `Szerepkör`-szűrő megtartása mint single-value FilterPillBar-pill (a pilot-on 1 szerepkör keresése elég gyakori, a multiselect-szelídítés indokolt — analóg az SF-44-mintával).
  - **(b) Spec-szelídítés:** `20` §4.2 oszlop-katalógus *"a role-szűrő multiselect-dropdown VAGY single-value FilterPillBar; pilot single-value preferált"*.
- **Hatás.** Mock-szintű korrekció + opcionális spec-szelídítés. **SPEC-FEEDBACK SF-53**.

#### 🔍 #4 — A8-lista `dispatcher`-szűrés `FILTERS_ACTIVE` State 2-n — count-label *"1 aktív szűrő"* literal **nem standard formátum**
- **Hol.** `DataTable.countLabel={<><strong>{rows.filter(...).length}</strong> diszpécser · 1 aktív szűrő</>}` — a count-label összevon **2 információt egy sorba**: a kapott darab-szám ("1 diszpécser") + az aktív-szűrő-jelzés ("· 1 aktív szűrő").
- **Spec.** `20` §4.2 a `countLabel` formátum-szerződését nem rögzíti. Az A1-lista (Phase 2A) + A4-lista (Phase 2B) count-label `<strong>{N}</strong> bejelentés` egysíkú szöveggel; az "aktív szűrő"-jelzés a FilterPillBar `hasActive` propján vagy a "Szűrők törlése"-ghost-action-on jelenik meg. **Az A8 a count-label-be olvasztja**.
- **Probléma.** A "1 aktív szűrő" rész **redundáns affordance** — a FilterPillBar `hasActive={true}` propja már vizuálisan jelzi (az aktív pill kiemelése + a "Szűrők törlése"-ghost-action), a count-label-en megint kimondani fölösleges.
- **Javaslat.** **Mock-korrekció** — a count-label egysíkúra redukálása `<strong>1</strong> diszpécser` formátummal (analóg az A1 + A4 mintával); a "1 aktív szűrő"-rész a FilterPillBar saját affordance-jára bízva. **SPEC-FEEDBACK SF-54** (alacsony prioritás).

#### 🔍 #5 — A8-lista FirstTime empty-card emoji 👋 + magyarázó **`a8-empty-card__title` "Te vagy itt egyedül." literal — a brand-tone vonalvezetésen kívüli megfogalmazás**
- **Hol.** State 4 `a8-empty-card__icon` "👋" (28px Unicode) + `a8-empty-card__title` *"Te vagy itt egyedül."* + magyarázó-desc *"Hívj meg másokat: diszpécsert a bejelentések kezelésére, terepi munkásokat a megoldásra, tartalomkezelőt a hírekhez. A meghívók e-mailben mennek ki."*
- **Spec / DS.**
  - `README.md` Emoji-szabály: *"Default: no emoji. Manager-felület emoji-tilalom."* + *"A home-screen greeting wave 👋 — pairs with a wave emoji as a recognised warm-greeting idiom"* — DE: a 👋 wave-emoji kivétel **csak citizen-home-screen-en** alkalmazható; manager-felületen NEM.
  - `TONE-OF-VOICE.md` magyar-vetülete: *"Tisztelt-távolság helyett kollégai. Konkrét, név-szerű. Trailing `!` tilos."* A *"Te vagy itt egyedül."* meleg-hang, de a "egyedül" szó (rövidsége + színezete) **enyhe-melancholikus**; a kollégai-hang inkább *"Még csak te vagy a tenanton."* / *"Egyedüli felhasználó vagy."*.
  - `20_felhasznalokezeles` §4.5.2 — *"Még nincs más felhasználó. Hívj meg kollégákat."* spec-literal.
- **Probléma — háromszintű:**
  - 👋 emoji a manager-felületen DS-szabály-megsértés (a wave a citizen-home greeting reserved).
  - "Te vagy itt egyedül." enyhe-melancholikus tónus; az `a8-empty-card__title` szövegspec-konformitásban *"Még csak te vagy a tenanton."* javasolt.
  - A magyarázó-desc (3 szerepkör-felsorolás "diszpécsert / terepi munkásokat / tartalomkezelőt") **pedagogikai értéke jó**, a tone-of-voice OK; de a spec literal-szöveggel összeolvasztható.
- **Javaslat.** **Háromrétű csere** (analóg SF-46-tal):
  - 👋 emoji → `<Icon name="user-plus" size={28} />` (Lucide stroke-ikon, semleges-affordance).
  - `a8-empty-card__title` átírás: *"Még csak te vagy a tenanton."* (kollégai-konform).
  - `a8-empty-card__desc` megtartani a 3-szerepkör pedagogikai-magyarázattal, esetleg enyhén tömörítve.
- **Hatás.** Mock-szintű DS-konformitás + tone-of-voice-igazítás. **HANDOFF.md átadási megjegyzés** (analóg SF-46-tal). **SPEC-FEEDBACK SF-55**.

---

## Backward pass — A8 UI-elemek osztályzata

**A8-lista (4 állapot):**

| UI-elem | Osztály | Megjegyzés |
|---|---|---|
| PageHeader title "Felhasználók" + description | ✅ | Spec §4.1 + §4.2. |
| "Új felhasználó" PageHeader-CTA (`InviteCta`) | ✅ + ⚠ #1 | Spec §4.2 + D-1 ✅; kanonikus `UserInviteDialog` open-state mock-rendering hiányzik (SF-47). |
| TabFilter 4-tab (Mind/Aktív/Meghívva/Letiltva) + darabszámok | ✅ + 🟡 #7 | Spec §4.2 status-szűrő ✅; tab vs. dropdown UD-1A spec-élesítés. |
| FilterPillBar `Szerepkör` + `Csoport` szűrők | 🔍 #3 (SF-53) | Spec katalógus szűrhetőség. |
| Search-input "Keresés név, e-mail alapján…" | ✅ | Spec §4.2. |
| DataTable 4 oszlop | partial — 🔍 #2 (Utoljára aktív) | 3 oszlop spec-konform, 4. oszlop (`lastActiveLabel`) spec-szinten új mezőt igényel (SF-52). |
| UserCell (avatar + name + "Te" chip + email) | partial — 🔍 #1 ("Te" chip SF-51) | `displayName` + `email` ✅; "Te" chip identitás-előjelzés. |
| StatusChip 3-állapot (lista) | ✅ | SD-37 enum-leképezés. |
| RoleChips cluster (lista) | ✅ | Spec §4.2 + D-9 UD-2A. |
| `lastActiveLabel` mono-formátum oszlop | 🔍 #2 | Spec-szintű mezőhiány (SF-52). |
| `dimDisabled` row-class (D-13 rowClassName API) | 🟡 #6 | D-13 contract + D-9 triage-perspektíva. |
| Count-label *"X felhasználó"* / *"X diszpécser · 1 aktív szűrő"* | partial — 🔍 #4 (SF-54) | Standard ✅; "1 aktív szűrő" összevonás redundáns. |
| FirstTime self-row "Te" chippel | partial — 🔍 #1 (SF-51) | Self-row pattern 🟡 (D-9 pilot-élmény); "Te" chip 🔍. |
| FirstTime empty-card 👋 + "Te vagy itt egyedül." | 🔍 #5 (SF-55) | Emoji + tone-of-voice + literal-szöveg. |
| `SettingsSubNav` HIÁNYA — D-14 Pattern N | 🟡 (cross-cutting SF-38) | |

**A8-adatlap (5 állapot):**

| UI-elem | Osztály | Megjegyzés |
|---|---|---|
| `a8d-back` "Vissza a felhasználókhoz" link | 🟡 | Detail-page back-nav minta (D-1 +). |
| User-fejléc (avatar + name H1 + email + status-chip) | ✅ | Spec §4.3 fejléc-mezősablon. |
| Avatar modifier (`--invited` amber / `--disabled` gray) | 🟡 | Pilot-vizuál (SD-37 status-szín-leképezés). |
| 3 inline-szekció (Alapadatok / Szerepkörök / Csoporttagság) | 🟡 #1 (D-9 UD-3A spec-felüldöntés) | Spec §4.3 modal helyett inline (SF-42-vel közös csomag). |
| Alapadatok grid (Név / E-mail / Meghívva / Aktiválva / Letiltva conditional) | ✅ + ⚠ #2 (language) | 5 mező ✅; `language` UI-fedés hiányzik (SF-48). |
| EditingProfile (Név textarea + E-mail locked + hint-szöveg) | 🟡 #10 | E-mail-locked-hint pilot-pedagógikus, D-9 implicit. |
| Szerepkörök szekció view-mode (`RoleChips` 4-érték magyar-vetülettel) | ✅ | Spec §3.3 + §4.3. |
| Szerepkörök szekció edit-mode (`RoleEditor` 4-checkbox + leírás + locks) | 🟡 #2 + #3 | D-9 UD-2A + UD-4A. |
| Csoporttagság chip-cluster vagy italic-fallback + "Csoportok kezelése →" link | 🟡 #9 | D-9 pilot-pedagógikus; spec §4.3.3 cross-screen affordance implicit. |
| Fiók-akciók sáv (status-szerinti CTA-szett) | partial — ⚠ #3 (SF-49 expiresAt) + ⚠ #4 (SF-50 tooltip) | A 3-status-szerinti változat ✅; lejárt-meghívó differenciálása + tooltip-keveredés. |
| Invited-Pál "Az eredeti meghívó {invitedAt}-i" hint | ✅ | Spec §3.5 + §4.3. |
| Disabled-Réka "{disabledAt}-án lett letiltva." hint | 🟡 #13 | Spec §2.3 implicit (audit-timestamp), D-9 alatt bake-in. |
| LastManager-Béla Deaktiválás-tooltip *"Te vagy az egyetlen vezető — nem deaktiválhatod magad."* | ⚠ #4 (SF-50) | Invariáns-keveredés a `cannotDeactivateSelf` + `cannotRemoveLastManager` között. |
| RoleEditor `locks={manager: {locked, reason}}` szöveg *"Te vagy az egyetlen vezető — utolsó-manager invariáns (SD-38)."* | 🟡 #3 | D-9 UD-4A; szöveg pontos. |
| `SettingsSubNav` HIÁNYA — D-14 Pattern N | 🟡 (cross-cutting SF-38) | |

---

## Batch 3 — záró összegzés

**Számok.** 24 spec-mező/végpont + 28 UI-blokk vizsgálva — **30 ✅** · **4 ⚠** (`UserInviteDialog` open-state mock-rendering + `language` UI-fedés + `UserInvitation.token/expiresAt/status` differenciálás + tooltip-szöveg invariáns-keveredés) · **13 🟡** (D-9 négy döntés + SD-37 enum-leképezés + D-13 DataTable + manager-pattern bake-inok + cross-cutting SF-38) · **5 🔍** ("Te" chip · "Utoljára aktív" oszlop · FilterPillBar `Csoport`+`Szerepkör` szűrők · count-label redundancia · FirstTime emoji+title).

**SF-tételek a Batch 3-ból.** 9 SF-tétel (SF-47..SF-55):

| # | Tétel | Kategória | Súly |
|---|---|---|---|
| SF-47 | A8-lista `UserInviteDialog` open-state mock-state-pótlás (AUDIT-2 §3.3 inline-pótlás retirement) | ⚠ mock-state-pótlás (SF-41 klaszterrel együtt) | közepes |
| SF-48 | `User.language` UI-fedés szándékos kihagyás vagy spec-bővítés (Beállítások 4. szekció) | ⚠ spec-szelídítés vagy szándékos-kihagyás | alacsony |
| SF-49 | `UserInvitation.status` (Pending/Expired/Revoked) lejárt-meghívó differenciálás a lista + adatlap-on | ⚠ mock-korrekció + szelektív spec-bővítés | alacsony-közepes |
| SF-50 | LastManager Deaktiválás-tooltip invariáns-szöveg-keveredés (`cannotDeactivateSelf` vs. `cannotRemoveLastManager`) | ⚠ mock-korrekció | közepes |
| SF-51 | **"Te" chip identitás-előjelzés** — D-9 UD-4A bővítés vagy új D-X "Self-aware identitás-előjelzés a manager-listákon" | 🔍 **spec-szelídítés vagy új D-X** | **közepes** |
| SF-52 | A8-lista `Utoljára aktív` oszlop — `User.lastActiveAt` spec-bővítés | 🔍 **spec-bővítés** | közepes |
| SF-53 | A8-lista FilterPillBar `Csoport`-szűrő mock-törlés + `Szerepkör`-szűrő multiselect→single spec-szelídítés | 🔍 mock-korrekció + opcionális spec-szelídítés | alacsony |
| SF-54 | A8-lista count-label *"X · 1 aktív szűrő"* redundancia visszavágás | 🔍 mock-korrekció | alacsony |
| SF-55 | A8-lista FirstTime empty-card 👋 emoji + "Te vagy itt egyedül." tone-of-voice + DS-konformitás | 🔍 mock-korrekció (SF-46 mintával) | alacsony |

**A "Te" chip-osztályzás (a prompt explicit kérdése) — verdikt:**
- **🔍 UI-találmány** (NEM 🟡), mert a SD-38 invariánsok kliens-oldali tükre **akció-szintű** előjelzés (disabled-button, locked-checkbox), nem **identitás-szintű** lista-chip; D-9 UD-4A konkrétan a RoleEditor + Deaktiválás-pattern-t rögzíti, nem self-aware identitás-chipet.
- **Pedagogiailag indokolt** azonban, és a SD-38 tág-szellemével konzisztens. **SF-51 spec-szelídítés-javaslat** vagy új D-X döntés (D-15? "Self-aware identitás-előjelzés a manager-listákon") — cross-screen érvényesítéssel az A8-listán túl az A7-csoport-tagok, A11-bejelentés-felelős, stb. helyeken.

**AUDIT-2 §3.3 `InviteCta` statikus pótlás:** a backward-pass-on **NEM UI-találmányként** kezeltük (AUDIT-2 explicit) — kanonikus `UserInviteDialog` organism-API-ra mappel; a HANDOFF.md-ben átadási megjegyzés rögzíti a retirement-feladatot (az Angular-portoláskor a `InviteCta.onClick` a kanonikus dialog-open-state-t triggereli).

**Új ⚠/🔍 jellegzetességek a Batch 3-ban (vs. Batch 1+2):**
- **Spec-bővítés-javaslatok szaporodása.** A Batch 1-ből hiányzottak, Batch 2-ben 1 (`Group.description` SF-43), Batch 3-ban 2 (`User.lastActiveAt` SF-52 + opcionálisan SF-48 `User.language` UI-fedés). A Beállítás-ági adatlap-mockok érdemi spec-felület-bővítést jeleznek.
- **A `UserInviteDialog` AUDIT-2 §3.3 pótlás** + **a "Te" chip 🔍** + **SD-38 tooltip-keveredés** együttesen a SD-38 invariáns-rendszer **UI-rétegének** spec-finomítás-igényét jelzi: D-9 UD-4A bake-in finomításra szorul (SF-50 + SF-51).
- **A delete-guard 409-confirm mock-state-klaszter** a Batch 3-ban **NEM jelenik meg** — az A8-on a deaktiválás-flow nem a `DELETE`-en megy, hanem a `POST .../deactivate`-en, és a `cannotRemoveLastManager` invariáns **proaktívan** (RoleEditor-locked + Deaktiválás-disabled) blokkolja a saját-deaktiválás-kísérletet. A SF-41-klaszter (A6 + A7 + A8) **valójában csak A6 + A7** — A8-on a `ConfirmDialog`-mintát csak akkor használnánk, ha **másik-user deaktiválás**-flow-on a `cannotRemoveLastManager` szerver-szintű 400-as válasz felugorna (a kliens-proaktívnak elkerülnie kellene; ha mégis felugrik, az **toast-szintű hiba-megjelenítés**, nem ConfirmDialog).
- **SF-41 klaszter felülvizsgálva:** csak A6 + A7 — az A8 deaktiválás-confirm rész **kihúzva** az SF-41 scope-ból (lásd SF-50 + Batch 3 ⚠ #4 megjegyzés).

---

---

# Batch 4 — A9 Általános

**Spec-fedés.** `00_domain_model` §3.2 (`Tenant` 11 mező — 7 meglévő `id/code/name/displayPrefix/dbConnectionRef/status/timeZone` + **4 új SD-58**: `logoFileRef/contactAddress/contactPhone/contactEmail`) + `30_beallitasok` §2.1 (Tenant-bővítés mezőtáblája) + §2.2 (új entitás `WeeklyReportRecipient` 4 mező: `id/name/email/isActive` + audit + tenant-szintű email-egyediség) + §3.3 (3 alszekció API + 1 PUT-mezőkészlet + 2 logó-multipart-végpont + standard CRUD a `WeeklyReportRecipient`-ra) + §4.4 (3 SettingsSection UI-szerződés) + **D-11** (T-1A locked-mezok info-tooltippal · L-1A dropzone · L-2A preview-meta-gombok · R-1A amber-tinted empty-card "saját e-mail" shortcut-tal).

**Screen.** `a9-beallitasok-altalanos.html` — 4 állapot (1 ReadOnly · 2 EditingTenant · 3 FirstTime-empty (nincs logó + nincs címzett) · 4 RecipientEdit).

**Organism-szerződés.** `TenantInfoForm` (`value` + `editing` + `onChange`; **locked-mezok**: `code`/`displayPrefix`/`timeZone` info-tooltippal D-11 T-1A) + `LogoUploader` (`logoUrl: null` → dropzone state / `logoUrl="__fallback__"` → preview-state meta-gombokkal) + `RecipientList` (`recipients` + `readOnly` vagy `editingId` inline-szerkesztés-állapot) + `SettingsSection` (title + description + opt. actions + body). 4 organism — mind kanonikus, AUDIT-2 §3.3 inline-pótlás itt **nincs**.

---

## Forward pass — `Tenant` 11 mező + `WeeklyReportRecipient` 4 mező + `TenantSettingsDto` derived + §3.3 6 végpont + §4.4 UI-szerződés

### ✅ Spec-ben + screen-en is megvan

| Spec-mező / végpont / UI-blokk | Spec-forrás | Screen-evidence |
|---|---|---|
| `Tenant.name` (max 200) | `00_domain_model` §3.2 + `30` §2.1 + §3.3.1 PUT-mezőkészlet | A9 `DEFAULT_TENANT.name: 'Balatonalmádi Városgondnokság'` — renderelve `TenantInfoForm`-on view + edit-mode-ban; State 2 EditingTenant a `React.useState`-en át text-input. |
| `Tenant.code` (max 50, **csak Urbino csapat módosíthatja**) | `00_domain_model` §3.2 + `30` §3.3.1 (4 mező CSAK olvasásra) + **D-11 T-1A locked** | `DEFAULT_TENANT.code: 'almadi'` — view-mode-ban mono-formátum + edit-mode-ban `disabled` input + info-tooltip "ezt csak az Urbino csapat módosítja". |
| `Tenant.displayPrefix` (max 10, bejelentés-id-prefix) | `00_domain_model` §3.2 + `30` §3.3.1 locked | `DEFAULT_TENANT.displayPrefix: 'ALM'` — locked. |
| `Tenant.timeZone` (IANA tz-string) | `00_domain_model` §3.2 + `30` §3.3.1 locked | `DEFAULT_TENANT.timeZone: 'Europe/Budapest'` — locked. |
| **`Tenant.logoFileRef`** (SD-58 új mező, S3-hivatkozás, `Attachment.fileRef`-mintával SD-15) | `30` §2.1 + §3.3.2 | A `LogoUploader.logoUrl` prop — 3 állapotú: `null` (nincs logó, dropzone) / `"__fallback__"` (sentinel string a mock-on a uploaded-state-hez) / valódi presigned-URL. State 1/2/4 uploaded; State 3 FirstTime `null`. |
| **`Tenant.contactAddress`** (SD-58, max 300) | `30` §2.1 + §3.3.1 PUT-mezőkészlet | `DEFAULT_TENANT.contactAddress: '8220 Balatonalmádi, Széchenyi sétány 1.'` — szerkeszthető a `TenantInfoForm`-on. |
| **`Tenant.contactPhone`** (SD-58, max 50, formátum-validáció nincs) | `30` §2.1 + §3.3.1 | `DEFAULT_TENANT.contactPhone: '+36 88 555 1234'`. |
| **`Tenant.contactEmail`** (SD-58, max 200) | `30` §2.1 + §3.3.1 | `DEFAULT_TENANT.contactEmail: 'info@balatonalmadi.hu'`. **Külön a `WeeklyReportRecipient.email`-től** (a §2.1 lábjegyzet explicit: `contactEmail` = polgári app "Ügyfélszolgálat"; `WeeklyReportRecipient.email` = riport-kézbesítés). |
| `TenantSettingsDto.logoUrl` (denormalizált, `logoFileRef`-ből presigned-URL, rövid TTL) | `30` §3.3.1 DTO-tábla | A `LogoUploader.logoUrl` prop fogyasztja a derived presigned-URL-t; `null` ha `logoFileRef == null` — a `LogoUploader` ekkor `state="empty"` (dropzone). |
| `WeeklyReportRecipient.id` (PK) | `30` §2.2 | A9 `RECIPIENTS_FULL[*].id` (1-4). |
| `WeeklyReportRecipient.name` (opcionális, max 200; ha üres, az UI az e-mailt mutatja) | `30` §2.2 | `RECIPIENTS_FULL[*].name` mind a 4 rekord kitöltött (`'Dr. Polgár Péter — polgármester'` / `'Nagy Tamás — alpolgármester'` / `'Hivatali titkárság'` / `'Tóth Béla — vezető'`). *(Az "üres-name → email-fallback"-eset a State 4 RecipientEdit-en sem mockolt — lásd ⚠ #1.)* |
| `WeeklyReportRecipient.email` (max 200, formátum-validáció, **tenant-szinten egyedi**) | `30` §2.2 + §3.3.3 | `RECIPIENTS_FULL[*].email` mind kitöltött (4 különböző domain-belüli e-mail). |
| `WeeklyReportRecipient.isActive` (default `true`, inaktív megmarad, de nem kap riport-emailt) | `30` §2.2 + AC-R3.4 | `RECIPIENTS_FULL[3].isActive: false` (Tóth Béla — vezető, inaktív) — a fejléc-count *"(3 aktív · 4 összesen)"* duplán számolja, jelezve az isActive differenciálást. *(Vizuális megjelenítés a sorszinten — lásd 🟡 #4.)* |
| §3.3.1 `GET /v1/tenants/settings` (saját-tenant TenantSettingsDto, SD-65) | `30` §3.3.1 | A `A9Screen` mock egy `DEFAULT_TENANT` objektumból render — implicit a GET-ekvivalens; az API-szerződés a 11 mezős DTO-t adja. |
| §3.3.1 `PUT /v1/tenants/settings` (4 szerkeszthető: name + contactAddress + contactPhone + contactEmail) | `30` §3.3.1 + SD-60 `field_not_editable` rejection | A `TenantInfoForm` editable-mezok pontosan 4 (`name`, `contactAddress`, `contactPhone`, `contactEmail`); a `code`/`displayPrefix`/`timeZone` `disabled` input — szerver-oldal `400 field_not_editable`-t ad ha bárki próbálná írni. |
| §3.3.2 `POST /v1/tenants/logo` (multipart, logó-feltöltés) + `DELETE` (logó-eltávolítás) | `30` §3.3.2 | `LogoUploader` 2 button: feltöltés (`onUpload`) + törlés (`onDelete`). State 3 FirstTime-on csak feltöltés-affordance (dropzone). |
| §3.3.3 standard CRUD a `WeeklyReportRecipient`-en (`GET` lista + `POST` + `PUT` + `DELETE`) | `30` §3.3.3 + SD-66 (40_riport SD-57 olvasó-elvárás formális teljesítése) | `RecipientList.recipients` lista (`GET`-ekvivalens) + `editingId` prop (`PUT`-kontextus) + `onAdd` + `onRemove` (a kanonikus organism szerződésén keresztül). |
| §4.4 3 SettingsSection (Tenant info / Logó / Recipients) — egy oldalon, scrollozható | `30` §4.4 + D-11 | A `A9Screen` 3 `SettingsSection`-t rendereli sorban — egyetlen scrollable page. |
| §4.4.1 Tenant info inline-szekciónkénti szerkesztés (NEM modal) | `30` §4.4.1 *"egyszerűsített elrendezés"* + D-9 inline-konzisztencia (SF-42 spec-szelídítés-csomag) | State 2 EditingTenant: a fejléc-szintű "Szerkesztés" gomb leváltja a szekciót edit-módba; a "Mégse / Mentés" `SaveRow` a szekció alján. |
| §4.4.2 Logó-uploader 2 állapota (üres dropzone vs. preview-meta-gombok) | `30` §4.4.2 + D-11 L-1A + L-2A | State 1/2/4 `logoUrl="__fallback__"` (uploaded preview-state filename + size + uploadedAt + uploadedBy meta-val); State 3 `logoUrl=null` (üres dropzone). |
| §4.4.3 RecipientList table-szerű olvasásra; inline-szerkesztés egy sorra egyszerre | `30` §4.4.3 | State 1 readOnly view; State 4 `editingId={2}` inline-szerkesztés (a 2. sor edit-módban). |
| §4.4.5 SD-61 induló-állapot-üres-card "saját e-mailem felvétele" shortcut + magyarázat | `30` §4.4.5 + D-11 R-1A | State 3 FirstTime `RecipientEmptyCard` amber-tinted card 2-button-tartalom: *"+ Saját e-mailem felvétele · `toth.bela@balatonalmadi.hu`"* + *"+ Új címzett"*. |
| AC-R1.2 — title-tooltip lockolt mezok | `30` §6 AC-R1.2 + D-11 T-1A | A `TenantInfoForm` `disabled` input + info-tooltip "ezt csak az Urbino csapat módosítja". |
| AC-R3.1 — tenant-szinten egyedi `WeeklyReportRecipient.email` (409 conflict) | `30` §6 AC-R3.1 | A `RecipientList`-szintű edit-mode-on az `EmailField` blur-on a `409 email_not_unique`-t a kanonikus organism kezeli (a screen-fájl-szintű mockon a hibakezelés-overlay nincs renderelt — lásd ⚠ #3). |
| AC-R3.4 — `isActive: false` címzett a következő riportból kimarad | `30` §6 AC-R3.4 | A `RECIPIENTS_FULL[3].isActive: false` mock-állapot + a fejléc-count differenciálás (3 aktív · 4 összesen). |

### ⚠ Spec-ben van, screen-en nincs — hiányosság

#### ⚠ #1 — `WeeklyReportRecipient.name` üres-eset fallback-render NEM mockolva
- **Spec.** `30` §2.2 mezőtábla: *"`name` opcionális. **Ha üres, a felület és a `resend`-megerősítő-dialógus az e-mailt mutatja**."*
- **Screen.** Mind a 4 mock-RECIPIENT kitöltött `name`-mel; az "üres-name → email-fallback"-eset egyetlen artboardon sem demonstrált.
- **Hatás.** A fejlesztő az Angular-portoláskor a `RecipientList` üres-name render-mintáját **csak a kanonikus organism-specimenből** látja (`manager-system/organisms/recipient-list.jsx` self-contained példányán át), nem screen-fájl-szintű composition-ből.
- **Javaslat.** **Mock-data-bővítés** — egy 5. RECIPIENT mock-rekord `name: '', email: 'titkar2@balatonalmadi.hu'`-mel a State 1 ReadOnly listán; vagy egy alternatív mock-szettel. Alacsony prioritás. **SPEC-FEEDBACK SF-56**.

#### ⚠ #2 — Email-uniqueness 409-validáció UI-hibakezelés mock-state nincs
- **Spec.** `30` §2.2 + §3.3.3 AC-R3.1 — *"tenant-szinten egyedi `email`; ütközéskor `409 email_not_unique`"*. A `[validationForm]`-minta szerinti UI-megjelenítés: a `EmailField` blur-on / form-submit-on `400`/`409` esetén field-error-megjelenítés (`u-input--error` modifier + `u-field-error` segéd-szöveg).
- **Screen.** State 4 RecipientEdit a 2. sort edit-módban mutatja, **ütközés-állapot nélkül**; a `u-input--error` + magyar-vetületű `409`-üzenet *"Ez az e-mail már szerepel a címzett-listán."* mock-state egyetlen artboardon sincs.
- **Hatás.** A fejlesztő nem látja, hogyan jelenik meg a `409 email_not_unique` UI-szinten. AC-R3.1 vizuális tükre hiányzik.
- **Javaslat.** **Mock-state-pótlás** — új 5. artboard `StateRecipientConflict` a State 4 mintára, de a 2. sor email-mezőjén `u-input--error` modifier + `u-field-error` hint: *"Ez az e-mail már szerepel a címzett-listán."* Alacsony-közepes prioritás. **SPEC-FEEDBACK SF-57**.

#### ⚠ #3 — `LogoUploader` upload-folyamat-állapotok (pending/uploading/error) NEM differenciáltak
- **Spec.** `30` §3.3.2 + AC-R2.1 (`POST /v1/tenants/logo` multipart, max 1MB, PNG/JPG/WEBP, max 2000×2000px). A pending upload (`Uploading…`) + sikertelen upload (méret-túllépés / formátum-hiba / 5xx) UI-mintát a `[validationForm]`-szerű hint-state-ek fednék.
- **Screen.** `LogoUploader` 2 állapot: empty (dropzone) + uploaded (preview-state). Az upload-folyamat-állapotok (`pending="uploading"` overlay + `error="file_too_large"` / `wrong_format`) nincsenek külön artboardokon.
- **Hatás.** A pilot-on a Béla a logót egyszer feltölti — a hibás-upload-flow (rossz méret, rossz formátum) ritka, de a UI-szerződésnek **rendelkezni kell** róla. AC-R2.1..R2.4 vizuális tükre részleges.
- **Javaslat.** **Mock-state-pótlás vagy organism-bővítés** — a `LogoUploader.jsx` organism-szinten egy `pendingState` + `errorState` prop, a screen-mock-on opcionálisan egy 6. artboard `StateLogoUploadError` a "fájl nagyobb, mint 1MB" / "csak PNG, JPG, WEBP elfogadott" magyar-vetülettel. Alacsony prioritás. **SPEC-FEEDBACK SF-58** (kombinálva a SF-47 + SF-57 mock-state-pótlás-klaszterrel).

### 🟡 Screen-en van, spec-ben nincs, DE D-X rögzíti

| Screen-elem | Hol jelenik meg | D-X hivatkozás |
|---|---|---|
| #1 `TenantInfoForm` 3 locked-mező (`code`/`displayPrefix`/`timeZone`) info-tooltippal *"ezt csak az Urbino csapat módosítja"* | `tenant-info-form.jsx` info-tooltip-popover | **D-11 T-1A** (spec §3.3.1 a 4 PUT-mezőt rögzíti; T-1A a 3 nem-szerkeszthető mezőhöz info-tooltip-pattern-t bake-in-eli) |
| #2 `LogoUploader` empty-state dropzone affordance (drag-drop-területe + "Tallózás" button) | `logo-uploader.jsx` State 3 | **D-11 L-1A** (a spec §4.4.2 csak "upload + preview"-t ír; az empty-state vizuális dropzone-mintát D-11 L-1A választja) |
| #3 `LogoUploader` preview-state meta-szöveg (filename + size + uploadedAt + uploadedBy) + cserélés + törlés gombok | `logo-uploader.jsx` State 1/2/4 | **D-11 L-2A** ("preview + meta-gombok"-pattern; a spec a meta-mezőket nem írja elő, D-11 L-2A audit-pedagógiai-bake-in) |
| #4 `RecipientList` inline-szerkesztés-állapot (`editingId` prop) — egyetlen sor edit-mode-ban egy időben | State 4 `editingId={2}` | **D-11 implicit** (a §4.4.3 *"inline-szerkesztés egy sorra egyszerre"*-spec-szelídítést bake-in-eli) |
| #5 `RecipientEmptyCard` amber-tinted card 2-button-tartalom + magyarázat *"a vezető saját magát is felveheti — érdemes így indulni"* | `a9-rec-empty` State 3 | **D-11 R-1A** + **spec §2.2 lábjegyzet** *"az induló állapot: a vezető nem kerül be automatikusan; első megnyitáskor informatív card 'saját e-mailem felvétele' shortcut-tal"* |
| #6 `RecipientEmptyCard` `'@'` ikon (36×36, amber-500 háttér, fehér karakter) | `a9-rec-empty__icon` | **D-11 R-1A pilot-ikonválasztás** — *(NB. 🔍 #2 alatt is — DS-konformitás-szempontból Lucide stroke-ikon javasolt)* |
| #7 `SettingsSection` saját-fejléc-toolbar "Szerkesztés" ghost-gomb a Tenant info + readOnly Recipients fejlécén | `SettingsSection.actions` slot | **D-11 + D-9 inline-szekciónkénti szerkesztés-konzisztencia** (a "Szerkesztés"-ghost-gomb Beállítás-ági pattern: A7 + A8 + A9) |
| #8 RecipientList fejléc-count duplán-számolás *"(3 aktív · 4 összesen)"* | `SettingsSection.title` interpoláció | **Pilot-pedagógiai bake-in** — a spec `isActive`-szabályt rögzíti, a count-duplázást D-11 nem említi explicit, de R-1A szellemén következik (vezető tudja, hány címzett aktív vs. inaktív). |
| #9 D-1 PageHeader-szintű CTA hiánya — az A9 NEM rendelkezik page-szintű elsődleges CTA-val | `A9Screen.PageHeader` actions-slot üres | **D-1 + spec §4.4** — az "Új címzett" CTA a 3. SettingsSection szintjén (NEM page-szintű); konzisztens (a Tenant info szerkesztés a szekció-szintű "Szerkesztés"-ghost-gombbal, a Logo upload a `LogoUploader` saját 2 gombjával). |

### 🔍 Screen-en van, spec-ben nincs, NEM dokumentált — UI-találmány

#### 🔍 #1 — **"péntek reggel 06:00"** literal — **direkt spec-konflikt** a `40_riport.md`-vel
- **Hol.** Mind a State 1 + State 2 + State 4 SettingsSection-leírás-szövegen *"Akik **péntek reggel 06:00-kor** megkapják a heti PDF-riportot e-mailben."* + State 3 FirstTime ugyanaz a literal. Plusz a `RecipientEmptyCard.a9-rec-empty__desc` *"A **pénteki riport-e-mail** nem megy ki senkihez, amíg fel nem veszel legalább egy címzettet."*
- **Spec — közvetlen ütközés:**
  - **`40_riport.md` §1.2 bevezetés (line 69):** *"E-mail-kézbesítés: **hétfő reggel** automatikus generálás az előző naptári hétre, e-mail-mellékletként a címzett-listának"*.
  - **`40_riport.md` §3.6 (line 475):** *"A generáló job. Egy ütemezett háttér-job minden **hétfőn reggel** (tenant-időzónában) fut..."*
  - **`40_riport.md` §3.6 (line 525):** *"a vasárnap 24:00 után **néhány órával** fut (hétfő reggel)..."*
  - **`30_beallitasok.md` §4.4** + `§4.4.3` — a recipient-szekció leírásában a konkrét időpont **NEM szerepel**; a `40_riport.md`-re hivatkozik.
- **Probléma — szóval:** a screen-mock a riport-kézbesítés időpontját **PÉNTEK 06:00**-ként hirdeti, miközben a spec szerinti generálás **HÉTFŐ reggel** történik. Ez nem hiányzó-precízió, hanem **direkt ténybeli ellentmondás** — a vezető a pilot-ban **hétfő reggel** kapja a múlt heti riportot, NEM péntek reggel.
- **Hatás.** **Súlyos pilot-félreértés-rizikó.** Béla a pilot-on a péntek reggelt várja a polgármester-leveléhez, és csak hétfőn érkezik meg. A polgármester ugyanígy — a riport-elvárás-időbenipattern félrekommunikálva.
- **Javaslat.** **Sürgős mock-korrekció — 3 helyen szövegcsere:**
  - 2× SettingsSection-leírás: *"Akik **péntek reggel 06:00-kor** megkapják..."* → *"Akik **hétfő reggel** megkapják..."* (vagy konkrétabban: *"hétfő reggel ~07:00-kor"* ha a `40_riport.md` időpontja precízálódik; lásd lent).
  - 1× RecipientEmptyCard-desc: *"A **pénteki** riport-e-mail..."* → *"A **hétfői** riport-e-mail..."*.
- **Plusz: SECONDARY 🔍 — a 06:00 konkrét időpont spec-szerinti hiányosság.** A `40_riport.md` §3.6 csak *"hétfő reggel"*-t mond, konkrét óra-precízió NEM. **Spec-szelídítés-javaslat:** a `40_riport.md` §3.6-ot precízálni *"hétfő reggel 06:00-07:00 között (a tenant-időzónában)"* mintával — így a vezető explicit várakozhat a riportra.
- **Hatás.** Mock-korrekció (HANDOFF.md sürgős átadási megjegyzés) + spec-precízálás-javaslat (`40_riport.md` §3.6). **SPEC-FEEDBACK SF-59** (**a Phase 2C legnagyobb spec-konfliktusa**).

#### 🔍 #2 — `RecipientEmptyCard.a9-rec-empty__icon` `'@'` karakter mint ikon — DS-konformitás
- **Hol.** State 3 `<div className="a9-rec-empty__icon" aria-hidden="true">@</div>` — 36×36px amber-500 háttér, fehér 18px `@` karakter Plus Jakarta Sans-ben renderelve.
- **Spec / DS.** `README.md` Iconography: *"System: Lucide — 1.5px stroke, rounded line caps, 24×24 default."* + *"A handful of Unicode glyphs are permitted as functional marks: ✓ → · …"* — DE: `@` nem szerepel az engedélyezett Unicode-glyph-szettben.
- **Probléma.** Pedagogiailag jó (a `@` szimbólum az e-mail-affordance-t kommunikálja), DS-konformitás-szempontból **karakter-ikon** ami sem Lucide stroke, sem engedélyezett Unicode-glyph.
- **Javaslat.** **Mock-korrekció** — `@` → `<Icon name="mail" size={20} />` (Lucide stroke-ikon, semleges email-affordance, a `--u-amber-500` háttéren fehér stroke-kal). **SPEC-FEEDBACK SF-60** (alacsony prioritás).

#### 🔍 #3 — A `LogoUploader.logoMeta` 4 derived-mezője (`filename` + `size` + `uploadedAt` + `uploadedBy`) — szerver-szerződés nincs explicit
- **Hol.** A `LOGO_META` mock: `{filename: 'balatonalmadi-logo.png', size: '12 KB', uploadedAt: '2026.05.10. · 14:22', uploadedBy: 'Tóth Béla'}` — renderelve `LogoUploader` preview-state alatt.
- **Spec.** `30` §3.3.1 DTO-tábla: `logoUrl` (derived presigned) + `logoFileRef` (S3-hivatkozás), DE a meta-mezok (`filename`/`size`/`uploadedAt`/`uploadedBy`) **nem szerepelnek a TenantSettingsDto-ban**. A `Tenant` `AuditableEntity` → `updatedAt`/`updatedBy`-t hordoz **tenant-szinten** (nem logó-szintűen); a logó-fájl-szintű audit (ki és mikor töltötte fel) **NEM része a spec-szerződésnek**.
- **Probléma.** A `LogoUploader` 4 derived-mezőt rendereli, ami **nem létezik a spec-DTO-ban**. Két opció:
  - **(a) Spec-bővítés:** `TenantSettingsDto.logoMeta: { filename, size, uploadedAt, uploadedBy }` — vagy szerver-oldali S3-objektum-metadata-feloldással (lazy, csak ha a kliens kéri), vagy a `Tenant` entitásra `logoFilename` + `logoSize` + `logoUploadedAt` + `logoUploadedBy` denormalizált mezők (4 új mező a 4-új-SD-58-on felül).
  - **(b) Mock-redukció:** `LogoUploader` preview-state meta-szöveg törlése; csak a fájl-kép-előnézet + 2 gomb (cserélés + törlés) marad.
- **Javasolt:** **(a) szelektív** — `uploadedAt` + `uploadedBy` érdemi pilot-érték (a Béla tudja, mikor töltötte fel utoljára), de `filename` + `size` minor (a vezető nem ezt a kérdést teszi fel). Spec-bővítés: a `Tenant` entitásra `logoUploadedAt: DateTimeOffset?` + `logoUploadedBy: User.id?` — 2 új mező a 4-SD-58 felül.
- **Hatás.** **SPEC-FEEDBACK SF-61** (spec-bővítés vagy mock-redukció).

#### 🔍 #4 — `RecipientList` fejléc-count *"(3 aktív · 4 összesen)"* literal-formátum
- **Hol.** `SettingsSection.title` interpolációja: ``Heti riport-címzettek (${RECIPIENTS_FULL.filter(r => r.isActive).length} aktív · ${RECIPIENTS_FULL.length} összesen)``.
- **Spec.** `30` §4.4.3 a recipient-szekció fejléc-formátumát NEM rögzíti; csak a táblázat-renderelést írja.
- **Probléma.** Pilot-pedagógiailag indokolt (a vezető azonnal látja az aktív/inaktív arányt), de a spec-konzisztencia szempontjából **screen-mock-saját stílusbéli döntés**. Az A8-lista TabFilter `'Aktív (4)'` `'Letiltva (1)'`-mintával stilisztikailag NEM kompatibilis.
- **Javaslat.** **NEM SF-tétel** — minor stilisztikai eltérés, OK megőrizni. *(Megjegyzés: opcionális finomítás — *"3/4 aktív címzett"* tömörebb forma, vagy a TabFilter-mintával harmonizált *"Aktív (3) · Inaktív (1)"*. Nem blokkoló.)*

#### 🔍 #5 — `SettingsSection.description` "A polgári app-ban és a heti PDF-riportban megjelenő tenant-adatok." + 2 további desc-szöveg
- **Hol.** State 1/2/4 minden SettingsSection-on `description` prop kitöltött:
  - Tenant info: *"A polgári app-ban és a heti PDF-riportban megjelenő tenant-adatok."*
  - Logó: *"A manager-felület fejlécében és a heti PDF-riport fejlécében jelenik meg."*
  - Recipients: *"Akik péntek reggel 06:00-kor megkapják a heti PDF-riportot e-mailben."* (🔍 #1-gyel együtt)
- **Spec.** `30` §4.4 az alszekció-leírást szabadon hagyja; a `40_riport.md` 4.2 hivatkozást írja a logó-megjelenítésre.
- **Probléma.** Pilot-pedagógikailag korrekt megfogalmazások; tone-of-voice OK ("polgári app" + "heti PDF-riport" tárgyilagos szóhasználat). NEM lényegi UI-találmány.
- **Javaslat.** **NEM SF-tétel** — D-11 implicit pilot-pedagogikai bake-in. *(Egy minor pontosítás: a `40_riport.md` szerint a riport "polgármester-felé kommunikálható", nem "polgári app"-pal egyenértékű — ez 2 különböző fogyasztó. A Tenant info desc-szövege ugyanazt mondja **mindkettőről** vegyesen — minor finomítás-lehetőség.)*

---

## Backward pass — A9 UI-elemek osztályzata

| UI-elem | Osztály | Megjegyzés |
|---|---|---|
| PageHeader title "Általános beállítások" + description | ✅ | Spec §4.1 + §4.4. |
| AppShell `active="altalanos"` + breadcrumb `['Beállítások', 'Általános']` | ✅ + 🟡 cross-cutting | Spec §4.1; D-14 Pattern N (SF-38). |
| 3 SettingsSection (Tenant / Logo / Recipients) egyetlen scrollable page | ✅ | Spec §4.4. |
| Tenant info `TenantInfoForm` view/edit-mode toggle | ✅ + 🟡 #1 | D-11 T-1A info-tooltip + spec §3.3.1 PUT-4-mezős szerződés. |
| 3 locked-mező (`code`/`displayPrefix`/`timeZone`) info-tooltippal | 🟡 #1 (D-11 T-1A) | Spec §3.3.1 a 4 PUT-mezőt rögzíti; D-11 a 3 nem-szerkeszthetőre tooltip-pattern. |
| EditingTenant `SaveRow` (Mégse / Mentés) | ✅ | Standard `[validationForm]`-pattern (`01_kozos_mintak` 5.5). |
| LogoUploader empty-state dropzone | 🟡 #2 (D-11 L-1A) | Spec §4.4.2 vizuális minta. |
| LogoUploader preview-state + meta-szöveg (filename + size + uploadedAt + uploadedBy) | partial — 🔍 #3 (SF-61) | Preview ✅, meta-mezok spec-DTO-n kívül. |
| LogoUploader 2 gomb (cserélés + törlés) | ✅ | Spec §3.3.2 + AC-R2.4. |
| LogoUploader upload-folyamat-állapotok (pending/error) NEM mockolva | ⚠ #3 (SF-58) | |
| RecipientList readOnly táblázatos megjelenítés | ✅ + 🟡 #4 (editingId pattern D-11) | |
| RecipientList inline-szerkesztés-mode (`editingId` prop) | 🟡 #4 (D-11) | |
| RecipientList sorszintű 4 mező (name + email + isActive + audit) — `name` üres-fallback nincs | partial — ⚠ #1 (SF-56) | |
| RecipientList email-uniqueness 409-validáció UI nincs mockolva | ⚠ #2 (SF-57) | |
| RecipientList fejléc-count *"(3 aktív · 4 összesen)"* | 🔍 #4 (NEM SF-tétel) | Minor stilisztikai eltérés. |
| RecipientEmptyCard amber-tinted + 2-gomb + magyarázat | 🟡 #5 (D-11 R-1A) | Spec §4.4.5 + SD-61. |
| RecipientEmptyCard `@` ikon | 🔍 #2 (SF-60) | DS-Lucide-konformitás. |
| "Új címzett" SettingsSection-szintű CTA | 🟡 #9 (D-11 + D-1) | A9 NEM rendelkezik page-szintű CTA-val — szekció-szintű. |
| SettingsSection-leírás-szövegek (3 desc) | 🔍 #5 (NEM SF-tétel) | Pilot-pedagógikai bake-in. |
| **"péntek reggel 06:00" literal mind 3 SettingsSection-on** | 🔍 #1 (**SF-59 — kritikus spec-konflikt**) | |
| `SettingsSubNav` HIÁNYA — D-14 Pattern N | 🟡 (cross-cutting SF-38) | A6 + A9 fájlokban halott `<script>` include (SF-38 (c)). |

---

## Batch 4 — záró összegzés

**Számok.** 19 spec-mező/végpont + 16 UI-blokk vizsgálva — **22 ✅** · **3 ⚠** (`name` üres-fallback + email-uniqueness 409-UI + logo-upload-folyamat-állapotok) · **9 🟡** (D-11 négy döntés + Beállítás-ági inline-szekció-pattern + D-1 page-CTA-pattern) · **5 🔍** (péntek-vs-hétfő spec-konflikt · `@` ikon · LogoMeta szerver-szerződés · count-format minor · description-tone minor; utóbbi 2 NEM SF-tétel).

**SF-tételek a Batch 4-ből.** 6 SF-tétel (SF-56..SF-61):

| # | Tétel | Kategória | Súly |
|---|---|---|---|
| SF-56 | `WeeklyReportRecipient.name` üres-eset fallback mock-data-bővítés | ⚠ mock-bővítés | alacsony |
| SF-57 | Email-uniqueness 409-validáció UI-hibakezelés mock-state-pótlás | ⚠ mock-state-pótlás | alacsony-közepes |
| SF-58 | `LogoUploader` upload-folyamat-állapotok (pending/error) mock-state vagy organism-bővítés | ⚠ mock-state-pótlás + organism-bővítés | alacsony |
| SF-59 | **"péntek 06:00" vs. spec "hétfő reggel" — direkt spec-konflikt** + spec-precízálás (40_riport §3.6 időpont) | 🔍 **mock-korrekció (sürgős) + spec-precízálás** | **MAGAS — kritikus** |
| SF-60 | `RecipientEmptyCard` `@` karakter-ikon → Lucide mail-stroke-ikon | 🔍 mock-korrekció (DS-konformitás) | alacsony |
| SF-61 | `LogoUploader.logoMeta` 4 derived-mező spec-bővítés (`logoUploadedAt`+`logoUploadedBy`) vagy mock-redukció | 🔍 spec-bővítés vagy mock-redukció | közepes |

**A Phase 2C legnagyobb találata.** A SF-59 (péntek vs. hétfő spec-konflikt) **kritikus pilot-félreértés-rizikó**: a vezető és a polgármester téves várakozással induló pilot-ja **érdemi UX-károkat okozhat**. A mock-korrekció (3 helyen szövegcsere) **azonnal beépítendő a HANDOFF.md-be sürgősség-megjelöléssel**; a spec-precízálás (`40_riport.md` §3.6 időpontprecízálás "hétfő reggel ~07:00") a Phase 3 spec-csapatának 1 mondat-átírás.

**Új jellegzetességek a Batch 4-ben.**
- **Spec-bővítés-szám tovább nő.** Batch 2: 1 (`Group.description`), Batch 3: 2 (`User.lastActiveAt` + esetleg `User.language`), Batch 4: 1-2 (`Tenant.logoUploadedAt/By` SF-61 + esetleg `40_riport.md` időpont-precízálás SF-59). Phase 2C **összesen 4 érdemi spec-bővítés-javaslat**.
- **`SettingsSubNav` halott script-include az A9 fájlban** — AUDIT-2 §3.4 dokumentált; SF-38 (c) része.

---

## Phase 2C — Záró összegzés

### Számok az ágon összesen

| Batch | Spec-mezők/végpontok | UI-blokkok | ✅ | ⚠ | 🟡 | 🔍 | SF-tételek |
|---|---|---|---|---|---|---|---|
| **1** A6 Kategóriák | 17 | 13 | 27 | 5 | 10 | 4 | SF-33..SF-38 (6) |
| **2** A7 Csoportok | 14 | 18 | 20 | 4 | 9 | 4 | SF-39..SF-46 (8) |
| **3** A8 Felhasználók | 24 | 28 | 30 | 4 | 13 | 5 | SF-47..SF-55 (9) |
| **4** A9 Általános | 19 | 16 | 22 | 3 | 9 | 5 | SF-56..SF-61 (6) |
| **Összesen** | **74** | **75** | **99** | **16** | **41** | **18** | **29 SF-tétel** |

Plusz **1 cross-cutting SF-tétel** a Batch 1-ben felvezetve (SF-38 D-14 Settings-nav, érvényes mind a 6 settings-screenre) — beleszámítva: **30 SF-tétel** a Phase 2C-ből.

### SF-tételek kategorizálva

- **Spec-bővítés-javaslatok** (érdemi entitás-bővülés): 4 db — SF-43 (`Group.description`) + SF-52 (`User.lastActiveAt`) + SF-61 (`Tenant.logoUploadedAt/By`) + SF-59 spec-precízálás (`40_riport` időpont).
- **Spec-szelídítés-javaslatok** (1-mondat-átírás vagy alapvető pattern-revízió): 6 db — SF-37 (§4.2.5 modal→inline) + SF-38 (Settings-nav Pattern N cross-cutting) + SF-42 (§4.3.2 modal→inline) + SF-44 (`Létrehozta` oszlop) + SF-48 (`User.language` UI-fedés) + SF-51 (D-9 UD-4A bővítés "Te" chip / új D-15).
- **Mock-state-pótlás** (új artboard-rétege): 4 db — SF-33 (A6 4-state) + SF-41 (A6+A7 delete-guard 409) + SF-47 (A8 invite-dialog open) + SF-57/SF-58 (A9 email-conflict + logo-upload-állapotok).
- **Mock-korrekció / organism-bővítés** (a kanonikus organism vagy screen-mock kód-szintű módosítás): 16 db — SF-34, SF-35, SF-36, SF-39, SF-40, SF-45, SF-46, SF-49, SF-50, SF-53, SF-54, SF-55, SF-56, SF-60 + a SF-43/SF-59 mock-korrekció-aspektusai.

### Kulcs-megfigyelések

1. **A Beállítás-ág spec-prescriptív voltát igazoltuk** — a 4 batchen összesen **18 🔍** UI-találmány-szintű tétel keletkezett (24%), szemben az A1 Bejelentés-ág (Phase 2A) ~40-45%-ával. A Beállítás-ági organismusok többsége (`CategoryTreeEditor`, `TenantInfoForm`, `LogoUploader`, `RecipientList`) hatékonyan tükrözi a spec-szerződéseket.
2. **A leghangsúlyosabb leletünk a SF-59** (péntek-vs-hétfő spec-konflikt) — **sürgős mock-korrekció szükséges** a HANDOFF.md-ben (3 helyen szövegcsere) + spec-precízálási javaslat. Pilot-félreértés-rizikó.
3. **Az SD-38 invariáns-rendszer UI-rétege** további spec-finomítást igényel (SF-50 tooltip-szöveg-keveredés + SF-51 "Te" chip identitás-előjelzés-pattern).
4. **A D-14 Settings-nav Pattern N** spec-szelídítése (SF-38) **a teljes Beállítás-ágon érvényes** — egységes spec-csapat-döntést igényel.
5. **AUDIT-2 §3.3 inline-pótlások** (A7 `MemberRow` + `.a7d-picker`; A8 `InviteCta`) **NEM UI-találmányok** — a backward-pass-on a kanonikus `GroupMemberList`/`UserPicker`/`UserInviteDialog` API-ra mappelve, retirement-feladat a HANDOFF.md-ben.
6. **SF-41 scope-finomítás Batch 3-ban** — az A8 deaktiválás-confirm rész **kihúzva** a delete-guard-klaszterből (proaktív invariáns-blokkolás D-9 UD-4A mintával, NEM ConfirmDialog).

### Phase 2C lezárható.

A teljes 4-batch fed (A6+A7+A8+A9) + a cross-cutting D-14 (SF-38) konszolidálva. A `SPEC-FEEDBACK.md` ági-fejezete **SF-33..SF-61** + a SF-41 scope-finomítás-megjegyzéssel **30 tétellel zárul**.

A következő chat-fázis: **Phase 2D** (A10 Felhasználói profil + A11/A12 — ha vannak ági képviselők), vagy közvetlenül **Phase 3** (átadási-csomag-konszolidáció: AUDIT-2 P1-fixek + SF-konszolidáció + HANDOFF.md generálás).
