Endringslogg
Gjeldende publisert versjon: v1.20.2
Her logges alle publiseringer til stoyvakt.sjekk.org i henhold til semver — PATCH for feilrettelser, MINOR for nye funksjoner, og MAJOR for bryteendringer.
Sikkerhetsherding: effektiv UPDATE-lockdown på fixed_measurement_stations
- Verifisering av v1.20.1 avdekket at kolonne-nivå `REVOKE UPDATE (hmac_secret, api_client_id, approval_status, …)` ikke fikk effekt fordi tabell-nivå `UPDATE`-grant til `authenticated` overstyrte den (Postgres kolonne-grants er additive, ikke restriktive).
- Fix: `REVOKE UPDATE ON public.fixed_measurement_stations FROM anon, authenticated, PUBLIC`, deretter `GRANT UPDATE` kun på trygge eier-redigerbare kolonner: `station_name`, `geom`, `hardware_type`, `hardware_kind`, `microphone_model`, `calibration_date`, `calibration_reference_db`, `measurement_interval_seconds`, `active`, `notes`, `description`, `contact_email_for_alerts`, `facility_id`.
- Bekreftet via `has_column_privilege`: `hmac_secret`/`api_client_id`/`approval_status`/`approved_by`/`approved_at`/`owner_user_id`/`public_slug` UPDATE = false for `authenticated`; ufarlige felter forblir editerbare.
Sikkerhetsherding: entities, correspondence, fixed_measurement_stations
- `entities`: REVOKE SELECT på kolonnene `phone` og `health_authority_email` fra `anon` og `authenticated`. Frontend bruker `entities_public`-viewet og påvirkes ikke; admin og service_role beholder full tilgang.
- `correspondence`: fjernet RLS-policy «Correspondence: anon insert on anon cases». Anonyme brukere kan ikke lenger plante falske korrespondanserader på saker hvis ID-er er offentlige via `cases_public`. Innkommende e-post fra anonyme avsendere går utelukkende via HMAC-signert webhook med service_role.
- `fixed_measurement_stations`: REVOKE SELECT på `hmac_secret` og `api_client_id` fra `anon` og `authenticated` (stasjons-eiere kan ikke lenger lese hemmelighetene via Data-API-et). REVOKE UPDATE på de samme kolonnene + `approval_status/approved_by/approved_at` — kun service_role/admin kan endre.
- Forenklet eier-UPDATE-policy «FixedStations: owner updates limited» til ren eierskapssjekk; de tidligere «frys»-subspørringene er overflødige etter kolonne-nivå REVOKE.
/hensetting: ny verifisert presedens — Hamar Briskebyen (sak 2023/6262)
- Ny verifisert CmsCard på /hensetting i seksjonen «Presedens og dokumentspor», plassert etter MHiG-saken (26/5032) og før Marienborg-blokken: «Hamar Briskebyen — klagesak om støy fra hensatte tog (sak 2023/6262)». Andre dokumenterte Bane NOR-presedens etter Skien.
- Direkte sitater fra Bane NORs brev (Magne Trønnes, prosjektleder, 04.07.2023) som erkjenner at Lden er årsgjennomsnitt og at vinduer forutsettes lukket i beregningene.
- Direkte sitater fra naboklage (Bjørn Inge Sletta, 13.08.2023) som bruker samme argumenter (gjennomsnitt vs. akutt belastning, kumulativ støy etter T-1442 kap. 2.5) som er aktuelle i sak 26/5032.
- Eksplisitt presisjon om at Statsforvalter Innlandet kun var kopimottaker, ikke har behandlet saken.
- To nye entries i `verified-case-numbers`-allowlist: `2023/6262` (Statsforvalter Innlandet) og `202300472-23` (Bane NOR). Saksnumrene vises nå uten `[ikke verifisert]`-tag.
- Anker `#hamar-2023-6262` for senere dyplenking.
Sikkerhetsherding: korrespondanse, HMAC-secret, måleinnsending, dispatch-logg
- `correspondence`: fjernet RLS-policy «Correspondence: case owner reads». Saks-eiere leser fortsatt korrespondanse via `correspondence_public`-viewet (uten e-postadresser/attachments). Admin leser alt som før. UI på `/saker/$caseRef` bruker allerede viewet, så ingen funksjonell endring.
- `correspondence`: INSERT-policy strammet inn — innloggede brukere kan kun opprette korrespondanse-rader på saker de selv eier, eller når de har admin-rollen. Hindrer at en innlogget bruker planter falske meldinger i andres saker via enumererbare case-ID-er. Server-funksjoner (e-post-webhook, sendCaseEmail, innsyn-loggføring) bruker service_role og er upåvirket.
- `fixed_measurement_stations.hmac_secret`: REVOKE SELECT på kolonnenivå fra `authenticated` og `anon`. Speiler tidligere lockdown av `api_client_id`/`api_key_hash`. Pi-installasjon henter secret kun via service_role-RPC.
- `measurements_external`: INSERT-policy for `authenticated` krever nå `station_id IS NOT NULL` og at brukeren eier stasjonen. Hindrer at en innlogget bruker dytter målinger inn i den offentlige datasettet med fritekst-`source_name` uten stasjonskobling. HMAC-signert `/api/v1/measurements` (service_role) er uendret.
- `dispatch_log`: REVOKE INSERT/UPDATE/DELETE fra `authenticated` og `anon`. Eksplisitt bekreftelse på at sende-loggen kun skrives av service_role (server-side). Kun admin SELECT-policy fra før.
Offentlig målestasjon: målepunkt-tabell viser nå Dom. Hz og Lav 63–500
- `get_public_station_events`: utvidet toleransevinduet for sammenstilling mellom `measurements_external` og `measurements_spectrum_external` fra ±30 sekunder til ±5 minutter. Pi-en sender spektraldata på et eget tidsraster (~1–3 min forskjøvet fra dB-målingene), så det gamle vinduet matchet aldri og kolonnene «Dom. Hz» og «Lav 63–500» sto tomme i tabellen på `/maalinger/skien-stasjon`. Ingen endring i datagrunnlag, Pi/API/HMAC, RLS eller andre RPC-er.
/innspill: utvidet argumentasjon + offentlig måleside som supplerende dokumentasjon
- Nytt felt `maalesideUrl` i InnspillData (default `https://stoyvakt.sjekk.org/maalinger/skien-stasjon`) som lar brukeren legge inn URL til offentlig måleside. Lagt inn i FIELDS etter `referanseRapport`.
- Seksjon 1: nytt avsnitt om offentlig måleside som supplement til klagen.
- Seksjon 2: nytt avsnitt om at monoton/vedvarende støy på dagtid også påvirker livskvalitet, konsentrasjon og bokvalitet — ikke bare søvn og natt.
- Seksjon 7: nytt punkt 6 om vurdering av lavfrekvent og tonal karakter.
- Seksjon 8 utvidet og omdøpt til «Supplerende egendokumentasjon og offentlig måleside» med tydelig avgrensning mellom egne målinger og fagkyndig kartlegging, og eksplisitt merking av frekvensanalysen som relativ/indikativ — ikke kalibrert dB SPL.
- Seksjon 9: nytt tredje kulepunkt om at måledata og offentlig måleside skal legges til grunn som indikasjon.
Offentlig målestasjon: tydeligere graftekster og LAeq/LAFmax-tittel
- Lydnivå-graf: tittel endret til «Lydnivå over tid · LAeq / LAFmax (dB)». LAmax-linjen fjernet fordi LAmax og LAFmax er sammenfallende i datagrunnlaget fra Wensn WS1361 — vises som overlappende linje uten ekstra informasjon. Forklaring lagt inn rett under tittelen.
- Hver graf på `/maalinger/$stationSlug` har nå en kort, praktisk forklaring rett under tittelen: lydnivå over tid, daglig oppsummering, døgnprofil, relativ frekvensanalyse, siste frekvensprofil og målepunkt-tabell. Mål: hjelpe publikum å forstå hva mønstrene betyr for opplevd støy.
- Ingen endring i RPC-er, datagrunnlag, Pi/API/HMAC-oppsett eller `/stasjoner/$stationId`.
Skien: slugene flyttet til den ekte Wensn WS1361-stasjonen
- Database hadde to Skien-stasjoner: en tom placeholder (`a19f120a-…`) hadde `facility_slug='skien'`/`public_slug='skien-stasjon'`, mens den ekte Pi-stasjonen (`ccfa9e06-…`, Wensn WS1361) med ~70 000 målinger og 201 spektrumrader manglet slugs. `/maalinger/skien-stasjon` viste derfor ingen data.
- Migrasjon: slugene flyttet til `ccfa9e06-…`. Placeholderen (`a19f120a-…`) satt til `active=false`, `approval_status='suspended'` for å unngå duplikatforvirring i admin. Ingen måledata eller Pi/API/HMAC-oppsett endret.
- Resultat: `/maalinger/skien-stasjon` viser nå reelle målinger fra Pi-en for 24t/7d/30d/90d, og `PublicFacilityStations` på Skien hensetting-side peker til riktig stasjon.
Skien-stasjonen reaktivert for offentlig presentasjon
- Eksisterende Skien-stasjon (a19f120a-…) satt til `active=true` og `approval_status='approved'` slik at public-RPC-ene (`get_public_station_*`, `list_public_stations`) returnerer data og `/maalinger/skien-stasjon` kan verifiseres. Ingen endring i Pi/API/HMAC-oppsett, ingen ny stasjon. `facility_slug='skien'` og `public_slug='skien-stasjon'` beholdt.
Offentlig presentasjon av målestasjoner (/maalinger/$stationSlug)
- Ny offentlig presentasjonsside `/maalinger/$stationSlug` med statuskort, periodevelger (24t/7d/30d/90d), lydnivå over tid (LAeq/LAmax/LAFmax), daglig oppsummering, døgnprofil, relativ FFT-serie, siste frekvensprofil og hendelsestabell. Tidsserier sorteres stigende på tid (eldste til venstre).
- Nye public-RPC-er (SECURITY DEFINER, kun godkjente + aktive stasjoner, ingen HMAC/mikrofonmodell/notes): `get_public_station_summary`, `get_public_station_levels`, `get_public_station_daily`, `get_public_station_hour_profile`, `get_public_station_spectrum`, `get_public_station_spectrum_latest`, `get_public_station_events`, `get_public_stations_for_facility`, `list_public_stations`. Aggregering velges via `_bucket` (raw/15min/hour/day).
- `fixed_measurement_stations`: nye kolonner `facility_slug` (kobling til hensettingsanlegg) og `public_slug` (lesbar URL, UNIQUE). Skien stasjon (a19f120a-…) satt til `facility_slug='skien'`, `public_slug='skien-stasjon'`.
- Skien hensetting-side viser nå offentlig liste over faste målestasjoner via ny komponent `PublicFacilityStations`, med direkte lenke til `/maalinger/skien-stasjon`.
- FFT/frekvensanalyse merket tydelig som «relativ», «indikativ», «ikke kalibrert dB SPL» — mikrofonmodell og LifeCam fjernet fra all offentlig tekst. Egen forklaringsseksjon «Hva viser målingene?» med syv kort (lydnivå, varighet, natt, tonalitet, lavfrekvent, gjentakelse, monoton dag).
- Diskret «Åpne teknisk stasjonsside»-knapp kun for innloggede eiere/admin. Anonyme brukere ser ren offentlig presentasjon.
- Sitemap: lagt til dynamiske `/maalinger/$slug`-entries fra `list_public_stations` (cache 1t). Eksisterende `/stasjoner/$stationId` (eier/admin), API, Pi-oppsett, InfluxDB/Grafana og admin er uendret.
Sikkerhet: hindre spoofing av målinger mot fremmede stasjoner
- RLS INSERT-policy på `measurements_external` strammet inn: innloggede brukere kan kun sette inn rader uten `station_id`, eller med en `station_id` som peker på en `fixed_measurement_stations`-rad de eier (`owner_user_id = auth.uid()`). Tidligere kunne enhver innlogget bruker tilskrive målinger til hvilken som helst stasjon. HMAC-signert `/api/v1/measurements` (service_role) er uendret.
SEO: per-side metadata, canonical, og:url, JSON-LD og sitemap-utvidelse
- Stasjonssiden (`/stasjoner/$stationId`): lagt til `head()` med unik title, description, og:title/og:description/og:url, og:type=article og self-referencing canonical.
- Forside (`/`): differensiert title fra root, lagt til og:url og canonical.
- `/changelog`: lagt til og:url, canonical og CollectionPage JSON-LD.
- `/hensetting`: lagt til og:url, canonical og Article JSON-LD.
- Sitemap: lagt til `/innspill` og `/presse` (mine-* er auth-gated og holdes utenfor indeks).
Fix: tidsakse på stasjonsgrafer sorteres stigende
- Stasjonssiden (`/stasjoner/$stationId`): tidsseriegrafer (Siste 24t Laeq/Lamax, daglig 30d) sorteres nå eksplisitt `measured_at ASC` før de sendes til Recharts. Tidligere `.slice().reverse()` antok DESC fra RPC og kunne gi feil retning på x-aksen. FFT-panelet brukte allerede `order ascending: true` og er uendret. Ingen API/Pi-endringer.
Fix: rotate_station_api_key feilet med 'gen_random_bytes does not exist'
- Aktivert `pgcrypto` i `extensions`-schema og oppdatert `public.rotate_station_api_key` til å kalle `extensions.gen_random_bytes(32)` med `search_path = public, extensions`. Rotasjon av HMAC-secret fungerer igjen. Ingen eksisterende secrets endret.
Skien reaktivert + kolonne-revoke på hmac_secret
- Skien-stasjonen (a19f120a-…) satt til `active = true`, `approval_status = approved`. HMAC-secret ikke rotert.
- Sikkerhet: `REVOKE SELECT (hmac_secret) ON public.fixed_measurement_stations FROM authenticated, anon`. Stasjonseiere kan ikke lenger lese HMAC-hemmeligheten via PostgREST; kun service-role (server-side HMAC-verifisering) har tilgang. Verifisert med `has_column_privilege('authenticated', …, 'hmac_secret', 'SELECT') = false`.
- Frontend publisert til produksjon (Publish → Update) slik at FFT-panelet på /stasjoner/$stationId blir synlig.
API-utvidelse: spectrum[] + ny FFT-tabell + UI-paneler for relativ frekvensanalyse
- POST /api/v1/measurements aksepterer nå både `measurements[]` (kalibrerte dB) og `spectrum[]` (relativ FFT/oktavbånd) i samme batch. Begge arrayer er valgfrie, men minst én må være ikke-tom. Eksisterende HMAC-modell uendret (timestamp + "." + raw_body, lowercase hex, sha256= prefix, konstant-tid, ±300s replay-vindu).
- Ny tabell `measurements_spectrum_external` med 8 oktavbånd (20–8000 Hz) + aggregert `low_band_63_500`, `peak_frequency_hz`, `peak_level_db_relative`, `microphone`, `sample_rate_hz`. RLS public read, kun service-role insert via RPC `insert_station_spectrum` (samme approved/active-sjekk som dB-RPC-en).
- Rename: `fixed_measurement_stations.api_key_hash` → `hmac_secret` (feltet inneholder selve HMAC-hemmeligheten, ikke en hash). Skien-stasjonens secret er bevart uendret. RPC-er `register_station` og `rotate_station_api_key` oppdatert. Admin-UI rotasjonsflyt uendret.
- /stasjoner/$stationId: nytt panel «Relativ frekvensanalyse (FFT)» som viser oktavbånd-energi 20–8000 Hz og dominerende frekvens (Hz) over tid. Tydelig merket «relativ FFT-energi — IKKE kalibrert dB SPL».
- Oppdatert `docs/pi-integration.md` med ny kontrakt, curl- og Python-eksempel (placeholders), responseksempler (200/401 bad_signature/401 replay), feilkode-tabell og sikkerhetsnotat.
- Sikkerhet: ingen ekte `hmac_secret` i docs, migrations, seed, frontend eller logs. Logging i API-handler kun `station_id` + DB feilkode — aldri signatur, secret, raw body eller auth-header.
/innspill: kontinuerlig eksponering — helger, helligdager og ferier (re-bekreftet)
- /innspill: bekreftet avsnitt i seksjon 2 «Hva slags støy dette gjelder» om at hensettingsstøy er kontinuerlig også lørdager, søndager, helligdager og ferier — naboer får ingen restitusjonsperiode mellom arbeidsuker. Argumentet underbygger varigheten av den helsemessige eksponeringen.