OpenHR är ett HR- och lönesystem med öppen källkod för svensk offentlig sektor. Det är byggt som en demonstrator, tänkt som ett alternativ till HEROMA. OpenHR är inte i drift hos någon region eller kommun och är inte klart för skarp drift med riktiga personuppgifter.
Projektet visar hur ett öppet HR- och lönesystem kan se ut: öppen källkod (AGPL-3.0-or-later), öppen PostgreSQL-databas, öppna filformat och svensk arbetsrätt och kollektivavtal i koden.
Demon finns på https://hr.404haven.se.
- Inloggningen är simulerad. BankID och SITHS är simuleringar. Ingen identifiering görs, och du väljer själv en demoprofil.
- All data är fiktiv. Anställda, löner och ärenden är genererade. De anställdas personnummer kommer från Skatteverkets lista över testpersonnummer.
- Gör inga belastningstester eller automatiserade skanningar mot demon. Se SECURITY.md.
| Demoprofil | Roll | Når bland annat |
|---|---|---|
| Anna Svensson | Anställd | Startsidan med de vanliga ärendena: sjukanmälan, VAB, ledighet, schema med passbyte och lediga pass, stämpling, lönespec med förklaringar, Mina ärenden och Mina dokument |
| Eva Nilsson | Chef | Sitt team på Avdelning 32: inkorgen Att besluta, schema, frånvaro, rehabilitering, LAS |
| Karl Berg | HR | Personalregister, lön, löneöversyn, rapporter, administration |
| Admin | Admin | Samma sidor som HR, men utan koppling till någon anställd |
Räknat i koden 2026-10-02:
- 38 modulprojekt under
src/Modules. Flera är små;Insurance,Offboarding,SelfServiceochWellnesshar en källfil var. - 238 sidor (Razor-komponenter med
@page) med sammanlagt 244 rutter. - 4 339 automatiska tester i 37 testprojekt i
RegionHR.sln(alla gröna med .NET 9 SDK 2026-10-02; 2 275 före rättningarna 2026-10-01). - Ingen versionstagg eller release ännu.
En granskning på utvecklarens uppdrag prövade 2026-10-01 demon, källkoden och den här GitHub-sidan mot Region Örebro läns underlag inför upphandlingen av ett nytt HR- och lönesystem. Den fann bland annat brister i behörigheten, en förenklad skattetabell som gav för lågt skatteavdrag, en AGI-fil som inte gick att lämna in, en trasig löneöversyn, sjukfrånvaro som inte nådde lönen och påståenden här och på säkerhetssidan som inte stämde.
Felen har rättats i flera omgångar. Vad som ändrats och vad som återstår står i CHANGELOG.md. Slutsatsen står sig: OpenHR är en bred demonstrator men kan inte i dag ersätta ett upphandlat lönesystem.
En andra granskning samma dag gällde användbarheten, mot principen att systemet ska vara experten, inte användaren: en medarbetare utan datorvana ska klara sina ärenden på mobilen utan utbildning. Den fann bland annat att HR-assistenten gav fel besked och låtsades sjukanmäla, att notiser bara syntes i appen, att medarbetaren inte kunde sköta sitt schema och att chefens attester låg på sju ställen. Rättningarna 2026-10-02 beskrivs under Självservice och chef nedan och i CHANGELOG.
Kortfattat, utan anspråk på fullständighet. Det mesta läser och skriver riktiga data i databasen.
Personal och organisation
- Personalregister med anställningar, lönehistorik med giltighetsdatum och organisationsträd. Ett personnummer kan bara registreras en gång.
- Rekrytering (vakanser, ansökningar, tillsättning som skapar en anställning), onboarding, offboarding och medarbetarresor.
Lön
- Lönekörning per månad med Skatteverkets skattetabeller för 2026 (tabell 29 till 42, alla kolumner, ur Skatteverkets öppna data). Nya års tabeller läses in under Lön > Skattetabeller.
- Arbetsgivaravgifter, O-tillägg per timme och kategori enligt AB 25 § 21, övertid, lön för del av månad, timlön, frånvaroavdrag, sjuklön och karensavdrag per sjuklöneperiod, föräldrapenningtillägg, resekrav, friskvårdsbidrag, löneutmätning och fackavgift.
- Godkännande före publicering och export, tvåhandsprincip (den som startar en körning får inte godkänna den) och högst en ordinarie körning per period. Retroaktiv lön räknas mot lönehistoriken.
- Löneöversyn med förslag, filimport och genomförande som skriver ny lön.
- Lönespecifikation som PDF, AGI-fil enligt Skatteverkets XSD 1.1 (valideras mot schemat i testsviten) och betalfil i formatet pain.001 med utbetalning på bankdag.
Frånvaro
- Ledighetsansökningar med attest av chef eller HR, aldrig av den sökande själv. Innan medarbetaren skickar visar systemet hur många semesterdagar det blir (enligt semesterlagen, utan helgdagar och aftnar), saldot efteråt och krockar. En ansökan kan tas tillbaka eller avbokas.
- Sjukanmälan som gäller direkt utan attest, är öppen tills friskanmälan och når lönen. Kvittot visar sjuklön och ett beräknat karensavdrag, och anmälan kan ångras i 15 minuter.
- VAB (Mitt barn är sjukt) registreras direkt som anmälan enligt föräldraledighetslagen 8 §, med påminnelse om Försäkringskassans 30-dagarsfrist. Guiden Jag ska bli förälder och föräldraledighet på deltid som når lönen.
- Ett gemensamt semestersaldo som alla sidor använder.
Schema och tid
- Grundschema som rullas ut till pass, stämpling (även nattpass över midnatt), justering av stämplingar med attest, flex enligt kollektivavtalets regler, övertid med attest och val mellan pengar och komptid.
- Kontroll mot arbetstidslagen (dygnsvila, veckovila och övertidstak) när pass läggs.
- Medarbetarens schema sex veckor framåt, byte och bortlämning av pass där systemet bara föreslår kollegor som kan ta passet, lediga pass att anmäla intresse för, schemaönskemål och påminnelse när man glömt stämpla in eller ut.
Arbetsrätt, hälsa och arbetsmiljö
- LAS-beräkning (även timavlönade) med varningar och konvertering till tillsvidareanställning, MBL-förhandlingar och klagomålsärenden.
- Rehabärenden (HälsoSAM) med uppföljning från sjukdag 1, tillbudsrapportering och skyddsronder.
Kompetens och utveckling
- Kompetenser, certifieringar, gapanalys, medarbetarsamtal, utvecklingsplaner, utbildningar och e-kurser.
Självservice och chef
- En startsida för medarbetaren med en att göra-lista och de vanliga ärendena som stora kort, menyer i klarspråk per roll, sökning med vardagsord, inställning för textstorlek och kontrast och en kort introduktion första gången. Webbappen fungerar som PWA.
- Lönespecifikation på skärmen med en förklaring per rad och jämförelse med föregående månad, byte av bankkonto med kontroll av kontonumret och notis vid ändring, totalersättning och lönekriterier med begäran om löneinformation (lönetransparensdirektivet, artikel 7).
- Mina ärenden (allt eget som pågår, med status och nästa steg) och Mina dokument (läkarintyg från mobilkameran, tjänstgöringsintyg, certifikat). Medarbetaren skriver sin egen självbedömning inför medarbetarsamtalet och svarar på anonyma enkäter.
- Chefens inkorg Att besluta samlar alla typer av beslut med underlag (saldo, vilka i teamet som redan är lediga, varningar mot arbetstidslagen). Påminnelser i rehabkedjan går till chefen (läkarintyg dag 8, anmälan till Försäkringskassan dag 15, plan för återgång senast dag 30).
- Varje notis går också ut som webbpush till medarbetarens registrerade enheter och, om SMTP är konfigurerat, som e-post, enligt medarbetarens inställningar och med en allmän text utan känsliga uppgifter.
- Nyanställning som guide i fyra steg med lönestöd per befattning, resekrav där traktamente och milersättning räknas automatiskt, och friskvårdsbidrag med kvitto.
Dataskydd och förvaltning
- Granskningslogg för ändringar och för läsning av lön och hälsoärenden. Känsliga fält maskeras i loggen.
- GDPR: registerutdrag och radering av personuppgifter (artikel 17) med lagstadgade undantag. E-arkiv och informationsklassning enligt KLASSA.
- Rapporter, nyckeltal och export till CSV och Excel. Import av personaldata från PAXml, ett semikolonseparerat Heroma-format och CSV.
- Integrationerna har ingen verklig överföring. Filerna (AGI, betalfil, konteringsfil, pensionsfil, statistikfiler med flera) skapas ur riktiga data men laddas ned för hand. Den så kallade SFTP-transporten skriver filer till en lokal katalog; någon SFTP-klient finns inte. Fyra adaptrar (Grade, KOLL/HOSP, MinKompetens och Troman) returnerar simulerade svar. HSA-katalogen är en sandlåda. Tessa saknas helt. Försäkringskassan, KPA, KOLL och folkbokföringen hanteras med egna filformat, inte motparternas. Betalfilen är inte kontrollerad mot bankens specifikation.
- Inloggningen. BankID och SITHS är simulerade. Inloggning med Entra ID (OIDC) finns förberedd men är avstängd som standard.
- HR-assistenten känner igen frågor genom att matcha hela ord mot en katalog med granskade svar och hämtar siffror ur koden och databasen. Är den osäker säger den det och erbjuder kontakt med HR. Den använder ingen språkmodell och gör något, till exempel en sjukanmälan, först efter att användaren tryckt Ja.
- Sms och BankID-signering finns inte. Båda kräver avtal med en leverantör. Notiser når telefonen som webbpush.
- Kollektivavtal. Avtal kan redigeras i gränssnittet, men lönemotorn läser O-tilläggen ur en tabell i koden för AB och HÖK. Andra avtal ger 0 kr i OB.
- REST-API:t (
src/Api) ingår inte i Docker-imagen och är inte driftsatt. - Språk. Gränssnittet är på svenska. Bara en liten del av sidorna går att visa på engelska.
- Leverantörsansvar. Det finns ingen leverantör eller organisation bakom OpenHR som kan ge SLA, jour, support, ansvar för löneutbetalningen eller årliga uppdateringar av avtal och regler. Det går inte att lösa med kod.
Fler kända begränsningar finns i CHANGELOG.md och i docs/security/owasp-asvs-self-assessment.md.
Kräver .NET 9 SDK. Versionen låses i global.json (9.0.300 eller en senare 9.0-version). En nyare SDK kan ge andra analysregler, och bygget behandlar varningar som fel.
dotnet build RegionHR.sln # ska ge 0 fel och 0 varningar
dotnet test RegionHR.sln # ingen databas behövsdocker-compose.yml är till för lokal körning med demodata. Den startar två tjänster: PostgreSQL 17 och appen, som byggs lokalt från Dockerfile.
cp .env.example .env # byt POSTGRES_PASSWORD i .env
docker compose up -dÖppna http://localhost:5076. Databasen nås bara från värden (127.0.0.1:54322).
- Compose sätter
SeedDemoData=true, så databasen fylls med omkring 11 000 fiktiva anställda vid första starten. - Appen körs i miljön Production, där demoinloggningen är avstängd som standard. Compose-filen för lokal demo sätter
Demo__Enabled: "true", så att man kan logga in med demoprofilerna. Ta bort raden om databasen ska innehålla riktiga personuppgifter. - Nycklar för inloggning och kryptering sparas i volymen
openhr-keys(/data/keysi containern). Om volymen försvinner blir inloggningar ogiltiga och krypterade bankuppgifter oläsbara.
För drift i en härdad miljö, se docs/security/deployment-guide.md.
dotnet run --project src/Web/RegionHR.Web.csprojAppen startar i miljön Development på http://localhost:5076. Där är demoinloggningen påslagen.
- Utan anslutningssträng, eller om PostgreSQL inte nås, använder appen i Development en InMemory-databas. Ingenting sparas då mellan omstarter. Utanför Development vägrar appen starta utan databas.
- För PostgreSQL: sätt
ConnectionStrings__RegionHR, till exempel mot databasen i Compose (docker compose up -d db):Host=localhost;Port=54322;Database=openhr;Username=openhr;Password=<lösenordet i .env>. - Sätt
SeedDemoData=trueför att få demodata. Utan demodata kopplas demoprofilerna inte till några anställda.
Appen kör Database.MigrateAsync() vid start. Det skapar schemat i en tom databas och uppdaterar en befintlig databas med de migrationer som saknas. Migrationerna finns i src/Infrastructure/Persistence/Migrations/ och utgår från en ny baslinje från 2026-10-01; de äldre migrationerna från mars 2026 är borttagna. En databas som skapats av en tidigare version (med EnsureCreated) har ingen migrationshistorik och behöver skapas om.
En installation utan demodata får bara grunddata för informationsklassningen (KLASSA). Kollektivavtal, lönearter och skattetabeller finns i demodatan; skattetabeller kan också läsas in under Lön > Skattetabeller.
Inställningar anges i src/Web/appsettings.json eller som miljövariabler, där kolon skrivs som dubbla understreck (Demo:Enabled blir Demo__Enabled). Hemligheter ska ges som miljövariabler eller hemligheter, aldrig skrivas in i filer i repot.
| Inställning | Standard | Betydelse |
|---|---|---|
Demo:Enabled |
false (true i Development) |
Slår på den simulerade BankID- och SITHS-inloggningen med fritt val av profil, även Admin. Bara för fiktiv data. Appen varnar i loggen om den är på i Production. |
ConnectionStrings:RegionHR |
tom | Anslutning till PostgreSQL. Krävs utanför Development. |
SeedDemoData |
false |
true fyller en tom databas med demodata. Aldrig i skarp drift. |
DataProtection:KeysPath |
/data/keys i containern |
Katalog för Data Protection-nycklarna (skyddar inloggningen) och den skyddade kolumnnyckeln. Ska vara en volym som säkerhetskopieras. |
Kryptering:Kolumnnyckel |
tom | Nyckel för krypteringen av bankuppgifter (base64, 32 byte). Om den saknas skapas en nyckel i DataProtection:KeysPath. Utanför Development startar appen inte utan någon av dem. |
ReverseProxy:KnownProxies, ReverseProxy:KnownNetworks, ReverseProxy:ForwardLimit |
bara loopback, 1 |
Vilka omvända proxyer appen litar på i X-Forwarded-For, och hur många led som läses. Bakom två proxyer (till exempel cloudflared och Caddy) anges båda näten och ForwardLimit=2. Startloggen visar vad som gäller. |
RateLimiting:Enabled, PermitLimit, WindowSeconds, QueueLimit |
true, 100, 60, 10 |
Anropsbegränsning per klientadress. |
Arbetsgivare:* |
Region Örebro län | Arbetsgivarens namn, organisationsnummer, adress, kontaktperson, utbetalningskonto (IBAN) och utbetalningsdag. Används i AGI, betalfil och lönespecifikation. |
Email:SmtpHost, Email:Sakerhet, Email:SmtpPort, Email:Username, Email:Password, Email:FromEmail, Email:FromName |
e-post avstängd | SMTP. Sakerhet är StartTls (standard, port 587), Tls (port 465) eller Ingen (bara lokal relä, utan inloggning). |
WebPush:Subject, WebPush:PublicKey, WebPush:PrivateKey |
tomma | VAPID-nycklar för webbpush. Tomma: ett par skapas vid första start och sparas krypterat i DataProtection:KeysPath. Utan nyckelkatalog är push avstängt utanför Development. |
Notiser:AppAdress |
tom | Appens publika adress. Ger notismejlen en knapp till rätt sida. |
Oidc:* |
avstängd | Inloggning med Entra ID: Enabled, TenantId, ClientId, ClientSecret och mappning av grupper och roller till de fyra rollerna. |
OpenHR:SessionTimeoutMinutes, OpenHR:SessionMaxHours |
30, 10 |
Inaktivitetstid och längsta tid för en inloggning. |
Skattetabeller:OppnaDataUrl |
Skatteverkets dataset | Adress för inläsning av skattetabeller. Inläsningen kräver utgående HTTPS till Skatteverket. |
OpenHR är fri programvara under GNU Affero General Public License, version 3 eller senare (AGPL-3.0-or-later). Licenstexten finns i LICENSE och upphovsrätten i NOTICE.
Den som kör en ändrad version av OpenHR som en tjänst över nätverk ska erbjuda användarna källkoden till den versionen (AGPL avsnitt 13). Appens sida /trust och inloggningssidan länkar till källkoden.
Förbehåll för QuestPDF. PDF-biblioteket QuestPDF används med sin Community-licens och omfattas inte av AGPL. QuestPDF:s nuvarande villkor undantar offentlig sektor från den kostnadsfria licensen. En region eller kommun som vill driftsätta OpenHR behöver därför utreda licensen, köpa en licens eller byta PDF-bibliotek. Se avsnittet om QuestPDF i NOTICE.
Rapportera sårbarheter privat enligt SECURITY.md, aldrig i ett öppet ärende. En beskrivning av skydden i koden, och av det som saknas, finns på sidan /trust i appen (till exempel https://hr.404haven.se/trust) och i docs/security/.
Se CONTRIBUTING.md. Kortfattat: .NET 9, 0 varningar, tester för ny logik, svenska med å, ä och ö i gränssnittet och behörighetskontroll där data läses och ändras.