cb7e9aa06b
Documents release a6b2b84 (the queryLatestTemperatures fix and the user's
CSS polish pass) in the changelog and README status line. Also fixes a real
bug in VPS_RELEASE_RUNBOOK.md's own checksum step, found by actually running
it for this release: it generated the .sha256 file against a full local
path rather than a bare filename, which fails verification on the VPS since
that path doesn't exist there.
52 lines
12 KiB
Markdown
52 lines
12 KiB
Markdown
# WeatherTool project documentation
|
||
|
||
This directory contains the working documentation for the WeatherTool modernization effort. The repository-root `README.md` is preserved as the original project overview; these documents describe the reviewed code, current staging environment, and changes being developed.
|
||
|
||
## Current status
|
||
|
||
- Windows is restricted to source editing, review, and Git operations. Rocky is the sole compile, build, development-runtime, and test environment. The Ubuntu VPS is a deployment target only.
|
||
- A production-like staging copy runs through Docker Compose on Rocky Linux at `http://192.168.1.101:9190`.
|
||
- Both Rocky and the VPS currently run on the free `data.gov.lv` open-data feed only. Real private FTP credentials (`ftp.meteo.lv`) were obtained 2026-08-23 and the code path is proven working (manual tests succeeded repeatedly, including once from Rocky as recently as 2026-08-24 morning), but enabling the *scheduled* fetch has failed unpredictably on both machines at different times, for reasons not yet understood — see the roadmap Phase 7 for the full timeline. `ENABLE_LVGMC_FTP_JOBS` stays `false` everywhere until the LVGMC contact can explain the account's actual connection/rate policy. DMI HARMONIE's credentials turned out not to be needed at all (DMI dropped its API key requirement — confirmed live, see the roadmap changelog) but wiring it up is deferred to a dedicated verification session, since the GRIB-parsing and map-rendering code has real, untested risk (a hardcoded crop/rotation calibration that may not match the current model grid).
|
||
- A real UTC-vs-local timezone mismatch between the two sources (open-data's timestamps were UTC, FTP's already local, both stored in the same column with no conversion) was found and fixed before enabling both together; both `weather` tables were backed up and wiped for a clean, consistently-timestamped restart.
|
||
- The safe scheduled jobs (open-data station ingestion, GRIB cleanup) always run; the FTP and HARMONIE jobs both stay off — FTP pending the LVGMC answer above, HARMONIE pending its own implementation/verification work.
|
||
- PostgreSQL is private to the project Compose network; only the Scala application publishes a host port.
|
||
- The operator-facing workspaces now use the Latvian workflow names **Stacijas**, **Kartes**, **Faktiskā**, **Ūdens**, **Brīdinājumi**, **Apskats**, **Arhīvs**, **Harmonie**, and **LVĢMC**. Kartes retains custom analytical map outputs, while Faktiskā is a fixed 13-position, latest-temperature newsroom workflow with a locked 3840×1440 export.
|
||
- Faktiskā symbol placement is automatic after manual image selection and is anchored to each rendered temperature badge. Temperature values can be corrected two ways: clicking a badge directly on the map preview (fast path for a one-off tweak) or the "Rādīt stacijas" panel (bulk view, timestamps, stale/missing indicators, reset) — both share the same override state. Valmiera's position sources from Priekuļi's real station reading as a provisional substitute, since LVĢMC has no station in or near Valmiera itself; pending confirmation from LVĢMC directly.
|
||
- A August-25 frontend pass added shared side padding on previously edge-to-edge pages (Kartes, Stacijas, Apskats), fixed a real CSS collision in Kartes' results grid, removed dead CSS/JSX found via a systematic per-class usage check, reworked Ūdens's six temperature cards to fit one row (`auto-fit` grid, catching and fixing a real narrow-width input-clipping bug along the way), and matched Ūdens's resolution buttons to the cards' visual style.
|
||
- **Ūdens** auto-populates its six ranges on load with real per-zone water-temperature min/max (65 LVĢMC stations classified into the 6 named zones), with manual override and reset still available. Uses separate authoritative 1920×1080 and 3840×1440 production templates; both exports have been visually validated.
|
||
- **Brīdinājumi** renders current LVĢMC warning polygons over a production border overlay with feathered severity fills, plus draggable/resizable per-warning weather-symbol placement. Its lon/lat-to-pixel projection is an affine fit calibrated against the same validated city pixel positions Kartes/Faktiskā already use, replacing an earlier bounding-box calibration that drifted up to ~200px on the 3840 canvas.
|
||
- Confirmed local Monda Regular/Bold files provide interface and generated-graphic typography; weather symbols use normalized transparent image assets.
|
||
- Release `b0b58d2` (`weathertool:b0b58d2f1e0ed47ca13795b64595386ec2f0e0c7`) replaced the hardcoded per-route static-file list with a general SPA fallback — a real, user-reported bug where refreshing `/faktiska` or `/udens-temperatura` 404ed instead of loading the app (those two routes were never added to the old list). A missing `/assets` file still 404s properly rather than silently serving HTML.
|
||
- An independent fresh-eyes security review (requested against the local Rocky version only) found a live-verified CRITICAL path-traversal vulnerability plus several HIGH/MEDIUM findings — see the roadmap changelog for `6b9c7cf`/`8c45d8d` for the full list. All are fixed and deployed. Rocky's `POSTGRES_PASSWORD` was rotated afterward since the old value had been exposed into the review's own output via `/proc/self/environ`. `LVGMC_PASSWORD` rotation is not yet done — that needs the user's own action via the LVGMC contact. A follow-up independent review then caught that the FTP auth-bypass fix was incomplete (a sibling route, `/api/show/lvgmc-forecast`, had the same live-FTP-trigger issue but had only gotten the traversal fix); fixed as `9bab93d`. That same review flagged several open architectural/testability findings (the `parMapN` scheduler crash-loop pattern, per-request `System.gc()`, an unenforced field-routing invariant, no JDBC connection pooling, and several files under `src/main/scala` that look like tests but aren't) — not yet acted on, tracked for a future session.
|
||
- Release `a6b2b84` is deployed as immutable image `weathertool:a6b2b8462c9adf1647ebddf92edb0e41d345d6e7`; release `001b014` remains the immediate application rollback. Fixes a real bug reported live by the user: Faktiskā showed blank temperatures for a stretch after every new hour started, because the "latest observation" query picked whichever row was newest regardless of whether its temperature field had actually landed yet (the open-data source publishes some fields, like snow, well before the hourly temperature aggregate). Isolated to Faktiskā — Kartes and Ūdens use different query shapes unaffected by the same timing gap. Also carries a small hover/focus-state and checkbox-styling polish pass. See the roadmap changelog for `a6b2b84`/`829319e`.
|
||
- Gitea Actions CI is live: a repository-scoped runner on Rocky (isolated behind its own Docker-in-Docker daemon, same pattern as HOP's Forgejo runner) runs `sbt test` plus the frontend typecheck/build/audit routine on every push/PR to `codex/staging-baseline`. See [Continuous integration](CONTINUOUS_INTEGRATION.md). CI-only for now — it does not deploy anywhere or touch any real credential.
|
||
- FTP (`ENABLE_LVGMC_FTP_JOBS`) is currently `false` on both Rocky and the VPS — re-testing the morning after enabling it turned up a second, unexplained failure (Rocky alone, VPS confirmed off, ~4 minutes after a successful manual test) that doesn't fit the original two-machine-collision theory. Decided to stop self-testing via trial and error and wait for the user to ask the LVGMC contact directly about the `ltv` account's connection/rate policy, rather than risk repeatedly tripping an unknown limit. See the roadmap Phase 7 for the full diagnosis timeline.
|
||
- The isolated VPS UAT stack is running and healthy: WeatherTool is bound to `127.0.0.1:8002`, Authelia to `127.0.0.1:9091`, and PostgreSQL has no host port. Public access is routed through Cloudflare, Nginx, and Authelia.
|
||
- Cloudflare delegation is active, strict origin TLS covers only `laikapstak.li` and `auth.laikapstak.li`, and the public Nginx/Authelia login flow is operational without changing the existing HOP site.
|
||
- The VPS `weather` table was wiped twice on 2026-08-23: first to remove the original 14-day synthetic dataset (backed up to `/srv/weathertool/backups/pre-real-data-release/`), then again after the UTC/local timezone fix (backed up to `/srv/weathertool/backups/pre-timezone-fix-wipe/`) so the two real sources it now holds — open-data (minutes 15/45) and FTP (minutes 11/13/23/30) — are consistently timestamped from a clean start.
|
||
- Approved 1920×1080 and 3840×1440 PNG production bases are now the rendering source for Faktiskā and Ūdens temperatūra; code draws only the changing values, selected weather symbols, and wind data over those fixed newsroom graphics.
|
||
- Browser branding assets and Latvian Open Graph/Twitter metadata are included for favicon, Apple home-screen icon, and link-preview support. Public crawler access still depends on the Nginx/Authelia policy used for the metadata and preview image.
|
||
- Browser and API verification is complete for the deployed `3eddf95` release: exact release image smoke-tested on Rocky before transfer (bundle hash and correct-local-time API responses matched the known-good local build), checksum verified on both ends, container health/loopback/public HTTPS confirmed.
|
||
- Every FTP failure so far has cascaded through `parMapN` into the app's top-level error handler, crash-looping the *entire* app in-process (DB, HTTP server, schedulers all torn down and rebuilt every ~5s) rather than just failing the one scheduled task — caught twice by watching logs after enabling the flag rather than assuming it was safe, reverted both times within minutes.
|
||
- Frontend dependency maintenance is complete: Solid runtime and Vite tooling were updated, obsolete packages were removed, TypeScript checking was added, and a clean Rocky `npm ci`, typecheck, production build, full audit, and production-only audit all pass with zero known vulnerabilities.
|
||
- This is not yet approved or hardened for workplace production.
|
||
|
||
## Documents
|
||
|
||
- [Architecture and data flow](ARCHITECTURE.md) — components, data sources, data flow, and repository layout.
|
||
- [Development and staging](DEVELOPMENT_AND_STAGING.md) — Windows source/Git workflow, Rocky development and verification, VPS deployment, synthetic data, and rollback.
|
||
- [Product workflows](PRODUCT_WORKFLOWS.md) — the intended purpose and current status of each visible workspace.
|
||
- [Update roadmap](UPDATE_ROADMAP.md) — phased technical, security, dependency, testing, and UI work.
|
||
- [Continuous integration](CONTINUOUS_INTEGRATION.md) — Gitea Actions topology, isolation boundary, and the current CI workflow.
|
||
- [Third-party notices](THIRD_PARTY_NOTICES.md) — licenses and attribution for adapted interface components.
|
||
- [Temporary VPS staging plan](VPS_STAGING_PLAN.md) — isolation, authentication, prepared deployment bundle, release, backup, verification, and rollback model for external user testing.
|
||
- [VPS release runbook](VPS_RELEASE_RUNBOOK.md) — the literal, copy-pasteable command sequence for shipping and rolling back a release, step by step.
|
||
|
||
## Documentation rules
|
||
|
||
1. Do not put passwords, API keys, workplace URLs, or production data in Git.
|
||
2. Document the behavior that exists separately from behavior that is proposed.
|
||
3. Update these documents in the same commit when a change alters deployment, data flow, or a user workflow.
|
||
4. Keep synthetic/development instructions clearly distinguished from workplace production procedures.
|
||
5. Preserve established Latvian names in operator-facing workspaces and production files even when development notes are written in English.
|