fartOLa
Architecture Decision Records

ADR — beslut som ligger fast.

Sju arkitekturbeslut i MADR 4.0.0-format. Ett ADR fångar varför ett val gjordes, inte hur det implementerades. Filerna lever i .planning/adr/ i repot. När ett beslut ersätts av ett nytt markeras det gamla superseded by ADR-NNNN — vi tar inte bort filer, ID:n återanvänds aldrig.

Innehåll

  1. 0001 — Reimplementera, forka inte MeOS
  2. 0002 — Tre-lagers arkitektur
  3. 0003 — Event sourcing som datamodell
  4. 0004 — ElectricSQL bara för read-sync
  5. 0005 — SportIdent-koden isolerad under MIT
  6. 0006 — Teknikstack
  7. 0007 — Standarder först
ADR-0001

Reimplementera, forka inte MeOS

accepted

2026-05-12Jonas Hagberg

Problem
MeOS dominerar svensk orientering och har mogen UX. Forka och modernisera, eller skriva om från noll?
Beslut
Skriv om från noll. Inspireras av MeOS, dela ingen kod.
Varför
MeOS ligger under AGPL-3.0, inte GPL-3.0. Ett derivat som nås över nätet triggar publiceringskrav mot fjärranvändare enligt AGPL §13. Den bördan vill vi inte bära.
licens scope → ADR-0005
ADR-0002

Tre-lagers arkitektur: edge-bridge + browser + valfri central

accepted

2026-05-12Jonas Hagberg

Problem
Systemet ska prata SportIdent-hårdvara, köra på Linux/macOS/Windows/Android (inte iOS som operatör), och tåla skogsnät. Vilken topologi?
Beslut
Tre lager. Node.js-bridge äger hårdvaran och den lokala händelseloggen. Webbläsare är ren UI över HTTP/WebSocket. Central tier är valfri — internet-aggregator, inte krav.
Varför
WebSerial finns inte på iOS Safari/Firefox och har ingen roadmap dit. En stängd flik får aldrig tappa stämplingar. En separat edge-process äger anslutningen — en modell varje plattform stöder identiskt.
arkitektur offline-first → ADR-0004 → ADR-0006
ADR-0003

Event sourcing som datamodell

accepted

2026-05-12Jonas Hagberg

Problem
MeOS-era system lagrar muterbara resultattabeller och saknar ren återhämtning från korrupt state. Multi-nod-samarbete och offline är pålimmat. Vilken datamodell gör de egenskaperna inbyggda?
Beslut
Event-sourced logg med deterministiska reducers för all härledd state. Varje stämpling är en oföränderlig händelse med nyckel (node_id, local_seq).
Varför
Resultat, sträcktider, placeringar, DNF, klassläge — allt räknas fram av rena reducers. Buggfix = uppdatera reducer + räkna om. Ingen korrupt state att reparera under press. Yjs sparas för formulär där samtidig redigering är reell.
REQ-EVT-001..007 datamodell
ADR-0004

ElectricSQL bara för read-sync, inte write-sync

accepted

2026-05-12Jonas Hagberg

Problem
Electric marknadsförs som sync-motor för Postgres ↔ klienter. Löser den vårt edge-till-edge-problem, eller är den smalare?
Beslut
Electric är read-only. Den driver flödet central → publika tittare. Edge-till-edge skriver vi själva: append-only-protokoll, idempotent på (node_id, local_seq).
Varför
Electric är en read-path-motor (Postgres → klienter via Shapes), inte multi-master write-sync. Det autonoma fältnoden-problemet är vårt ansvar. Electric gör det den är bra på: partial sync, SSE, reconnect.
sync scope
ADR-0005

SportIdent-koden isolerad under MIT

accepted

2026-05-12Jonas Hagberg

Problem
SportIdent-protokollet har ingen officiell öppen licens; implementationer bygger på reverse engineering för interoperabilitet. Hur ska den koden hanteras juridiskt och arkitekturellt?
Beslut
Isolera i packages/sportident/ under MIT. Övriga paket konsumerar ett rent SiReader-interface.
Varför
(1) Reverse engineering för interop är tillåtet enligt EU InfoSoc-direktivet art. 6. (2) SPORTident har tolererat tredjepartsimplementationer (MeOS, SI-Droid, OE12, QuickEvent) i 20+ år. (3) Att avgränsa juridiskt känslig kod till ett MIT-paket begränsar worst-case-exponering medan resten av projektet lever under AGPL-3.0.
licens isolering → ADR-0001
ADR-0006

Teknikstack: Node.js + Fastify + SQLite/Postgres + SvelteKit

accepted

2026-05-12Jonas Hagberg

Problem
Tre-lagers-arkitekturen från ADR-0002 behöver konkreta teknikval för edge, central, frontend.
Beslut
Edge-backend: Node.js 24 + Fastify · edge-DB: SQLite via better-sqlite3 · central: Node.js 24 + Fastify · central-DB: Postgres 16 · read-sync: ElectricSQL Shapes · collab: Yjs (bara formulär) · frontend: SvelteKit PWA · print: node-thermal-printer · edge-HW: Raspberry Pi 5 + PiJuice UPS.
Förkastat
Electron (för tungt). React (Svelte bundlar mindre — viktigt i skogen på 4G). GraphQL (overengineering). Microservices (overengineering). Kafka/NATS (kanske Phase 5). CRDTs för stämplingar (onödigt — händelseloggen är konfliktfri redan i datamodellen).
stack node-24 → ADR-0002
ADR-0007

Standarder först: IOF XML, Eventor, ROC, SIRAP, MeOS TCP

accepted

2026-05-12Jonas Hagberg

Problem
Klubbar byter inte tävlingsmjukvara över en natt — de migrerar en tävling i taget. Ett system som inte kan utbyta data med Eventor, MeOS, ROC och Livelox är dött vid lanseringen, oavsett intern kvalitet.
Beslut
Standarder är v1-krav, inte plugin. Datamodellen designas runt dem.
· Phase 1: IOF XML 3.0 import + export, IOF 2.0.3 läs.
· Phase 2: Eventor REST (pull entries, push results).
· Phase 4: ROC, SIRAP TCP, MeOS TCP-input output (sidecar), Livelox export.
Migrationstrick
MeOS TCP-input som output: en klubb kan köra MeOS som primärt sekretariat och fartOLa parallellt som barn-mål/live-tavla — bygga tillit innan primärsystemet byts.
REQ-STD-001..008 interop migration
+

Nytt ADR?

Kopiera .planning/adr/0000-template.md, nästa ID är 0008. När det är mergat, lägg till ett <article class="adr">-block i den här sidan med samma struktur som ovan. Inga ID-återanvändningar — om beslutet ersätts, sätt status superseded by ADR-NNNN på det gamla, behåll filen.