--- name: environmental-permit-decisions description: Query KOTKAS public server-side forms for environmental permits, applications, proceedings, documents, and permit details. module: kotkas.mjs execution: get --- # Environmental Permits (KOTKAS) ## Vetted module (use this first) `kotkas.mjs` ships in https://kodanikukratt.ee/kratt-agent.tar.gz (plain ESM, Node 22+) and is re-verified against the live source: ```js import { show } from "./kratt.mjs"; import { envPermits, envPermitDetails, envApplications, envDocuments } from "./kotkas.mjs"; const p = await envPermits({ owner_name: "Tallinna Vesi" }); show({ kokku: p.totals, note: p.note }); show(p.rows.slice(0, 5)); const d = await envPermitDetails(p.rows[0].permitId); show({ nr: d.number, liik: d.kind, olek: d.status, kehtivus: d.validity, omanikud: d.holders }); show(d.versions); // the permit's whole history show(await envDocuments({ keyword: "eelnõu" })); // drafts still out for comment ``` - `envPermits(...)` reports **`totals.records`, the register's own "Kokku N kirjet"**, and returns one page at a time. `totals.pages` says how many there are — if more than one, either fetch the rest with `{page}` or say the list is partial. Never total by counting rows. - **The page size differs per listing**: 20 permits, 40 applications, 100 documents (measured live 2026-08-01). The module steps by the right one; stepping by the wrong number silently returns overlapping pages. - **The same permit legitimately appears more than once.** Each lifecycle version is its own row, so `Arhiveeritud` next to `Kehtiv` is one permit's history, not two permits. - A search matching nothing answers HTTP 200 with the form and **no counter**, so `totals.records: 0` with `ran: true` is a real zero rather than a failed request; when `{page}` is past the end the note says so instead. - `envPermitDetails(permitId)` takes the row's **`permitId`**, not the permit number, and returns `holders`, `proceedings` (the M-numbers that produced it) and `versions`. - `envApplications` is what is being **asked for** and grants nothing; `envDocuments` is the correspondence, and the rows titled "… eelnõu kohta arvamuse küsimine" are draft decisions circulated for comment — which is where a citizen still has something to say. A visible row does not mean the file itself is public. - **A valid permit is not evidence that nothing is wrong**: this register holds what is allowed, not whether the holder complies. The endpoints below are the fallback if a module call throws. ## Access - Permits: `https://kotkas.envir.ee/permits/public_index` - Applications: `https://kotkas.envir.ee/permits/public_application_index` - Documents: `https://kotkas.envir.ee/permits/public_document_index` - Public HTML forms; no login is required. ## Retrieve The register runs the same search from a **GET query string** as from the POST its own form submits — both verified live, same `Kokku N kirjet` (`GET .../permits/public_index?search=1&owner_name=Tallinna+Vesi` returned `Kokku 40 kirjet` and 20 `permit_id` links on 2026-08-02). Use GET: it needs no request body, and paging re-reads the same URL. Send `search=1` plus the filters. Permit filters include `permit_nr`, `owner_name`, `object_name`, `permit_type`, `permit_status`, issue/validity date ranges, `well_number`, and location/activity fields. Application filters include `applicant`, `application_type`, `permit_nr`, `proceeding_nr`, `proceeding_public_status`, and registration dates. Document filters include `document_number`, `external_number`, `document_type`, `title`, `keyword`, sender/recipient, publication level, and registration dates. Permit results are server-rendered rows with links to `/permits/public_view?...&permit_id={id}`. Page with `qs` in increments of 20 while preserving the filters. The result footer states the current page and total record count. On a permit, use the registration/detail, documents, and assignments tabs rather than treating the list row as complete. ## Return - Preserve permit/application/proceeding/document identifiers, holder or applicant, object and location, type, status, relevant dates, detail/document URLs, query, total, and retrieval time. - Keep application, proceeding, permit, and document records as separate record types. ## Limits - This is HTML extraction, not a public JSON API. Estonian labels and form fields may change. - A permit number can appear in several lifecycle/version rows; do not deduplicate without retaining internal `permit_id` and status dates. - Some files or fields may be restricted even when the public register row is visible. ## Verify - Require a focused search to return a positive `Kokku ... kirjet` count and `/permits/public_view?...permit_id=` links. - Require a selected detail page to expose status plus registration, documents, and assignments tabs. ## Module API envPermits({permit_nr, owner_name, object_name, permit_type, permit_status, page}) -> {source, page, filter, ran, totals, rows, note} envPermitDetails(permitId) -> {source, page, number, kind, status, issuedOn, validity, holders, proceedings, versions, fields, note}