diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..f9de5b9 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,154 @@ +# GitJog — belépő agenteknek + +A magyar törvények szövege és változástörténete git-ben. Ez a kód-repo +(`godavid/gitjog`): crawler, normalizáló, pipeline, weboldal, REST API és +MCP-szerver. Az adat a külön publikus adat-repóban él (`godavid/magyar-jog`). +Ez a fájl az egyetlen belépési pont; a `CLAUDE.md` erre mutató symlink. + +Ellenőrizve a kóddal: 2026-10-27. + +## Olvasási sorrend + +1. Ez a fájl: deploy, tilalmak, parancsok, invariánsok, szótár. +2. [PRODUCT.md](PRODUCT.md) — közönség, termékhatár, márkaszabály. Az + `` jelölőt és a `##` címeket ne módosítsd. +3. [docs/uzemeltetes.md](docs/uzemeltetes.md) — az üzemeltetés igazságforrása: + pipeline, parser-hiba, keresés, titkok, deploy, biztonsági scan, agent-felület, + átnevezés. Pipeline-, SQL-, cache- vagy deploy-munka előtt olvasd el az érintett + szakaszát. +4. [DESIGN.md](DESIGN.md) — csak UI-munkához. +5. [docs/superpowers/](docs/superpowers/) — leszállított munkák (keresés, + agent-felület) lezárt tervei és specjei. Történeti rekordok, nem utasítások: a + nyitott jelölőnégyzeteik és a deploy- vagy push-lépéseik érvénytelenek. + +## Landolás és deploy + +- A `main` védett (GitHub ruleset): csak PR, csak squash; kötelező a `biztonsag` + check és a CodeQL. Az admin megkerülheti, de az csak vészhelyzetre van. +- A zöld PR csak a biztonsági ellenőrzéseket bizonyítja: a CI nem futtat tesztet és + típusellenőrzést. Merge előtt futtasd a változott csomag tesztjét (Parancsok). +- A napi delta (03:30 UTC) a `godavid/gitjog` main ágát futtatja írási joggal az + adat-repóban: ami a main-re kerül, az ott kódként fut. +- A prod deploy CSAK a + [`release-production.yml`](.github/workflows/release-production.yml)-ből megy. + A main-re érkező push indítja, ha `apps/web/**`, `packages/szoveg/**`, a gyökér + `package.json`, `pnpm-lock.yaml`, `pnpm-workspace.yaml` vagy maga a workflow + változott: a merge tehát élesít. A `packages/pipeline` változása nem deployol. + Kézi indítás: `gh workflow run release-production.yml -R godavid/gitjog`. +- Szünet: `DEPLOY_HOLD=true` repo-változó + (`gh variable set DEPLOY_HOLD --body true -R godavid/gitjog`; feloldás: `--body false`). +- Adatváltozáshoz nem kell deploy: az adat-repo push-webhookja (`/api/revalidate`) + frissíti a cache-t. + +## Ne tedd (a legdrágább elöl) + +`[kapu]` = gépi eszköz kikényszeríti; a többit csak ez a lista és a kódkomment őrzi. + +| # | Ne tedd | Miért | Helyette | +|---|---|---|---| +| 1 | Helyi prod deploy (`vercel --prod`, `vercel deploy` az `apps/web`-ből) | 2026-10-06 óta tilos; az `apps/web`-ből a `workspace:*` függőség miatt el is hasal | merge a main-re, vagy `gh workflow run release-production.yml -R godavid/gitjog` | +| 2 | Közvetlen push a main-re `[kapu: ruleset]` | a napi delta a main kódját írási joggal futtatja | PR, squash, zöld `biztonsag` + CodeQL | +| 3 | A `napi-delta.yml` egyik példányának módosítása | az élő példány a `godavid/magyar-jog/.github/workflows/`-ban fut; a kettő byte-azonos | mindkettőt egy körben; ha az élőhöz nem nyúlhatsz, a PR-ben írd le, hogy frissíteni kell | +| 4 | A `02-kereses.sql` vagy `04-api-kereses.sql` önálló újrafuttatása | a `05-kereses-gyors.sql` mindkét függvényt (`kereses`, `kereses_api`) felülírja; az újrafuttatás a régi, lassú változatot állítja vissza (2026-09-16-án ez 500-at okozott) | módosítás a `05`-ben vagy új, magasabb sorszámú fájlban; teljes újraépítésnél 01→05 sorrendben (a `03`-hoz `-v szinkron_jelszo=…` kell) | +| 5 | Mellékes változás a normalizálás kimenetében | a teljes history diffje „ugrik” egyet a következő delta-commitnál | kerüld; ha szándékos, a golden hasheket lemez-cache-es gépen generáld újra, és írd le a PR-ben | +| 6 | Az `index/allapotok.json` lekérését `revalidate`-re állítani; a `CACHE_VERZIO` léptetését kihagyni | a Next adat-cache 2 MB-os limitje miatt némán elavult adat jön (2026-08-10) | `no-store` + `unstable_cache`; ha egy cache-elt eredmény tartalma változik, léptesd az `apps/web/lib/adat.ts` `CACHE_VERZIO`-ját | +| 7 | HTML (``) a keresési kiemelésben, `dangerouslySetInnerHTML` a találatra | a `ts_headline` nem escape-el: XSS | STX/ETX (`chr(2)`/`chr(3)`); a ``-ot a React építi (`apps/web/app/kereses/page.tsx`) | +| 8 | Kliens oldali diff (`"use client"` a `DiffNezet`-ben) | a Bing és az AI-crawlerek nem futtatnak JS-t: a diff-oldalak kiesnek az indexből | a `DiffNezet` szerver-komponens marad | +| 9 | Az adat-repo `AGENTS.md`-jének kézi szerkesztése `[kapu: a következő, új időállapotot felvevő delta-futás visszaírja]` | a módosítás elvész | a `packages/pipeline/src/sablonok.ts` `AGENTS_MD` sablonját módosítsd (angolul) | +| 10 | A régi márkanév szava új doksiban, commitban, UI-ban | védjegyfelszólítás (2026-09-16), lásd [PRODUCT.md](PRODUCT.md) Brand Commitments | GitJog; a régi azonosítók maradnak (Szótár) | + +## Parancsok + +Node >= 24, pnpm; a repo gyökeréből, ha nincs más jelölve. + +- Telepítés: `pnpm install --frozen-lockfile` +- Teszt csomagonként: `pnpm --filter @gitjog/szoveg test`, `pnpm --filter @gitjog/pipeline test` + (vitest), `pnpm --filter @gitjog/web test` (`node --test`); mind: `pnpm test`. A 4 + golden-hash teszt csak lemez-cache mellett fut (`data/cache` vagy `NYILT_CACHE_DIR`), + nélküle kimarad. +- Típusellenőrzés: `pnpm --filter @gitjog/szoveg exec tsc` (tiszta). + `pnpm --filter @gitjog/pipeline exec tsc --noEmit` ma 7 ismert hibát ad: 6× TS2835 a + `packages/szoveg/src/index.ts` kiterjesztés nélküli importjaira (NodeNext alatt), és + 1× TS7006 a `kereso-index.ts`-ben, ami ezekből következik. Csak az ezeken felüli hiba a + tiéd. A web típusait csak a release `next build`-je ellenőrzi, a merge UTÁN: + típushibánál a deploy elbukik, és a prod a régi verzión marad. +- Delta helyben: `NYILT_ADAT_REPO_DIR= pnpm delta -- --no-push`; valós + rövidülés egyszeri átengedése: `pnpm delta -- --anomalia-ok=[,]`. +- Backfill: `pnpm backfill` (`-- --push`; folytatás: `-- --folytat`). Előfeltételek: az + üzemeltetési leírás „A pipeline” szakasza. +- Parser-próba (a `packages/pipeline`-ból): + `pnpm exec tsx src/parse-proba.ts ` +- Keresőindex újraépítése: `NYILT_DB_URL=… pnpm --filter @gitjog/pipeline kereso-feltoltes` + (részleges: `-- --slugok=,`). + +## Invariánsok és őreik + +| Invariáns | Hol él | Mi őrzi | +|---|---|---| +| Determinizmus: azonos njt-bemenet → byte-azonos Markdown | `packages/pipeline/src/parse.ts`, `normalize.ts` | `packages/pipeline/test/normalize.test.ts` (a mini fixture mindig; a golden hashek csak lemez-cache mellett) | +| Horgony: a `szakaszokraBont()` horgonya bit szerint egyezik az `mdRender()`-ével (`-2`, `-3` utótagokkal) | `packages/szoveg/src/szakaszok.ts`, `apps/web/lib/md.ts` | `packages/szoveg/test/szakaszok.test.ts` | +| XSS: minden szövegcsomópont `esc()`-en megy át; a horgony-id `[a-z0-9-]` | `apps/web/lib/md.ts` | csak a kódkomment (teszt nincs) | +| Keresési kiemelés STX/ETX, nem HTML | `packages/pipeline/supabase/02-`, `04-`, `05-*.sql`; `apps/web/app/kereses/page.tsx` | csak komment | +| Rossz adat nem kerül az adat-repóba: szerkezeti hibánál a delta semmit nem commitol, terjedelem-anomáliánál az érintett jogszabályt kihagyja | `packages/pipeline/src/delta.ts`, `health.ts` | `packages/pipeline/test/health.test.ts` (terjedelem-őr, szétcsúszás-őr, parser-őrfeltételek; a delta commit-elhagyó ága maga teszteletlen) | +| Az index-szinkron hibája nem buktatja a deltát | `delta.ts` `keresoIndexSzinkron()` | csak a kód | +| A diff szerver oldalon renderel | `apps/web/components/DiffNezet.tsx` | csak a kódkomment | +| A `napi-delta.yml` két példánya byte-azonos | `packages/pipeline/adatrepo/napi-delta.yml` ↔ `godavid/magyar-jog` | kézi | + +## Kódterületek és importszabályok + +| Terület | Cél | Importálhat | Nem importálhat | Import-stílus | +|---|---|---|---|---| +| `packages/szoveg/src` | tiszta, I/O nélküli szövegmodul (§-bontás, horgony, hivatkozás, §-diff); a pipeline és a web közös forrása | `diff`, saját fájlok | `node:*` I/O, `next`, `react`, pipeline, `apps/web` | relatív, kiterjesztés nélkül (Bundler) | +| `packages/pipeline/src` | njt-crawler, parser, normalizáló, commit-pipeline, delta/backfill, keresőindex-szinkron | `@gitjog/szoveg`, `cheerio`, `domhandler` (csak típus), `postgres`, `node:*` | `apps/web`, `next`, `@supabase/supabase-js` | relatív import `.js`-sel (NodeNext) | +| `packages/pipeline/supabase` | a keresőindex SQL-je: kézzel, `psql`-lel futtatott, újrafuttatható szkriptek, nem migrációk | – | – | – | +| `packages/pipeline/adatrepo` | az élő adat-repo `napi-delta.yml`-jének forrása | – | – | byte-azonos az élővel | +| `apps/web` | Next 16 oldal; a `lib/api/*` a szolgáltatásréteg, az `app/api/v1/*` és az `app/api/mcp` csak ezt hívja | `@gitjog/szoveg`, `next`, `react`, `zod`, `mcp-handler`, `@vercel/analytics`, `@supabase/supabase-js` és `node:*` (csak szerveren) | `packages/pipeline/**` (a változása nem deployolna), `NEXT_PUBLIC_` titok | `@/` alias, kiterjesztés nélkül | + +Kivételek: a `node --test` alatt futó `apps/web/lib/**/*.test.ts` `.ts`-kiterjesztéssel +importál, és csak import nélküli modult tesztelhet. A `packages/szoveg/test` importálhatja +az `apps/web/lib/md.ts`-t (horgony-egyezés teszt). + +Ne szerkeszd kézzel: `pnpm-lock.yaml`; `packages/pipeline/data-static/torvenyek.json` +(`torvenylista-generalas.ts` írja); `apps/web/next-env.d.ts`; az `apps/web/` alatti +`AGENTS.md` és `CLAUDE.md` (a `next dev` hozza létre, gitignore-olt: olvasható +Next-útmutató, de ne commitold); az `apps/web/public/` IndexNow-kulcsfájlját (ne nevezd át). + +## Nyelv és kód + +- Doksi, azonosító, komment, commit, PR és felhasználói szöveg: magyar. Angol csak a + külső agenteknek szóló szöveg: `packages/pipeline/src/sablonok.ts` `AGENTS_MD`, + `server.json`. +- Nincs `any` típus; adatalakhoz `interface` a fájl tetején. +- Commit: magyar, javításnál `fix(): …`; a squash-merge `(#szám)`-ot fűz hozzá. + +## Szótár + +- **kód-repo** = `godavid/gitjog` (ez); **adat-repo** = `godavid/magyar-jog`. Régi neve + `magyar-jogtar`: a GitHub átirányítja, ezért azon a néven új repót ne hozz létre. +- Szándékosan megtartott régi azonosítók, NE nevezd át őket: Supabase-projekt + `nyilt-jogtar`, DB-szerep `jogtar_szinkron`, env `NYILT_DB_URL`, `NYILT_ADAT_REPO_DIR`, + `NYILT_CACHE_DIR`, `NYILT_CSAK`. A régi csomag-scope (`@nyilt-jogtar/*`) ma `@gitjog/*`. +- **időállapot** = egy jogszabály egy hatálybalépési napra érvényes szövege = egy commit. + A commit dátuma a hatálybalépés napja, nem a bekerülésé; a bekerülést a **felvételi + napló** (`index/felvetel/ÉÉÉÉ-HH.jsonl`) rögzíti. Az njt **verziószáma** nem monoton a + dátummal: sorrendezéshez a dátumot használd. +- **documentId** = njt-azonosító (`ÉÉÉÉ-SZÁM-00-00`); **slug** = URL és könyvtárnév az + adat-repóban; **megjelölés** = hivatalos név („2013. évi V. törvény”). +- **kiemelt** = a `packages/pipeline/src/config.ts` `JOGSZABALYOK` kézzel gondozott + tétele; ütközésnél győz a generált lista felett. **réteg** = `aktiv` | `lezart` | + `nincs-szoveg` (enumerálás, `enumeralas.ts`). +- **delta** = napi növekmény (Actions, az adat-repóban); **backfill** = egyszeri vagy + folytatólagos visszatöltés (helyben). +- UI-terminológia (kötelező): *időállapot*, *megjelölés*, *hatályos szöveg*, + *mi változott?*, *hatálybalépés*. + +## Ütközés esetén + +1. A kód, a workflow-k és a GitHub-ruleset az igazság. +2. Utána `docs/uzemeltetes.md` (üzemeltetés, deploy, titkok), majd `PRODUCT.md` + (termékdöntések), majd `DESIGN.md` (UI). +3. Ez a fájl a Kódterületek és a Nyelv szakaszban hiteles; máshol összefoglaló, ott + a 2. pont forrása győz. +4. A `docs/superpowers/` rekordjai történetiek: ha ellentmondanak, nem érvényesek. + +Ellentmondást ugyanabban a PR-ben javíts, a kódhoz igazítva; ne válassz csendben. 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/DESIGN.md b/DESIGN.md index 41fdd9e..ef75394 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -16,24 +16,42 @@ törvényszöveget és diffet görget: VILÁGOS téma az alap (papír-érzet), hover/aktív: `oklch(0.38 0.09 165)`. Max ~10% felület. - Diff (funkcionális): beszúrás-háttér `oklch(0.94 0.05 150)`, törlés-háttér `oklch(0.94 0.045 25)`; sötétben ugyanez L≈0.30-on. -- Sötét téma: háttér `oklch(0.22 0.01 85)`, szöveg `oklch(0.90 0.008 85)`. -- Soha #000/#fff; minden neutrális a papír-hue (85) felé húz. +- Sötét téma (`@media (prefers-color-scheme: dark)`, minden token felülírva): háttér + `oklch(0.22 0.01 85)`, mélyebb papír `oklch(0.25 0.012 85)`, szöveg `oklch(0.90 0.008 85)`, + halvány tinta `oklch(0.68 0.01 85)`, vonal `oklch(0.34 0.012 85)`, pecsétzöld + `oklch(0.72 0.09 165)`, hover/aktív `oklch(0.80 0.09 165)` (sötétben a hover világosabb). +- Soha #000/#fff; minden neutrális a papír-hue (85) felé húz. Egyetlen kivétel a + nyomtatás (`@media print`): ott a papír `#fff`, és mindig a világos tokenek élnek. +- A tokenek forrása `apps/web/app/globals.css` (`:root`). A megosztókártyák + (`apps/web/app/opengraph-image.tsx`, `apps/web/app/jogszabaly/[slug]/opengraph-image.tsx`, + `apps/web/app/jogszabaly/[slug]/diff/[tol]/[ig]/opengraph-image.tsx`) és a favicon + (`apps/web/app/icon.svg`) a világos tokenek sRGB hex-másolatát használják (papír + `#f7f5f1`, tinta `#211f1a`, halvány tinta `#58554e`, pecsétzöld `#0e6549`, vonal + `#dad7d2`); tokenváltozáskor ezeket is frissíteni kell. ## Tipográfia - Jogszabályszöveg: serif stack — `"Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif` - UI-elemek (nav, gombok, meta): system sans — `system-ui, -apple-system, "Segoe UI", sans-serif` - Kód/diff: `ui-monospace, "SF Mono", Menlo, Consolas, monospace` -- Skála (1.29-es ráta): 13 / 15 / 17 (törzs) / 22 / 28 / 36 +- Skála (1.29-es ráta): 13 / 15 (UI-törzs, `body`) / 17 (jogszöveg-törzs, `.jogszoveg`) + / 22 / 28 / 36. Köztes fokok a kódban: 14 (nav, meta, táblázat, keskenyen a kiemelt + kódsor), 16 (beviteli mező az iOS-zoom ellen, találatcím, kiemelt kódsor), 20 / 24 + (jogszöveg h3 / h2; a gépi sáv MCP-címe 20), 18 (szöveges oldal h3), 11 + (hatálytalan-jelölő); keskeny képernyőn h1 26, szekciócím 20. - Törzs sorhossz max 70ch, sorköz 1.65 a jogszövegben. ## Komponens-elvek -- Nincs kártya-grid: a jogszabály-lista strukturált TÁBLÁZAT/lista sor-elemekkel - (megjelölés + cím + rövidítés + utolsó változás), teljes sorra kattintható. +- Nincs kártya-grid: a jogszabály-lista (`.jsz-lista`, főoldal és `/evek/[ev]`) + strukturált lista sor-elemekkel (megjelölés + cím + rövidítés), teljes sorra + kattintható. Az utolsó változás dátuma 2026-08-01 (22508c9) óta nincs a sorban; a + friss módosítások a „Legutóbbi változások” listában (`.friss-lista`) látszanak. - Az idővonal valódi függőleges idővonal (dátum-tengely, csomópontok), nem kártyasor. -- Diff-nézet: sorszintű, +/− háttértint, egyesített (unified) nézet; a fejlécben - a két időállapot dátuma és a köztük eltelt idő. +- Diff-nézet (`DiffNezet`): sorszintű, +/− háttértint, egyesített (unified) nézet; a + változatlan blokkokból 3 sor kontextus marad, a többi egy „⋯ N változatlan sor ⋯” + sorba csukódik. A fejlécben a két időállapot dátuma, nem szomszédos állapotoknál az + összevont módosítási lépések száma, és a bekerült/kikerült sorok száma. - § headingek horgony-linkkel (hover-en látszó ¶ jel, pecsétzöld). - Disclaimersáv: keskeny, papírnál egy árnyalattal sötétebb sáv, nem banner. - Fókuszgyűrű: 2px pecsétzöld outline, offset 2px — minden interaktív elemen. diff --git a/PRODUCT.md b/PRODUCT.md index 0558063..5a23dc8 100644 --- a/PRODUCT.md +++ b/PRODUCT.md @@ -9,7 +9,8 @@ web ## Users - **Elsődleges: fejlesztők és gépi felhasználók.** Klónozzák az adat-repót, vagy a - domain gépi végpontjait fogyasztják (`/llms.txt`, nyers `szoveg.md`, RSS, sitemap). + domain gépi végpontjait fogyasztják (`/llms.txt`, nyers `szoveg.md`, RSS, sitemap, + REST API `/api/v1`, MCP-szerver `/api/mcp`; összefoglaló: `/agenteknek`). Ide tartoznak az AI-asszisztensek és -crawlerek is: számukra a weboldal egyszerre belépési pont és kirakat. Minden későbbi terméki döntés ehhez a közönséghez igazodik. - Másodlagos: újságírók, kutatók, jogászok, civil szervezetek — a tényleges kérdésük @@ -46,16 +47,23 @@ adatbázis, hanem adat, amihez a felület csak hozzáférés. - **Forrás:** az njt.jog.gov.hu publikus felülete, automatikus feldolgozással. Nem minden jogszabály szerepel: kimaradnak azok, amelyeknek nincs konszolidált szövegük az njt-n. -- **Ritmus:** napi egyszeri delta (GitHub Actions az adat-repóban). Az aznap - hatályba lépő módosítások új commitként kerülnek be, és néhány órán belül - megjelennek a weben (ISR). +- **Ritmus:** napi egyszeri delta (GitHub Actions az adat-repóban, 03:30 UTC). Az aznap + hatályba lépő módosítások új commitként kerülnek be; az adat-repo push-webhookja + (`/api/revalidate`) perceken belül frissíti a webet, tartalékként a 6 órás ISR-ablak. + Adatváltozáshoz nem kell deploy. - **Repók:** adat `github.com/godavid/magyar-jog`, kód `github.com/godavid/gitjog` - (pnpm monorepo: `packages/pipeline` crawler + normalizáló, `apps/web` Next.js). -- **Kiszolgálás:** Vercel. A main-re pusholás önmagában NEM deployol — a produkciós - deploy CLI-ből indul. Keresés: Supabase Postgres FTS, magyar szótövezéssel. + (pnpm monorepo: `packages/pipeline` crawler + normalizáló, `packages/szoveg` közös + §-bontás, horgony és §-diff, `apps/web` Next.js). +- **Kiszolgálás:** Vercel. A prod deploy 2026-10-06 óta CSAK a + `.github/workflows/release-production.yml`-ből megy: a main-re érkező, webet érintő + push (`apps/web/**`, `packages/szoveg/**`, gyökér `package.json`, `pnpm-lock.yaml`, + `pnpm-workspace.yaml`) automatikusan deployol, tehát a merge élesít; helyi gépről + (Vercel CLI) a prod deploy tilos. Szünet: `DEPLOY_HOLD=true` repo-változó + (`/deploy hold|resume`). Részletek: [docs/uzemeltetes.md](docs/uzemeltetes.md#titkok). + Keresés: Supabase Postgres FTS, magyar szótövezéssel. - **Találkozási pontok:** keresőtalálat egy „mi változott” kérdésre, RSS-feed, `git clone`, illetve AI-asszisztens, amely a domain gépi végpontjait olvassa, vagy az MCP-szerverhez kapcsolódik (Claude, ChatGPT, Cursor). -- Részletes üzemeltetési leírás: `docs/uzemeltetes.md`. +- Részletes üzemeltetési leírás: [docs/uzemeltetes.md](docs/uzemeltetes.md). ## Capabilities and Constraints diff --git a/apps/web/app/llms.txt/route.ts b/apps/web/app/llms.txt/route.ts index ddc04eb..00c3bc0 100644 --- a/apps/web/app/llms.txt/route.ts +++ b/apps/web/app/llms.txt/route.ts @@ -87,7 +87,7 @@ A cursor a repóba kerülés ideje, nem a hatálybalépés: a késve felvett, r - Repó: https://github.com/${ADAT_REPO} - Nyers szöveg (Markdown): ${RAW}/jogszabalyok/{slug}/szoveg.md -- Jogszabály-index: ${RAW}/index/jogszabalyok.json — slug, documentId, megjelölés, cím, rövidítés +- Jogszabály-index: ${RAW}/index/jogszabalyok.json — [{slug, documentId, megjeloles, cim, rovidites}] - Időállapot-térkép: ${RAW}/index/allapotok.json — slugonként [{datum, verzio, sha}] (4+ MB; egy törvényhez: ${RAW}/jogszabalyok/{slug}/allapotok.json) - Felvételi napló: ${RAW}/index/felvetel/{ÉÉÉÉ-HH}.jsonl — soronként {felveve, slug, datum, sha}: mikor került be egy időállapot - Agent-útmutató a klónozott repóhoz: https://github.com/${ADAT_REPO}/blob/main/AGENTS.md diff --git a/apps/web/lib/kereso.ts b/apps/web/lib/kereso.ts index 2089f31..5c29c93 100644 --- a/apps/web/lib/kereso.ts +++ b/apps/web/lib/kereso.ts @@ -13,7 +13,10 @@ export interface Talalat { jogszabaly: string; // "Ptk. (2013. évi V. törvény)" szakasz: string; horgony: string; - reszlet: string; // jelöléssel kiemelve + // INVARIANT: a kiemelést STX/ETX (\u0002/\u0003) jelöli, NEM HTML — a -ot a React + // építi (app/kereses/page.tsx kiemelve()); soha ne add át dangerouslySetInnerHTML-nek. + // Lásd: docs/uzemeltetes.md → Keresés, Kiemelés-invariáns. + reszlet: string; hatalyos: boolean; } diff --git a/docs/superpowers/plans/2026-08-07-teljes-szoveges-kereses.md b/docs/superpowers/plans/2026-08-07-teljes-szoveges-kereses.md index da213be..6065da3 100644 --- a/docs/superpowers/plans/2026-08-07-teljes-szoveges-kereses.md +++ b/docs/superpowers/plans/2026-08-07-teljes-szoveges-kereses.md @@ -1,5 +1,13 @@ # Teljes szövegű keresés — implementációs terv +> **Állapot (2026-10-27): KÉSZ — archivált történeti rekord, nem utasítás.** Megvalósult +> 2026-08-07-én (2c96bba…4013482); a nyitott checkboxok nem nyitott munkát jelentenek. +> A deploy 2026-10-06 óta CSAK a `.github/workflows/release-production.yml`-ből megy, a +> main-re csak PR-en át (squash) kerül kód; a benne lévő `vercel`- és +> `git push origin main`-lépések érvénytelenek. Azóta egyes útvonalak is változtak (pl. a +> `szakaszok.ts` és a tesztje a `packages/szoveg`-be költözött). Az aktuális állapot: +> [docs/uzemeltetes.md](../../uzemeltetes.md). + > **Ügynök-munkatársnak:** KÖTELEZŐ AL-SKILL: `superpowers:subagent-driven-development` (ajánlott) vagy `superpowers:executing-plans` a terv taskonkénti végrehajtásához. A lépések checkbox (`- [ ]`) jelöléssel követhetők. **Cél:** A weboldal keresője a 37 kiemelt törvény helyett mind a 4332 törvény hatályos szövegében keressen, magyar szótövezéssel. diff --git a/docs/uzemeltetes.md b/docs/uzemeltetes.md index 44c4366..f4d636b 100644 --- a/docs/uzemeltetes.md +++ b/docs/uzemeltetes.md @@ -32,7 +32,8 @@ `Btk. — mi változott? 2026. augusztus 7.` (a „Diff" szót senki nem keresi). A látható `

` a lap tetején áll és tartalmazza a rövidítést + a teljes címet; a Markdown saját nyitó sora ezért `

` (a `lib/md.ts` szint-1 ága). Ez a heading - NEM kap horgonyt, így a `szakaszok.ts`-szel közös horgony-invariáns sértetlen marad. + NEM kap horgonyt, így a `packages/szoveg/src/szakaszok.ts`-szel közös horgony-invariáns + sértetlen marad. - **Havi változás-oldalak**: `/valtozasok/{ev}-{ho}` (pl. `/valtozasok/2026-01`), jelenleg 404 hónap 1902-től. Erre a keresletre („mi változott januárban?") ma csak kézzel írt újságcikkek válaszolnak. Az adat a `lib/adat.ts` `getHaviBontas()`-ából jön: ez a nagy @@ -44,8 +45,9 @@ `/jogszabaly/{slug}/valtozasok.xml` (egy törvény változásainak RSS-e — a fizetős jogi adatbázisok „figyeltetés" funkciójának ingyenes megfelelője). 2026-09-16 óta **REST API és MCP-szerver** is — lásd a külön szakaszt lent. -- **Strukturált adat**: `Legislation` a törvényoldalon (`legislationDate` és - `temporalCoverage` is), `Dataset` az `/adatok`-on, `BreadcrumbList` az idővonal- és +- **Strukturált adat**: `Legislation` a törvényoldalon (`temporalCoverage` és + `legislationDateVersion`; `legislationDate` SZÁNDÉKOSAN nincs: az első időállapot a + hatálybalépés, nem a kihirdetés napja), `Dataset` az `/adatok`-on, `BreadcrumbList` az idővonal- és diff-oldalakon, `WebSite` a layoutban. A sitelinks-keresődoboz (`SearchAction`) SZÁNDÉKOSAN kimarad: a `/kereses` a robots.txt-ben tiltott. - **A Search Console / Bing tokenje környezeti változóból jön**: @@ -64,7 +66,16 @@ ## A pipeline (packages/pipeline) -- `config.ts` — az MVP jogszabály-lista (documentId, slug, megjelölés). Bővítés = új sor. +- `config.ts` — a kiemelt (kézzel gondozott, rövidítéses) `JOGSZABALYOK` lista és az + njt-konstansok (`NJT_BASE`, `USER_AGENT`, `RATE_LIMIT_MS`). A feldolgozott teljes lista a + `teljesJogszabalyLista()`: `JOGSZABALYOK` + a generált `data-static/torvenyek.json` + (documentId-ütközésnél a kiemelt győz). Új törvény: a lista újragenerálása + (`torvenylista-generalas.ts`, lásd a karbantartó eszközöket lent), majd + `pnpm backfill -- --folytat` a következő napi delta ELŐTT — backfill nélkül a delta + szétcsúszás-őre leállítja a napi futást (lásd „Ha törik a parser”). Kiemelt sor + felvételekor a slug egyezzen a már bent lévővel (ez az URL és az adat-repo + könyvtárneve), és a `torvenylista-generalas.ts` `KIEMELT_SLUGOK`-jába is kerüljön be + (ezt teszt nem őrzi). - `crawl.ts` — njt-letöltés. KRITIKUS tudás: csak a `njt.jog.gov.hu` host működik (a `njt.hu` TLS-szinten reseteli a nem böngésző klienseket); HTTP/1.1; azonosítható User-Agent. Verziólista: POST `/ajax/collectAllDocumentVersion.json` (form-encoded @@ -74,8 +85,10 @@ - `parse.ts` + `normalize.ts` — HTML → determinisztikus Markdown. A determinizmus szent: azonos bemenet = byte-azonos kimenet, mert a diff-minőség ezen áll. - `backfill.ts` — egyszeri teljes visszatöltés (lokálisan futtatandó). `pnpm backfill`, - push-sal: `pnpm backfill -- --push`. Üres `data/repo`-t vár; a letöltés `data/cache`-be - cache-elődik, így az újrafuttatás olcsó. + push-sal: `pnpm backfill -- --push`. NEM létező `data/repo`-t vár (ha a könyvtár + létezik, akár üresen is, hibával kilép; a helyét a `NYILT_ADAT_REPO_DIR` állítja, alapból + `/data/repo`); a letöltés `data/cache`-be (`NYILT_CACHE_DIR`) cache-elődik, + így az újrafuttatás olcsó. - `delta.ts` — napi növekmény, idempotens. Az Actions futtatja, de lokálisan is megy: `NYILT_ADAT_REPO_DIR= pnpm delta -- --no-push`. Megszakadt LOKÁLIS futás után mindig friss klónból futtasd újra (a részben @@ -94,14 +107,32 @@ enumeralas-init [-- --push]` (a backfill után; utána a delta tartja karban). Ha a fájl hiányzik vagy sérült, a delta a teljes végigjárásra esik vissza — lassabb, de nem hagy ki adatot. -- `szakaszok.ts` — markdown → §-szintű szakaszok a keresőindexhez. A horgony- - generálás az `apps/web/lib/md.ts` `mdRender()`-ével bit szerint egyezik (lásd - a Keresés szakasz horgony-invariánsát). +- A §-szintű bontás NEM itt él: `@gitjog/szoveg` `szakaszokraBont()` + (`packages/szoveg/src/szakaszok.ts`) — markdown → §-szintű szakaszok a keresőindexhez; + a pipeline `kereso-index.ts`-e innen importál. A horgony-generálás az + `apps/web/lib/md.ts` `mdRender()`-ével bit szerint egyezik (lásd a Keresés szakasz + horgony-invariánsát). - `kereso-index.ts` + `kereso-feltoltes.ts` — a keresőindex szinkronja és teljes újraépítése (lásd a Keresés szakaszt). - `health.ts` — riasztás (Issue) + terjedelem-anomália-őr. A riasztás CÍM szerint dedupol: azonos című nyitott issue mellett nem nyit újat, más hibafajta viszont saját issue-t kap. +- `commit.ts` — dátumhelyes commit-stream (egy commit = egy hatálybalépési nap), itt + dől el az adat-repo helye (`NYILT_ADAT_REPO_DIR`). `felvetel.ts` — a felvételi napló + (lásd Agent-felület). +- Karbantartó eszközök (a `packages/pipeline` könyvtárból, + `NYILT_ADAT_REPO_DIR=`-val): + - `pnpm index-ellenorzes` — az index-fájlok és a per-jogszabály fájlok összevetése; + csak olvas. + - `pnpm exec tsx src/index-ujraepites.ts` — a teljes index újraépítése a + `meta.json`-okból és a git-történetből; ÍR és COMMITOL az adat-repóba (pusholni kézzel + kell). Index-séma változás után ezt használd, ne kézi szerkesztést. + - `pnpm exec tsx src/torvenylista-generalas.ts data-static/torvenyek.json` + — a törvénylista újragenerálása az njt-sitemap letöltött példányából (a + `torvenyek.json`-t kézzel ne szerkeszd). + - `src/osztaly-leltar.ts` (a kiemeltek aktuális snapshotjainak ismeretlen njt-osztályai) + és `src/crawl-teszt.ts` (a Ptk./Btk./Mt. múltbeli állapotainak letöltése cache-be) — + egyszeri felderítő eszközök, hálózatot használnak. - A napi-delta.yml két példányban él: az élő az adat-repo `.github/workflows/`-ában, a forrás itt a `packages/pipeline/adatrepo/`-ban — módosításnál MINDKETTŐT frissítsd. @@ -117,7 +148,8 @@ egyetlen módosító törvény duzzadása miatt 37 más törvény állapota sem ez volt a tanulság.) 1. Nézd meg a hibát az Actions logban (melyik jogszabály, melyik osztály/feltevés). -2. Lokálisan reprodukáld: `pnpm exec tsx src/parse-proba.ts /tmp/ki.md` +2. Lokálisan reprodukáld (a `packages/pipeline` könyvtárból): + `pnpm exec tsx src/parse-proba.ts /tmp/ki.md` 3. Tipikus törések és javításuk: - **Új elem-osztály** (`Ismeretlen njt-osztályok` hiba): vedd fel a `parse.ts` `ISMERT_OSZTALYOK` halmazába ÉS a `normalize.ts` leképezésébe @@ -132,7 +164,13 @@ ez volt a tanulság.) hogy (a) van-e benne `borderStart` (ha igen, lazy-blokk hiányzik → valódi parser-hiba), és (b) csökkent-e a `§` jelek száma. Ha a rövidülés valós — a módosító törvényeknél ez a normális életciklus —, a futás egyszer - átengedhető: `pnpm delta -- --anomalia-ok=` (vesszővel több is). + átengedhető, lokálisan, friss adat-repo-klónból (a workflow kézi indításának + nincs ilyen paramétere): + `NYILT_ADAT_REPO_DIR= NYILT_DB_URL= pnpm delta -- --anomalia-ok=` + (vesszővel több is; alapból pushol az adat-repóba). `NYILT_DB_URL` nélkül ezek + keresőindexe kimarad, és a későbbi futások sem pótolják (azok csak a saját + változásaikat szinkronizálják) — akkor utána: + `NYILT_DB_URL=... NYILT_ADAT_REPO_DIR= pnpm --filter @gitjog/pipeline kereso-feltoltes -- --slugok=`. A „…módosításáról" végű című törvényeket az őr 2026-08-15 óta magától engedékenyebben kezeli (`modositoTorveny()` a `health.ts`-ben): náluk csak az 5% alatti maradék számít anomáliának, a duzzadás NEM. A módosító törvény @@ -147,8 +185,34 @@ ez volt a tanulság.) módosító fejezetet tartalmazó törvényeket is átengedi — a 2026. évi XXXIV. 79 748 → 233 444 → 94 755 kar volt (0 → 718 → 1 „helyébe”), és 2026-09-27-én emiatt kellett kézi futás. -4. Tesztek: `pnpm test`. Ha a normalizálás SZÁNDÉKOSAN változott, regeneráld a - golden hasheket (`parse-proba` + `shasum -a 256`) a `test/normalize.test.ts`-ben. + - **„Gyanúsan sok (…) régi vagy előzmény nélküli új állapot — config/repo + szétcsúszás? Nem commitolok.”** (`szetcsuszasGyanu()` a `health.ts`-ben, küszöb: + `MAX_GYANUS_UJ` = 50 a `delta.ts`-ben): gyanús az az új állapot, amelynek + jogszabályához még nincs ismert állapot (a lista bővült backfill nélkül), vagy amely + 30 napnál (`FRISS_NAPOK`) régebben lépett hatályba (sérült/hiányos index). A friss, + előzménnyel bíró tömeges hatálybalépés (negyedévente; 2026-10-01: ~210 törvény) NEM + számít. Az `--anomalia-ok` itt nem segít, az őrt ne lazítsd. Teendő: új + jogszabályoknál `pnpm backfill -- --folytat`; gyanús indexnél + `NYILT_ADAT_REPO_DIR= pnpm --filter @gitjog/pipeline index-ellenorzes`. + + - **„N verziólista-kérés hiúsult meg M-ből — njt-kimaradás vagy blokkolás? Nem + commitolok.”** (`MAX_HALOZATI_HIBA` = 20 a `delta.ts`-ben): njt-oldali gond; a futás + semmit nem commitol, a következő újrapróbál. Ha tartós: host, User-Agent és végpontok + a `crawl.ts`-ben (lásd fent). + - **Nincs napi futás, és issue sincs:** a workflow lehet letiltva (hosszú backfill + idejére szokás). Ellenőrzés: + `gh api repos/godavid/magyar-jog/actions/workflows --jq '.workflows[] | {name, state}'`; + `disabled_manually` esetén `gh workflow enable napi-delta.yml -R godavid/magyar-jog`. +4. Tesztek, csomagonként (CI ma EGYETLEN tesztet sem futtat — ez lokális lépés): + `pnpm --filter @gitjog/pipeline test` (parser, normalizáló, őrök), a szövegmodulé + `pnpm --filter @gitjog/szoveg test`; egy fájl: + `pnpm --filter @gitjog/pipeline exec vitest run test/normalize.test.ts`. A + `test/normalize.test.ts` mini fixture-je minden futásban ellenőrzi a determinizmust, + a golden hashek viszont CSAK akkor futnak, ha a lemez-cache-ben (`data/cache` vagy + `NYILT_CACHE_DIR`) megvan a négy snapshot (`describe.skipIf`) — friss klónban vagy + worktree-ben csendben kimaradnak, ott a zöld futás nem bizonyítja a byte-azonos + kimenetet. Ha a normalizálás SZÁNDÉKOSAN változott, regeneráld a golden hasheket + (`parse-proba` + `shasum -a 256`) a `packages/pipeline/test/normalize.test.ts`-ben. Vigyázz: a golden-változás azt jelenti, hogy a teljes history diffje "ugrik" egyet a következő delta-commitnál — kerüld, ha csak lehet. 5. Kézi delta-futtatás ellenőrzésre, majd az issue lezárása. @@ -159,8 +223,10 @@ A teljes törvényállomány betöltve: **4332 jogszabály, 5404 commit** az ada 1254 tétel kihagyva (nincs konszolidált szöveg az njt-n). A lista a sitemapból generálódik (`torvenylista-generalas.ts` → `data-static/torvenyek.json`, 5585 tétel). -- A backfill folytatható: `pnpm backfill -- --folytat` (tiszta worktree-ről indul, - a már commitolt (jogszabály, dátum) párokat parse nélkül átugorja, kötegenként pushol). +- A backfill folytatható: `pnpm backfill -- --folytat` (meglévő adat-repo-klónban; + indításkor `git checkout -- .` + `git clean -fdq` fut a klónban — MINDEN commitolatlan + változást eldob —, a már commitolt (jogszabály, dátum) párokat parse nélkül átugorja, + 500 commitonként és a végén pushol). - A napi delta ehhez a mérethez a réteges enumerálással igazodik (lásd fentebb). Ami még hátravan: rendeletek, határozatok (a lista jelenleg csak törvény). @@ -172,15 +238,29 @@ A weboldal keresője a `nyilt-jogtar` Supabase-projekt Postgres FTS-ét használ memóriabeli MiniSearch-index ~200 törvényig bírta, ezért volt a keresés a kiemeltekre szűkítve; ez megszűnt. -- **Séma és lekérdezés:** `packages/pipeline/supabase/01-sema.sql` (táblák, GIN - index, RLS) és `02-kereses.sql` (a `kereses()` függvény). Mindkettő - újrafuttatható: `psql "$NYILT_DB_URL" -f `. +- **Séma és lekérdezés:** `packages/pipeline/supabase/` — `01-sema.sql` (táblák, GIN + index, RLS), `02-kereses.sql` (`kereses()`), `03-szinkron-szerep.sql` + (`jogtar_szinkron` szerep + írási policyk), `04-api-kereses.sql` (`kereses_api()`), + `05-kereses-gyors.sql` (a `kereses()` és a `kereses_api()` ÉLŐ, gyors változata: + felülírja a 02-t és a 04-et). Mind újrafuttatható, de csak SORRENDBEN (01→05): a 02 + vagy a 04 önálló újrafuttatása visszahozza a lassú kiemelést, és a webes kereső + 500-zal esik el. Függvényt a 05-ben (vagy egy új, magasabb sorszámú fájlban) módosíts. + Ezek nem migrációk: a commit önmagában semmit nem változtat a prod DB-n, kézzel kell + alkalmazni, a **superuser** pooler-stringgel (a `NYILT_DB_URL` a `jogtar_szinkron` + szerepé, annak nincs joga a sémához): + `psql "" -v ON_ERROR_STOP=1 -f ` (`ON_ERROR_STOP` + nélkül a psql hibánál is 0-val lép ki). A 03-hoz `-v szinkron_jelszo="'...'"` is kell — + új jelszóval újrafuttatva a `NYILT_DB_URL` secretet is cserélni kell (lásd Titkok). - **Magyar szótövezés:** `to_tsvector('hungarian', …)` — ettől talál a „szerződést" a „szerződés" szóra. A generált oszlop csak a KÉTARGUMENTUMOS alakot fogadja el (az egyargumentumos nem immutable). -- **Az index származtatott adat.** Bármikor eldobható és újraépíthető: - `NYILT_DB_URL=... pnpm --filter @gitjog/pipeline kereso-feltoltes` - (~4332 jogszabály, teljes újraépítés kb. háromnegyed óra Frankfurtba). +- **Az index származtatott adat.** Bármikor eldobható és újraépíthető: a 01–05 SQL + sorrendben (lásd fent) + az anon `statement_timeout` (lásd Agent-felület → SQL), majd + `NYILT_DB_URL=... NYILT_ADAT_REPO_DIR= pnpm --filter @gitjog/pipeline kereso-feltoltes` + (~4332 jogszabály, teljes újraépítés kb. háromnegyed óra Frankfurtba; célzott pótlás: + `-- --slugok=,`). `NYILT_ADAT_REPO_DIR` nélkül a + `/data/repo`-t olvassa (az `index/jogszabalyok.json`-t és az + `index/enumeralas.json`-t). - **Napi szinkron:** a delta a push után frissíti a változott jogszabályokat. KÜLÖN hibaágon: ha a szinkron elhasal, riasztó issue-t nyit, de a delta kilépési kódját nem rontja el — az adat-repo integritása előbbre való. @@ -195,10 +275,12 @@ kiemeltekre szűkítve; ez megszűnt. linkel). Darabolni KELL: egy 443 KB-os szakasz a hossznormalizált relevanciát és a `ts_headline` kiemelést is elrontaná. A headinges szakaszokat viszont nem daraboljuk, hogy a mélylink egy §-ra mutasson. -- **Horgony-invariáns:** a `szakaszok.ts` bontója ugyanazt a horgony-id-t adja, - mint az `apps/web/lib/md.ts` `mdRender()`-e (az ismétlődő címek `-2`, `-3` - utótagjával együtt). A `test/szakaszok.test.ts` mindkét implementációt - futtatja és összeveti — ha ez elromlik, a találatok mélylinkje rossz §-ra visz. +- **Horgony-invariáns:** a `packages/szoveg/src/szakaszok.ts` `szakaszokraBont()`-ja + ugyanazt a horgony-id-t adja, mint az `apps/web/lib/md.ts` `mdRender()`-e (az + ismétlődő címek `-2`, `-3` utótagjával együtt). A `horgonyId()` közös + (`@gitjog/szoveg`), az ütközésfeloldás viszont két helyen él, ezért a + `packages/szoveg/test/szakaszok.test.ts` mindkettőt futtatja és összeveti — ha ez + elromlik, a találatok mélylinkje rossz §-ra visz. A tesztet ne töröld. ## Titkok @@ -228,8 +310,12 @@ push-webhookjának HMAC-titka (`/api/revalidate`). Ugyanez a titok a A prod deploy **csak a `.github/workflows/release-production.yml`-ből** megy (2026-10-06 óta; helyi gépről a prod deploy tiltott): a main-re érkező, webet érintő push automatikusan deployol, kézzel `gh workflow run release-production.yml`. Szünet: -`DEPLOY_HOLD=true` repo-változó (`/deploy hold|resume`). Kell hozzá a `VERCEL_TOKEN` -repo-secret — a `gitjog` projektre szűkített Vercel-token; a Vercel CLI nem tud ilyet +`DEPLOY_HOLD=true` repo-változó — `gh variable set DEPLOY_HOLD --body true -R godavid/gitjog`; +folytatás: `gh variable set DEPLOY_HOLD --body false -R godavid/gitjog`, majd +`gh workflow run release-production.yml -R godavid/gitjog` (így megy ki a függőben lévő +main). Claude-ban ugyanez a `/deploy hold|resume` (globális skill, nem ennek a repónak +a része). A workflow-hoz kell a `VERCEL_TOKEN` repo-secret — a `gitjog` projektre +szűkített Vercel-token; a Vercel CLI nem tud ilyet kiadni (403), a dashboardon kell létrehozni. Git-integráció nincs: a Vercel GitHub-appja csak a Remeny-Farm orgot látja, a `godavid` fiókot nem. @@ -250,8 +336,12 @@ adat-repóban — ami a main-re kerül, az ott kódként fut. Ezért a main véd frissítés-PR-ek, secret scanning + push protection, a `GITHUB_TOKEN` alapból csak olvas, külsős fork-PR workflow-ja csak jóváhagyással indul. -Hamis riasztásnál: gitleaks → `.gitleaks.toml` allowlist (a `[allowlist]` -alá a konkrét commit vagy útvonal, soha nem egész szabály); zizmor → sor +Hamis riasztásnál: gitleaks → `.gitleaks.toml` a repo gyökerében (ma még nincs +ilyen fájl). A gitleaks (a `biztonsag.yml` `--config` nélkül hívja) ezt magától +betölti, és `[extend]` alatt `useDefault = true` nélkül a beépített szabálykészlet +HELYETT csak a fájl saját szabályaival fut — a titokkeresés csendben kikapcsolna. Ezért +mindig: `[extend]` / `useDefault = true`, alatta `[[allowlists]]` a konkrét commit +(`commits = [...]`) vagy útvonal (`paths = [...]`), soha nem egész szabály; zizmor → sor végi `# zizmor: ignore[]` indoklással; `pnpm audit` → előbb `overrides` a `pnpm-workspace.yaml`-ban a javított verzióra, csak ha nincs javítás, akkor `auditConfig.ignoreGhsas` a GHSA-azonosítóval és indokkal. @@ -272,23 +362,31 @@ művelet, kulcs nélkül, ugyanabban a Next appban: | `diff` | `GET /api/v1/diff?slug=&tol=&ig=` | két időállapot §-szintű diffje | - **Rétegek:** `packages/szoveg` (megosztott: §-darabolás, horgony, hivatkozás-parser, - §-diff — a pipeline és a web is innen importál, ez váltotta a két külön implementáció - bit-egyezés tesztjét), `apps/web/lib/api/*` (szolgáltatásréteg, JSON), `app/api/v1/*` + §-diff — a pipeline és a web is innen importál; az `mdRender()` horgony-ütközésfeloldása + külön él, ezért a bit-egyezés teszt maradt: `packages/szoveg/test/szakaszok.test.ts`), + `apps/web/lib/api/*` (szolgáltatásréteg, JSON), `app/api/v1/*` (REST, zod-validálás, `Cache-Control: s-maxage`), `app/api/mcp/route.ts` (`mcp-handler` 2.x, stateless streamable HTTP; a négy tool + ChatGPT `search`/`fetch` alias), `app/api/v1/openapi.json`. - **Felvételi napló:** a delta minden futás végén `index/felvetel/ÉÉÉÉ-HH.jsonl`-be írja a - bekerült állapotokat (`felveve, slug, datum, sha`). Ez a `valtozasok` cursora — a - commit-dátum a hatálybalépés, NEM a bekerülés ideje, ezért kell külön napló. Backfill - nem ír naplót; ha egy hónapra nincs fájl, a végpont a hatálybalépés-ágra esik vissza. + bekerült állapotokat (`felveve, slug, datum, sha`). Ez a `valtozasok` cursora (ma nem + veszteségmentes, lásd Ismert korlátok) — a commit-dátum a hatálybalépés, NEM a + bekerülés ideje, ezért kell külön napló. Backfill nem ír naplót; ha a cursor hónapjától + máig EGYETLEN havi naplófájl sincs, a végpont a hatálybalépés-ágra esik vissza + (`mod: "hatalybalepes"`); ha legalább egy van, a napló-ágon marad, a fájl nélküli + hónapok tételei nélkül. - **AGENTS.md az adat-repóban:** forrása a `sablonok.ts` `AGENTS_MD`; a delta minden - futáskor kiírja, változásnál az index-utócommitba kerül. Kézzel ne szerkeszd az - adat-repóban — a következő futás visszaírja. + olyan futáskor kiírja, amely új időállapotot vesz fel (az index-utócommitba kerül) — + új időállapot nélküli futás nem frissíti. Kézzel ne szerkeszd az adat-repóban — a + következő ilyen futás visszaírja. - **Frissesség:** GitHub push-webhook a `godavid/magyar-jog`-on → `POST /api/revalidate` (HMAC, `GITHUB_WEBHOOK_SECRET` Vercel env) → `revalidateTag("adat-repo", "max")`. Az adat-cache minden `napi` fetch-e és `unstable_cache`-e ezt a címkét viseli. A REST- - válaszok CDN-cache-e: `valtozasok` 15 perc, `kereses` 1 óra, `szakasz`/`diff` konkrét - dátummal 1 nap. Ha a webhook elromlik, a 6 órás revalidate továbbra is frissít. + válaszok CDN-cache-e (`s-maxage`, mindegyiken `stale-while-revalidate=86400`): + `valtozasok` 15 perc, `kereses` 1 óra, `diff` 1 nap; `szakasz` múltbeli `datum`-mal + 1 nap, mai vagy jövőbeli `datum`-mal 15 perc, `datum` nélkül 1 óra + (`apps/web/lib/api/cache-ido.ts`). Ha a webhook elromlik, a 6 órás revalidate + továbbra is frissít. - **Deploy-változás:** a `workspace:*` függőség miatt a Vercel-projekt root directory-ja `apps/web`, és a build a **monorepo gyökeréből** indul (nem az `apps/web`-ben — onnan npm-mel próbálna telepíteni és elhasal): `vercel build`, majd `vercel deploy --prebuilt` @@ -296,9 +394,14 @@ művelet, kulcs nélkül, ugyanabban a Next appban: - **SQL:** `04-api-kereses.sql` (`kereses_api`, a § szövegével) és `05-kereses-gyors.sql` (a `ts_headline` csak a limitált találatokra fut — a „termőföld" 2,8 s → 70 ms; előtte az anon 3 s-os statement_timeout-ja miatt a webes kereső rendszeresen 500-zal esett - el). Az anon `statement_timeout` 8 s-re emelve. Alkalmazás a superuser pooler- - stringgel; **2026-09-16-án a 5432-es session pooler helyben nem fogadott - kapcsolatot, a 6543-as (transaction) igen** — psql-hez az is jó. + el). Az anon `statement_timeout` 8 s-re emelve — ez NINCS benne egyik SQL-fájlban sem: + új vagy újraépített DB-n kézzel kell beállítani (superuserrel: + `alter role anon set statement_timeout = '8s';`, majd `notify pgrst, 'reload config';` + ), ellenőrzés: + `select rolconfig from pg_roles where rolname = 'anon';`. Alkalmazás a superuser + pooler-stringgel (lásd Keresés → Séma és lekérdezés); **2026-09-16-án a 5432-es + session pooler helyben nem fogadott kapcsolatot, a 6543-as (transaction) igen** — + psql-hez az is jó. - **Registry:** `server.json` a repo gyökerében (`io.github.godavid/gitjog`), 2026-09-16-án publikálva (1.0.0, `active`). A `mcp-publisher login github` eszközkódos böngészős jóváhagyást kér, de nem kell: a `gh auth token` GitHub-tokenje a registry @@ -306,8 +409,14 @@ művelet, kulcs nélkül, ugyanabban a Next appban: `POST /v0.1/validate` és `POST /v0.1/publish` (`--data-binary @server.json`). Új verziónál a `server.json` `version` mezőjét léptesd, majd ugyanez a két hívás. Ellenőrzés: `GET /v0.1/servers/io.github.godavid%2Fgitjog/versions/`. +- **Rate limit:** Vercel Firewall-szabály `API rate limit (v1 + mcp)`, 120 kérés/perc/IP — + a 2026-09-25-i állapot szerint csak `log` módban (nem blokkol). Az élesítés (`rate_limit` + akció) owner-döntés; előtte a dashboardon a forgalmat kell nézni. +- **Ha egy § „nincs”:** csak ~36 törvénynek van rövidítése az indexben, és sok + törvényben a §-ok nem headingek — ezt a `paragrafusKivag()` (`@gitjog/szoveg`) és a + `ROVIDITES_ALIAS` (`apps/web/lib/api/kereses.ts`) hidalja át; előbb ezeket nézd. - **Füstteszt deploy után:** `curl "$OLDAL/api/v1/kereses?q=Ptk.+6:272.+§"`, - `.../szakasz?slug=2013-evi-cxxii-torveny-foldforgalmi`, `.../valtozasok?since=2026-01-01&q=termőföld|földek forgalm|Földalap`, + `.../szakasz?slug=2013-evi-cxxii-torveny-foldforgalmi`, `.../valtozasok?since=2026-01-01&q=termőföld|földek+forgalm|Földalap`, `.../diff?slug=…&tol=…&ig=…`, `.../openapi.json`; MCP: `curl -X POST $OLDAL/api/mcp -H 'Accept: application/json, text/event-stream' -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'`; `POST /api/revalidate` aláírás nélkül → 401. @@ -322,17 +431,27 @@ művelet, kulcs nélkül, ugyanabban a Next appban: új időállapotot kap az njt-n, az legfeljebb egy körforgásnyi (7 nap) késéssel kerül be. A hatályos jogszabályok napi pontossága ettől nem sérül. - A keresés a jogszabályok SZÖVEGÉBEN, §-címeiben, valamint a jogszabály - CÍMÉBEN, MEGJELÖLÉSÉBEN és RÖVIDÍTÉSÉBEN is keres (`01-sema.sql` és - `02-kereses.sql` unió). A jogszabály-cím találatok kiemelt rangsorolással + CÍMÉBEN, MEGJELÖLÉSÉBEN és RÖVIDÍTÉSÉBEN is keres (a `01-sema.sql` két `tsv` + oszlopa; a két tábla találatait az élő `kereses()` — `05-kereses-gyors.sql` — + egyesíti). A jogszabály-cím találatok kiemelt rangsorolással közvetlenül a törvény hatályos oldalára mutatnak. +- A `valtozasok` `felveve_utan` cursora jelenleg NEM veszteségmentes: a következő + cursor a lap legnagyobb `felveve`-je, a szűrés szigorú `>`, ezért ha a lap határa egy + azonos `felveve` időbélyegű köteg (egy napi futás akár 200+ sora) közepére esik, a + köteg maradékát a következő lap már nem adja vissza (#26, nyitott; 2026-10-21-i élő + repro: 221-ből 171 tétel kimaradt). Amíg nincs javítva, ne írd le és ne ajánld + veszteségmentesnek; a javítás módja az issue-ban nyitott kérdés. ## Átnevezés: Nyílt Jogtár → GitJog (2026-09-16) A Wolters Kluwer Hungary Kft. védjegyfelszólítása („Jogtár", lajstromszám 207067 és 185290) miatt a projekt neve GitJog lett. Ami változott, és ami szándékosan nem: -- Weboldal: `gitjog.remenyfarm.hu`; a régi `jogtar.remenyfarm.hu` a `next.config.ts` - host-alapú redirectjével 308-cal az újra mutat (bejövő linkek miatt marad). +- Weboldal: `gitjog.remenyfarm.hu` — 2026-09-23 óta ez az EGYETLEN link mindenhol. A + régi `jogtar.remenyfarm.hu`-ra a `next.config.ts` host-alapú (308-as) redirectje kész, + de a DNS-rekord 2026-09-16 óta nincs (NXDOMAIN), így az átirányítás ma nem él. Döntés + (owner, 2026-09-23): a régi címet ne használd, a DNS-ének helyreállítását ne javasold, + és ne jelentsd hibaként. - Adat-repo: `godavid/magyar-jogtar` → `godavid/magyar-jog` (a GitHub a régi nevet átirányítja, amíg nem jön létre ugyanazon a néven új repó — ne jöjjön). - Vercel-projekt: `jogtar` → `gitjog`; csomagnevek: `@nyilt-jogtar/*` → `@gitjog/*` diff --git a/packages/pipeline/src/sablonok.ts b/packages/pipeline/src/sablonok.ts index 51d0a03..2311c75 100644 --- a/packages/pipeline/src/sablonok.ts +++ b/packages/pipeline/src/sablonok.ts @@ -92,7 +92,7 @@ Parliament** (4,300+ acts, 1827–today), maintained as a git repository: - \`jogszabalyok//szoveg.md\` — consolidated text of one act (HEAD = current state) - \`jogszabalyok//meta.json\` — identifiers, title, source URL, list of point-in-time versions - \`jogszabalyok//allapotok.json\` — versions of this act: \`[{datum, verzio, sha}]\` -- \`index/jogszabalyok.json\` — list of all acts: slug, documentId, megjelölés (official designation), cím (title), rövidítés (abbreviation) +- \`index/jogszabalyok.json\` — list of all acts: \`[{slug, documentId, megjeloles, cim, rovidites}]\` (official designation, title, abbreviation) - \`index/allapotok.json\` — all versions of all acts (4+ MB; prefer the per-act file) - \`index/felvetel/YYYY-MM.jsonl\` — **ingestion log**: one line per version added, with the time it entered the repo @@ -141,8 +141,11 @@ git blame -L 120,140 -- jogszabalyok//szoveg.md cat index/felvetel/2026-09.jsonl | jq -c 'select(.felveve > "2026-09-15T00:00:00Z")' \`\`\` -Sections (§) are Markdown headings (\`##\`–\`####\`). A heading such as \`18. § [Elővásárlási jog]\` -has the anchor \`18-sz-elovasarlasi-jog\` on the website (\`/jogszabaly/#\`). +Structural units (book, part, chapter, subtitle) and many sections (§) are Markdown headings (\`##\`–\`####\`), +but not all: in many acts a § is plain text (e.g. \`18. § (1) …\`) under the nearest heading, and some acts have no headings at all. +A heading such as \`6:272. § [Megbízási szerződés]\` (Ptk.) has the anchor \`6-272-sz-megbizasi-szerzodes\` on the +website (\`/jogszabaly/#\`). To get a § by number, call \`szakasz\` with \`paragrafus\` (e.g. \`18. §\`); +do not build the anchor yourself. ## Caveats diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bd6443b..5d6edf4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,7 +6,8 @@ settings: overrides: nanoid@<3.3.18: ^3.3.18 - undici@>=7.0.0 <7.29.1: ^7.29.1 + undici@>=7.0.0 <7.30.1: ^7.30.1 + zod@<4.6.6: ^4.6.6 vite@>=7.0.0 <7.3.7: ^7.3.7 importers: @@ -40,8 +41,8 @@ importers: specifier: ^19.2.8 version: 19.2.8(react@19.2.8) zod: - specifier: ^4.2.0 - version: 4.6.5 + specifier: ^4.6.6 + version: 4.6.7 devDependencies: '@types/node': specifier: ^24.0.0 @@ -1146,8 +1147,8 @@ packages: undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - undici@7.30.0: - resolution: {integrity: sha512-dkrQXeHSaoamnItlYbmzG0wFYrM0ZwDxCIg0A7aKjTyyhh9svRzCNFEzV+Vm05/yehjCzjDZ31KXfGEjYSztDQ==} + undici@7.30.1: + resolution: {integrity: sha512-03KrMbjIFDWQR5RNPrSw3bd1r12JpyFQl9/yxjUbJtqkjmllqC5lFjZh6ujeuJCKr8EOQvRW872Oy/az+nLYxg==} engines: {node: '>=20.18.1'} vite@7.3.7: @@ -1245,8 +1246,8 @@ packages: engines: {node: '>=8'} hasBin: true - zod@4.6.5: - resolution: {integrity: sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==} + zod@4.6.7: + resolution: {integrity: sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==} snapshots: @@ -1451,12 +1452,12 @@ snapshots: '@modelcontextprotocol/core@2.3.1': dependencies: - zod: 4.6.5 + zod: 4.6.7 '@modelcontextprotocol/server@2.3.1': dependencies: '@modelcontextprotocol/core': 2.3.1 - zod: 4.6.5 + zod: 4.6.7 '@next/env@16.4.2': {} @@ -1724,7 +1725,7 @@ snapshots: parse5: 7.3.0 parse5-htmlparser2-tree-adapter: 7.1.0 parse5-parser-stream: 7.1.2 - undici: 7.30.0 + undici: 7.30.1 whatwg-mimetype: 4.0.0 client-only@0.0.1: {} @@ -2050,7 +2051,7 @@ snapshots: undici-types@7.18.2: {} - undici@7.30.0: {} + undici@7.30.1: {} vite@7.3.7(@types/node@24.13.3)(tsx@4.23.13): dependencies: @@ -2097,4 +2098,4 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 - zod@4.6.5: {} + zod@4.6.7: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 7d90528..c4ffee8 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -8,6 +8,9 @@ overrides: # GHSA-2v37-7h3g-55p8 (high): a postcss tranzitív nanoid-ja; a javított 3.x ág "nanoid@<3.3.18": "^3.3.18" # GHSA-rfgv-xxqx-mfg5, GHSA-w293-vg96-wgc3 (high): a cheerio tranzitív undici-ja; javított a 7.29.1 - "undici@>=7.0.0 <7.29.1": "^7.29.1" + # GHSA-xjj6-f33q-929c (high): túl sok content-encoding; javított a 7.30.1 + "undici@>=7.0.0 <7.30.1": "^7.30.1" + # GHSA-mrhx-c7xc-m3w5 (high): a Zod memóriát fogyaszt a túl nagy kollekción; az MCP szerver SDK tranzitív zod-ja; javított a 4.6.6 + "zod@<4.6.6": "^4.6.6" # GHSA-587h-7wmj-h5pm (high): a vitest tranzitív vite-ja (launch-editor); javított a 7.3.7 "vite@>=7.0.0 <7.3.7": "^7.3.7"