Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i
server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma
strängvärde byggs med konkatenering i stället för att matcha mönstret.
Lägger docs/production-readiness.md och siax/production-gaps.json enligt SIAX Master Definition of Done. Underlag: git-, kod- och live-evidens 2026-11-11. Nivån är evidensbaserad, inte ett leveransgodkännande.
* feat(mileage): suggest driving distance from the from/to addresses
When both endpoints are typed in the trip form (create mode), a debounced
lookup geocodes them via Nominatim and fetches the driving distance via
OSRM, both proxied through /api/mileage/distance so addresses leave only
our server, without user identifiers. The suggestion renders as a
click-to-apply hint under the distance field, never auto-fills, and stays
fully editable. Tooltip shows what the geocoder matched.
In-instance caching (24h hits, 10min misses) plus 1.1s politeness spacing
keep usage inside the OSM public-endpoint policies. OSMF is disclosed as a
data recipient on the privacy page.
Requested by a beta user: first-time routes had to be measured by hand;
route memory (PR #1657) only helps from the second trip onward.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(mileage): resolve skeptic findings on the distance suggestion
Compliance: routing switched from router.project-osrm.org (demo server,
non-commercial use only) to FOSSGIS's routing.openstreetmap.de; the lookup
is now click-triggered ("Foresla stracka") instead of as-you-type, per
Nominatim's no-autocomplete policy; visible OpenStreetMap attribution next
to the applied suggestion; privacy page reworked to name OSMF and FOSSGIS
e.V. as independent recipients outside the sub-processor table, with an
honest note that typed addresses can themselves be personal data.
Correctness: suggestion-cache key separator changed from '|' (collidable
by address text) to newline; routes rounding to 0.0 km are no longer
suggested (the form rejects 0); the Nominatim politeness queue is bounded
at 3s wait and bails to null instead of holding request handlers open.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(mileage): resolve CodeRabbit findings on the distance suggestion
A generation counter invalidates in-flight lookups when the route or km
field changes or the dialog closes, so a slow response can never write an
old route's distance into a changed form. Privacy page now states each
recipient's actual payload (Nominatim gets address texts, FOSSGIS only
coordinates), discloses the 24h in-memory server cache, and carries
today's revision date.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(mileage): körjournal with milersättning booking, MCP tools and CSV export
New mileage_trips table (RLS, booked-delete trigger per BFL retention),
lib/mileage service reusing the payroll schablon rates, /api/mileage routes
(trips CRUD, period booking to 7331, salary-run push, körjournal CSV),
Körjournal dashboard page + nav, and three staged MCP tools (search-only
catalog). Trips book as one verifikat per period via the engine; salary
path inserts mileage_taxfree line items. mileage_trips classified in the
full-archive export.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(mileage): use shared roundOre helper per tightened ratchet baseline
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(mileage): pending_operations op-type migration + Swedish review findings
- New migration pair adds log_mileage_trip/book_mileage_period to the
pending_operations operation_type CHECK (pg-real audit).
- bookMileagePeriod refuses a period spanning several employees and names
the employee in the verifikationstext when scoped (BFL motpart).
- vehicle_registration required for förmånsbil trips (schema, service,
MCP staging, UI surfaces the field).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(mileage): claim-first booking, CSV injection guard and driver column
- bookMileagePeriod claims trips (draft to booked CAS) before creating the
verifikat, so a concurrent second booking loses the race instead of
double-booking; claim reverts if verifikat creation fails.
- Körjournal CSV neutralizes formula-injection triggers (OWASP) and adds a
Förare column naming the employee per trip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(mileage): resolve CodeRabbit + Swedish review round: race, drift and hardening
- Copying a round trip no longer re-doubles the stored distance.
- pushMileageToSalaryRun claims trips before inserting line items (retry can
no longer double-pay); CLAIM_LOST replaces misleading NO_TRIPS on lost races.
- Booked trips are DB-immutable via a BEFORE UPDATE trigger (new migration
20260807113215): only claim/link/revert transitions and notes edits pass.
- Cross-year periods rejected (schablon rates are per calendar year); payroll
config year read from the date string, not TZ-dependent getFullYear().
- MCP staged bookings freeze the previewed trip set (trip_ids in params) and
the commit fails on drift; validation errors return 400, not 500.
- PATCH enforces the förmånsbil regnr rule on the effective row; export
validates dates before they reach the Content-Disposition header; employee_id
is verified company-scoped on trip creation; stale orphaned claims released.
- UI: fetch flags reset in finally; ICU plural for draft summary; distance
stored at the column's 1-decimal precision.
- Tests: [id] route suite, pushMileageToSalaryRun suite, claim-race, drift,
cross-year and update-trigger pg cases.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(mileage): revert-to-draft must clear salary_run_id at the trigger level
New migration 20260807114924 replaces the booked-immutability function: a
booked -> draft revert now rejects rows keeping salary_run_id, closing the
DB-level double-pay path CodeRabbit flagged. pg test pins both directions;
the CLAIM_LOST unit test now asserts the revert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(mileage): company-scope employee_id on PATCH (Superagent P2)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test(mileage): valid v4 uuid in cross-company employee PATCH test
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>