尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Malayalam-first public project accountability for Kerala. Rust on Cloudflare Workers.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
Public project accountability for Kerala: what was sanctioned, who got the contract, what has been paid, how far the work has come. It covers KIIFB projects in all 14 districts from two KIIFB sources, and the Public Works Department's list of finished works still under contractor liability. Every number links to a stored copy of its source.
Live at https://keralakanakku.com (Malayalam) and https://keralakanakku.com/en/ (English). www. and the old kanakku.thesolohacker47.workers.dev address redirect there; POST /admin/ingest works on either host.檢視完整 README ↗Public project accountability for Kerala: what was sanctioned, who got the contract, what has been paid, how far the work has come. It covers KIIFB projects in all 14 districts from two KIIFB sources, and the Public Works Department's list of finished works still under contractor liability. Every number links to a stored copy of its source.
Live at https://keralakanakku.com (Malayalam) and https://keralakanakku.com/en/ (English). www. and the old kanakku.thesolohacker47.workers.dev address redirect there; POST /admin/ingest works on either host.
The product spec is in kanakku-spec.md. The design of this build is in docs/design.md.
Everything runs on Cloudflare, written in Rust.
| Part | What it does |
|---|---|
crates/core | Pure Rust: the KIIFB parser, flag rules, change diffing, Indian number formatting and the Malayalam/English strings. Tested natively. |
crates/worker | The Worker (workers-rs): server-rendered pages, open-data endpoints and the nightly ingest. |
migrations/ | D1 schema. |
assets/ | Static files: fonts, icons, the share image, and the map script with its two libraries. Pages other than the map load no JavaScript. |
A page is one HTML request with its stylesheet inlined and one D1 round trip. Fonts are self-hosted and cached for a year.
You need Rust with the wasm32-unknown-unknown target, worker-build (cargo install worker-build) and Node.
npm install
npx wrangler d1 migrations apply kanakku --local
npm run dev
.dev.vars needs an INGEST_TOKEN of your choosing, and EDGE_CACHE=off so edits show up immediately. Then load the data:
curl -X POST -H "Authorization: Bearer $INGEST_TOKEN" http://localhost:8787/admin/ingest
The map needs a basemap file in R2. scripts/basemap.sh builds it and explains how to upload it.
These are committed, so you only need the scripts when something changes.
| Script | Writes | Needs |
|---|---|---|
scripts/icons.py | crates/worker/src/icons.rs from Lucide | npm install |
scripts/district.py | crates/worker/src/district.rs, the district outline from OpenStreetMap | network |
scripts/brand.py | share image and app icons in assets/ | Google Chrome, running dev server |
scripts/vendor.sh | map libraries in assets/vendor/ | npm install |
scripts/basemap.sh | tiles/kerala.pmtiles | brew install pmtiles |
scripts/districts.py | crates/worker/src/district.rs (district outlines) | Python 3 |
scripts/constituencies.py | crates/core/src/constituencies.rs | Python 3, a saved dashboard page |
scripts/ogfonts.py | crates/worker/fonts/*.ttf (share-image fonts) | pip install fonttools brotli |
scripts/shot.sh URL out.png WIDTH HEIGHT takes a screenshot with headless Chrome. It cannot go narrower than about 500 px.
cargo test -p kanakku-core
To see what an ingest would store from a saved copy of the dashboard:
cargo run -p kanakku-core --release --example inspect -- page.html '*' 2026-09-30
A cron trigger runs at 02:30 IST. It fetches https://gis.kiifb.org/ once, and only that page. If the data has changed it stores the page in R2, updates the projects that changed and records each changed field. Flags are recomputed on every run, because "overdue" depends on today's date.
The same trigger then reads KIIFB's project status page (https://www.kiifb.org/prjStatus.jsp) through its public form: one request for the district list, then one per project whose figures changed, plus ten of the longest-unchecked, with a second's pause between requests. To run it by hand, capped at 40 work tables:
curl -X POST -H "Authorization: Bearer $INGEST_TOKEN" "https://<your-domain>/admin/ingest?source=status&details=40"
Once a week it also reads the Kerala PWD defect-liability list for the district's divisions (22 requests). To force a read:
curl -X POST -H "Authorization: Bearer $INGEST_TOKEN" "https://<your-domain>/admin/ingest?source=liability"
If KIIFB blocks Cloudflare's addresses, fetch the page from a machine in India and push it instead:
curl -A "KanakkuBot/0.1" https://gis.kiifb.org/ -o page.html
curl -X POST -H "Authorization: Bearer $INGEST_TOKEN" --data-binary @page.html https://<your-domain>/admin/ingest
PILOT_DISTRICT in wrangler.toml is * for the whole state, or one district's name./status shows the last good read of each source; /api/v1/status answers 503 when a source is stale, so any uptime monitor can watch it.npx wrangler secret put ALERT_WEBHOOK.?ref= tags on links we hand out (counted, then redirected away so the tag is not copied onward), and per-page counts for individual projects. Daily totals in visit_counts; top sources and tags on /status. Hand out links like https://keralakanakku.com/?ref=datameet.curl -X POST -H "Authorization: Bearer $INGEST_TOKEN" "https://keralakanakku.com/admin/review?source=dashboard&record=PWD015-69-03&type=overdue" (source=status with a status-page ref for payment flags; add &off=1 to clear). The mark shows on the page and as under_review_since in the API.ALERT_WEBHOOK with the Monday 02:30 IST run. To send one now: curl -X POST -H "Authorization: Bearer $INGEST_TOKEN" https://keralakanakku.com/admin/digest.search_misses), never with who searched. Text that looks like an email address or phone number is not kept. To read them:
npx wrangler d1 execute kanakku --remote --command "SELECT q, surface, SUM(n) AS n FROM search_misses GROUP BY q, surface ORDER BY n DESC LIMIT 50"| Path | What |
|---|---|
/, /d/{district} | Front page for the state and for a district |
/projects, /p/{code} | Dashboard projects; search works in Malayalam |
/funding, /f/{ref} | What KIIFB approved and what has been paid |
/liability | Finished PWD works still under contractor liability |
/contractors, /c/{key} | Contractors across the sources |
/agencies, /a/{key} | Implementing agencies |
/og/p/{code}.png, /og/f/{ref}.png | Share images, drawn on request |
/status, /methodology, /data, /map | Health, method, downloads, map |
/about | Who runs it, corrections, takedown requests, privacy, accuracy and use, licences. The contact shown is CONTACT in wrangler.toml |
/press | Two-minute brief for journalists, with live figures and the payment-listing finding explained |
Everything is under /api/v1/, described in full at /api/v1/openapi.json (a static file in assets/api/v1/). Full downloads: projects, funding, liability (JSON and .csv), projects.geojson, projects/{code}. Paged, 500 rows a page with a next link: changes?since=yyyy-mm-dd, flags?status=open|cleared|all&type=…, snapshots?source=1|2|3; all three take district=. Version 1 only grows; a breaking change would be /api/v2/.
license and attribution.