From ef9db696ffc0abed3abac8846e42211fd967d086 Mon Sep 17 00:00:00 2001 From: godavid Date: Tue, 27 Oct 2026 14:20:53 +0100 Subject: [PATCH] =?UTF-8?q?docs:=20hypo=20higi=C3=A9nia-k=C3=B6r=202026-10?= =?UTF-8?q?-27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AGENTS.md újraírva: Állapot (a csomag nincs az npm-en, a név szabad), olvasási sorrend, ütközési szabály, szabályok, hét pontos invariáns, kódtérkép, rangsorolt csapdalista, triggerek, szótár, nyelv, landolás. - CLAUDE.md symlink az AGENTS.md-re. - SKILL.md: npx-tiltás a description mezőben, pontos hostlista és Node-tartomány, git-őr, --since és --json kivételek, kilépési kódok (4-es: nincs képernyőképes nyilvános issue; 5-ös: failures[] alak). - README.md: forrásból telepítés receptje, pontos hostlista, git-őr, képernyőkép-szabály, szintetikus eid a mintában, CI-sorrend. - INVARIANT-kommentek a src/kau/login.ts és a src/tarhely/api.ts fájlban (csak komment, viselkedés nem változik). Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 191 ++++++++++++++++++++++++++++++++++-- CLAUDE.md | 1 + README.md | 69 +++++++++---- skills/tarhely-cli/SKILL.md | 84 +++++++++++----- src/kau/login.ts | 8 +- src/tarhely/api.ts | 5 + 6 files changed, 307 insertions(+), 51 deletions(-) create mode 120000 CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md index da98d71..a57826b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,12 +3,189 @@ Ez a repó a `tarhely-cli` npm-csomag: Ügyfélkapu+ belépés és a hivatali tárhely leveleinek letöltése, csak olvasó módban. -- **Használathoz** (nem fejlesztéshez) a skill a mérvadó: `skills/tarhely-cli/SKILL.md`. +> **Állapot (2026-10-27):** az npm-csomag még nincs közzétéve (`npm view tarhely-cli` +> → E404), és a név nincs lefoglalva. Amíg ez a bekezdés itt áll, ne futtass és ne +> javasolj `npx tarhely-cli …` vagy `npm install -g tarhely-cli` parancsot: idegen kódot +> futtatna, és az `init` annak adná át a belépőt. Helyben: +> `pnpm install --frozen-lockfile && pnpm build`, majd `node dist/cli.js `. +> A CLI saját tanácsai még `npx tarhely-cli …`-t írnak (az 1-es, 2-es és 3-as kód `hint`-je, +> a `doctor` `belepo` ellenőrzésének `detail`-je, az `init` zárósora: `src/errors.ts`, +> `src/store/credentials.ts`, `src/commands/doctor.ts`, `src/commands/init.ts`, +> `src/browser.ts`). Ezeket ne add tovább szó szerint: közzétételig `node dist/cli.js …` +> alakban mondd a felhasználónak. +> A közzététel után ezt a bekezdést töröld (a többi helyet lásd: Ha ehhez nyúlsz, npm-kiadás). + +## Olvasási sorrend + +1. Ez a fájl: szabályok, invariánsok, kódtérkép, csapdák. +2. Használat, CLI-felület, JSON-kimenet, kilépési kódok: `skills/tarhely-cli/SKILL.md`; + felhasználói leírás: `README.md`. +3. A módosított forrásfájl fejléc-kommentje (ha van) és a tesztje: `test/.test.ts`, + kivéve `src/main.ts` → `test/cli.test.ts` és `src/store/index.ts` → + `test/index-store.test.ts`. Saját teszt nélkül: `src/cli.ts`, `src/errors.ts`, + `src/index.ts`, `src/prompt.ts`, `src/kau/login.ts` és a `doctor`-on kívüli + `src/commands/*`. A `test/session.test.ts` csak a `selectMailboxes`-t nézi, a + `withSession`-t nem; a `src/tarhely/mailbox.ts`-ből a `test/inbox.test.ts` csak az + egypostafiókos utat járja be. + Ezeknél a zöld fókuszált futás nem bizonyíték. + +Ütközésnél a kód és a teszt a mérvadó; az eltérő doksit ugyanabban a PR-ben javítsd. +Kivétel az Invariánsok: ha a kód lazább náluk, az hiba, és a doksit csak emberi döntés után +igazítsd hozzá. Doksik között használati kérdésben (parancs, kapcsoló, JSON, kilépési kód) a +`SKILL.md`, fejlesztési kérdésben ez a fájl a mérvadó. + +## Szabályok + +- **Használathoz** (nem fejlesztéshez) a skill szól: `skills/tarhely-cli/SKILL.md`. Telepítés: `npx skills add godavid/tarhely-cli`. - **Belépőt soha ne kérj a chatben** és ne írj fájlba. A felhasználó a saját - terminálában futtatja: `npx tarhely-cli init`. -- **Fejlesztéshez**: `pnpm install`, `pnpm test`, `pnpm typecheck`, `pnpm lint`, - `pnpm build`. A forrás `src/`, a tesztek `test/`. Tesztfixture csak szintetikus - (`Példa Kft.`, `12345678`); valódi név, törzsszám, érkeztetési szám nem kerülhet a repóba. -- **Invariánsok**: csak `*.gov.hu` hálózat (`src/browser.ts` allowlist); a portálon csak - olvasó végpontok (`src/tarhely/api.ts`); a belépési lépésekről nincs képernyőkép. + terminálában futtatja az `init`-et (közzétételig `node dist/cli.js init`, lásd Állapot). +- **Élő portál csak a tulajdonos kérésére.** A `mailboxes`, `list`, `download` és `init` + valódi Ügyfélkapu+-belépést indít a gépen tárolt belépővel (kulcstartó vagy env), vagyis a + gép tulajdonosának saját hatósági fiókjával. A `download` hatósági iratokat tölt le; a + letöltés jogi hatása (átvétel) nincs tisztázva. Fejlesztés és hibakeresés közben ezeket ne + futtasd magadtól: az alap a szintetikus teszt (`test/`). Élő próba csak kifejezett kérésre, + `--max`-szal és repón kívüli `--out` mappával. A `forget` törli a tárolt belépőt: az is csak + kérésre. A `doctor` és a `--help` belépés nélkül fut, ezek szabadok. +- **Fejlesztéshez**: `pnpm install --frozen-lockfile`. Helyben fókuszáltan ellenőrizz: + `pnpm exec vitest run test/.test.ts`, `pnpm exec biome check `, típushibára + az editor (LSP) diagnosztikája; a CLI-t `pnpm build` után `node dist/cli.js --help`-pel + próbáld. A teljes kör a CI-ban fut (lásd Landolás és CI). A forrás `src/`, a tesztek `test/`. +- **Tesztfixture csak szintetikus** (`Példa Kft.`, `12345678`, `000000012026010100000001`); + valódi név, törzsszám, érkeztetési szám nem kerülhet a repóba. +- **Publikus repó.** Más (privát) projektek neve, útvonala, belső azonosítója nem kerülhet + ide: se kódba, se doksiba, se commit- vagy PR-szövegbe. Ha a származás számít, + személytelenül írd („a szerző saját rendszeréből”). + +## Invariánsok + +- **Hálózat**: a böngésző csak az `ALLOWED_HOSTS` hostjaira mehet: `kau.gov.hu`, + `*.kau.gov.hu`, `idp.gov.hu`, `tarhely.gov.hu`, `*.tarhely.gov.hu` (`src/browser.ts`, + `context.route`). Ez nem a teljes `*.gov.hu`, és az `idp.gov.hu` aldomainjei sincsenek + benne. A listát a `test/browser.test.ts` rögzíti; bővítése emberi döntés. Böngészőn kívül + csak a `doctor` hálózati próbája (`TARHELY_URL`) és az `init` Chromium-letöltése megy ki. +- **Csak olvasás**: a portál REST-hívásai a `src/tarhely/api.ts`-ben vannak: + `POST /uzenetek/BEERKEZETT/kereses` (keresés), `GET /uzenet/beerkezett/{eid}`, + `GET /uzenet/letoltes/beerkezett/{eid}`, `GET /mailbox/details`; a `/mailbox/reload` + választ csak figyeli. A felületen csak postafiók-váltás és felugró ablak bezárása + történik (`src/tarhely/mailbox.ts`). Küldés, törlés, áthelyezés, címkézés tilos. Teszt + nem őrzi. +- **Diagnosztika**: képernyőkép és aria-snapshot csak a `withSession` hibaágán + (`src/session.ts`), a `reporter.capture`-rel (`src/report.ts`), `--debug-dir` mellett. Két + eset ad képet: a titkok előtti, `capturable = true` hiba (`src/kau/login.ts`, a KAÜ-gomb + lépése) és a sikeres belépés utáni hiba. A titkok begépelése és a sikeres belépés között + soha. A belépés utáni kép és `.aria.yaml` a postafiók leveleit mutathatja; alapjoggal, + git-őr nélkül íródik, ezért nyilvános issue-ba csak kitakarva kerülhet. Teszt nem őrzi. +- **Belépő**: csak a rendszer-kulcstartóban (service `tarhely-cli`, account `default`) vagy + env-ben (`TARHELY_USERNAME`, `TARHELY_PASSWORD`, `TARHELY_TOTP_SEED`: mind a három vagy + egyik sem, különben 2-es kód); fájlba vagy parancssori argumentumba soha + (`src/store/credentials.ts`, `test/credentials.test.ts`). +- **Letöltési mappa**: git-munkafán belüli, nem ignorált `--out` mappába a `download` nem ír, + 1-es kóddal leáll (`src/outdir.ts`, `test/outdir.test.ts`). Másik repóban futva ezért + repón kívüli `--out` mappát adj meg (ebben a repóban az alap `tarhely/` ignorált). A + letöltött mappák `0700`, a fájlok `0600` joggal jönnek létre (`src/tarhely/inbox.ts`, + `src/store/index.ts`, `src/extract.ts`). +- **Postafiók-elszigetelés**: minden API-hívás `address-id` fejléce egyezik a kért + postafiókéval; eltérésnél 4-es kód, mert más postafiók iratai jönnének (`apiHeaders`, + `src/tarhely/api.ts`; `test/api.test.ts`). +- **Zip**: kilépő vagy abszolút útnál, 2000-nél több bejegyzésnél vagy 200 MB fölötti + kibontott méretnél a kibontás leáll (`src/extract.ts`). A `test/extract.test.ts` az + útvonal-szűrést és a 2000-es korlátot őrzi, a 200 MB-osat nem. + +## Kódtérkép + +A rétegek körmentesek. Az egyedüli gazdák biztonsági határok: ne kerüld meg őket. + +| Terület | Feladat | Importálhat | Tilos / egyedüli gazda | +|---|---|---|---| +| `src/cli.ts`, `src/main.ts` | bin-belépés; `parseCli`, `USAGE`, diszpécser | `commands/*`, `report`, `errors`, `store/credentials` | – | +| `src/commands/` | fájlonként egy parancs; kimenet a riporteren át | `session`, `store/credentials`, `tarhely/inbox`, `browser` (`isChromiumInstalled`), `outdir`, `prompt`, `report`, `errors`, `kau/totp`, `tarhely/api` (csak `TARHELY_URL`) | `kau/login`, saját böngésző, képernyőkép; `fetch` csak a `doctor` hálózati próbája | +| `src/session.ts` | `withSession`: belépő, böngésző, KAÜ-belépés, API-fejlécek, diagnosztika | `browser`, `kau/login`, `tarhely/api`, `report`, `store/credentials`, `errors` | egyedül hívja a `loginToKau`-t és a `reporter.capture`-t | +| `src/browser.ts` | Chromium, hálózati allowlist | `errors` | egyedül indít böngészőt (`chromium.launch`, `context.route`) | +| `src/kau/` | KAÜ-belépés (`login.ts`), TOTP (`totp.ts`) | `errors`, egymás | `tarhely/`, `session`, `report`, `store/` | +| `src/tarhely/` | portál-API (`api.ts`), postafiók-váltás (`mailbox.ts`), lista és letöltés (`inbox.ts`) | `errors`, `extract`, `store/index`, egymás; `kau/login` és `session` csak típusként | `browser`, `store/credentials`, `report`; lapon belüli `fetch` csak az `api.ts`-ben | +| `src/store/` | belépő (`credentials.ts`), jegyzék (`index.ts`, `/index.jsonl`) | `errors` | a belépőt csak a `credentials.ts` olvassa és írja | +| `src/report.ts` | JSON- és emberi kimenet, `--debug-dir` capture | `errors`; `kau/login` csak típusként | JSON-t a stdout-ra csak ez ír | +| `src/errors.ts`, `extract.ts`, `outdir.ts`, `prompt.ts` | kilépési kódok; zip; git-őr; terminál-bekérés | `errors` | – | +| `src/index.ts` | könyvtári újraexport | bármit | ami innen kimegy, nyilvános API | +| `test/` | vitest, szintetikus fixture | `src/*` | valódi portál, belépő, hálózat | + +## Ismert csapdák (a legdrágább elöl) + +1. **Képernyőkép vagy aria-snapshot a belépőmezők kitöltése után.** Miért: a jelszó és a + TOTP-kód bekerül az artefaktumba. Helyette: diagnosztika csak a `withSession`-ön át; + titok előtt `capturable = true`, egyébként csak sikeres belépés után. +2. **Az `ALLOWED_HOSTS` bővítése (pl. `*.gov.hu`).** Miért: a belépő kijuthatna az + allowlistről. Helyette: konkrét host, emberi jóváhagyással. A `test/browser.test.ts` őrzi. +3. **REST-hívás az `apiRequest`-en kívül, vagy író végpont (küldés, törlés, áthelyezés).** + Miért: a csomag ígérete a csak olvasás. Helyette: új hívás csak olvasó végponttal, a + `src/tarhely/api.ts` `apiCall`/`apiRequest` függvényén át. +4. **Valódi név, törzsszám, érkeztetési szám vagy privát projektnév a repóban.** Miért: + publikus repó, és a gitleaks ezeket nem fogja meg. Helyette: `Példa Kft.`, `12345678`, + `000000012026010100000001`. +5. **DOM-os letöltés (kijelölés, toolbar, modál).** Miért: élesben sorra eltört. Helyette: a + REST API (`downloadLetter`). +6. **String átadása a `page.evaluate`-nek.** Miért: a Playwright kifejezésként értékeli, az + argumentum elvész. Helyette: valódi függvény (`fetchInPage`). +7. **Kattintás a KAÜ-gombra a KAÜ-lap `load` eseménye előtt, vagy fix várakozás.** Miért: a + lenyíló nem köt be („intercepts pointer events”). Helyette: `waitForKauPage` és az + `aria-expanded` ellenőrzése (`src/kau/login.ts`). +8. **„Közvetlen futás” ellenőrzés a `src/cli.ts`-ben (`import.meta.url` és `argv[1]` + összevetése).** Miért: npx/pnpm symlinken a CLI némán semmit nem tesz. Helyette: a + `cli.ts` mindig futtat, a logika a `main.ts`-ben él. +9. **`require.resolve("playwright/cli")`.** Miért: a playwright nem exportálja ezt az + útvonalat. Helyette: `dirname(require.resolve("playwright/package.json"))` + `cli.js` + (`src/commands/init.ts`). +10. **Az `erkezesiDatum` helyi időként olvasása.** Miért: nyári időszámításban két órát + csúszik, rossz nap kerül a mappanévbe. Helyette: UTC-ben (`apiRow`). A teszt ezt nem + fogja meg, mert a CI UTC-ben fut. + +## Ha ehhez nyúlsz + +- **Parancs, kapcsoló, kilépési kód vagy JSON-mező**: `src/main.ts` `USAGE`, + `skills/tarhely-cli/SKILL.md` és `README.md` ugyanabban a PR-ben. +- **`ALLOWED_HOSTS`**: `test/browser.test.ts`, a host-lista ebben a fájlban, a `README.md`-ben + és a `SKILL.md`-ben; emberi jóváhagyással. +- **Portálhívás vagy felületi kattintás**: Invariánsok, „Csak olvasás”. +- **`skills/tarhely-cli/SKILL.md`**: a `main`-ről közvetlenül települ külső agentekhez + (`npx skills add godavid/tarhely-cli`), ezért csak már működő viselkedést írj bele. A + frontmatter Agent Skills-érvényes marad (`name: tarhely-cli`, egyezik a mappanévvel). +- **`hint`, `detail` vagy hibaszöveg** (főleg `src/errors.ts`, `src/store/credentials.ts`, + `src/browser.ts`, `src/commands/doctor.ts`): az agentek szó szerint továbbadják. Titok nem + kerülhet bele, és nem buzdíthat képernyőkép, `.aria.yaml` vagy levéltartalom nyilvános + feltöltésére. A `SKILL.md` Kilépési kódok táblája ugyanabban a PR-ben. +- **npm-kiadás** (`npm publish`, csak a tulajdonos kérésére): ugyanabban a PR-ben töröld az + „Állapot” bekezdést és a rá utaló „közzétételig” megjegyzéseket ebből a fájlból, a + `README.md`-ből (a magyar és az angol részből) és a `SKILL.md`-ből, a `SKILL.md` + `description` mezőjének „not published yet” mondatát is. + +## Szótár + +- **KAÜ**: Központi Azonosítási Ügynök (`kau.gov.hu`). **Ügyfélkapu+**: KAÜ-belépés + felhasználónévvel, jelszóval és TOTP-kóddal. +- **tárhely / hivatali kapu**: a `tarhely.gov.hu` postafiók-portál. Az **Értesítési + tárhely** a személyes postafiók neve a portálon. +- **postafiók** (`MailboxRef`): egy belépővel látható fiók (személyes vagy képviselt cég); + `slug` a mappaneve, `addressId` a portál `address-id` fejléce. +- **eid**: érkeztetési szám (API: `erkeztetesiSzam`), a levél azonosítója és az + `index.jsonl` kulcsa. +- **TOTP-seed**: a hitelesítő alkalmazás base32 kulcsa. +- **`kibontva/`**: a zip tartalma a levél mappáján belül. + +## Nyelv + +Doksi, kódkomment, commitüzenet és PR magyarul; a tesztcímek (`it(...)`) angolul. A +`README.md` végén az angol összefoglaló marad; a `SKILL.md` `description` mezőjében az angol +trigger-szavak maradnak. + +## Landolás és CI + +- Magyar conventional commit (`type(scope): leírás`), PR a `main`-re, squash merge `(#n)` + utótaggal. A `main`-re közvetlenül ne pusholj. +- CI (`.github/workflows/ci.yml`, `check` job, minden PR-en és a `main`-re pusholáskor): + `pnpm install --frozen-lockfile` → `pnpm lint` → `pnpm typecheck` → `pnpm test` → + `pnpm build` → gitleaks a teljes git-történeten. Titok a történetben is bukást okoz, és + törlés után is ott marad (publikus repó). +- A Markdown formáját és tartalmát semmi nem ellenőrzi: a `biome.jsonc` csak a `src/`, a + `test/` és a JSON-fájlokat nézi. Titokmintára viszont a gitleaks a Markdownt is átvizsgálja + a teljes történetben, ezért valódinak tűnő példa-jelszó vagy -seed a doksiba se kerüljön. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/README.md b/README.md index 40be646..d1b187f 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,24 @@ Letölti a hivatali tárhelyed (tarhely.gov.hu) beérkezett leveleit a gépedre, Ügyfélkapu+ belépőddel, parancssorból. **Csak olvas**: a portálon semmit nem küld, nem töröl, nem helyez át. Nem hivatalos eszköz, nincs köze az államhoz. +> **Állapot (2026-10-27): az npm-csomag még nincs kiadva.** Az `npx tarhely-cli …` és az +> `npm install -g tarhely-cli` most 404-es hibával bukik. Ha közben valaki más ad ki ilyen +> nevű csomagot, az `npx` az ő kódját futtatná, és az `init` neki adná a jelszavadat és a +> TOTP-seededet. Addig forrásból futtasd: +> +> ```bash +> git clone https://github.com/godavid/tarhely-cli +> cd tarhely-cli +> # Node.js 22.13 vagy újabb kell (node --version) +> corepack enable # Node 25-től előbb: npm install -g corepack +> pnpm install --frozen-lockfile +> pnpm build +> node dist/cli.js init +> ``` +> +> Ilyenkor a lenti parancsokban és az eszköz saját „Tanács” soraiban is az `npx tarhely-cli` +> helyére `node /dist/cli.js` kerül. + Kinek jó: aki nem akarja, hogy a hatósági levelei 30 nap után eltűnjenek a tárhelyről; aki egy mappában, kereshetően szeretné látni őket; aki az AI-agentjével (Claude Code, Codex, Gemini CLI és társai) szeretné kezelni a hivatalos postáját. @@ -23,12 +41,16 @@ npx tarhely-cli download # utána: az új levelek a ./tarhely mappába - **Nem** küld levelet, **nem** töröl, **nem** nyúl a tartós tárhoz, **nem** intéz ügyet. Ha később jön e-Papír támogatás, az is csak piszkozatot készít majd; a küldés gombot mindig te nyomod meg. -- **Nem** beszél mással, csak a `*.gov.hu` címekkel. Nincs telemetria, nincs +- **Nem** beszél mással, csak a `kau.gov.hu`, `idp.gov.hu` és `tarhely.gov.hu` címekkel + (és a `kau.gov.hu`, `tarhely.gov.hu` aldomainjeivel). Egyetlen kivétel: az `init` + egyszer letölti a Chromiumot a Playwright szerveréről. Nincs telemetria, nincs frissítés-ellenőrzés, nincs saját szerver. ## Előfeltételek -1. **Node.js 20 vagy újabb** — [nodejs.org](https://nodejs.org). Ellenőrzés: `node --version`. +1. **Node.js 20.16 vagy újabb (a 22-es ágon 22.4 vagy újabb)** — [nodejs.org](https://nodejs.org). Ellenőrzés: `node --version`. + Forrásból futtatáshoz (lásd „Állapot”) Node.js 22.13 vagy újabb kell: a repó + `pnpm@11.6.0`-ja 21.x és 22.0–22.12 alatt el sem indul. 2. **Ügyfélkapu+ hitelesítő alkalmazással.** Ha még e-mailes kóddal lépsz be, előbb [állíts át hitelesítő alkalmazásra](https://kau.gov.hu/dap/sugo/ugyfelkapu-plusz). 3. **A hitelesítő alkalmazás kulcsa** (TOTP-seed). Ezt az Ügyfélkapu+ a hitelesítő @@ -85,7 +107,7 @@ A letöltés eredménye: tarhely/ index.jsonl # jegyzék, soronként egy levél ertesitesi-tarhely/ - 2026-09-08_1263939602026…_feladasi-igazolas/ + 2026-09-08_000000012026090800000001_feladasi-igazolas/ feladasi_igazolas.pdf # az eredeti fájl, ahogy a portál adta kibontva/ # ha zip volt, a tartalma meta.json # feladó, tárgy, dátum, érkeztetési szám @@ -97,6 +119,10 @@ Az `index.jsonl` miatt a `download` idempotens: ugyanabba a mappába akárhánys futtathatod, csak az új leveleket hozza le. Ha egy levél letöltése elbukik, a többi megy tovább, és a bukott levél a következő futáson újra sorra kerül. +Ha a letöltési mappa egy git-repón belül van, és nincs a `.gitignore`-ban, a `download` +el sem indul (1-es kód), hogy a hatósági levelek ne kerülhessenek véletlenül commitba. +Ilyenkor adj meg repón kívüli mappát, vagy vedd fel a mappát a `.gitignore`-ba. + ## Használat AI-agenttel Az eszköz úgy készült, hogy egy agent (Claude Code, Codex, Gemini CLI, Cursor…) vezesse @@ -115,18 +141,22 @@ terminálodban futtasd az `init`-et (a belépőt soha nem kéri el a chatben), m és elolvassa a leveleket a mappából. Agenteknek a gépi felület a `--json` kapcsoló: a stdout-ra egyetlen JSON-objektum -kerül, a kilépési kód pedig a hiba osztályát adja (lásd lent). +kerül, a kilépési kód pedig a hiba osztályát adja (lásd lent). Hibás kapcsolónál, rossz +`--since`/`--max` értéknél vagy ismeretlen parancsnál nincs JSON: a hiba a stderr-en +jelenik meg, 1-es kóddal. ## Biztonság - **Hol van a belépőm?** A rendszer kulcstartójában, `tarhely-cli` néven. Törlés: `npx tarhely-cli forget`, vagy a kulcstartó saját felületén. - **Mit lát az eszköz?** A felhasználónevet, a jelszót és a TOTP-seedet, kizárólag a - belépés pillanatában, a saját gépeden futó böngészőben. Képernyőképet a belépési - lépésekről sosem készít. -- **Hová beszél?** Csak `kau.gov.hu`, `idp.gov.hu` és `tarhely.gov.hu` (és aldomainjeik) - felé; minden más kérést a böngésző elutasít. A forrás nyílt, ellenőrizhető: - `src/browser.ts`. + belépés pillanatában, a saját gépeden futó böngészőben. Képernyőképet csak hibánál és + csak `--debug-dir` mellett készít: a belépésből legfeljebb a KAÜ-választó lapról, még a + titkok begépelése előtt, utána csak a sikeres belépés után. A kitöltött belépési + űrlapról sosem. +- **Hová beszél?** A böngésző csak a `kau.gov.hu`, `idp.gov.hu` és `tarhely.gov.hu` + címek, valamint a `kau.gov.hu` és `tarhely.gov.hu` aldomainjei felé enged kérést; + minden mást elutasít. A forrás nyílt, ellenőrizhető: `src/browser.ts` (`ALLOWED_HOSTS`). - **Ha a gépem illetéktelen kézbe kerül?** Aki a kulcstartódhoz hozzáfér, az a belépődhöz is. Ilyenkor az Ügyfélkapu+ beállításainál regisztráld újra a hitelesítő alkalmazást (új kulcs), és változtass jelszót. @@ -140,10 +170,10 @@ kerül, a kilépési kód pedig a hiba osztályát adja (lásd lent). | --- | --- | --- | | 0 | siker | – | | 1 | egyéb hiba | a kiírt üzenet és tanács szerint | -| 2 | nincs belépő | `npx tarhely-cli init` | +| 2 | nincs (vagy hiányos) belépő | `npx tarhely-cli init`; ha a hiba a kulcstartót vagy a `TARHELY_*` változókat említi, előbb azt javítsd: Linuxon Secret Service háttér kell (gnome-keyring, KWallet), env-ben pedig mindhárom változó együtt kell | | 3 | belépés sikertelen | rossz felhasználónév, jelszó vagy seed: `init` újra; pontatlan gép-óra is okozhatja | -| 4 | a portál megváltozott | a portál felülete átalakult; futtasd `--debug-dir ./debug`-gal, és [nyiss issue-t](https://github.com/godavid/tarhely-cli/issues) a képernyőképpel | -| 5 | részleges letöltés | néhány levél nem jött le; futtasd újra | +| 4 | a portál megváltozott | a portál felülete átalakult; [nyiss issue-t](https://github.com/godavid/tarhely-cli/issues) a hibaüzenettel és a lépések nevével; a postafiók- és cégnevet, törzsszámot, érkeztetési számot és levélleírást előtte takard ki. Ha `--debug-dir ~/tarhely-debug`-gal képet is készítesz, az csak neked szól: a képernyőkép és az `.aria.yaml` a belépés utáni lapot mutatja (feladók, tárgyak, cégnevek), ezért nyilvános issue-ba kitakarás nélkül ne tedd fel | +| 5 | részleges letöltés | néhány levél nem jött le; futtasd újra. Ha a hiba zip-korlátot (2000 bejegyzés, 200 MB kibontva) vagy gyanús zip-útvonalat említ, az újrafuttatás nem segít: töltsd le `--no-extract`-tal, kibontás nélkül | `--headed` kapcsolóval látható böngészőben fut, így magad is végignézheted, mit csinál. @@ -160,7 +190,8 @@ A letöltött iratok hatósági dokumentumok: kezeld őket ennek megfelelően. A portál felülete időnként változik, és akkor az eszköz eltörik (4-es kód). Nincs támogatási vállalás; issue-t és pull requestet szívesen fogadok. A kód MIT-licencű. -Fejlesztéshez: `pnpm install`, `pnpm test`, `pnpm typecheck`, `pnpm lint`, `pnpm build`. +Fejlesztéshez: `pnpm install --frozen-lockfile`. A CI ezután sorban a `pnpm lint`, +`pnpm typecheck`, `pnpm test` és `pnpm build` parancsot futtatja. Agenteknek szóló megjegyzések: `AGENTS.md`. --- @@ -171,7 +202,11 @@ Agenteknek szóló megjegyzések: `AGENTS.md`. user's own Ügyfélkapu+ account (username, password and TOTP secret stored in the OS keychain), lists the available mailboxes and downloads incoming letters into per-letter folders with extracted contents and a JSONL index. It is strictly -read-only, talks only to `*.gov.hu` hosts and ships an -[Agent Skills](https://agentskills.io) definition (`skills/tarhely-cli/SKILL.md`) so -coding agents can drive it without ever handling credentials. Install the skill with -`npx skills add godavid/tarhely-cli`. Unofficial, MIT-licensed, no warranty. +read-only, its browser talks only to `kau.gov.hu`, `idp.gov.hu` and `tarhely.gov.hu` +(plus the kau/tarhely subdomains; `init` downloads Chromium once from Playwright's CDN), +and it ships an [Agent Skills](https://agentskills.io) definition +(`skills/tarhely-cli/SKILL.md`) so coding agents can drive it without ever handling +credentials. Install the skill with `npx skills add godavid/tarhely-cli`. As of +2026-10-27 the npm package is not published yet: run the CLI from a source checkout +(see „Állapot” above), never from a look-alike npm package. Unofficial, MIT-licensed, +no warranty. diff --git a/skills/tarhely-cli/SKILL.md b/skills/tarhely-cli/SKILL.md index d14cfb6..5d72111 100644 --- a/skills/tarhely-cli/SKILL.md +++ b/skills/tarhely-cli/SKILL.md @@ -1,8 +1,8 @@ --- name: tarhely-cli -description: Ügyfélkapu+ (KAÜ) belépés és a hivatali tárhely (tarhely.gov.hu) beérkezett leveleinek listázása és letöltése parancssorból, kizárólag olvasó módban. Use when the user mentions tárhely, hivatali kapu, Ügyfélkapu, Ügyfélkapu+, KAÜ, e-ügyintézés, hatósági levél, értesítési tárhely, or wants to download, back up or list official Hungarian government letters. Never ask the user for credentials in chat; the user runs `npx tarhely-cli init` themselves. +description: Ügyfélkapu+ (KAÜ) belépés és a hivatali tárhely (tarhely.gov.hu) beérkezett leveleinek listázása és letöltése parancssorból, kizárólag olvasó módban. Use when the user mentions tárhely, hivatali kapu, Ügyfélkapu, Ügyfélkapu+, KAÜ, e-ügyintézés, hatósági levél, értesítési tárhely, or wants to download, back up or list official Hungarian government letters. Never ask the user for credentials in chat; the user runs `init` in their own terminal. The npm package is not published yet, so never run or suggest `npx tarhely-cli` or a look-alike package; run the CLI from a source checkout as the skill body explains. license: MIT -compatibility: Node.js 20+, npx, internet access to *.gov.hu. The user's own Ügyfélkapu+ account with an authenticator app (TOTP). +compatibility: Node.js 20.16+ (on 22.x, 22.4+), npx, internet access to kau.gov.hu, idp.gov.hu and tarhely.gov.hu; the first run also downloads Chromium from Playwright's CDN. The user's own Ügyfélkapu+ account with an authenticator app (TOTP). metadata: author: godavid version: "0.1" @@ -12,7 +12,19 @@ metadata: Parancssori eszköz, amely belép a felhasználó Ügyfélkapu+ fiókjával a hivatali tárhelyre, és letölti a beérkezett leveleket. **Csak olvas**: a portálon semmit nem -küld, nem töröl, nem helyez át. Kizárólag `*.gov.hu` felé beszél. +küld, nem töröl, nem helyez át. A böngészője csak a `kau.gov.hu`, `idp.gov.hu` és +`tarhely.gov.hu` (és a `kau.gov.hu`, `tarhely.gov.hu` aldomainjei) felé enged kérést +(`src/browser.ts`); a Chromiumot egyszer a Playwright szerveréről tölti le (`init`, +illetve a klón mappájában `pnpm exec playwright install chromium`). + +> **Állapot (2026-10-27):** a `tarhely-cli` még nincs kiadva az npm-en, ezért az +> `npx tarhely-cli …` 404-es hibával bukik. Ne keress és ne futtass helyette más, +> hasonló nevű csomagot: az `init` a felhasználó jelszavát és TOTP-seedjét kéri. Ha a +> felhasználó forrásból telepítette ([README](https://github.com/godavid/tarhely-cli#readme), +> „Állapot”), a lenti parancsokban és a CLI saját `hint`/`detail` szövegeiben is (azok még +> `npx tarhely-cli …`-t írnak) az `npx tarhely-cli` helyére `node /dist/cli.js` +> kerül; a felhasználónak is így add tovább. Ha nem, ajánld fel a forrásból telepítést a +> README szerint; az `init`-et akkor is a felhasználó futtassa. ## Aranyszabályok @@ -21,8 +33,11 @@ küld, nem töröl, nem helyez át. Kizárólag `*.gov.hu` felé beszél. rögzítése a felhasználó dolga, a saját terminálában: `npx tarhely-cli init`. 2. **Első lépésként mindig** `npx tarhely-cli doctor --json`. A kimenet megmondja, mi hiányzik (Node, Chromium, belépő, hálózat). -3. `--json`-nal futtass minden parancsot: a stdout egyetlen JSON-objektum, a kilépési - kód a hiba osztályát adja. Ember-olvasható szöveg csak `--json` nélkül, a stderr-en. +3. `--json`-nal futtass minden parancsot (az `init` kivétel: azt csak a felhasználó + futtatja, `--json` nélkül). A stdout egyetlen JSON-objektum, a kilépési kód a hiba + osztályát adja. Kivétel: hibás kapcsolónál, rossz `--since`/`--max` értéknél és + ismeretlen parancsnál nincs JSON, a hiba a stderr-en van (1-es kód); ilyenkor a + stderr-t olvasd. Ember-olvasható szöveg csak `--json` nélkül, a stderr-en. 4. A letöltött iratok hatósági dokumentumok. **Ne küldd el, ne töltsd fel sehová**, ne idézd a tartalmukat külső szolgáltatásnak a felhasználó kérése nélkül. 5. `forget` (belépő törlése) csak a felhasználó kifejezett kérésére. @@ -34,25 +49,35 @@ npx tarhely-cli doctor --json # környezet-ellenőrzés, b npx tarhely-cli mailboxes --json # elérhető postafiókok (személyes, céges) npx tarhely-cli list --json [--mailbox X] [--since YYYY-MM-DD] [--out ./tarhely] npx tarhely-cli download --json --out ./tarhely [--mailbox X] [--since YYYY-MM-DD] [--max N] [--no-extract] -npx tarhely-cli forget --yes # CSAK a felhasználó kérésére +npx tarhely-cli forget --json --yes # CSAK a felhasználó kérésére ``` -- `--mailbox`: `all` (alap), sorszám (`1`, `2`), vagy a név egy részlete (`céges`, `12345678`). -- `--since`: csak az ettől a naptól érkezett levelek. -- `--out`: a letöltési mappa; itt él az `index.jsonl`, ezért a `download` idempotens - (ugyanabba a mappába futtatva csak az újakat tölti le). -- `list --out ` megjelöli, melyik levél van már meg (`isNew: false`). +- `--mailbox`: `all` (alap), sorszám a `mailboxes` listájából (`1`, `2`), vagy a név egy + részlete (pl. `példa`). A csak számjegyből álló érték mindig sorszám: a törzsszámot + (`12345678`) is sorszámnak venné, és 1-es kóddal bukna; ilyenkor a sorszámot add meg. +- `--since`: a `download` csak az ettől a naptól érkezett leveleket tölti le; a `list` + minden levelet visszaad, a korábbiakat `isNew: false`-szal. Felső határ nincs. +- `--out`: a letöltési mappa (alap: `./tarhely`); itt él az `index.jsonl`, ezért a + `download` idempotens (ugyanabba a mappába futtatva csak az újakat tölti le). +- A `download` 1-es kóddal megáll, mielőtt belépne, ha az `--out` mappa egy git-munkafán + belül van, és nincs a `.gitignore`-ban („git-repóban van” üzenet), hogy a hatósági + levelek ne kerülhessenek commitba. Agentként a munkakönyvtárad gyakran egy repó: + ilyenkor kérdezd meg a felhasználót, hová töltsön (repón kívüli mappa, pl. + `~/tarhely`), és a `.gitignore`-t kérés nélkül ne írd át. +- A `list` az `--out` mappa (alap: `./tarhely`) `index.jsonl`-jéhez méri az `isNew` + mezőt, ezért ugyanazt a mappát add meg, mint a `download`-nál. `isNew: false`, ha a + levél már megvan, ha a `--since` előtt érkezett, vagy ha nincs érkeztetési száma. ## Kilépési kódok | Kód | Jelentés | Mit tegyél | | --- | --- | --- | -| 0 | siker | dolgozd fel a JSON-t | +| 0 | siker | dolgozd fel a JSON-t; ha `skippedByLimit` > 0, a `--max` korlát (alap: 200) miatt maradt letöltetlen levél: futtasd újra | | 1 | egyéb hiba | olvasd el `error` és `hint` mezőt, mondd el a felhasználónak | -| 2 | nincs belépő | kérd meg a felhasználót: futtassa `npx tarhely-cli init` a saját terminálában, majd folytasd | +| 2 | nincs (vagy hiányos) belépő | olvasd el a hibát (`hint`; a `doctor`-nál a `belepo` ellenőrzés `detail`-jét). Kulcstartó-hibánál vagy hiányos `TARHELY_*` env-nél lásd Hibaelhárítás; egyébként kérd meg a felhasználót: futtassa `npx tarhely-cli init` a saját terminálában, majd folytasd | | 3 | belépés sikertelen | rossz felhasználónév/jelszó/seed: a felhasználó `init`-tel rögzítse újra; NE találgass | -| 4 | a portál megváltozott | futtasd újra `--debug-dir ./tarhely-debug`-gal, és javasold issue nyitását a képernyőképpel | -| 5 | részleges letöltés | a `failures` tömb mondja, mely levelek buktak; újrafuttatás újra megpróbálja őket | +| 4 | a portál megváltozott | mondd el a felhasználónak a hibát, és javasolj issue-t a `steps[].step` és `ok` mezőkkel. Az `error` szövege és a `steps[].detail` postafiók- és cégnevet, törzsszámot, érkeztetési számot és levélleírást tartalmazhat: ezek csak a felhasználó átnézése és kitakarása után kerülhetnek az issue-ba. Issue-t csak a felhasználó nyisson. `--debug-dir`-t csak a kérésére használj, repón kívüli mappába (pl. `~/tarhely-debug`). A képernyőkép és az `.aria.yaml` a belépés utáni lapot mutatja (feladók, tárgyak, cégnevek): ne töltsd fel, ne csatold sehová, és ne tedd git-repóba, akkor sem, ha a `hint` mást javasol | +| 5 | részleges letöltés | a `failures` tömb (`{ "eid", "mailbox", "error" }`) mondja, mely levelek buktak; az újrafuttatás újra megpróbálja őket. Felső szintű `error` mező itt nincs. Ha egy `failures[].error` zip-korlátot (2000 bejegyzés, 200 MB kibontva) vagy gyanús zip-útvonalat említ, az újrafuttatás nem segít: kérdezd meg a felhasználót, letöltsd-e `--no-extract`-tal, kibontás nélkül | ## A `download --json` kimenete @@ -68,22 +93,31 @@ npx tarhely-cli forget --yes # CSAK a felhasználó kér ``` Minden levél saját mappát kap: `//_<érkeztetési szám>_/` -benne az eredeti fájl, a kibontott tartalom (`kibontva/`) és egy `meta.json`. +benne az eredeti fájl (a neve a `file` mezőben), zipnél a kibontott tartalom +(`kibontva/`) és egy `meta.json`. ## Tipikus kérések +A `` a letöltési mappa: mindig ugyanazt add meg (lásd `--out` fent). + | A felhasználó mondja | Te futtatod | | --- | --- | -| „Töltsd le a tárhelyem leveleit” | `doctor --json` → `download --json --out ./tarhely` | -| „Jött-e új hatósági levelem?” | `list --json --out ./tarhely` és szűrd `isNew: true`-ra | -| „Csak a céges postafiókot” | `mailboxes --json` → `download --json --mailbox ` | -| „Az augusztusiakat” | `download --json --since 2026-08-01` | -| „Mi van a letöltött levélben?” | olvasd a `meta.json`-t és a `kibontva/` PDF-et helyben | +| „Töltsd le a tárhelyem leveleit” | `doctor --json` → `download --json --out ` | +| „Jött-e új hatósági levelem?” | `list --json --out ` és szűrd `isNew: true`-ra | +| „Csak a céges postafiókot” | `mailboxes --json` → `download --json --out --mailbox ` | +| „Az augusztusiakat” | `download --json --out --since 2026-08-01`. Felső határ nincs: az augusztus 1. óta érkezett összes új levelet letölti. Ha a későbbiek nem kellenek, előbb `list --json --out `, és a `receivedOn` alapján kérdezz | +| „Mi van a letöltött levélben?” | olvasd a levél mappájában a `meta.json`-t, majd a `file` mezőben megadott eredeti fájlt (zipnél az `extracted` listában szereplő `kibontva/` alatti fájlokat), helyben | ## Hibaelhárítás -- A `doctor` `chromium: hiányzik` → `npx playwright install chromium` (az `init` is megteszi). -- Linuxon `kulcstartó nem érhető el` → Secret Service háttér kell (gnome-keyring, KWallet), - vagy a felhasználó dönthet az env-változók mellett (`TARHELY_USERNAME`, - `TARHELY_PASSWORD`, `TARHELY_TOTP_SEED`) — ezt csak ő állítsa be. +- A `doctor` `chromium: hiányzik` → a klón mappájában `pnpm exec playwright install chromium` + (az `init` is megteszi). A `doctor` és a hiba `npx playwright install chromium`-ot ír, de más + mappából az `npx playwright` a legújabb Playwrightot hozza, annak a Chromiumát a CLI nem találja. +- Linuxon a `belepo` sor vagy a hiba: `Nem érhető el az operációs rendszer kulcstartója` + → Secret Service háttér kell (gnome-keyring, KWallet), vagy a felhasználó dönthet az + env-változók mellett (`TARHELY_USERNAME`, `TARHELY_PASSWORD`, `TARHELY_TOTP_SEED`) — + ezt csak ő állítsa be. Ilyenkor az `init` sem segít. +- `Hiányos env-belépő` → a három `TARHELY_*` változó csak együtt érvényes, és az env + megelőzi a kulcstartót, ezért az `init` ezen nem segít: a felhasználó adja meg + mindhármat, vagy törölje őket. - A belépés TOTP-lépése pontatlan rendszeróránál bukik: kérd meg, ellenőrizze a gép óráját. diff --git a/src/kau/login.ts b/src/kau/login.ts index 7d97478..30ba1db 100644 --- a/src/kau/login.ts +++ b/src/kau/login.ts @@ -4,8 +4,10 @@ // lépéssor élesben, napi futásban bevált; a szándékos várakozások a portál lassan // renderelődő választólapját és a TOTP-ablak lejáratát kezelik. // -// A belépési lépésekről SZÁNDÉKOSAN nem készül képernyőkép vagy -// accessibility-snapshot: a kitöltött mezők értéke bekerülne az artefaktumba. +// INVARIANT: kitöltött belépőmezőről soha nincs képernyőkép vagy aria-snapshot, mert +// a mezők értéke bekerülne az artefaktumba. Egyetlen kivétel a titkok begépelése előtti +// hiba: azt `capturable = true` jelöli (a KAÜ-gomb lépése, lent), a képet a +// `withSession` készíti (src/session.ts). Lásd AGENTS.md, Invariánsok, „Diagnosztika”. import type { Page } from "playwright"; @@ -166,6 +168,8 @@ export async function loginToKau(page: Page, options: LoginOptions, step: StepFn `nem található az „${KAU_BUTTON_LABEL}" belépési út (${message(error)})` ); // Itt még semmilyen titok nincs a lapon, a képernyőkép veszélytelen és hasznos. + // INVARIANT: capturable csak itt, a #name kitöltése előtt; a fill után dobott hiba + // soha nem capturable. Lásd AGENTS.md, Invariánsok, „Diagnosztika”. failure.capturable = true; throw failure; } diff --git a/src/tarhely/api.ts b/src/tarhely/api.ts index 9a10af8..26501a0 100644 --- a/src/tarhely/api.ts +++ b/src/tarhely/api.ts @@ -221,6 +221,8 @@ export async function primeApiHeaders( // A postafiók-azonosítót KÉTFELŐL ellenőrizzük: rossz address-id-vel egy MÁSIK // postafiók iratai jönnének vissza. Az eltérés ezért hiba, nem figyelmeztetés. +// INVARIANT: az address-id egyezik a kért postafiókéval, különben 4-es kód (más +// postafiók iratai jönnének). Lásd AGENTS.md, Invariánsok, „Postafiók-elszigetelés”. export function apiHeaders(sniffed: SniffedState, mailbox: MailboxRef): Record { if (sniffed.addressId !== mailbox.addressId) { throw portalChangedError( @@ -241,6 +243,9 @@ export interface PageLike { ): Promise; } +// INVARIANT: a portálhoz csak olvasó hívás mehet (keresés, részletek, letöltés, kvóta); +// küldés, törlés, áthelyezés, címkézés tilos. Minden REST-hívás ezen a függvényen át megy. +// Lásd AGENTS.md, Invariánsok, „Csak olvasás”. async function apiRequest( page: PageLike, sniffed: SniffedState,