# BACKLOG.md

> STRICT PATTERN (MUST FOLLOW EXACTLY)
> - Entry header: "- [TYPE] (BL-YYYYMMDD-###) TITLE"
> - Immediately followed by (exact keys, colon-space, indented 2 spaces):
>   - "  status: <EMOJI status-key>"
>   - "  priority: <low|medium|high|urgent>"
>   - "  source: <user|system|assistant>"
>   - "  area: <ui|backend|infra|docs|tests|ux|general>"
>   - "  details: <single-line summary>"
> - NO blank line between header and fields (parser reads i+1..i+5).
> - One blank line between entries (readability).
> - TYPE values: FEATURE, BUG, IMPROVEMENT, QUESTION, RESEARCH, TASK
> - STATUS EMOJI: ❌ ⏳ 🔄 ✅ ⚠️ ❓
> - IDs: unique, format BL-YYYYMMDD-### (increment ###).

- [IMPROVEMENT] (BL-20260518-003) LVS hybrid: BM25 corpus + numberOfCandidates pre-filter cache (FR-004 followup)
  status: ⏳ pending
  priority: low
  source: assistant
  area: backend
  details: A jelenlegi hybrid search minden vectorSearch hívásnál ujraepiti a BM25 corpus-t (O(N×|doc|)) és a cosine-t ALL candidate-re futtatja, nem csak top-N-re. ~100..10000 doc LVS-pool-ra elfogadható (ms-mp), de 100K+ doc + ~1KB/doc → ~100MB token allocation per query + GC pressure. Two-pronged optim: (1) opt-in BM25 index cache (corpus-key alapján, invalidate on data write), (2) `numberOfCandidates` érdemi haszna — cosine top-numberOfCandidates pre-filter, BM25 csak ezeken fut. CCAP RAG batch-hívásokra különösen releváns. Spec: lvs-bm25.util.ts (cache layer) + lvs-local-vector-search.data-service.ts (pre-filter branch hybrid módban).

- [IMPROVEMENT] (BL-20260518-002) LVS hybrid: Partial<hybridWeight> API ergonomics (FR-004 followup)
  status: ⏳ pending
  priority: low
  source: assistant
  area: backend
  details: A jelenlegi `vectorSearch({ ..., hybridWeight: { vector: number; text: number } })` típus mindkét mezőt kötelezővé teszi ha `hybridWeight` megadva. Ergonomikusabb: `hybridWeight?: Partial<{ vector: number; text: number }>` — `{ vector: 0.8 }` esetén `text` default 0.5 (vagy `1 - vector` semantic-szal). Default-merge a `vectorSearch`-ben: `wVector = hybridWeight?.vector ?? 0.5`, `wText = hybridWeight?.text ?? (1 - wVector)`. Non-breaking (jelenlegi `{vector:0.7,text:0.3}` továbbra is valid). 1-2 új spec a partial override-ra. Fájl: lvs-local-vector-search.data-service.ts:130 + spec extension.

- [BUG] (BL-20260518-001) FR-002 cost-event batch test mock/assertion mismatch
  status: ✅ done
  priority: medium
  source: assistant
  area: tests
  details: Fix opció (a) választva — mockEmbeddingsCreate.and.returnValue per-test override 2-elem data + usage:{prompt_tokens:10,total_tokens:10} a batch szándékát tükrözve. A spec-fájl `it('| createEmbeddings emits 1 cost-event with embedding-batch callType')` (oai-embedding.control-service.spec.ts:~275-290) override-ot kapott a top-level beforeEach (line 22-47) `prompt_tokens:5` default fölé. Verifikáció: `npx tsc` (build regenerate) + `npx jasmine` → 1232 specs / 0 failures. **Process root-cause azonosítva**: `spec/support/jasmine.json` `spec_dir: build/` — a jasmine a TS-fordított JS-ből fut, NEM a src-ből. A 08defee pre-commit smoke-ban `npx tsc --noEmit` (csak type-check, NEM emit) + `npx jasmine` futott → a `build/` STALE volt (az új teszt-em NEM volt benne), így a régi 1195 spec-pool fut zöldön, az új 10 spec-em sem assertelt. **5-stage cycle Test stage policy** (saját magamra): pre-commit jasmine futtatás MINDIG `npx tsc` (emit) ELŐZZE MEG, NEM `--noEmit`-tel ellenőrizni. Followup ez a process-tanulság a memóriába (feedback_test_locally_first kiegészítés).

- [FEATURE] (BL-20260517-002) Per-call cost-event hook on AI services (FR-002)
  status: ✅ done
  priority: high
  source: user
  area: backend
  details: CCAP CT_ cost-tracking blokkoló (MP3-C, MP4-D, MP6-D). Non-breaking, additív: új `DyNTS_AI_CostEvent` interface (callType, provider, model, tokensUsed: {input, output?, total}, durationMs, issuer, timestamp, estimatedCostUsd?) + `DyNTS_AI_CostEventCallback` type alias. `DyNTS_AI_Provider_ServiceBase`-en protected `onCostEvent?` field + protected `emitCostEvent(event)` safe helper (try/catch, log warn — callback hibája NEM akasztja meg az AI-call-t). OAI emit-helyek: `DyNTS_OAI_Embedding_ControlService.createEmbedding` ('embedding-single'), `.createEmbeddings` ('embedding-batch'), `DyNTS_OAI_LLM_ServiceBase.resolveMessage` ('llm-completion' ha 1 user-msg, 'llm-chat' ha több), `DyNTS_OAI_LLM_Chat_ServiceBase.resolveConversation` ('llm-chat'). Timing: Date.now() start/end, durationMs >= 0. Provider/model auto-resolved (this.aiProvider + String(callInput.model)). Constructor opt: `DyFM_OAI_Settings & { onCostEvent? }` intersection. `estimatedCostUsd` Dynamo-szinten mindig undefined (nincs pricing registry); CCAP CT_ consumer tölti ki. 'llm-tool-use' callType jövőbeli FR. Anthropic / FDP-AI provider-ek csak az alap-osztály onCostEvent mezőt öröklik (még nem implementálnak embedding/LLM-et, saját emit-helyek külön FR). oai-vector-data.service.ts SKIPPED — fájl nem létezik (a spec hivatkozása konceptuális). 10 új jasmine teszt (4 base + 4 embedding + 2 LLM + 1 constructor). Full suite: 1195/0. Spec: __agent/feature-requests/FR-002-per-call-cost-event-hook.md (workspace).

- [FEATURE] (BL-20260517-003) LVS hybrid search: cosine + BM25 text-match (FR-004)
  status: ✅ done
  priority: low
  source: user
  area: backend
  details: CCAP MVP3-candidate — exact-identifier matchre (UserController, REQ-RAG-MGMT-001) BM25 felülmúlja a pure cosine-t. Implementálva: LVS_Search_Mode.hybrid enum value + vectorSearch signature bővítés `hybridWeight?: {vector,text}` (default 0.5/0.5) + `textSearchKey: keyof T` (required hybrid módban). Pure-TS DyNTS_LVS_BM25_Corpus util (canonical k1=1.2 b=0.75, [\w]+ tokenizer case-insens, BM25+ IDF formula). Hybrid pipeline: cosine ALL candidate-re + BM25 ALL candidate-re + min-max [0,1] norm + weighted linear sum + sort desc + top-N slice. Throws: VS4 (missing textSearchKey) + VS5 (invalid hybridWeight). All-zero BM25 → effective cosine-only fallback. Non-breaking: új enum value + új optional params. Specs: 20/20 BM25 util + 8/8 hybrid (1232 spec total / 1 pre-existing FR-002 unrelated failure). Scope-out: MongoDB Atlas $search DB-backed variant (külön ticket), L2+hybrid kombinacio (explicit reject).

- [FEATURE] (BL-20260517-001) Generic compareData() method a DyNTS_DataService base-en (FR-001)
  status: ✅ done
  priority: high
  source: user
  area: backend
  details: CCAP RAG-blokkoló (MP3-B, MP5-A/D/E/F) — eddig csak DyNTS_LVS_DocChunkDataService.compareChunk volt DocChunk-T-specifikus delta-detection; non-DocChunk RAG-okra (Rules/Knowledge/CodingPatterns/Memory) anti-DRY. Implementálva: `compareData(newData, oldData, options?): { result: 'equal'|'modified', changedFields? }` a base-en (sync), default deep-equal (primitive/Date/Array/POJO + Object.is fallback), DyFM_Metadata skip (_id, __created, __createdBy, __lastModified, __lastModifiedBy), `options.fields` scope-szűkít (+ skip-list-override), `options.customComparators` per-field, throw 400 (DyNTS-DS0-CD1) null input + 400 (DyNTS-DS0-CD2) üres fields. Non-breaking: új optional method; meglévő compareChunk változatlan. Spec: __agent/feature-requests/FR-001-generic-compareData.md (workspace). 15/15 új jasmine spec + 1195/0 full suite zöld.

- [FEATURE] (BL-20260417-001) Dynamo NTS kliens kiszolgálás képesség
  status: ✅ done
  priority: medium
  source: user
  area: backend
  details: Alkalmassá kell tenni a Dynamo NTS-t, hogy kiszolgálja a klienst (frontend/client-side serving). Audit eredménye (2026-05-17): a capability MÁR implementálva van 2026-03-30 óta (commit 8ffe535) — DyNTS_App_Server.mountStaticClient() + getStaticClientSettings?() opt-in override + DyNTS_StaticClient_Settings interface (root, fallbackPath, assetCacheMaxAge, assetCacheImmutable, fallbackCacheMaxAge). Featureset: Express.static mount /-en az API route-ok után, SPA fallback sendFile-lal, asset+fallback Cache-Control (Angular hashed fájl optimalizálásra), default 404 HTML ha nincs fallbackPath, mindkét http/https express-en mount. Integration test megvan (app-extended.integration.spec.ts + app-integration-test.mock.ts). How-to doc: __documentations/2026-05-17-static-client-serving-howto.md (config matrix + example subclass + cache stratégia + edge case-ek).

- [FEATURE] (BL-20260420-001) Átfogó file-based log kezelési rendszer
  status: ✅ done
  priority: medium
  source: user
  area: backend
  details: Config-vezérelt log rendszer, ahol egy boolean flag-gel be lehet kapcsolni a file-ba történő log írást, és további config opciókkal lehet állítani a maximum tárolt log mennyiséget (file size / rotation / retention) és egyéb log kezelési paramétereket. Implementálva (2026-05-17): DyNTS_FileLog_Service (singleton) — process.stdout/stderr.write monkey-patch, per-session log fájl, sync appendFileSync (crash-safe), config: file_log.{enabled, logDir, filenamePrefix, maxFileSizeMb, maxFiles, retentionDays, stripAnsi, includeStdout, includeStderr}. Rotation size-limitre, retention by count + age (ami előbb teljesül). Silent failure (file IO sosem blokkolja a szervert). Spec: 11 spec / 0 fail. Full suite: 1133/0. Smoke verified.

- [FEATURE] (BL-20260420-002) Admin API key alapú authentikációs réteg (env-ből)
  status: ✅ done
  priority: high
  source: user
  area: backend
  details: Új admin authentikációs mechanizmus bevezetése, ahol az admin API key-t environment variable-ből olvassuk (pl. DYNTS_ADMIN_API_KEY), és ezzel lehet védeni az érzékeny / admin endpointokat. Implementálva (2026-05-17): DyNTS_AdminApiKey_AuthService (singleton) — preProcess `.verify(req, res)` fn opt-in átadható `DyNTS_Endpoint_Params.preProcesses`-be vagy `DyNTS_getLogsRoutingModule({ authPreProcess })`-be. Default env var DYNTS_ADMIN_API_KEY, header x-admin-api-key + Authorization Bearer fallback. Konfig: `configure({ envVarName, headerName, allowAuthorizationBearer })`. Timing-safe compare (crypto.timingSafeEqual + length-mismatch dummy compare). Hibák: 500 ha env nincs, 401 ha header hiányzik/rossz. Env minden híváskor olvasott (nem cache-elt). 15/15 spec + 1148/0 full suite + smoke verifikálva. Foundational a BL-003 (log fetch) és BL-004 (errors retrofit) entry-knek.

- [FEATURE] (BL-20260420-003) Server log file-ok lekérése admin endpointon keresztül
  status: ✅ done
  priority: medium
  source: user
  area: backend
  details: A BL-20260420-001 file-based log rendszerre épülve egy új endpoint, amin keresztül le lehet kérni a szerverről a kiírt log file-ok tartalmát (pl. paged / range / tail módon). Implementálva (2026-05-17): DyNTS_FileLogs_Controller (GET /list + GET /file/:filename) + DyNTS_getFileLogsRoutingModule() factory + DyNTS_FileLog_Service bővítés (listLogFiles, readLogFile, getCurrentLogFilename). Olvasási módok: tail / head / range (max 10000 sor). Safeguards: filename whitelist regex prefix-szel, path traversal védelem (resolvedPath + sep ellenőrzés), 503/404/400 helyes status code-ok. Auth opt-in: `DyNTS_getFileLogsRoutingModule({ authPreProcess: adminAuth.verify })`. Default route /file-logs. 38/38 FileLog spec (24 service + 14 controller) + 1175/0 full suite + smoke 4/4 verifikálva.

- [IMPROVEMENT] (BL-20260420-004) Errors endpointok opcionális admin API key védelme
  status: ✅ done
  priority: medium
  source: user
  area: backend
  details: A BL-20260420-002 admin API key auth réteget opcionálisan rá kell tudni húzni a meglévő DyNTS_Errors_Controller endpointjaira (errors.controller.ts) is, hogy érzékeny error-listázó / kezelő endpointok admin auth mögé kerülhessenek. Implementálva (2026-05-17): static `DyNTS_Errors_Controller.configure({ authPreProcess?, protectedEndpoints? })` — opt-in, default = no auth (backwards compatible). `authPreProcess` jelenléte esetén default mind a 8 endpoint védett, vagy `protectedEndpoints` subset-tel fine-grained kontroll. `getAuthConfig()` + `_resetAuthConfigForTesting()` segéd-fnk-ek. Per-endpoint `preProcesses: this.getPreProcessesFor(name)` thread-elve mind a 8 endpoint-konstrukcióba. 16/16 errors controller spec (11 régi backwards-compat + 5 új retrofit) + 1180/0 full suite + smoke 3/3 (default, full, subset).
