Arkitektur, integrationskontrakt och säkerhetsmodell – för dig som utvärderar eller bygger mot sviten.
Översikt
Två scheman innan texten: vilka tjänster sviten faktiskt består av, och var data kommer ifrån. Varje ruta går att spåra till en riktig fil i respektive repo.
Sviten som tjänster
Nio moduler, fem driftsatta tjänster. Rutorna är tjänster; namnen inuti är modulerna de levererar.
Drift och datakällor
Vad som ligger var, och vilka källor appen faktiskt frågar. Streckat = används bara i premiumläget, med din egen nyckel.
Arkitektur
Waybound Studio är en produktsvit i tio delar, inte ett monolitiskt system. Det är ett medvetet arkitekturval, inte historiskt arv: varje modul äger sitt eget ansvar, sin egen data där det är möjligt, och pratar med grannmodulerna genom uttalade kontrakt snarare än delade databaser.
Sviten som repon
WB core (Reseguiden, Ruttplaneraren, Resan, Uppdrag, Happy Trails) är en FastAPI/Python-backend med en vanilla JS/CSS-frontend, Supabase som databas, deploy på Render. Det är sviten enda stateful backend – identiteten, sparade resor och uppdragskatalogen bor här.
Platserna (WB Open Places) är en egen tjänst: FastAPI + PostgreSQL/PostGIS, en spårbar öppen platsdatabas byggd från OpenStreetMap-extrakt. Den svarar bara på var, aldrig på när – ruttlogik och tidsplanering hör inte hemma där.
Upptäckaren och Spanaren är statiska sajter utan egen backend alls. De anropar Platserna direkt från webbläsaren (Upptäckaren) eller kör helt offline mot ett delat frö (Spanaren, med en tunn Supabase-tjänst enbart för att dela anpassade brickor).
Android Auto är en native Android-app som läser en redan planerad resa direkt ur WB core:s Supabase-data. Den planerar aldrig en rutt själv och ritar aldrig en egen karta.
Varför uppdelningen ser ut så här
Gränsen mellan Ruttplaneraren och Platserna är medveten och försvaras: Ruttplaneraren äger resan och vet när man ska stanna, Platserna äger platserna och vet vad som finns där. Ett försök att flytta ruttintelligens ner i platslagret slutar med två system som är oense om sanningen.
Moduler som kontrakt
Varje intern modul i WB core deklarerar sitt eget kontrakt: den exporterade ytan, vad varje anrop lovar, och vad en anropare därför aldrig behöver kontrollera själv. Det är inget dokument som kan glida isär från koden – kontraktet är ett test, inte en kommentar.
Samma princip gäller mellan repona: gränssnittet mellan WB core och Platserna, och mellan WB core och Android Auto-appen, är skrivna kontrakt ägda av den sida som har mest att förlora på att bryta dem. En Android Auto-app som redan ligger i en bil kan inte uppdateras samma eftermiddag – därför äger WB core det kontraktet, testar mot det, och ändrar det innan appen någonsin rörs.
Driftmodell
Samtliga tjänster körs på Render. Statiska sajter (Upptäckaren, Spanaren, Platserna) deployar direkt från `main` utan byggsteg; WB core har en fullständig testsvit som körs vid varje ändring.
Ett undantag från "alltid över ett API", medvetet: Android Auto-appen läser WB core:s Supabase-data direkt – samma resenärskonto, samma sparade resor – i stället för att gå via ett separat API. Det är en avvägning, inte en genväg: gränsen upprätthålls av Supabase Row Level Security (varje resenär ser bara sina egna rader) och av det skrivna kontraktet mellan de två repona, inte av ett nätverksanrop. Platserna, däremot, är helt fristående och nås alltid via dess publika HTTP-API, aldrig genom att läsa dess databas direkt.
Kontrakt och integration
För dig som utvärderar sviten som utvecklare: så här ser gränssnitten ut mellan de delar som faktiskt pratar med varandra över en repogräns.
Platserna (WB Open Places) — öppet HTTP-API
Ett publikt, läsande HTTP-API utan autentisering, byggt för att kunna anropas direkt från en webbläsare. Centrala ytor:
Listning och radiesökning av platser, med kategori- och faciliteter-filter
Klustrad räkning för breda kartvyer
Ruttkorridor-sökning: skicka en väglinje, få platser inom ett angivet avstånd från den, sorterade och med avstånd till både korridoren och en eventuell ankarpunkt
Kategori-, käll- och statistiklistor för den som vill bygga sin egen vy ovanpå katalogen
Faciliteter är medvetet tre-tillstånd – finns, okänt, eller uttryckligen frånvarande – snarare än en binär flagga. Standardläget döljer aldrig en okartlagd plats bara för att en fasilitet saknas; ett striktare läge finns för den som hellre vill filtrera hårt.
CORS är öppet men listat: endast `GET`/`OPTIONS`, inga cookies eller autentiseringsuppgifter, och en uttrycklig lista över tillåtna ursprung snarare än en vild wildcard. Det är byggt för att en fristående statisk sajt utan egen server – som Upptäckaren – ska kunna anropa det direkt.
WB core ↔ Platserna
Gränsen mellan ruttmotorn och platsdatabasen är ett skrivet kontrakt, inte en implicit överenskommelse: WB core äger tidsplaneringen och avgör *när* ett stopp behövs, Platserna äger geografin och svarar på *var* det finns något. Stopptypen (sovplats, lunch, tankning …) mappas till en uppsättning platskategorier på WB core-sidan av gränsen.
WB core ↔ Android Auto
Bilappen läser en redan planerad resa – aldrig en beräkning den själv initierar. Gränssnittet är skrivet och testat innan appen någonsin rörs, av ett enkelt skäl: en app som redan ligger i en bil kan inte uppdateras samma eftermiddag som ett fel upptäcks. Ändras kontraktet, ändras testerna som bevisar det – sedan, och bara sedan, appen.
Vad som medvetet inte är ett kontrakt
Ingen extern integration mot Reseguiden, Uppdrag eller Happy Trails finns idag – de är interna ytor i WB core, nådda via samma inloggade session som resten av appen, inte via ett separat publikt API. Det kan ändras, men är inget att bygga mot i dagsläget.
Licenser och attribution vid integration
Bygger du något ovanpå Platserna: attributionen som följer med varje plats (OpenStreetMap, i förekommande fall Trafikverket) måste bevaras där du visar datan vidare. Se Legal och licenser för exakt vilka villkor som gäller respektive källa.
Säkerhet och guardrails
Säkerhet är arkitektur, inte ett lager som läggs på i slutet. Så här ser vi på det, för dig som utvärderar sviten som utvecklare, arkitekt eller säkerhetsgranskare.
Grundprinciper
Säkert som standard. Gratisnivån bär aldrig en Google-nyckel – det är en egenskap hos anropet, inte en inställning någon kan glömma.
Minsta möjliga behörighet. Varje resenär ser och rör bara sin egen data, upprätthållet på databasnivå (Row Level Security) snarare än enbart i applikationskoden.
Explicit autentisering och auktorisering. Inloggning via Google, Microsoft, e-post eller ett rent lokalt läge utan konto. Adminfunktioner (uppdragskatalogen, felloggar) skyddas av samma explicita behörighetskontroll oavsett vilken yta de nås från.
Fail securely. En tjänst som inte svarar, som WB Open Places vid ett tillfälligt driftstopp, ger ett tomt resultat snarare än att appen kraschar eller läcker ett internt fel.
Vad plattformen är byggd för att motstå
Trafikinformation och ruttdata är i sig inte känsliga, men kontot, de sparade resorna och platsen du befinner dig på är det. Arkitekturen är byggd med följande i åtanke:
Cross-Site Scripting (XSS) – all dynamisk text som visas i gränssnittet escapas innan den sätts in i sidan.
Broken Object Level Authorization – en resenär kan aldrig läsa eller ändra en annan resenärs resa genom att gissa ett ID.
JWT-manipulation och obehörig projektåtkomst – sessionen valideras vid varje anrop, inte bara vid inloggning.
API-missbruk och kostnadskontroll – se guardrails-avsnittet nedan.
Informationsläckage – felmeddelanden till användaren avslöjar aldrig interna system- eller databasdetaljer.
Clickjacking och innehållsinjektion – låst ner via HTTP-säkerhetsrubriker (Content Security Policy och motsvarande).
Guardrails som är produktbeslut, inte bara teknik
Kostnadstak per konto. Både ruttberäkning och Reseguidens sökningar har en budget, och ett långt sökanrop kan avbrytas av resenären mitt i – testat mot en riktig, lång sökning, inte bara mot koden.
Sökradien får aldrig vara mindre än den omväg resenären redan sagt sig acceptera. En smal sökradie som ändå respekterar resenärens uttalade preferens vore teknisk korrekthet som gör resan sämre – hellre den extra milen till civilisationen.
Ingen användargenererad information i det som delas offentligt. Happy Trails-berättelser byggs enbart av resenärens egna val under resan, aldrig av fritext eller uppladdade bilder. Det är inte bekvämlighet – det tar bort en hel kategori av moderationsrisk och integritetsrisk på en gång, eftersom tröskeln för att publicera går mot noll utan att någonsin behöva granska innehåll.
Uppdrag är hedersbaserade med flit. Ingen geofencing, inget foto krävs. Det är ett medvetet val bort från att samla in mer platsdata än nödvändigt, inte en begränsning vi råkade hamna i.
Radering är självbetjäning, inte en process som kräver att någon läser ett mejl och agerar manuellt.
Datahantering i korthet
Platsdata i WB Open Places är ärligt ofullständig och sägs vara det: en saknad uppgift om till exempel toalett betyder oftast "inte kartlagd", aldrig en gissning framställd som fakta. Se Legal och licenser för exakt vilka datakällor som används och under vilka villkor.
*Det här är en översikt på arkitekturnivå, inte en fullständig säkerhetsrevision, och inte ett löfte om frånvaro av framtida sårbarheter. Hittar du något som ser fel ut, hör av dig via appens systemmeny.*
Hur hanterar vi data?
Datakällor, sekretess och villkor — vad vi faktiskt granskat, med källa och datum där det är relevant.