--- name: state-audit-reports description: Retrieve National Audit Office audit records, topics, dates, findings, recommendations, responses, and linked report files. module: riigikontroll.mjs execution: get --- # State Audit Reports ## Access - Estonian audit index: `https://www.riigikontroll.ee/auditiaruanded/koik` - English audit index: `https://www.riigikontroll.ee/en/audits` - Public server-rendered HTML and files; no login is required. - `https://www.riigikontroll.ee/auditid` — named here until 2026-08-01 — answers HTTP 404 with a full 60 KB "Otsitud lehekülge ei leitud" page, i.e. a document containing no audits and no error worth noticing. ```probe-limit claim answers HTTP 404 with a full 60 KB "Otsitud lehekülge ei leitud" page GET https://www.riigikontroll.ee/auditid expect-status 404 expect /Otsitud lehekülge ei leitud/ # Both halves are asserted because both are the trap: a 404 that arrives as a # full page of site furniture is what an agent parses as "the index has no # audits" instead of "wrong path". # The control is the real index. If the site went down or behind a challenge, # every path would 404 and this claim would keep passing while the guide's own # main route was dead — which is the failure a control exists to catch. control GET https://www.riigikontroll.ee/auditiaruanded/koik ``` ## Retrieve Parse records only from the index's audit result list. Each card links to an audit detail page and includes report type, topic tags, title, teaser, and date. Use `?page=N` (0-based) for later result pages; a page with fewer than 30 cards is the last one. The whole Estonian index was 9 pages and 244 audits on 2026-08-01, so it can be walked and counted in full. The site's own facet/search API is `search.service.eu-live.vportal.ee`, the same host `government-session-agendas` uses, and it answers: `GET /v1/search/riigikontroll?q=audit` with `Origin: https://www.riigikontroll.ee` returned `numFound: 622` (verified 2026-08-02 with Node). Like the valitsus.ee index it needs that `Origin`/`Referer` pair — without them it answers HTTP 200 with a body of literally `null`, which is not an empty result. It was unreachable from Node until 2026-08-02; `certs/estonian-state-chain.pem` fixed that centrally. The paged HTML index above still works and remains the simpler route when you need the whole list in order. ```probe-limit claim without them it answers HTTP 200 with a body of literally `null`, which is not an empty result GET https://search.service.eu-live.vportal.ee/v1/search/riigikontroll?q=audit expect-status 200 expect /^null$/ # Both halves, because the refusal IS a 200: the status alone can never catch # this one going stale, and the body alone would keep passing behind an error # page. The control is the same query carrying the header the sentence names, # which is the only thing that tells the missing header from a host that has # stopped answering — an outage returns `null` to everyone. control GET https://search.service.eu-live.vportal.ee/v1/search/riigikontroll?q=audit header Origin: https://www.riigikontroll.ee ``` On the detail page, extract title, teaser, report type, topic tags, publication information, body findings, recommendations, audited institutions' responses, and links under the report/sidebar fields. Resolve `/sites/default/files/...` links against the host and verify each file type before parsing. ## Return - `auditReports()` rows are `{title, url, type, date, teaser, topics}`; `auditReport()` adds `findings`, `files:[{url, name, note}]` and `responses:[{by, text}]`. - Keep the National Audit Office's finding and the audited body's response as separate attributed fields. On the detail page the responses are accordion blocks whose header names the body ("Taristuministri vastus") — flattened without their headers they read as one document written by the auditor. - The full report is usually only in the linked PDF. Read it with `fileText(file.url)` before stating a number from it. ## Limits - The index mixes audit reports (222), annual reports to the Riigikogu (8), evaluations of the state's annual accounts (11) and untagged reports (3). Retain the type. - Four of the thirty cards on the first page link an unaliased `/node/` rather than an `/auditiaruanded/` path — the Audit Office's own annual report among them. Take the URL from the card; do not compose a slug. - A detail page publishes no structured date: no `