{"version":"https://jsonfeed.org/version/1.1","title":"Engineer — Advisory — Portefølje og noter","home_page_url":"https://advisory.engineer.company/da/","feed_url":"https://advisory.engineer.company/da/feed.json","description":"Engineer ApS — softwareudvikling \u0026 IT-rådgivning i København, Danmark. En portefølje af dokumenterede ingeniørresultater inden for software, data, cloud og IT.","language":"da","icon":"https://advisory.engineer.company/assets/images/brand/card.webp","favicon":"https://advisory.engineer.company/assets/icons/apple/apple-touch-icon.png","authors":[{"name":"Engineer ApS","url":"https://advisory.engineer.company/da/"}],"items":[{"id":"https://advisory.engineer.company/da/portfolio/increased-brand-popularity-by-200x-through-successful-brand-1/","url":"https://advisory.engineer.company/da/portfolio/increased-brand-popularity-by-200x-through-successful-brand-1/","title":"Har øget brandets popularitet 200 gange gennem succesfuld brandudvikling på tværs af offline- og onlineplatforme.","summary":"Øgede brandets rækkevidde omkring 200× på tværs af offline- og onlineplatforme — fra ukendt nytilkommen til et genkendt navn.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Engineer ApS var en helt ny konsulentvirksomhed med reel teknisk dybde og næsten ingen, der havde hørt om den. Det er en bestemt slags frustrerende: kunnen er der, arbejdet ville være godt, men intet af det betyder noget, hvis de kunder og partnere, der ville have det, ikke ved, man findes. En ung virksomhed skal ses, før den kan vinde noget som helst.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Opgaven var at opbygge et brand, folk faktisk ville genkende — på tværs af både offline- og onlinesiden — og at omsætte virksomhedens tekniske troværdighed til synlig tilstedeværelse på markedet frem for at lade den ligge som en velbevaret hemmelighed.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Brandet blev bygget bevidst og holdt konsistent. Det startede med en klar identitet — en tone, et visuelt sprog og en portefølje, der førte an med konkrete tekniske resultater frem for det vage \u0026ldquo;vi skaber værdi\u0026rdquo;-sprog, alle andre bruger. Så kørte det på tværs af de kanaler, der betyder noget for den slags virksomhed — websitet, LinkedIn, GitHub, fysiske arrangementer — med hvert kontaktpunkt, der sagde det samme frem for hver at drive af på sin egen måde. Den røde tråd var at føre an med rigtige case‑studier og rigtige resultater, så troværdigheden var noget, man kunne se bevis for, ikke bare en påstand.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Brandets rækkevidde voksede omkring 200 gange på tværs af offline- og onlineplatforme — en ukendt nytilkommen blev til noget, folk faktisk genkendte. Og det var ikke forfængelig rækkevidde; synligheden begyndte at producere en stabil strøm af indgående henvendelser og muligheder, der simpelthen ikke havde været der før.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Brand \u0026 marketing","Produkt \u0026 krav","Stakeholder \u0026 rapportering","Brand, marketing \u0026 SEO","Produktstrategi \u0026 kravspecifikation"]},{"id":"https://advisory.engineer.company/da/portfolio/drove-brand-engagement-and-loyalty-by-100-through-2/","url":"https://advisory.engineer.company/da/portfolio/drove-brand-engagement-and-loyalty-by-100-through-2/","title":"Har øget brandengagement og -loyalitet med 100 % gennem analyse af markedstendenser og indsigt i forbrugeradfærd.","summary":"Fordoblede brandengagement og -loyalitet (+100 %) via analyse af markedstendenser og forbrugeradfærd — et publikum, der kom tilbage.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Efterhånden som synligheden klatrede, nåede Engineer ApS flere mennesker — men engagementet var tyndt. Folk lagde mærke til det og gik videre; den tidlige interesse blev ikke til relationer, der holdt. Rækkevidde uden engagement er bare støj, og brandet lavede støj mere end forbindelser.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Målet var at uddybe engagementet og loyaliteten, og gøre det ved faktisk at kigge på, hvad markedet og publikummet reagerede på, frem for at stole på mavefornemmelse.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Så brandet blev datainformeret i stedet for intuitionsstyret. Det betød at kigge på markedstendenserne og på, hvordan publikummet faktisk opførte sig på tværs af kanalerne — ikke hvad nogen antog, de ville kunne lide, men hvad de påviseligt engagerede sig i. Det afslørede de emner og formater, der trak ægte opmærksomhed, og indholdet og opsøgningen blev styret mod dem. Den vigtige del var at stramme loopet: se, hvad der landede, udgiv mere af den form næste gang, og lad hver cyklus være en smule bedre rettet end den forrige.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Engagement og loyalitet blev fordoblet — en forbedring på 100 % — med et publikum, der kom tilbage og engagerede sig frem for at kigge én gang og gå, og markant stærkere relationer til potentielle kunder og partnere. Brandet holdt op med at udsende ud i tomrummet og begyndte at opbygge noget, der kom tilbage.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Brand \u0026 marketing","Dataanalyse","Produkt \u0026 krav","Stakeholder \u0026 rapportering","Brand, marketing \u0026 SEO","Dataanalyse \u0026 BI‑dashboards","Produktstrategi \u0026 kravspecifikation"]},{"id":"https://advisory.engineer.company/da/portfolio/designed-a-comprehensive-infrastructure-framework-for-dtu-impacting-3/","url":"https://advisory.engineer.company/da/portfolio/designed-a-comprehensive-infrastructure-framework-for-dtu-impacting-3/","title":"Har designet en omfattende infrastrukturramme for DTU, der berører 14 afdelinger, med fleksible moduler, samlede datapipelines og strukturerede supportstrategier med henblik på langsigtet udbredelse.","summary":"Designede en omfattende infrastrukturramme for DTU på tværs af 14 afdelinger — modulær, med samlede datapipelines og supportstrategier.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e På et forskningsinstitut bestående af 14 forskellige forskningsgrupper arbejdede hver gruppe med forskellige datakilder, formater, skalaer og softwareværktøjer. Den tekniske ekspertise og de tilgængelige IT‑ressourcer varierede meget på tværs af grupperne. Mens nogle få havde formået at skabe og udrulle skræddersyede IT‑løsninger, kæmpede mange med kompleksiteten af deres datainfrastrukturbehov, hvilket tog værdifuld tid og fokus fra deres kerneforskning.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Opgaven var at udtænke en løsning, der ville give forskerne mulighed for at fokusere på deres videnskabelige arbejde frem for IT‑udfordringer. Målet var at designe og implementere en skalerbar, institutdækkende datainfrastruktur, der kunne rumme de brede og forskelligartede behov hos størstedelen af forskningsgrupperne.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e En robust og fremtidssikret infrastrukturplan blev udviklet, der balancerede fleksibilitet og standardisering. Planen skitserede nøglekomponenter såsom modulær arkitektur, integrationsveje for forskellige datakilder, brugervenlige grænseflader tilpasset varierende tekniske niveauer samt skalerbare lagrings- og behandlingsløsninger. Den omfattede også strategier for onboarding, support og governance for at sikre udbredelse og bæredygtighed.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Den resulterende infrastrukturplan var både teknisk solid og strategisk afstemt med instituttets forskningsmål. Den forenede visionen for datahåndtering på tværs af organisationen, gav en klar vej til at reducere IT‑byrden på forskerne og lagde fundamentet for et fælles, effektivt og fremtidsklart forskningsdatamiljø. Planen blev vel modtaget for sin inklusivitet, klarhed og tilpasningsevne og satte en stærk retning for instituttets transformation af datainfrastrukturen.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Data engineering","Data governance","Datapipelines (ETL/ELT)","Dokumentation","Infrastruktur","Løsningsarkitektur","Platformarkitektur","Stakeholder \u0026 rapportering","Teknisk ledelse","Data governance \u0026 datakvalitet","Platform- \u0026 løsningsarkitektur","Teknisk dokumentation","Teknisk ledelse \u0026 rådgivning","Udvikling af datapipelines (ETL/ELT)"]},{"id":"https://advisory.engineer.company/da/portfolio/delivered-8-power-bi-projects-with-comprehensive-manuals-10/","url":"https://advisory.engineer.company/da/portfolio/delivered-8-power-bi-projects-with-comprehensive-manuals-10/","title":"Har leveret 8 Power BI‑projekter med omfattende manualer, hvor Microsoft Power BI‑værktøjer er integreret med NodeJS API og Python FastAPI for effektiv dataanalyse og visualisering.","summary":"Leverede 8 Power BI-analyseprojekter (Node.js API, Python FastAPI) med manualer — 60 % mere effektiv rapportgenerering.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Organisationen havde behov for dynamiske, visuelle indsigter i komplekse datasæt om elnettets ydeevne og geografisk fordeling for at understøtte beslutninger på tværs af tekniske og strategiske teams.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e At udvikle interaktive dashboards og rapporteringsløsninger, der effektivt kunne præsentere både realtids- og historiske geografiske og elektriske data, så interessenter hurtigt kunne identificere tendenser, anomalier og nøgletal.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Microsoft Power BI blev integreret med en skræddersyet backend baseret på NodeJS API og Python FastAPI for at strømline dataindtagelse, transformation og visualisering. Dashboards blev designet og implementeret med kortvisualiseringer, målinger af energiforbrug, sporing af nedbrud og indikatorer for neteffektivitet, og genanvendelige skabeloner og detaljeret dokumentation udviklet for at understøtte skalerbarhed og brugervenlighed.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e 8 dataanalyseprojekter blev leveret, hvilket forbedrede effektiviteten af rapportgenerering med 60 % og gjorde det muligt for tværfaglige teams at træffe hurtigere, datadrevne beslutninger. Interessenterne rapporterede en markant øget forståelse af den regionale elektriske ydeevne og nøjagtigheden af ressourceplanlægningen.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["API'er \u0026 integration","Backend‑udvikling","Data engineering","Dataanalyse","Dokumentation","GIS / Geospatial","Produkt \u0026 krav","Python","Backend- \u0026 API‑udvikling","Dataanalyse \u0026 BI‑dashboards","Teknisk dokumentation"]},{"id":"https://advisory.engineer.company/da/portfolio/led-the-software-development-of-a-gis-map-24/","url":"https://advisory.engineer.company/da/portfolio/led-the-software-development-of-a-gis-map-24/","title":"Har ledet softwareudviklingen af en GIS‑kortapplikation, øget omsætningen 10 gange og positioneret produktet som et primært dataaktiv.","summary":"Ledede udviklingen af en GIS-kortapplikation, der blev en platformshjørnesten og drev en 10× omsætningsstigning via mersalg og datalicensering.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Kerneudfordringen var at bygge en platform, der kunne spore, overvåge og optimere vedvarende energiaktiver som solpaneler og vindmøller. Den oprindelige løsning manglede dog robuste geospatiale funktioner, hvilket gjorde det svært for kunder at visualisere aktivlokationer, analysere spatiale data eller udlede handlingsorienterede indsigter. Ledelsen prioriterede derfor udviklingen af en GIS‑kortapplikation for at øge platformens værdi.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Opgaven var at lede udviklingen af GIS‑applikationen, en kritisk komponent til at differentiere produktet på det konkurrenceprægede marked for grøn energi. Rollen strakte sig ud over softwareudvikling — som teknisk leder, DevOps‑ingeniør, dataingeniør og SRE. Målet var at skabe et skalerbart, intuitivt GIS‑værktøj, der integrerede problemfrit med SaaS‑platformen, og som kunne udvikle sig i takt med virksomheden.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Det begyndte med at samarbejde med interessenter om at definere applikationens kernefunktioner med fokus på integration med den eksisterende SaaS‑platform og realtidsvisualisering. På grund af det lille team blev en modulær arkitektur designet med open source‑GIS‑biblioteker for at holde systemet let og skalerbart. CI/CD‑pipelines, automatiseret infrastrukturprovisionering og overvågning blev også implementeret. Efterhånden som teamet voksede, blev nye ingeniører mentoreret, tværfagligt samarbejde faciliteret og brugerfeedback prioriteret for at forfine applikationen iterativt.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e GIS‑applikationen blev en hjørnesten i SaaS‑platformen og drev en 10‑dobbelt stigning i omsætningen gennem mersalg, datalicensering og nye kunder. Dens evne til at visualisere grønne energiaktiver i realtid forbedrede kundernes driftseffektivitet, og den løbende forfining positionerede den som et primært dataaktiv. Projektets succes styrkede virksomhedens omdømme i sektoren for vedvarende energi og demonstrerede værdien af en tværfaglig tilgang i et hurtigt voksende startup‑miljø.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["DevOps","Drift \u0026 backup","Full stack‑udvikling","GIS / Geospatial","Løsningsarkitektur","Mentoring \u0026 coaching","Platformarkitektur","Produkt \u0026 krav","Teamledelse","Teknisk ledelse","Full stack‑produktudvikling","GIS \u0026 geospatiale løsninger","Platform- \u0026 løsningsarkitektur","Produktstrategi \u0026 kravspecifikation","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/directed-full-stack-gis-map-development-overseeing-postgresql-25/","url":"https://advisory.engineer.company/da/portfolio/directed-full-stack-gis-map-development-overseeing-postgresql-25/","title":"Har styret full‑stack‑udvikling af GIS‑kort med ansvar for PostgreSQL, Mapbox, ReactJS og NodeJS for at levere en integreret løsning.","summary":"Styrede full-stack GIS-kortudvikling (PostgreSQL, Mapbox, React, Node.js) — én integreret, udvidbar kerne i platformen.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e På det her tidspunkt var GIS‑kortet holdt op med at være en funktion og var blevet grunden til, at kunderne overhovedet loggede ind. Problemet var, at det var vokset op i stumper. De spatiale data lå i PostgreSQL, selve kortet blev tegnet med Mapbox, og applikationen omkring det var ReactJS i frontenden med NodeJS bagved. Hver del virkede for sig. De var bare ikke bygget til at passe sammen, og sømmene begyndte at vise sig.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Rollen dækkede full‑stack‑udviklingen af kortet og den tekniske retning, der fulgte med: datamodellen, renderingen, API\u0026rsquo;et og React‑frontenden. Målet var at gøre fire ting, der tilfældigvis delte et repository, til ét produkt, der var værd at stå inde for.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Arkitekturen blev fastlagt først, og så blev arbejdet tæt på koden i stedet for at styre på afstand. På datasiden blev den spatiale model i PostgreSQL holdt ryddelig, så forespørgslerne ikke sneglede sig af sted, efterhånden som datasættene voksede. Mapbox stod for tegningen; opgaven var at fodre den med de rigtige data på de rigtige zoomniveauer i stedet for det hele på én gang. På applikationssiden blev ReactJS- og NodeJS‑arbejdet reviewet, teamet skubbet mod fælles konventioner, og ansvar flyttet tilbage til det lag, det hørte til i, når ét begyndte at lække ind i det næste. En god del af det var uglamourøst arbejde: at fange de små inkonsistenser, før de størknede til arkitektur.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Det, der kom ud, var én integreret kortapplikation, hvor data, rendering og grænseflade endelig trak samme vej. Den blev en central del af platformen og noget, teamet kunne blive ved med at bygge videre på, uden at den knækkede sammen, hver gang et lag blev tilføjet.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["API'er \u0026 integration","Backend‑udvikling","Databaser","Frontend‑udvikling","Full stack‑udvikling","GIS / Geospatial","Performanceoptimering","Platformarkitektur","PostgreSQL","Teknisk ledelse","Backend- \u0026 API‑udvikling","Full stack‑produktudvikling","GIS \u0026 geospatiale løsninger","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/saved-4-000-hours-by-mentoring-and-growing-26/","url":"https://advisory.engineer.company/da/portfolio/saved-4-000-hours-by-mentoring-and-growing-26/","title":"Har sparet 4.000 timer ved at mentorere og udvide et team fra 2 til 18 medlemmer, optimere workflows og fremme tværfagligt samarbejde.","summary":"Sparede ~4.000 timer ved at udvide og mentorere et team fra 2 til 18, redesigne workflows og opbygge varig engineering-kapacitet.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Et team på to kunne ikke følge med længere. Produktet trak mere arbejde ind, end et par mennesker kunne levere, og måden, arbejdet foregik på — viden i hovederne, ingen rigtige konventioner — ville ikke overleve at blive skaleret op. At kaste flere folk efter et så løst team gør som regel bare kaosset større.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Opgaven var at udvide teamet og samtidig bygge den struktur, der ville lade en større gruppe bevæge sig hurtigere i stedet for langsommere. At mentorere de nye var den ene halvdel. At rette arbejdsgangene, så ingen gik i stå og ventede på en anden, var den anden.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Teamet voksede fra 2 til 18 over tid, med ansættelsen og mentoreringen behandlet som det samme job: alle, der kom til, skulle kunne arbejde uden opsyn. Fælles standarder betød, at kode og proces så ens ud uanset hvem der skrev dem, og der blev lagt reelt arbejde i overleveringerne mellem specialer, for det er dér, teams stille og roligt taber deres dage. Når noget blev ved med at spænde ben, gik rettelsen til processen i stedet for symptomet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Det større, bedre mentorerede team, der kørte på arbejdsgange, der faktisk var designet, sparede i omegnen af 4.000 timer. Men tallet er ikke rigtig pointen. Det, der blev bygget, var varig engineering‑kapacitet — en gruppe, der kunne bære arbejdet, uanset om nogen enkelt person var i rummet eller ej.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Agile \u0026 Scrum","Mentoring \u0026 coaching","Projektledelse","Teamledelse","Teknisk ledelse","Projektledelse (Agile)","Teamopbygning \u0026 mentoring","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/optimized-forecasting-and-investment-strategies-for-11-electricity-27/","url":"https://advisory.engineer.company/da/portfolio/optimized-forecasting-and-investment-strategies-for-11-electricity-27/","title":"Har optimeret prognose- og investeringsstrategier for 11 eldistributionsoperatører og øget driftseffektiviteten gennem datadrevne GIS‑løsninger.","summary":"Optimerede prognoser og investeringsstrategi for 11 eldistributionsoperatører med datadrevet GIS — troværdig, målrettet planlægning.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Eldistributionsoperatører står og falder på beslutninger om, hvor de skal forstærke nettet, og hvor de skal placere deres penge, og elleve af dem traf de beslutninger uden meget geospatial analyse under sig. De havde driftsdataene. Det, de ikke havde, var en måde at se dem på kortet, dér hvor mønstrene faktisk lever.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Opgaven var at skærpe deres prognoser og investeringsstrategier med GIS — at gøre tabeller af aflæsninger til noget, der viste dem, hvor kapaciteten blev knap, hvor risikoen byggede sig op, og hvor den næste krone var bedst givet ud.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Deres driftsdata blev bragt sammen med geospatial modellering, så de to forstærkede hinanden. I stedet for at lave prognoser i det abstrakte kunne nettet ses rumligt og stilles konkrete spørgsmål: hvilke strækninger var på vej mod deres grænser, hvilke områder retfærdiggjorde investering først. For elleve operatører betød det at tilpasse analysen til, hvordan hver af dem faktisk drev deres net, ikke at række alle den samme skabelon og håbe, den passede.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Operatørerne gik derfra med prognoser, de kunne stole på, og investeringsbeslutninger, der var målrettede frem for håbefulde. At forankre planlægningen i det, kortet viste, gjorde det hele mere effektivt — penge og opmærksomhed gik derhen, hvor dataene pegede, i stedet for derhen, hvor vanen gjorde.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Data engineering","Dataanalyse","GIS / Geospatial","Produkt \u0026 krav","Stakeholder \u0026 rapportering","Dataanalyse \u0026 BI‑dashboards","GIS \u0026 geospatiale løsninger","Produktstrategi \u0026 kravspecifikation"]},{"id":"https://advisory.engineer.company/da/portfolio/presented-200-ui-ux-improvements-for-the-gis-28/","url":"https://advisory.engineer.company/da/portfolio/presented-200-ui-ux-improvements-for-the-gis-28/","title":"Har præsenteret 200 UI/UX‑forbedringer til GIS‑kortapplikationen og øget omsætningen 10 gange gennem forbedrede softwarefunktioner.","summary":"Leverede 200 UI/UX-forbedringer til en GIS-kortapplikation og bidrog til en 10× omsætningsstigning — omhyggelig UX som kommerciel driver.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Kortgrænsefladen var blevet kraftfuld og undervejs kompliceret. Der var steder, hvor man kunne mærke kunderne ikke få den værdi, der sad lige foran dem — god funktionalitet fanget bag klodsede interaktioner. Det gab mellem, hvad produktet kunne, og hvad folk fandt let at gøre, kostede os stille og roligt.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Opgaven var at finde de gab og skubbe rettelserne igennem: det brugervenlighedsarbejde, der ville gøre produktet lettere at få værdi ud af og — ikke tilfældigt — mere værd kommercielt.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e I stedet for at gætte på, hvad der var galt, gik arbejdet i feedbacken og brugsdataene, og ud af det kom en backlog på 200 konkrete UI/UX‑forbedringer. De blev ikke behandlet som ens — rangeret efter effekt, med dem, der betød noget, argumenteret for og ført gennem teamet for at blive sendt ud som rigtige funktioner i stedet for en ønskeliste, der lå og blev forældet i et dokument.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Grænsefladen blev mærkbart bedre at bruge, og produktets værdi fulgte efter: arbejdet bidrog til en tidobling af omsætningen. Det er et eksempel, der er værd at vende tilbage til, fordi det gør pointen rent — omhyggeligt UX‑arbejde er ikke kosmetik, det dukker op på fakturaen.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Dataanalyse","Designsystemer \u0026 UI","Frontend‑udvikling","Produkt \u0026 krav","Stakeholder \u0026 rapportering","UX/UI‑design","Produktstrategi \u0026 kravspecifikation","UI/UX‑design \u0026 designsystemer"]},{"id":"https://advisory.engineer.company/da/portfolio/designed-and-managed-5-000-hours-of-map-29/","url":"https://advisory.engineer.company/da/portfolio/designed-and-managed-5-000-hours-of-map-29/","title":"Har designet og styret 5.000 timers kortudvikling ved hjælp af agile metoder som Scrum og Jira for effektiv projektledelse.","summary":"Planlagde og styrede 5.000 timers kortudvikling med Scrum og Jira — synligt arbejde, afstemt med roadmappen.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Kortet blev ikke bygget i en sprint. Det var tusindvis af timers arbejde spredt over en masse mennesker og en masse måneder, og den slags indsats skrider, hvis ingen holder linjen på scope og tidsplan. Overladt til sig selv bliver den stille og roligt forsinket.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Ansvaret var at designe og køre udviklingsindsatsen, så den blev leveret med vilje frem for ved held — at holde prioriteterne ærlige og fremdriften synlig for enhver, der ville kigge.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Det kørte på agile: ordentlig Scrum, med ceremonierne faktisk brugt frem for opført, og arbejdet sporet i Jira, så folk kunne se, hvor tingene stod, uden at skulle spørge. Et sted omkring 5.000 timers kortudvikling gik gennem den proces. Vægten lå mindre på ceremoni for dens egen skyld og mere på at holde prioriteterne rettet mod det, der betød noget, og fange skred tidligt, mens det stadig var billigt at rette.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e De 5.000 timer landede på en kontrolleret, synlig måde i stedet for at forsvinde ind i en sort boks. Projektledelsen gjorde det, den skal — og det, der mest går ubemærket hen, når den virker: den holdt arbejdet afstemt med målene og nogenlunde på tidsplanen, uden heltemod til sidst.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Agile \u0026 Scrum","Produkt \u0026 krav","Projektledelse","Stakeholder \u0026 rapportering","Teamledelse","Produktstrategi \u0026 kravspecifikation","Projektledelse (Agile)","Teamopbygning \u0026 mentoring"]},{"id":"https://advisory.engineer.company/da/portfolio/wrote-50-000-words-of-comprehensive-software-documentation-30/","url":"https://advisory.engineer.company/da/portfolio/wrote-50-000-words-of-comprehensive-software-documentation-30/","title":"Har skrevet 50.000 ord omfattende softwaredokumentation med Markdown i GitHub, Craft og Confluence og derved sikret fastholdelse af viden og gennemsigtighed i processen.","summary":"Skrev 50.000 ord softwaredokumentation i GitHub, Craft og Confluence — varig, gennemsigtig og reviderbar viden.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Det meste af det, der betød noget om produktet, og om hvordan teamet arbejdede, lå i folks hoveder. Det går fint lige indtil nogen ny kommer til, eller nogen forlader firmaet — og så sneglede onboardingen sig af sted, og en klump institutionel hukommelse var én opsigelse fra at være væk for altid.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Målet var at få den viden ud af hovederne og ind i dokumentation, folk faktisk ville beholde og bruge: klar nok til at blive læst, struktureret nok til at blive vedligeholdt frem for droppet efter en måned.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e En stor del af den blev skrevet i hånden, omkring 50.000 ord til sidst, i Markdown på tværs af GitHub, Craft og Confluence alt efter hvor hvert stykke hørte til. Den dækkede arkitekturen, processerne og det praktiske how‑to‑materiale — de spørgsmål, folk blev ved med at stille. Den blev holdt versionsstyret og, mindst lige så vigtigt, mulig at finde, for dokumentation, ingen kan lokalisere, kan lige så godt ikke eksistere.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Videnen holdt op med at være skrøbelig. Nye folk kom hurtigere op i tempo, processen blev noget, man kunne pege på i stedet for at rekonstruere efter hukommelsen, og det hele blev reviderbart: man kunne se hvordan og hvorfor arbejdet blev gjort frem for at tage det på tro.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Dokumentation","Mentoring \u0026 coaching","Teamledelse","Teknisk ledelse","Teknisk dokumentation","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/gathered-and-analyzed-business-requirements-to-translate-into-31/","url":"https://advisory.engineer.company/da/portfolio/gathered-and-analyzed-business-requirements-to-translate-into-31/","title":"Har indsamlet og analyseret forretningskrav og omsat dem til konkrete funktioner og user stories i overensstemmelse med data governance‑standarder.","summary":"Omsatte forretningskrav til klare funktioner og user stories efter data governance-standarder — mindre tvetydighed og omarbejde.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Krav plejede at ankomme som samtaler — nogen ville have noget, sådan cirka, og det faldt tilbage på udviklerne at gætte på kanterne. At gætte betyder omarbejde, og omarbejde er omtrent den dyreste måde, der findes, at bygge noget på.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Rollen sad mellem forretningen og engineeringen og oversatte den ene til den anden: at gøre løse behov til arbejde, en udvikler kunne tage fat på uden at gætte, og at holde det i tråd med data governance‑standarderne undervejs.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Kravene blev arbejdet ud med interessenterne direkte, med de akavede spørgsmål stillet tidligt i stedet for opdaget sent, og skrevet op som funktioner og user stories, der faktisk sagde, hvad \u0026ldquo;færdig\u0026rdquo; betød. Hver enkelt blev holdt op mod governance‑reglerne, for en funktion, der er nyttig, men håndterer data forkert, er ikke rigtig færdig. Hele formålet var, at nogen kunne læse en story og bygge det rigtige første gang.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Udviklingen kørte ud fra klare, aftalte funktioner i stedet for halvt forståede ønsker. Tvetydigheden faldt, og omarbejdet faldt med den, og leveringen forblev rettet mod de faktiske forretningsmål — inden for data governance‑linjerne frem for pyntet til at passe bagefter.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Agile \u0026 Scrum","Data governance","Dokumentation","Produkt \u0026 krav","Projektledelse","Stakeholder \u0026 rapportering","Data governance \u0026 datakvalitet","Produktstrategi \u0026 kravspecifikation","Projektledelse (Agile)"]},{"id":"https://advisory.engineer.company/da/portfolio/managed-the-execution-of-30-successful-gis-projects-32/","url":"https://advisory.engineer.company/da/portfolio/managed-the-execution-of-30-successful-gis-projects-32/","title":"Har styret gennemførelsen af 30 succesfulde GIS‑projekter og udvist lederskab i leveringen af innovative løsninger på tværs af feltet.","summary":"Leverede 30 succesfulde GIS-projekter — en historik af konsistent, innovativ levering, der skabte varig kundetillid.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Mappitall tjente sine penge på at levere GIS‑projekter, og der kørte mange af dem på én gang. Virksomhedens vækst red på at få dem ud ad døren pålideligt — ikke ét flagskibsprojekt gjort strålende, men en stabil strøm af dem, der landede til tiden og hang sammen, hvilket kun sker, når koordineringen på tværs af teamet faktisk fungerer.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Ansvaret var at få den portefølje leveret — at holde scope, folk og tidsplaner på linje på tværs af det hele og give teamet den retning, der skulle til for at levere.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Gennem de år kørte leveringen af tredive GIS‑projekter gennem den her rolle. I praksis betød det at holde scope i ro, når det ville krybe, at pege de rigtige folk mod det rigtige arbejde og at være tæt nok på hvert projekt til at fange problemer, mens de stadig var små. Når noget var ved at skride, bedre at vide det tidligt og rokere om end finde ud af det ved deadline. En stor del af jobbet var bare at holde tallerknerne i luften og kundens forventninger ærlige om, hvad der kom hvornår.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Alle tredive kom i mål. Den konsistens betød mere, end noget enkelt projekt ville have gjort — en kunde, der har set dig levere tredive gange, bekymrer sig ikke om den enogtredivte, og det omdømme er en god del af, hvorfor virksomheden blev ved med at vokse.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Agile \u0026 Scrum","GIS / Geospatial","Projektledelse","Stakeholder \u0026 rapportering","Teamledelse","GIS \u0026 geospatiale løsninger","Projektledelse (Agile)","Teamopbygning \u0026 mentoring"]},{"id":"https://advisory.engineer.company/da/portfolio/led-company-growth-from-4-to-14-employees-33/","url":"https://advisory.engineer.company/da/portfolio/led-company-growth-from-4-to-14-employees-33/","title":"Har ledet virksomhedens vækst fra 4 til 14 medarbejdere ved at anvende agile metoder og effektiv projektledelse.","summary":"Ledede virksomhedens vækst fra 4 til 14 medarbejdere med agile metoder — skalerede teamet uden at miste kvalitet eller sammenhold.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Mappitall var klar til at vokse, og der er en bestemt fare i det øjeblik: man tilføjer folk hurtigere, end man tilføjer proces, og både kvaliteten og den fælles fornemmelse af, hvordan tingene gøres, begynder at flosse. Fire personer, der alle ved, hvad alle andre laver, er noget helt andet end fjorten, der ikke gør.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e At lede den vækst var jobbet — at få folk ind og samtidig holde leveringen disciplineret og teamet trækkende i samme retning.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Virksomheden gik fra fire personer til fjorten. Det var ansættelse og onboarding gjort bevidst frem for i panik, men den større brik var at få de arbejdsmåder på plads, der lod et team af den størrelse ikke snuble over sig selv — agile praksisser, rigtig projektledelse, de vaner, der holder alles arbejde synligt for alle andre. Den tiende og fjortende ansættelse skulle træde ind i noget, der allerede havde en form, ikke gætte sig til, hvordan tingene blev gjort.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Teamet nåede fjorten, uden at kvaliteten faldt, eller det splintrede i folk, der ikke vidste, hvad de andre var i gang med. Det agile er det, der holdt en større gruppe produktiv — processen voksede med antallet af hoveder i stedet for at halte bagefter.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Agile \u0026 Scrum","Mentoring \u0026 coaching","Projektledelse","Teamledelse","Teknisk ledelse","Projektledelse (Agile)","Teamopbygning \u0026 mentoring","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/improved-team-communication-and-collaboration-by-implementing-slack-34/","url":"https://advisory.engineer.company/da/portfolio/improved-team-communication-and-collaboration-by-implementing-slack-34/","title":"Har forbedret teamets kommunikation og samarbejde ved at implementere Slack, Mattermost, 1Password og Jira og sparet 8.000 arbejdstimer.","summary":"Sparede ~8.000 timer ved at indføre Slack, Mattermost, 1Password og Jira — mindre jagt på information, mere faktisk levering.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Efterhånden som teamet blev større, havde kommunikationen og værktøjerne ikke fulgt med, og det kunne mærkes. Ting blev sagt ét sted og overset af dem, der havde brug for dem, arbejde blev lavet dobbelt, fordi ingen kunne se, hvad en anden allerede havde gjort, og at koordinere noget som helst tog længere tid end selve arbejdet. Den slags friktion er usynlig fra dag til dag, men den løber op i en masse tabt tid.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Målet var at rette op på, hvordan teamet kommunikerede og arbejdede sammen, og kradse den tid tilbage, der stille og roligt blev blødt til al den friktion.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Værktøjerne blev indført og standardiseret, og — det er den del, der faktisk betyder noget — praksis for at bruge dem blev sat, så de ikke bare blev endnu et sted at tjekke. Slack og Mattermost til kommunikation, 1Password, så delte secrets ikke blev sendt rundt på måder, ingen kunne holde styr på, Jira, så arbejdet blev tracket ét sted i stedet for at leve i folks hoveder og indbakker. Værktøjerne var den nemme del; at få alle til faktisk at bruge dem på samme måde var det egentlige arbejde.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Kommunikation og samarbejde blev mærkbart bedre, og det strømlinede opsæt sparede noget i størrelsesordenen 8.000 arbejdstimer — tid, der havde gået til at jage information og lave arbejde om, som nu gik til faktisk levering.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Agile \u0026 Scrum","Automatisering \u0026 CI/CD","Dokumentation","Projektledelse","Sikkerhed","Teamledelse","Projektledelse (Agile)","Sikkerhed \u0026 adgangsstyring","Teamopbygning \u0026 mentoring"]},{"id":"https://advisory.engineer.company/da/portfolio/led-the-development-deployment-and-support-of-over-35/","url":"https://advisory.engineer.company/da/portfolio/led-the-development-deployment-and-support-of-over-35/","title":"Har ledet udvikling, idriftsættelse og support af over 30 GIS‑projekter og udvist ekspertise i PostgreSQL, Bash, Python, JavaScript, GDAL, ArcGIS, PostGIS og Mapbox.","summary":"Ledede udvikling, drift og support af 30+ GIS-projekter med PostgreSQL, Python, GDAL, ArcGIS, PostGIS og Mapbox — hele livscyklussen.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Virksomhedens hele output var made‑to‑measure GIS — skræddersyet kortlægning og geodata‑systemer bygget til en kundes konkrete problem og så holdt kørende, når de var live. At bygge tingen er kun halvdelen; et geospatialt projekt, der ryger ud og så vælter i produktion, er ikke rigtig blevet leveret.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e De projekter kørte fra ende til anden gennem den her rolle — udviklingen, udrulningen og supporten, når de først var live — med den tekniske retning på tværs af en ret bred stak.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Leveringen kørte på mere end tredive GIS‑projekter, hands‑on på tværs af stakken hele vejen. PostgreSQL med PostGIS under til geodataene, GDAL/OGR til at flytte dem mellem formater — shapefiles, GeoJSON, GeoTIFF, KML, vector tiles — og QGIS og JOSM til selve dataarbejdet. Foran på det webkort bygget på Mapbox GL og Leaflet, nogle gange mod ArcGIS- eller HERE‑API\u0026rsquo;erne, med app‑laget i JavaScript, Python, PHP og SQL. Arbejdet spændte fra 2D- og 3D‑digital kortlægning over LiDAR‑behandling, georektifikation og vektorisering til indendørs kortlægning og navigation. Og ansvaret rakte forbi det punkt, tingen var sendt af sted — udrulningen og den løbende support i produktion var også en del af det, så problemer blev ikke givet videre; beslutningerne skulle leves med.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Tredive‑plus projekter bygget, udrullet og supporteret på tværs af hele det spænd. At stå på krogen for hele livscyklussen frem for bare bygget er det, der holdt kvaliteten ærlig — man designer anderledes, når man ved, det er en selv, der får opkaldet, hvis det går i stykker.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Backend‑udvikling","Data engineering","Databaser","Drift \u0026 backup","Full stack‑udvikling","GIS / Geospatial","PostgreSQL","Python","SQL","Teamledelse","Teknisk ledelse","Webudvikling","Backend- \u0026 API‑udvikling","Full stack‑produktudvikling","GIS \u0026 geospatiale løsninger","Teknisk ledelse \u0026 rådgivning","Udvikling af datapipelines (ETL/ELT)"]},{"id":"https://advisory.engineer.company/da/portfolio/guided-the-execution-of-numerous-company-projects-offering-37/","url":"https://advisory.engineer.company/da/portfolio/guided-the-execution-of-numerous-company-projects-offering-37/","title":"Har vejledt gennemførelsen af talrige virksomhedsprojekter og ydet ekspertsupport i softwareudviklingsfaserne.","summary":"Vejledte gennemførelsen af mange virksomhedsprojekter med ekspertsupport i de sværeste udviklingsfaser — stabil levering.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Der kørte mange projekter på samme tid, hvert midt i sin udviklingsfase, og de havde alle brug for stabil teknisk vejledning for at blive på sporet. Ladt alene driver projekter — en forkert tilgang taget tidligt bliver dyr, når først nogen bemærker det.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e At vejlede den gennemførelse var jobbet — at være den tekniske support, teamene kunne læne sig op ad gennem udviklingsfaserne.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Arbejdet holdt sig hands‑on på tværs af mange af virksomhedens projekter på én gang. Det betød at fjerne blokeringer, når folk sad fast, at kigge hårdt på en tilgang, før for meget blev bygget oven på den, og generelt at være tæt nok på til at fange et projekt på vej i den forkerte retning, mens det stadig var en kurskorrektion og ikke en genbygning. Idéen var at være tilgængelig frem for en port — at holde tingene i bevægelse, ikke at få alt til at vente på én person.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Projekterne bevægede sig mere gnidningsfrit gennem deres vanskelige udviklingsfaser med en erfaren at læne sig op ad på de rigtige tidspunkter, og det stabiliserede leveringen tværs igennem virksomhedens portefølje.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Mentoring \u0026 coaching","Projektledelse","Teamledelse","Teknisk ledelse","Projektledelse (Agile)","Teamopbygning \u0026 mentoring","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/overhauled-internal-processes-saving-8-000-hours-by-38/","url":"https://advisory.engineer.company/da/portfolio/overhauled-internal-processes-saving-8-000-hours-by-38/","title":"Har gennemgribende fornyet interne processer og sparet 8.000 timer ved at forbedre softwarearkitektur, systemer og planlægningseffektivitet.","summary":"Fornyede interne processer og sparede ~8.000 timer ved at forbedre softwarearkitektur, systemer og planlægningseffektivitet.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Måden, tingene blev gjort internt på, havde samlet den sædvanlige rust — softwarearkitektur, der var vokset ved aflejring frem for design, systemer, der virkede, men ikke effektivt, planlægning, der lod folk enten vente eller være pressede. Intet af det brændte, hvilket er præcis derfor, det var blevet ladt i fred, men det kostede stille og roligt en masse tid.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Målet var at forny de processer gennemgribende — at gå ud og finde spildet og tage det ud frem for at blive ved med at betale for det.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e De interne processer blev omarbejdet på tre fronter: softwarearkitekturen, så den var noget, man kunne ræsonnere om og bygge på i stedet for at arbejde uden om; systemerne, strømlinet, så det rutineprægede arbejde holdt op med at tage længere tid, end det burde; og planlægningen, så kapaciteten faktisk blev matchet med arbejdet. Og ændringerne blev gjort til at sidde fast — forankret i, hvordan teamet opererede, frem for efterladt som et notat, alle nikkede til og glemte — for procesforbedringer, der ikke gøres permanente, forfalder bare tilbage til den gamle måde.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Fornyelsen sparede omkring 8.000 timer ved at gøre arkitekturen, systemerne og planlægningen mærkbart mere effektive. Det er kapacitet, der gik direkte tilbage i arbejde med højere værdi i stedet for i overhead, ingen havde tænkt på at stille spørgsmål ved.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Infrastruktur","Løsningsarkitektur","Performanceoptimering","Platformarkitektur","Projektledelse","Teknisk ledelse","DevOps \u0026 CI/CD‑automatisering","Platform- \u0026 løsningsarkitektur","Projektledelse (Agile)","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/established-a-technical-support-department-servicing-over-10-40/","url":"https://advisory.engineer.company/da/portfolio/established-a-technical-support-department-servicing-over-10-40/","title":"Har etableret en teknisk supportafdeling, der har betjent over 10.000 kunder med IT‑support og fejlfindingsløsninger.","summary":"Etablerede en teknisk supportafdeling, der betjente 10.000+ kunder — support gik fra reaktiv til en skalerbar virksomhedsstyrke.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Kundebasen voksede og havde brug for pålidelig teknisk support, og der var bare ikke en dedikeret funktion til at give dem den i nogen egentlig skala. Support skete ad hoc, hvilket virker for en håndfuld kunder og stille og roligt falder fra hinanden, efterhånden som tallene klatrer.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e At rejse en egentlig teknisk supportkapacitet — en, der kunne betjene en stor og stadig voksende kundebase — var jobbet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e En teknisk supportafdeling blev bygget op fra ingenting. Det betød at beslutte, hvordan den faktisk skulle fungere, før der blev ansat ind i den — processen for, hvordan en henvendelse kom ind og blev løst, værktøjerne til at håndtere mængden, standarden for, hvordan god support så ud — og så bygge kapaciteten til at levere IT‑support og fejlfinding til mange kunder på én gang. At starte fra bunden var ærligt talt fordelen; den kunne designes til den skala, virksomheden var på vej mod, i stedet for at lappe på noget, der var vokset op ved et tilfælde.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Afdelingen endte med at betjene over ti tusind kunder med pålidelig support og fejlfinding. Support gik fra en ting, der blev gjort reaktivt, til en ægte styrke for virksomheden — noget, der skalerede med kundebasen i stedet for at bukke under for den.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Mentoring \u0026 coaching","Produkt \u0026 krav","Projektledelse","Stakeholder \u0026 rapportering","Systemadministration","Teamledelse","IT‑support \u0026 helpdesk","Projektledelse (Agile)","Teamopbygning \u0026 mentoring"]},{"id":"https://advisory.engineer.company/da/portfolio/streamlined-ci-cd-processes-saving-4-000-hours-42/","url":"https://advisory.engineer.company/da/portfolio/streamlined-ci-cd-processes-saving-4-000-hours-42/","title":"Har strømlinet CI/CD‑processer og sparet 4.000 timer ved at indføre automatisering i softwareudviklingspipelines.","summary":"Strømlinede CI/CD og sparede ~4.000 timer — hurtigere, mere pålidelige releases, så teamet kunne udgive med tillid.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e At få software ud ad døren afhang af manuelle, inkonsistente trin — nogen der huskede rækkefølgen og gjorde det en anelse forskelligt hver gang — og det bremsede releases og åd engineering‑timer, der skulle være gået til at bygge ting.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Målet var at strømline CI/CD‑processen og få automatisering ind i pipelines, så releases holdt op med at være et manuelt ritual.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Automatiserede build-, test- og udrulningspipelines blev sat op, så vejen fra en ændring til, at den kørte i produktion, var standardiseret i stedet for improviseret. De gentagne manuelle trin — dem, der var langsomme og, værre, blev gjort forskelligt afhængigt af, hvem der gjorde dem — kom ud. Når først pipelinen gør det på samme måde hver gang, holder en hel klasse af \u0026ldquo;det virkede på min maskine\u0026rdquo; og halvt huskede udrulningstrin bare op med at ske.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Automatiseringen gav omkring 4.000 timer tilbage og gjorde releases både hurtigere og mere pålidelige. Teamet kunne udgive uden at spænde ben for det — tilliden kom fra, at processen var konsistent, ikke fra at alle var forsigtige.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Drift \u0026 backup","Teknisk ledelse","Test \u0026 QA","DevOps \u0026 CI/CD‑automatisering","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/developed-a-data-analytics-reporting-system-increasing-quarterly-44/","url":"https://advisory.engineer.company/da/portfolio/developed-a-data-analytics-reporting-system-increasing-quarterly-44/","title":"Har udviklet et rapporteringssystem til dataanalyse og øget den kvartalsvise softwareomsætning med 400 % gennem Python‑baserede PDF‑rapporter.","summary":"Byggede et Python-rapporteringssystem til dataanalyse, der øgede den kvartalsvise softwareomsætning 400 % med klare, rettidige rapporter.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Interessenterne fik ikke analyse i nogen rettidig, læsbar form. Dataene fandtes, men at omsætte dem til noget, man faktisk kunne træffe en beslutning ud fra, var langsomt og manuelt, så indblikket i, hvordan tingene præsterede, haltede, og de kommercielle beslutninger haltede med.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e At bygge et rapporteringssystem til dataanalyse — et, der omsatte rådata til klar, regelmæssig indsigt uden at nogen håndsamlede det hver gang — var jobbet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Et rapporteringssystem genererede PDF‑rapporter i Python og automatiserede hele kæden: at trække dataene, køre analysen og præsentere det i et rent, konsistent format, interessenterne faktisk kunne læse. Pointen var regelmæssighed og klarhed — den samme professionelle rapport landede forudsigeligt, så tallene blev noget, folk kiggede på som en selvfølge frem for noget, de skulle gå ud og grave frem.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Den rapportering er det, der drev den kvartalsvise softwareomsætning op med 400 %. At gøre analysen bedre og hurtigere var ikke en back‑office‑finesse — sæt klare, rettidige tal foran de folk, der træffer kommercielle beslutninger, og beslutningerne bliver bedre, og her viste det sig direkte på omsætningen.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Backend‑udvikling","Data engineering","Dataanalyse","Produkt \u0026 krav","Python","Stakeholder \u0026 rapportering","Backend- \u0026 API‑udvikling","Dataanalyse \u0026 BI‑dashboards","Produktstrategi \u0026 kravspecifikation"]},{"id":"https://advisory.engineer.company/da/portfolio/enhanced-project-efficiency-saving-150-hours-per-month-46/","url":"https://advisory.engineer.company/da/portfolio/enhanced-project-efficiency-saving-150-hours-per-month-46/","title":"Har forbedret projekteffektiviteten og sparet 150 timer om måneden på tværs af 30 projekter ved at optimere workflows og ressourcestyring.","summary":"Sparede ~150 timer om måneden på tværs af 30 projekter ved at optimere workflows og ressourcestyring — en tilbagevendende gevinst.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e På tværs af en portefølje på omkring tredive projekter blev der tabt tid hver eneste måned til arbejdsgange, der aldrig var blevet optimeret, og ressourcestyring, der var ujævn — nogle folk underudnyttede, nogle overbelastede, arbejde planlagt forskelligt fra det ene projekt til det næste.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Målet var at gøre porteføljen mere effektiv og genvinde den tid, der gik tabt måned efter måned.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e De tredive projekter blev gennemgået, med arbejdsgangene og ressourcestyringen arbejdet på samlet — flaskehalsene taget ud, arbejdsbelastningerne balanceret, så de samme få folk ikke altid var flaskehalsen, og standardiseret, hvordan arbejdet blev planlagt og kørt, så hvert projekt ikke var sit eget særtilfælde. Tredive projekter, der hver taber lidt tid, løber op; rettelsen handlede mest om at gøre de gode vaner konsistente frem for at opfinde noget smart.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Ændringerne sparede omkring 150 timer om måneden på tværs af porteføljen. Det er en tilbagevendende månedlig besparelse, ikke en engangs — tredive projekter, der kører slankere, måned ud og måned ind.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Agile \u0026 Scrum","Automatisering \u0026 CI/CD","Performanceoptimering","Projektledelse","Teamledelse","Projektledelse (Agile)","Teamopbygning \u0026 mentoring"]},{"id":"https://advisory.engineer.company/da/portfolio/managed-a-team-delivering-it-support-data-recovery-47/","url":"https://advisory.engineer.company/da/portfolio/managed-a-team-delivering-it-support-data-recovery-47/","title":"Har ledet et team, der leverede IT‑support, datagendannelse og hardwarereparation til over 1.000 kunder og sikret service i høj kvalitet.","summary":"Ledede et team, der leverede IT-support, datagendannelse og hardwarereparation til 1.000+ kunder — et ry for pålidelig service.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Virksomheden var stedet, en stor base af kunder kom til, når deres IT gik i stykker — support, datagendannelse, hardwarereparation, hele spektret. At møde den slags stabile, uglamourøse efterspørgsel handler ikke om heltemod; det handler om at have et team, der kører godt dag efter dag, for arbejdet holder aldrig rigtig op med at komme.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e At lede det team, der leverede det hele, var jobbet, og at holde kvaliteten konsistent, om det så var en stille uge, eller alt kom på én gang.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Teamet kørte IT‑support, datagendannelse og hardwarereparation for over tusind kunder. En stor del af det var organiseringen nedenunder — at sikre, at arbejde blev samlet op og ikke tabt, at sætte en standard for, hvad \u0026ldquo;repareret\u0026rdquo; faktisk betød, så folk ikke fik halve reparationer tilbage, og at holde teamet effektivt, når køen var lang. Datagendannelse især er arbejde, man ikke kan være ligeglad med; det er som regel nogens billeder eller deres forretning, der ligger på det drev, og de har allerede en dårlig dag, når de når frem til dig.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Teamet betjente over tusind kunder og opbyggede et ægte omdømme for pålidelig service. I den slags forretning er omdømmet alt — folk kommer tilbage, og de fortæller andre om det, netop fordi du sidste gang, noget gik i stykker, faktisk fik det ordnet.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Mentoring \u0026 coaching","Stakeholder \u0026 rapportering","Systemadministration","Teamledelse","Hardwarereparation \u0026 datagendannelse","IT‑support \u0026 helpdesk","Teamopbygning \u0026 mentoring"]},{"id":"https://advisory.engineer.company/da/portfolio/migrated-the-http-api-from-fiber-to-huma-60/","url":"https://advisory.engineer.company/da/portfolio/migrated-the-http-api-from-fiber-to-huma-60/","title":"Har migreret HTTP‑API'et fra Fiber til Huma v2 — 649 paths og 760 operationer — og opnået og fastholdt 100 % paritet mellem de ruter, serveren registrerer, og den OpenAPI‑beskrivelse, den udgiver.","summary":"Migrerede HTTP-API'et fra Fiber til Huma v2 — 649 paths, 760 operationer — 100 % paritet mellem registrerede ruter og den udgivne OpenAPI-beskrivelse.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e API\u0026rsquo;et startede sit liv på Fiber, med request‑validering skrevet ud i hånden, endpoint for endpoint. Det er fint, når der er en håndfuld endpoints. Det holder op med at være fint, efterhånden som fladen vokser: den håndskrevne validering bliver til en vedligeholdelsesskat, og små inkonsistenser sniger sig ind, fordi hvert endpoints tjek er dets eget lille særtilfælde. Og der var ingen enkelt beskrivelse af API\u0026rsquo;ets form nogen steder.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Målet var validering, der kom fra typerne i stedet for fra håndskrevne tjek, og en egentlig kontrakt, der beskrev API\u0026rsquo;et — uden at stoppe op for at lave en big‑bang‑omskrivning.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e HTTP‑laget flyttede over på Huma v2, oven på Fiber, så den eksisterende runtime blev bevaret. Hvert endpoint får input- og output‑structs, og Huma genererer request‑valideringen og respons‑modelleringen ud fra de typer. En OpenAPI‑beskrivelse falder ud af det gratis, hvilket betyder, at dokumentationen følger koden i stedet for at rådne i en wiki. Alt nyt blev skrevet mod Huma og de eksisterende ruter migreret over, med præcis to endpoints efterladt på rå Fiber — WebSocket‑dem, hvor man reelt vil have socket\u0026rsquo;en, og Humas request/response‑model ikke passer. Det, det er vokset til, er 649 paths, der bærer 760 operationer, og et tjek i CI, som sammenligner de ruter, serveren faktisk registrerer, med dem, OpenAPI‑beskrivelsen annoncerer. Pariteten er 100 %, og den bliver der, fordi en rute, der ikke er beskrevet, får buildet til at fejle.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Nye endpoints får validering og opdateret dokumentation, uden at nogen laver ekstra arbejde for det, og en hel klasse af request‑fejl — \u0026ldquo;nå ja, vi glemte at tjekke det felt her\u0026rdquo;-slagsen — forsvandt. Ved 760 operationer er beskrivelsen den eneste praktiske måde, nogen læser API\u0026rsquo;et på, så garantien for, at den er komplet, betyder mere, end den gjorde ved halvtreds. Den typede kontrakt gjorde API\u0026rsquo;et både sikrere at ændre og lettere at give videre til en anden, for typerne fortæller dig, hvad et endpoint forventer.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["API'er \u0026 integration","Backend‑udvikling","Dokumentation","Migrering \u0026 modernisering","Platformarkitektur","Test \u0026 QA","Backend- \u0026 API‑udvikling","Platform- \u0026 løsningsarkitektur","Teknisk dokumentation"]},{"id":"https://advisory.engineer.company/da/portfolio/authored-578-go-task-automation-targets-70/","url":"https://advisory.engineer.company/da/portfolio/authored-578-go-task-automation-targets-70/","title":"Har skrevet 578 go‑task‑automatiseringsmål på tværs af native-, Docker- og HTTPS‑udviklingstilstande, linting, test, database og deployment.","summary":"Skrev 578 go-task-mål på tværs af native-, Docker- og HTTPS-tilstande — linting, test, database og deployment i én værktøjskæde.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e NextMariner er et polyglot‑monorepo — Go, TypeScript, SQL, Python, shell — og hvert af dem medbringer sin egen måde at bygge, teste, linte og køre på. Overladt til sig selv betyder det, at alle går rundt med et mentalt spikseddel af værktøjsspecifikke kommandoer, og at nytilkomne bruger deres første dag på bare at finde ud af, hvordan man får tingene til at køre.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Giv hele projektet én hoveddør: én konsistent måde at køre hvad som helst på, uanset hvilket sprog det tilfældigvis er skrevet i.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Det er bygget ud med go‑task — et Taskfile‑lag, der er vokset til 578 navngivne mål, 50 i rodfilen og 528 i namespacede filer under den. Der er udviklingstilstandene (native, Docker, en HTTPS‑variant til at teste PWA og mobil), kodekvalitetssiden (lint, format, test, fix på tværs af alle sprogene), databasehåndtering og de miljøspecifikke build- og deploy‑opgaver. Der er endda en low‑memory‑tilstand til maskiner, der ikke kan undvære den RAM, det kræver at bygge frontenden på den sædvanlige måde. Pointen var aldrig at have mange tasks; den var, at man aldrig behøver at kende den underliggende kommando.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Enhver kan køre task \u0026ndash;list og se hele værktøjskæden lagt frem og køre en hvilken som helst del af den på samme måde uanset, hvad der er under motorhjelmen. Onboarding blev kortere, og de små, dumme fejl — forkert flag, forkert mappe, halvt husket kommando — forsvandt for det meste. Tallet er også en advarsel: 578 mål er forbi, hvad nogen kan holde i hovedet, så navngivningen og namespacingen er det, der holder det brugbart, frem for at antallet er noget at være stolt af.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Dokumentation","Teknisk ledelse","Test \u0026 QA","DevOps \u0026 CI/CD‑automatisering","Teknisk dokumentation"]},{"id":"https://advisory.engineer.company/da/portfolio/designed-the-product-s-ui-and-ux-end-76/","url":"https://advisory.engineer.company/da/portfolio/designed-the-product-s-ui-and-ux-end-76/","title":"Har designet produktets UI og UX fra ende til anden — directory‑grids, dobbelte kort/tabel‑visninger, live‑kravvalidatorer og breadcrumb‑navigation.","summary":"Designede produktets UI/UX fra ende til anden — directory-grids, kort/tabel-visninger, live-validatorer og breadcrumbs — til maritime data.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e NextMariner stiller en masse forskellige entiteter foran folk — professionelle, virksomheder, skibe, jobs, anmeldelser — og grænsefladen skulle være to ting, der slås med hinanden: flot og oprigtigt brugbar. Tæt nok til at vise rigtige maritime data, men ikke så tæt, at den bliver til en mur, man preller af på.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Produktets UI og UX blev ejet fra ende til anden — layoutene, interaktionsmønstrene og det mindre, som hvordan nogen bliver ført gennem en formular uden at føle sig hakket på.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Et par beslutninger gjorde det meste af arbejdet. Directory‑grids har en kort/tabel‑toggle, så man kan browse visuelt eller scanne en tæt tabel, og appen husker, hvilken man valgte. Formularer bruger live‑kravvalidatorer, der sidder over inputtet og viser hver regel i grønt, når den er opfyldt, og ravgult, når den ikke er, så man bliver vejledt, mens man skriver, i stedet for hakket på, efter man har sendt. Navigationen er konsistente breadcrumbs og to‑kolonne‑entitetslayouts, så sider føles som det samme produkt frem for et sæt urelaterede skærme. Og fejlfilosofien er vejledning frem for fejl — ingen røde mure, redirects i stedet for blindgyder, appen prøver at holde dig i bevægelse frem for at stoppe dig.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Det, der kom ud, er en poleret, konsistent oplevelse, der gør tætte maritime data overskuelige og styrer folk gennem de komplicerede dele. Den fremstår gennemtænkt og troværdig, hvilket ikke er kosmetisk på en platform, folk bruger til deres faktiske karriere — hvis den så sjusket ud, ville de stole mindre på dataene, og de ville have ret i det.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Designsystemer \u0026 UI","Frontend‑udvikling","Produkt \u0026 krav","UX/UI‑design","Webudvikling","Produktstrategi \u0026 kravspecifikation","UI/UX‑design \u0026 designsystemer"]},{"id":"https://advisory.engineer.company/da/portfolio/set-a-zero-warnings-quality-bar-across-six-79/","url":"https://advisory.engineer.company/da/portfolio/set-a-zero-warnings-quality-bar-across-six-79/","title":"Har sat en zero‑warnings‑kvalitetsstandard på tværs af seks sprog — Go, TypeScript, SQL, Python, Shell og Markdown — håndhævet af pre‑commit‑hooks.","summary":"Satte en zero-warnings-kvalitetsstandard på tværs af Go, TypeScript, SQL, Python, Shell og Markdown — håndhævet af pre-commit-hooks.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Advarsler, der hober sig op, er stille og roligt ætsende. Hver diagnostik, man ignorerer, sænker barren en smule, og når først buildet spytter fyrre af dem ud, læser ingen nogen af dem, og et reelt problem sidder i den liste i fuldt dagslys, fordi \u0026ldquo;advarsler\u0026rdquo; er blevet til baggrundsstøj. I et polyglot‑kodebase er der så mange flere kilder til støj til at lade det ske.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Repoet skulle have én kompromisløs kvalitetsstandard på tværs af hvert sprog, så ting blev rettet i stedet for at hobe sig op.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e En zero‑warnings‑politik gik ind, med værktøjerne som det, der håndhæver den, for en politik, der bygger på alles årvågenhed, taber til den første travle uge. Hver linter‑diagnostik er en fejl — der er intet \u0026ldquo;warn\u0026rdquo;-niveau at gemme sig i — og det er det samme på tværs af hele stakken: Go med golangci‑lint, TypeScript med ESLint, SQL med SQLFluff, Python med Ruff, shell med ShellCheck, Markdown med markdownlint. Inline‑suppressions er forbudt, så man kan ikke papre hen over en diagnostik; man er nødt til faktisk at rette tingen. Pre‑commit- og pre‑push‑hooks kører linterne og testene, så en commit, der ville introducere et problem, slet ikke bliver lavet i første omgang. Der er endda grænser for funktions- og fillængde for at holde moduler fra at brede sig ud over det punkt, hvor de er læsbare.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Problemer bliver rettet ved kilden i stedet for udskudt til en backlog, ingen rydder, og kodebasen forbliver ren som standard frem for ved periodiske heltemodige indsatser. Standarden er identisk, uanset hvilket sprog man er i, og det er værktøjerne, der holder den — ikke nogens viljestyrke — hvilket er derfor, den faktisk holder.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Dokumentation","Teknisk ledelse","Test \u0026 QA","DevOps \u0026 CI/CD‑automatisering","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/set-the-platform-s-founding-decisions-in-november-2025-80/","url":"https://advisory.engineer.company/da/portfolio/set-the-platform-s-founding-decisions-in-november-2025-80/","title":"Har fastlagt platformens grundlæggende beslutninger i ugerne efter, at kodebasen blev åbnet i november 2025 — lagdelingen, database‑first‑dataadgang og zero‑warnings‑standarden — og de holder stadig ni måneder senere.","summary":"Fastlagde platformens grundlæggende beslutninger i november 2025 — lagdelingen, database-first-dataadgang og zero-warnings-standarden — og de holder stadig.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Repositoriet blev åbnet den 25. november 2025 uden noget i sig. Det, der bliver besluttet i de første par uger af et projekt som det, vejer uforholdsmæssigt tungt: lagdelingen, hvor forretningslogikken må bo, hvad kvalitetsstandarden er. De valg er billige at træffe på dag tre og tæt på umulige at vende om på i måned seks, hvor alt skrevet siden da forudsætter dem.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e De grundlæggende beslutninger skulle træffes bevidst og tidligt og træffes i en form, der kunne overleve at blive givet videre til andre mennesker og til en langt større kodebase, end der fandtes dengang.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Tre beslutninger gjorde det meste af arbejdet. Stakken blev lagdelt, så hver del har ét job — en Next.js‑frontend, et Go‑API, der validerer og videresender, et PostgreSQL‑funktionslag, der ejer forretningsreglerne — frem for at logik blev placeret, hvor det nu var bekvemt den eftermiddag. Dataadgang blev lagt bag stored functions fra starten, hvilket er det valg, alt andet i databasearbejdet følger af; at eftermontere det senere ville have betydet at skrive hver handler om. Og en zero‑warnings‑standard kom ind, før der var meget kode at holde til den, for en standard indført ved commit 5.000 er et oprydningsprojekt, hvorimod den samme standard ved commit 50 bare er, hvordan repositoriet fungerer. Ingen af de tre var den nemme mulighed dengang, og alle tre kostede momentum i den første måned.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Ni måneder og flere tusinde commits senere holder alle tre stadig: lagene er ikke blevet slørede, ingen handler taler direkte med en tabel, og buildet har stadig ingen warnings i sig. Det er den prøve, det er værd at lægge på en grundlæggende beslutning — ikke om den lød rigtig, men om den overlevede kontakten med den mængde arbejde, der kom efter, hvilket er det punkt, hvor bekvemme valg som regel stille og roligt bliver opgivet.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Backend‑udvikling","Databaser","DevOps","Frontend‑udvikling","Full stack‑udvikling","Løsningsarkitektur","Platformarkitektur","Sikkerhed","Teamledelse","Teknisk ledelse","Backend- \u0026 API‑udvikling","Full stack‑produktudvikling","Platform- \u0026 løsningsarkitektur","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/delivered-analysis-and-regular-progress-reports-to-the-81/","url":"https://advisory.engineer.company/da/portfolio/delivered-analysis-and-regular-progress-reports-to-the-81/","title":"Har leveret analyser og løbende statusrapporter til CEO'en og omsat engineering‑metrikker og leveringsstatus til beslutninger.","summary":"Leverede analyser og løbende statusrapporter til CEO'en — omsatte engineering-metrikker og leveringsstatus til trygge beslutninger.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Efterhånden som platformen kom sammen, skulle dens fremdrift og tilstand være synlig for ledelsen i termer, de faktisk kunne gøre noget med. Rå engineering‑signaler — build‑status, leveringstempo, incidents — betyder ikke meget i sig selv for en, der træffer produkt- og investeringsvalg; de er i den forkerte højde. Nogen måtte oversætte.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Den oversættelse var jobbet: at tage engineering‑virkeligheden — hvor leveringen stod, hvad systemmetrikkerne sagde — og rapportere den til CEO\u0026rsquo;en klart og regelmæssigt, så beslutninger hvilede på fakta i stedet for gætværk.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e En fast rapporteringsrytme gik ind frem for at rapportere, når der blev spurgt, hvilket altid er en anelse for sent. Leveringsfremdriften, scope, risiciene og systemtilstanden blev fulgt og omsat til klare, beslutningsorienterede opdateringer — hvad der var på sporet, hvad der var i risiko, og hvad en given prioritet faktisk ville koste i afvejninger. Det, der skulle undgås, var at aflevere rå tal og overlade fortolkningen til nogen uden konteksten; hver rapport kom med konkrete anbefalinger, og hvor det hjalp, blev fortællingen understøttet af de underliggende analyser, så ledelsen kunne gå i dybden, hvis de ville, frem for at skulle tage det på tro.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Ledelsen endte med et klart, ærligt og aktuelt billede af engineering og kunne styre produktprioriteter og investeringer med en vis tillid i stedet for at flyve i blinde. Rapportering holdt op med at være et statusritual, ingen læser, og blev til noget, beslutninger faktisk blev truffet ud fra — hvilket holdt det tekniske arbejde og forretningsretningen pegende samme vej.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Dataanalyse","Produkt \u0026 krav","Projektledelse","Stakeholder \u0026 rapportering","Teknisk ledelse","Dataanalyse \u0026 BI‑dashboards","Projektledelse (Agile)","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/designed-a-time-management-and-reporting-system-that-88/","url":"https://advisory.engineer.company/da/portfolio/designed-a-time-management-and-reporting-system-that-88/","title":"Har designet et tids- og rapporteringssystem, der forblev i produktion i årevis uden væsentlige ændringer.","summary":"Designede et tids- og rapporteringssystem, der forblev i produktion i årevis uden væsentlige ændringer.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Teamet havde ikke en pålidelig måde at styre tid og rapportere fremdrift på. Hvilket som regel betyder, at det sker i en spredning af regneark og hukommelse, og at rapporteringen bliver en kamp ved slutningen af hver periode frem for noget, der bare falder ud af, hvordan folk arbejder.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e At bygge et system til begge dele, der faktisk ville holde, var opgaven.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Et tids- og rapporteringssystem blev designet op omkring den måde, teamet reelt arbejdede på, frem for at påtvinge en hyldevareproces, de ville ruter uden om. Det er hele kunsten med interne værktøjer — hvis det passer til det virkelige workflow, bruger folk det; hvis det slås med workflowet, forlader de det stille og roligt, og man er tilbage ved regneark. Så det blev bygget til at matche virkeligheden frem for et ideal.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Det forblev i produktion i årevis uden nogen væsentlig ændring. Det er den kompliment, man vil have for et internt værktøj — ikke at det var imponerende, men at det bare blev ved med at virke, og ingen nogensinde behøvede at udskifte det. Noget, der overlever år med daglig brug urørt, var tydeligvis bygget til at passe.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Produkt \u0026 krav","Projektledelse","Teknisk ledelse","Dataanalyse \u0026 BI‑dashboards","Produktstrategi \u0026 kravspecifikation","Projektledelse (Agile)"]},{"id":"https://advisory.engineer.company/da/portfolio/automated-team-collaboration-password-management-task-and-time-89/","url":"https://advisory.engineer.company/da/portfolio/automated-team-collaboration-password-management-task-and-time-89/","title":"Har automatiseret teamsamarbejde, adgangskodehåndtering, opgave- og tidsstyring og bygget et semi‑automatisk projektvisningssystem, hvilket øgede teamets produktivitet.","summary":"Automatiserede samarbejde, adgangskode-, opgave- og tidsstyring og byggede et semi-automatisk projektvisningssystem — højere produktivitet.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e En stor del af teamets driftsarbejde — at koordinere, håndtere adgangskoder, tracke opgaver og tid — blev lavet i hånden, og manuel koordinering er en stille skat: det er aldrig det, man bemærker, men det æder støt timer, der kunne gå et bedre sted hen.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e At automatisere det gentagne driftsarbejde var målet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e De dele, der egnede sig til det, blev automatiseret — teamsamarbejde, adgangskodehåndtering, opgavestyring, tidsstyring — med et semi‑automatisk projektvisningssystem oveni. Idéen på tværs af det hele var at tage rutinekoordineringen af folks bord, så den kørte af sig selv, og lade dem bruge den genvundne opmærksomhed på arbejde, der faktisk krævede et menneske. Visningssystemet var det samme instinkt anvendt på noget mere synligt: at gøre det at præsentere arbejdet mest muligt automatisk frem for en manuel pligt hver gang.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Driftseffektiviteten steg, og teamet blev mere produktivt, fordi den rutinekoordinering, der før krævede konstant menneskelig opmærksomhed, nu i vid udstrækning kørte af sig selv. Den tid, der lækkede ud i pseudoarbejde, gik tilbage i det faktiske arbejde.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Projektledelse","Sikkerhed","Teknisk ledelse","DevOps \u0026 CI/CD‑automatisering","Projektledelse (Agile)","Sikkerhed \u0026 adgangsstyring"]},{"id":"https://advisory.engineer.company/da/portfolio/built-a-layered-automated-test-suite-across-four-layers-94/","url":"https://advisory.engineer.company/da/portfolio/built-a-layered-automated-test-suite-across-four-layers-94/","title":"Har bygget en lagdelt automatiseret testsuite — 981 Go‑tests, 543 frontend- og browserspecs, 494 SQL‑adfærdstests — med mutationstest, property‑based tests og en tilgængelighedsgate.","summary":"Byggede en lagdelt testsuite — 981 Go-tests, 543 frontend-specs og 494 SQL-adfærdstests — med gates for mutation, property-based test og tilgængelighed.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e En platform, der holder sin forretningslogik i databasen, har et testproblem, de fleste projekter ikke har. Logikken er ikke i det sprog, testframeworket er godt til — den er i SQL, bag funktionsgrænser, og SQL er præcis den slags kode, der ender utestet, fordi det er akavet at teste. Læg et Go‑API og en Next.js‑frontend oven på det, og \u0026ldquo;de vigtige dele er dækket\u0026rdquo; bliver stille og roligt til \u0026ldquo;de dele, der var nemme at dække, er dækket.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Hvert lag skulle have sin adfærd kontrolleret dér, hvor adfærden faktisk bor, frem for at alt blev kontrolleret udefra gennem en browser.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Fire lag fik fire slags test. Go‑API\u0026rsquo;et bærer 981 testfunktioner fordelt på 310 filer. Frontenden bærer 543 Vitest- og Playwright‑specs, heraf 48 end‑to‑end‑filer og 30 browser‑specs. Databasen bærer 494 adfærdstestfiler — 116.876 linjer SQL, der tjekker sine antagelser gennem 6.654 rejste exceptions — så en stored function bliver testet i databasen frem for gennem tre lag applikation ovenover. Over dem ligger de test, der tester testene: Stryker mutation testing ødelægger med vilje en linje kode og fejler, når intet opdager det, og fast‑check genererer input, ingen tænkte på at skrive ned. En axe‑core‑gate kræver nul WCAG 2.0- og 2.1‑overtrædelser på niveau A og AA, hvilket gør tilgængelighed til noget, der får buildet til at fejle, frem for et revisionsfund måneder senere. Coverage‑tærskler bevæger sig kun opad. Hele suiten kører som 10 jobs i et 612‑linjers workflow.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e At ændre noget strukturelt holdt op med at være skræmmende, og det er det eneste, der holder et kodebase af den størrelse fra at forkalke. Den ærlige omkostning er tid — suiten er langsom, den beskatter hver eneste ændring, og i den størrelse skal den selv vedligeholdes. Det, den køber, er evnen til at blive ved med at bevæge sig hurtigt, og det er mere værd end de minutter, det tager.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Backend‑udvikling","DevOps","Drift \u0026 backup","Frontend‑udvikling","PostgreSQL","Test \u0026 QA","Backend- \u0026 API‑udvikling","DevOps \u0026 CI/CD‑automatisering","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/built-the-repository-s-guard-engine-of-268-checks-95/","url":"https://advisory.engineer.company/da/portfolio/built-the-repository-s-guard-engine-of-268-checks-95/","title":"Har bygget kodebasens guard‑motor — 268 registrerede commit‑tjek, 277 lint‑regler og 15 egne ESLint‑regler — plus 146 tests af selve tjekkene, så det er builden, der holder standarden, ikke reviewet.","summary":"Byggede en guard-motor med 268 registrerede commit-tjek, 277 lint-regler og 15 egne ESLint-regler — plus 146 tests af selve tjekkene.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Standarder, der er skrevet ned i en contributing‑guide, er forslag. Alle er enige i dem, og så er det fredag, ændringen er lille, og guiden taber. Zero‑warnings‑barren ville kun nogensinde holde, hvis noget andet end velvilje holdt den — og de lintere, der følger med hvert sprog, når slet ikke frem til de projektspecifikke regler, der faktisk betyder noget, dem om, hvordan netop dette kodebase er ment at virke.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e De regler, projektet gik op i, skulle kunne eksekveres, så det at bryde en fik en commit til at fejle frem for at vente på en reviewer med tid og hukommelse nok til at fange det.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Det, der voksede ud af det, er en guard‑motor. Der er 274 check‑scripts, 268 af dem registreret i commit‑hooks, ved siden af 277 JavaScript‑lintere og 96 shell- og 17 Python‑validatorer, der dækker de ting, hyldevareværktøj ikke har nogen mening om — at en migration kan rulles tilbage, at en oversættelsesnøgle findes i begge locales, at en registreret rute optræder i OpenAPI‑beskrivelsen, at ingen stille og roligt har tilføjet en inline‑suppression. Femten custom ESLint‑regler holder husets mønstre på plads i TypeScript. Én regel er værd at nævne for sig: enhver commit med præfikset fix: skal bære en test, der fejler uden den, så en fejl, der er rettet, bliver ved med at være rettet. Og fordi en ødelagt guard er værre end slet ingen guard — den lader alt passere, og ingen opdager det — har selve guard‑laget 146 test.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Review‑tiden flyttede fra mekanik til design, fordi de mekaniske indvendinger allerede var fremsat af en maskine, før branchen blev pushet. Trade‑off\u0026rsquo;et er reelt og værd at sige højt: det er langsomt at committe, og en dårligt skrevet guard er oprigtigt irriterende at arbejde uden om. De 146 test findes, fordi netop det skete.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Dokumentation","Teknisk ledelse","Test \u0026 QA","DevOps \u0026 CI/CD‑automatisering","Teknisk dokumentation","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/built-the-payments-and-entitlements-layer-96/","url":"https://advisory.engineer.company/da/portfolio/built-the-payments-and-entitlements-layer-96/","title":"Har bygget betalings- og rettighedslaget — Stripe side om side med Apple og Google in‑app purchase — så directory, søgning og eksport spærres af en adgangsmodel på 11 tabeller, der tjekkes på serveren.","summary":"Byggede betalings- og rettighedslaget — Stripe med Apple og Google in-app purchase — directory, søgning og eksport spærret af en adgangsmodel.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Penge er den del af en platform, ingen har lov til at tage let på. Et abonnement skal overleve, at et kort udløber, en refusion, et planskifte, en webhook, der ankommer to gange, og en webhook, der ankommer i forkert rækkefølge. I det øjeblik betaling kan ske i tre butikker — et kort på nettet, Apple i den ene app store, Google i den anden — findes der tre forskellige udlægninger af, hvad nogen har købt, og produktet har stadig brug for ét svar på ét spørgsmål: hvad må denne person lige nu?\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e At tage imod penge og at give adgang skulle være to systemer frem for ét, så det at tilføje en butik ikke betød at omskrive hver eneste gate i produktet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Stripe håndterer kort og abonnementer gennem 18 Go‑filer, og Apple- og Google‑in‑app‑køb kommer ind gennem deres egen kvitteringsverifikation. Alle tre løber sammen i et payments‑skema på 9 tabeller og 34 funktioner — og stopper så dér. Det, produktet faktisk spørger om, er et separat access‑skema på 11 tabeller og 34 funktioner, som svarer på \u0026ldquo;må denne konto det her?\u0026rdquo; uden at vide eller bryde sig om, hvilken butik der har betalt for det. Det svar styrer adgangen til virksomhedskataloget, søgningen og dataeksporten, og det genkontrolleres på serveren ved hver request, for en skjult knap er en høflighed og ikke en kontrol.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e At tilføje en butik rører nu ved payments‑siden og lader alle gates være, og et supportspørgsmål om nogens adgang har én tabel at kigge i frem for tre. Omkostningen er to skemaer, hvor et mindre produkt ville nøjes med ét, plus et rettighedsopslag på requests, der ellers ville have været gratis.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["API'er \u0026 integration","Backend‑udvikling","Databaser","PostgreSQL","Produkt \u0026 krav","Sikkerhed","Backend- \u0026 API‑udvikling","Databasedesign \u0026 datamodellering","Produktstrategi \u0026 kravspecifikation","Sikkerhed \u0026 adgangsstyring"]},{"id":"https://advisory.engineer.company/da/portfolio/built-the-operator-back-office-for-the-platform-102/","url":"https://advisory.engineer.company/da/portfolio/built-the-operator-back-office-for-the-platform-102/","title":"Har bygget operatørernes back‑office — omkring 40 admin‑ruter og 128 komponenter, der dækker claims, moderation, feature flags, cache og diagnostik — så platformen kan drives uden databaseadgang.","summary":"Byggede operatørernes back-office — omkring 40 admin-ruter og 128 komponenter til claims, moderation, feature flags, cache og diagnostik.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Enhver platform får stille og roligt en applikation nummer to, og det er som regel den, ingen planlægger. Nogen skal godkende et ejerskabskrav, skjule en anmeldelse, slå en funktion til for en delmængde af brugerne, rydde en cache eller finde ud af, hvorfor én konto ser noget mærkeligt. Når den applikation ikke findes, er svaret en engineer med en databasekonsol — hvilket er langsomt, ulogget og én slåfejl fra en hændelse.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e At drive platformen fra dag til dag skulle kunne lade sig gøre uden en shell, så driften hørte til hos den, der havde vagten, frem for hos den, der havde adgangsoplysningerne.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Back‑officen endte på omkring 40 admin‑ruter bygget af 128 komponenter, og den dækker arbejdet, som det faktisk kommer ind: at afgøre ejerskabskrav på virksomheder, moderere anmeldelser og opslag, vippe feature flags, inspicere og rydde caches, læse diagnostik og den rapportering, CEO\u0026rsquo;en beder om. Den kører på det samme designsystem og den samme genererede API‑klient som det offentlige produkt, hvilket var det afgørende valg — et internt værktøj bygget på sin egen stak bliver den del, ingen opdaterer, og derefter den del, ingen stoler på.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e De folk, der driver platformen, kan drive den, og hver handling går gennem den samme autorisation og efterlader det samme spor som alt andet. Det er en stor flade at holde testet og tilgængelig for et lille internt publikum, og den omkostning løber videre. Den er stadig billigere end alternativet, som er en engineer, der taster UPDATE mod produktion klokken ni en søndag aften.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Backend‑udvikling","Frontend‑udvikling","Full stack‑udvikling","Produkt \u0026 krav","Systemadministration","UX/UI‑design","Full stack‑produktudvikling","Produktstrategi \u0026 kravspecifikation"]},{"id":"https://advisory.engineer.company/da/portfolio/built-company-ownership-claims-end-to-end-103/","url":"https://advisory.engineer.company/da/portfolio/built-company-ownership-claims-end-to-end-103/","title":"Har bygget ejerskabskrav på virksomheder fra ende til anden — en bruger gør krav på en virksomhed, en administrator afgør sagen, og en godkendelse omskriver den autorisationsgraf, der afgør, hvem der må redigere hvad.","summary":"Byggede ejerskabskrav på virksomheder fra ende til anden: en bruger gør krav, en administrator afgør, og godkendelsen omskriver autorisationsgrafen.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Et katalog seedet fra offentlige kilder har et strukturelt problem: virksomhederne i det har ikke selv sat sig der. Før eller siden dukker nogen fra en af dem op og vil rette sin egen post — og der er ingen relation mellem den person og den post, kun en påstand om, at der er en. Giver man det for villigt, redigerer en konkurrent din side. Giver man det for langsomt, bliver kataloget ved med at være forkert.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Der skulle være en vej fra \u0026ldquo;det her er min virksomhed\u0026rdquo; til reel myndighed over posten, med en menneskelig beslutning i midten og et spor bagefter.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Ejerskabskrav blev bygget fra ende til anden, over 108 commits og begge applikationer. En bruger indsender et krav med dokumentation; det lander i en kø i back‑officen; en administrator gennemgår det og godkender eller afviser det med en begrundelse, der går tilbage til den, der rejste kravet. Det interessante er, hvad en godkendelse gør — det er ikke et flag på en række. Godkendelsen omskriver autorisationsgrafen, så kontoen får en rigtig relation til organisationen, og det er den samme relation, som hvert eneste rettighedstjek i platformen allerede slår op i. Gaten er afgørelsen, ikke kodestien, og ingen funktion har været nødt til at lære om ejerskabskrav for at respektere den.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e En virksomhed kan overtage og rette sin egen post, uden at nogen redigerer databasen i hånden, og hver tildeling af myndighed har en navngiven godkender og en begrundelse hæftet på. Den menneskelige gennemgang er flaskehalsen med vilje; et automatisk tjek på et domænenavn ville være hurtigere og ville tage fejl i præcis de tilfælde, der betyder mest.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Backend‑udvikling","Frontend‑udvikling","Full stack‑udvikling","Produkt \u0026 krav","Sikkerhed","Full stack‑produktudvikling","Produktstrategi \u0026 kravspecifikation","Sikkerhed \u0026 adgangsstyring"]},{"id":"https://advisory.engineer.company/da/portfolio/established-a-continuous-security-programme-104/","url":"https://advisory.engineer.company/da/portfolio/established-a-continuous-security-programme-104/","title":"Har etableret et løbende sikkerhedsprogram — code scanning, DAST, afhængigheds- og sårbarhedstjek, SBOM‑generering, secret scanning og SHA‑pinnede actions — sammen med 21 skrevne sikkerhedsaudits.","summary":"Etablerede et løbende sikkerhedsprogram — code scanning, DAST, afhængighedstjek, SBOM, secret scanning og pinnede actions — plus 21 audits.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Sikkerhedsarbejdet inde i applikationen — Content‑Security‑Policy\u0026rsquo;en, least‑privilege‑databaserollerne, gentjekket af rettigheder — beskytter platformen ved runtime. Intet af det siger noget om det, der bliver sendt afsted: om en dependency samlede en kendt sårbarhed op i tirsdags, om en adgangsoplysning blev committet og rullet tilbage, eller om en third‑party‑action pinnet til et tag stille og roligt er blevet til et andet stykke kode.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Supply chain- og kodesikkerhed skulle være løbende og automatiseret, så tilstanden af det var et build‑resultat frem for en holdning.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Statisk analyse kører gennem CodeQL, dynamisk test mod en kørende instans gennem ZAP, og Go‑dependencies tjekkes med govulncheck. En SBOM genereres ved hvert build med Anchore og Syft, så det, der blev sendt afsted, er kendt frem for rekonstrueret bagefter. Gitleaks scanner historikken for adgangsoplysninger. Hver third‑party GitHub Action er pinnet til en commit‑hash frem for et tag, hvilket er den uglamourøse kontrol, der forhindrer, at et tag bliver flyttet under dig. Dependabot holder øje med 6 økosystemer. Ved siden af automatiseringen ligger 21 skrevne sikkerhedsaudits, heriblandt en threat model og en vurdering op mod OWASP‑testguiden — for scannere finder de klasser af problemer, nogen allerede har beskrevet, og en threat model er der, hvor dem, der er specifikke for netop denne platform, får et navn.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e En sårbarhed, der bliver offentliggjort upstream, dukker op som et fejlende build frem for som en nyhed. Mængden af fund er den reelle omkostning — en scanner, der rapporterer alt, træner folk i at ignorere den, og at holde signalet brugbart kræver løbende triage frem for en engangsopsætning.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Dokumentation","Drift \u0026 backup","Sikkerhed","DevOps \u0026 CI/CD‑automatisering","Sikkerhed \u0026 adgangsstyring","Teknisk dokumentation"]},{"id":"https://advisory.engineer.company/da/portfolio/built-the-loyalty-and-reputation-system-105/","url":"https://advisory.engineer.company/da/portfolio/built-the-loyalty-and-reputation-system-105/","title":"Har bygget loyalitets- og omdømmesystemet — 67 funktioner over et ledger på 31 tabeller, med ligaer, badges og en indløsningsshop — med en row lock på saldoen, der lukker double‑spend‑vinduet.","summary":"Byggede loyalitets- og omdømmesystemet — 67 funktioner over et ledger på 31 tabeller, ligaer, badges og en shop — med row lock på saldoen.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Professionelt netværk har et cold start‑problem: platformen er værd at bruge, når andre allerede bruger den, og indtil da er der ikke meget grund til at komme tilbage. Den sædvanlige løftestang er et belønningssystem — point for at bidrage, en standing der afspejler omdømme — som er nemt at beskrive og lumsk at bygge, for i det øjeblik point kan bruges, er de penge, og hver eneste fejl, penge kan lave, kan laves her.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Bidrag skulle kunne måles og belønnes, med en saldo, der ikke kunne bruges to gange.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Loyalty‑skemaet løber op i 31 tabeller og 67 funktioner, med standing i yderligere 5 tabeller og 32 funktioner, og discovery- og personalization‑skemaer ved siden af til at afgøre, hvad et givent medlem ser. Oven på ledgeren sidder ligaer, badges og en indløsningsshop, hvor en saldo bliver til noget virkeligt. Det, der krævede omhuen, er den ældste fejl i bogen: tjek saldoen, brug den så, og to requests, der ankommer samtidig, passerer begge tjekket. Hver mutation tager en row lock på walleten, før den læser den, så den anden request venter på, at den første bliver færdig, frem for at kappes med den. At walleten ligger i den samme database som alt andet er det, der overhovedet gør det muligt — saldoen og det, den købte, committer sammen eller slet ikke.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Bidrag bliver målt og belønnet, og en saldo er et regnestykke frem for en tilnærmelse. Row locking er det langsommere svar og blev valgt alligevel: kamp om den samme wallet bliver til en kø, og alternativet er et medlem, der bruger de samme point to gange, og nogen, der afstemmer det i hånden bagefter.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Backend‑udvikling","Databaser","Performanceoptimering","PostgreSQL","Produkt \u0026 krav","SQL","Backend- \u0026 API‑udvikling","Databasedesign \u0026 datamodellering","Produktstrategi \u0026 kravspecifikation"]},{"id":"https://advisory.engineer.company/da/portfolio/built-the-platform-s-social-layer-106/","url":"https://advisory.engineer.company/da/portfolio/built-the-platform-s-social-layer-106/","title":"Har bygget platformens sociale lag — opslag, feed, grupper, mentions, en følgergraf og et digest over mærkedage — på samme function‑first datalag som resten af produktet.","summary":"Byggede platformens sociale lag — opslag, feed, grupper, mentions, følgergraf og et digest over mærkedage — på samme function-first datalag.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Et katalog over virksomheder er et opslagsværk. Folk slår op i det og går igen. Det, der gør en professionel platform værd at vende tilbage til, er, at der er andre mennesker på den — hvilket betyder opslag, grupper og en grund til at komme tilbage, som ikke er en mail, der beder dig om det.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Der skulle lægges et socialt lag på, uden at det blev til et system nummer to med sine egne regler, sine egne rettigheder og sin egen måde at gemme ting på.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Opslag, et feed, grupper, mentions, en follower‑graf og et digest over mærkedage gik ind over 188 commits, alt sammen på det samme function‑first datalag som resten af platformen. Den begrænsning gjorde det meste af arbejdet: follower‑grafen er tabeller og funktioner som alt andet, en mention slås op gennem det samme identity‑skema, som kataloget bruger, og et opslag arver den moderationskø, der allerede var bygget til anmeldelser. Intet her havde brug for sit eget lager eller sin egen rettighedsmodel. Feedet er det ene sted, der satte sig imod, for at samle en personaliseret timeline effektivt er et oprigtigt anderledes problem end at hente en række, og det er der, personalization- og discovery‑arbejdet gør sig fortjent til sin plads.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Platformen har en grund til at blive åbnet på en dag, hvor ingen har brug for at slå en virksomhed op, og den kom uden en parallel stak at vedligeholde. Om et socialt lag er den rigtige investering for et maritimt katalog, er et produktspørgsmål frem for et engineering‑spørgsmål — det er her, fordi produktet bad om det, og det er bygget på samme måde som alt omkring det.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Backend‑udvikling","Databaser","Frontend‑udvikling","Full stack‑udvikling","Produkt \u0026 krav","Webudvikling","Backend- \u0026 API‑udvikling","Full stack‑produktudvikling","Produktstrategi \u0026 kravspecifikation"]},{"id":"https://advisory.engineer.company/da/portfolio/built-the-hiring-marketplace-and-career-workspace-107/","url":"https://advisory.engineer.company/da/portfolio/built-the-hiring-marketplace-and-career-workspace-107/","title":"Har bygget rekrutteringsmarkedspladsen og søfarendes karriere‑workspace — 151 stored functions på tværs af 48 tabeller — med ledige stillinger, ansøgninger, certifikater, avancement i grader og verificeret sejltid.","summary":"Byggede jobmarkedspladsen og søfarendes karriereområde — 151 stored functions på tværs af 48 tabeller — stillinger matchet på dokumenterede kvalifikationer.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Det kommercielle argument for et maritimt professionelt netværk er rekruttering: virksomheder har brug for besætning og officerer, og søfarende har brug for hyre. Begge halvdele fandtes allerede på platformen i den forkerte form — virksomhederne lå i kataloget, de professionelle havde profiler, og der var intet, der forbandt en ledig stilling med den person, der var kvalificeret til at udfylde den. Kvalifikationen er den svære del, for i denne branche er det certifikater, grader og dokumenteret sejltid frem for en jobtitel.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Ledige stillinger, ansøgninger og verificerbare kvalifikationsbeviser for søfarende skulle modelleres ordentligt frem for som fritekst på en profil.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e To domæner blev bygget. Rekrutteringssiden løber op i 32 tabeller og 118 funktioner, der dækker ledige stillinger, ansøgninger, shortlisting og arbejdsgiverens billede af en pipeline. Karriere‑workspacet bærer 16 tabeller og 33 funktioner, der rummer certifikater, gradprogression og sejltid, med dokumentupload og en gennemgangskø, så et kvalifikationsbevis bliver kontrolleret frem for påstået. At modellere progression som en graf frem for en liste er det, der gør matchningen brugbar — en grad er nåelig fra en anden grad givet bestemte certifikater og nok registreret tid til søs, og den struktur er det, der lader en ledig stilling blive matchet mod en karriere frem for mod et nøgleord. Karriere‑workspacet sendes bag et feature flag og er ikke fuldt released; rekrutteringssiden er live.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e En ledig stilling kan matches mod dokumenterede kvalifikationer i stedet for en selvbeskrevet jobtitel, og det er hele forskellen mellem et jobopslagssite og et rekrutteringsværktøj i denne branche. Verifikationen er flaskehalsen, med vilje — en gennemgangskø skalerer ikke, som et automatisk tjek ville, og et automatisk tjek ville certificere folk, der ikke burde certificeres.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Backend‑udvikling","Data governance","Databaser","Full stack‑udvikling","PostgreSQL","Produkt \u0026 krav","Backend- \u0026 API‑udvikling","Databasedesign \u0026 datamodellering","Full stack‑produktudvikling","Produktstrategi \u0026 kravspecifikation"]},{"id":"https://advisory.engineer.company/da/portfolio/built-seven-read-only-host-reporting-roles-120/","url":"https://advisory.engineer.company/da/portfolio/built-seven-read-only-host-reporting-roles-120/","title":"Har bygget syv skrivebeskyttede rapporteringsroller, der gengiver en levende vært som Markdown — fakta, adgang, git, metrikker, trafik, sikkerhed og udbyderinventar — under en regel om, at intet tal printes, som kørslen ikke har målt.","summary":"Miljøet kan beskrives fra repositoryet på forlangende, og rapporterne har fundet virkelige ting: de to døde sikkerhedskontroller, en uerklæret lyttende port,…","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Værten havde intet dashboard og fik ikke et, for en metrikstak passer ikke på 464 MB og ville ikke have været sin pris værd, hvis den gjorde. Det efterlod et ærligt hul: der var ingen måde at besvare spørgsmål som hvem har adgang, hvor meget er dette repository vokset, hvordan ser trafikken ud, eller er hærdningen faktisk håndhævet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e De spørgsmål havde brug for svar, der kunne frembringes på forlangende, ikke kostede værten noget mens ingen spurgte, og aldrig kunne ændre det de beskrev.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Syv skrivebeskyttede roller, hver der gengiver en levende vært til Markdown i repositoryet. Et faktabillede der dækker styresystem, hardware, lagring, netværk, tjenester, pakker, lyttende sockets og processorudnyttelse beregnet ud fra to stikprøver af kernens egen tæller. En adgangsrapport der dækker konti, sudo‑omfang, nøglefingeraftryk, forge‑brugere og databaseroller. En git‑rapport per repository. En metrikrapport over dagens indsamlede stikprøver. En trafikrapport bygget på webserverens privatlivsmaskerede log. En udbyderoversigt på tværs af fire udbyderflader — DNS, to cloud‑API\u0026rsquo;er og et API til dedikerede servere. Og en sikkerhedsrapport der besvarer, om hærdningen er håndhævet frem for konfigureret, og udskriver firewallreglerne i matchrækkefølge og det levende blokeringsregelsæt. Den styrende regel på tværs af alle syv er, at intet tal udskrives, som kørslen ikke målte — en rapport der fylder et hul med et plausibelt tal, er værre end en der lader det stå tomt, for det er kun det plausible der bliver troet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Miljøet kan beskrives fra repositoryet på forlangende, og rapporterne har fundet virkelige ting: de to døde sikkerhedskontroller, en uerklæret lyttende port, og den iagttagelse at trafikarkivet kun er så gammelt som sidste gang nogen huskede at høste det. Den sidste er skrevet op som en begrænsning med en konkret pris noteret — seksten dages historik for ét site, der roterede væk mellem høstninger og ikke findes nogen steder.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Dokumentation","Infrastruktur","Linux \u0026 servere","Monitorering \u0026 observability","Stakeholder \u0026 rapportering","Site reliability \u0026 monitorering","Systemadministration","Teknisk dokumentation"]},{"id":"https://advisory.engineer.company/da/portfolio/wrote-a-scope-rule-after-a-credential-leak-124/","url":"https://advisory.engineer.company/da/portfolio/wrote-a-scope-rule-after-a-credential-leak-124/","title":"Har skrevet en scoperegel ind i kodebasen, efter at en omstrukturering bar en anden virksomheds inventar, firewalltilladelser og prosa med ind i den — og har holdt det karantæneramte restmateriale under hemmelighedsscanneren frem for at udelukke det.","summary":"Omfangsgrænsen er en skreven regel med en oplyst test, resterne er synlige frem for begravet, og den konkrete form for legitimationsoplysning der slap igennem,…","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Arbejde udført for en anden virksomhed kørte med gennem en omstrukturering af repositoryet og blev liggende. Det der fulgte med var ikke abstrakt: en kladdelog med levende legitimationsoplysninger i klartekst, som lå i træet forbi hver eneste vagtpost gennem det meste af repositoryets historie; en forældet inventarliste der navngav den virksomheds vært; og en firewall‑opgavefil der åbnede porte til seksten af dens kundenetværk. Intet af det kørte. Det er præcis derfor det overlevede — noget der ikke kører nogen steder, bliver aldrig gennemgået igen.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Grænsen skulle blive til en regel med en test knyttet til sig frem for en hensigt, og resterne skulle håndteres på en måde, der ikke blot skjulte dem.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Reglen er nu åbningsafsnittet i repositoryets instruktionssæt: dette repository håndterer én virksomheds infrastruktur og kun den, og en anden parts vært, inventarliste, firewalltilladelse, DNS‑zone eller legitimationsoplysning hører ikke hjemme i det — ikke engang deaktiveret, udkommenteret eller parkeret i en fil, ingen playbook importerer. Den praktiske test står ved siden af: ville denne virksomhed stadig være ansvarlig for dette, hvis forholdet ophørte. Resterne blev sat i karantæne i et tydeligt navngivet katalog frem for slettet, så historikken forbliver læselig, og karantænen er bevidst delvis — de to strukturelle linters springer den over, og hemmelighedsskanneren, boksvagten og emoji‑tjekket læser den bevidst stadig, for det er de tre, der ville fange det, der slap ind. Selve lækagen frembragte en linterregel: et brugerdefineret mønster der markerer en legitimationsoplysning sendt som et kommandolinjeflag, hvilket er den form den lækkede havde, og som standardregelsættet ikke matchede.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Omfangsgrænsen er en skreven regel med en oplyst test, resterne er synlige frem for begravet, og den konkrete form for legitimationsoplysning der slap igennem, fejler nu et commit. Læren noteret ved siden af er den generelle: det farlige artefakt er ikke det der kører, det er det der ikke gør, for det er det, ingen læser igen.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Data governance","Dokumentation","Infrastruktur","Sikkerhed","Data governance \u0026 datakvalitet","Sikkerhed \u0026 adgangsstyring","Teknisk dokumentation"]},{"id":"https://advisory.engineer.company/da/portfolio/built-a-22-linter-commit-gate-127/","url":"https://advisory.engineer.company/da/portfolio/built-a-22-linter-commit-gate-127/","title":"Har bygget en commit‑gate af 22 en‑linjes lintere plus fem, der fortjener et afsnit, uden et advarselsniveau og uden tilladte inline‑undertrykkelser, med dækning af HTML, CSS, JavaScript, Python, YAML, Markdown, shell, links, stavning, hemmeligheder og typografi.","summary":"Mekaniske indvendinger fremsættes af en maskine, før et commit findes, og gaten er den eneste anmelder dette projekt har.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e En bidragsvejledning er et sæt forslag. Alle er enige i den, og så er det fredag, ændringen er lille, og vejledningen taber. På et enmandsprojekt er det værre frem for bedre, for der er slet ingen anmelder — det eneste mellem en dårlig ændring og produktion er den person der skrev den, i det øjeblik hvor de er mindst tilbøjelige til at skændes med sig selv.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Standarderne skulle være eksekverbare, så at bryde en fejler et commit frem for at vente på at blive bemærket.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Det der voksede frem er en gate på 22 linters uden advarselsniveau: hver diagnostik er en fejl, og sitegeneratoren selv kører med advarsler forfremmet til fejl, så selv en udfasning standser bygningen. De oplagte er der — HTML‑validering, CSS, JavaScript, Python, YAML, Markdown, shell, stavning, hemmeligheder, døde links. De interessante er de projektspecifikke tjek, som intet standardværktøj har en holdning til: at begge farvetemaer maler hver lagdelt flade med det samme antal lag, at intet fotografi vises bredere end halvdelen af sine kildepixels, at det udrullede træ ikke indeholder nogen privat sti eller værtsnavn, at teksten adlyder toneregelsættet på alle tre sprog, at en side har en Markdown‑tvilling og en gyldig repræsentation i et alternativt protokolformat. Inline‑undertrykkelser er direkte forbudt — ingen ignorér‑kommentar, intet deaktiveringsdirektiv, ingen omgåelse af hooket og ingen omdøbning af en fil for at undvige en matcher. Reglen der holder det ærligt er, at en allerede eksisterende fejl ikke er en undskyldning: et tjek der bringer en defekt frem, som ingen indførte, bliver rettet i samme omgang.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Mekaniske indvendinger fremsættes af en maskine, før et commit findes, og gaten er den eneste anmelder dette projekt har. Prisen er oplyst frem for skjult: det er langsomt at committe, og en dårligt skrevet vagtpost er oprigtigt irriterende at arbejde uden om, hvilket er grunden til at vagtposterne selv senere kom under en formatter og en linter af deres egen.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Dokumentation","Frontend‑udvikling","Python","Test \u0026 QA","DevOps \u0026 CI/CD‑automatisering","Produktstrategi \u0026 kravspecifikation","Teknisk dokumentation"]},{"id":"https://advisory.engineer.company/da/portfolio/cut-the-visual-quality-gate-to-ten-minutes-128/","url":"https://advisory.engineer.company/da/portfolio/cut-the-visual-quality-gate-to-ten-minutes-128/","title":"Har skåret sitets browserdrevne kvalitetsgate fra 1.636 sekunder til 615 ved at planlægge dens tjek længst‑først gennem en worker‑pulje begrænset til fire baner, efter at have målt at alfabetisk rækkefølge kostede 320 sekunder mod 224.","summary":"Gaten gik fra 1.636 sekunder til 615, mens tjekkene blev bredere frem for tyndere — den serielle omkostning steg, og den samlede tid faldt.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Elleve af sitets tjek driver en browser uden grænseflade: layout ved hver vinduesform designet tegner, typeskala, udvidelse af oversat tekst, kontrast, tilgængelighedsregler, tvungne farver, maskotstørrelse, bevægelse, print på tværs af seks papirkombinationer, konsolfejl og visuel regression. Kørt én ad gangen tog de 1.636 sekunder, lidt over syvogtyve minutter. En gate der tager syvogtyve minutter er en gate der bliver sprunget over, og et oversprunget tjek kan ikke skelnes fra et der består.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Den samlede tid skulle ned langt nok til, at det at køre dem var standarden frem for en beslutning, uden at svække nogen af dem.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Arbejdet var måling først. Hvert tjek blev tidsmålt enkeltvis på en maskine med tolv kerner: layout på 405 sekunder, type på 301, oversættelse på 282, kontrast på 189, tilgængelighed på 178, og så videre ned til sytten. To fund formede svaret. At køre dem alle på én gang var langsommere end at køre fire ad gangen — 265 sekunder mod 224 — for hvert tjek er selv en browser der arbejder parallelt, og at overbelaste maskinen koster mere, end samtidigheden vinder. Og at ordne efter længste behandlingstid først slog alfabetisk rækkefølge med næsten en tredjedel, 224 sekunder mod 320, hvilket er det klassiske planlægningsresultat og viser sig her, fordi tjekkene varierer med en faktor tyve i omkostning. Så kørslen er en afgrænset arbejderpulje, dimensioneret ud fra kerneantallet med et gulv på to og et loft på fire, fodret med det længste først. Ved siden af den blev tjekkene udvidet frem for indsnævret: de deler nu én viewport‑tabel med toogtyve vinduesformer, udledt af hver medieforespørgsel stylesheetet faktisk indeholder, hvilket tog layouttjekket alene fra 95 sekunder til 405.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Gaten gik fra 1.636 sekunder til 615, mens tjekkene blev bredere frem for tyndere — den serielle omkostning steg, og den samlede tid faldt. Målingen er den del der er værd at beholde: to fornuftigt lydende valg, at køre alt på én gang og at køre tingene i den rækkefølge de blev skrevet, var hver især målbart dårligere end alternativet.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Frontend‑udvikling","Performanceoptimering","Python","Test \u0026 QA","DevOps \u0026 CI/CD‑automatisering","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/ran-development-as-49-written-initiatives-141/","url":"https://advisory.engineer.company/da/portfolio/ran-development-as-49-written-initiatives-141/","title":"Har kørt sitets udvikling som 51 skrevne initiativer fordelt på 54 plandokumenter, hver med sine åbne felter, sine målinger og de beslutninger, den afviste — herunder seks af otte fund om agentparathed afvist med begrundelsen noteret.","summary":"Enoghalvtreds beslutninger med deres begrundelse vedhæftet, omtrent tre fjerdedele lukket, og de afviste er lige så fremfindelige som de accepterede.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Et enmandsfirma har intet planlægningsmøde, ingen backlog‑gennemgang og ingen til at være uenig i en beslutning. Hvad det har i stedet er en stærk tilbøjelighed til at lave det arbejde der lige nu er interessant, og ingen optegnelse bagefter over hvorfor noget blev valgt — hvilket bliver et problem første gang en beslutning skal genovervejes eller forsvares.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Sitets udvikling havde brug for en skreven optegnelse per initiativ, der overlever at blive genlæst måneder senere, og som dækker dem der blev afvist såvel som dem der blev bygget.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Enoghalvtreds initiativer fordelt på fireoghalvtreds nummererede og indekserede plandokumenter, hver med problemet, de foretagne målinger, beslutningen og dens åbne felter. De er ikke sammendrag skrevet bagefter. De rummer de tal der afgjorde argumentet — planlægningsmålingerne der formede tjekkøreren, billedformatet der blev testet og afvist fordi det kom ud større, prisstigen bekræftet af ejeren, auditen der fandt sitet bevise formåen på tværs af 371 sider uden at oplyse nogen pris, nogen samarbejdsform eller noget minimum nogen steder. Afviste fund får den samme behandling som accepterede: en gennemgang af agentparathed frembragte otte fund, og seks blev afvist, hver med dommen noteret, netop så et senere automatiseret forslag ikke tavst kan omgøre en skreven beslutning. Statustavlen læser en plans afkrydsningsfelter frem for dens tekst, for tekst siger \u0026ldquo;færdig\u0026rdquo; og felter siger hvad der er åbent. Den skelnen var ikke teoretisk — en dokumentationslinter fandt senere seks planer markeret som færdige, mens de bar uafkrydsede felter.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Enoghalvtreds beslutninger med deres begrundelse vedhæftet, omtrent tre fjerdedele lukket, og de afviste er lige så fremfindelige som de accepterede. Hvad det koster er, at hvert initiativ har en opskrivning, hvilket er en reel skat på småt arbejde og lejlighedsvis har betydet, at optegnelsen er længere end den ændring den beskriver.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Agile \u0026 Scrum","Dokumentation","Produkt \u0026 krav","Projektledelse","Stakeholder \u0026 rapportering","Teknisk ledelse","Produktstrategi \u0026 kravspecifikation","Projektledelse (Agile)","Teknisk dokumentation","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/put-the-documentation-under-its-own-linter-142/","url":"https://advisory.engineer.company/da/portfolio/put-the-documentation-under-its-own-linter-142/","title":"Har sat dokumentationen under sin egen linter — et linjebudget pr. fil, der kun skruer nedad, et indekskrav og et tjek af faktiske stier — som fandt seks af ni planer markeret som færdige, mens de bar uafkrydsede felter, og fjorten opgaver, der spærrede hver commit uden at være nævnt i noget dokument.","summary":"Seksogtyve dokumenter på i alt omkring 2.666 effektive linjer, hvert under et budget der ikke kan vokse, med hver sti og hvert symbol de navngiver tjekket mod…","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Repositoryet styrer sig selv med skrevne instruktioner — seksogtyve dokumenter der dækker kvalitetspolitikken, designsystemet, tilgængelighed, print, metadata, oversættelse og git. Instruktioner har et bestemt forfaldsmønster: de bliver længere, de driver væk fra koden, de begynder at henvise til filer der er flyttet, og ved en vis størrelse holder de op med at blive læst. En ulæst regel er ikke en regel.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Dokumentationen havde brug for den samme behandling som koden — en linter med grænser der fejler frem for at råde.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Otte politikker, hver mekanisk. Et hårdt loft over dokumentlængde og et blødere der advarer. Et linjebudget per fil, der kun nogensinde skruer nedad, så et dokument kan skrumpe og ikke vokse tilbage. Et indekskrav over en tærskel og et afsnitsindeks over en mindre. En placeringsregel om hvilket dokument der ejer hvilket emne. Linkgyldighed. Planærlighed — den status en plan påstår, skal svare til dens egne afkrydsningsfelter. En regel om at hver opgave der spærrer et commit, er navngivet i et eller andet dokument. Og et tjek af virkelige stier, at hver katalogkvalificeret sti og hvert kodesymbol et dokument navngiver, faktisk findes. Den første kørsel var argumentet for hele øvelsen: seks planer markeret som færdige, mens de bar uafkrydsede felter, fjorten opgaver der spærrede hvert commit og var navngivet i intet dokument overhovedet, tre brudte links, ét forældreløst dokument og tre døde stier fordelt på fem dokumenter. Budgettet afviste derefter sin egen forfatter — at skrive sammendraget af dette arbejde ind i udviklingsdokumentet skubbede det over grænsen, hvilket er sådan et særskilt dokument opstod, hvilket er politikken der virker præcis efter hensigten.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Seksogtyve dokumenter på i alt omkring 2.666 effektive linjer, hvert under et budget der ikke kan vokse, med hver sti og hvert symbol de navngiver tjekket mod træet. Det ubehagelige fund er det der er værd at gentage: fjorten tjek spærrede hvert eneste commit, mens de optrådte i intet dokument, så de regler maskinen håndhævede, og de regler menneskene læste, var allerede kommet fra hinanden.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Dokumentation","Projektledelse","Python","Teknisk ledelse","Test \u0026 QA","Projektledelse (Agile)","Teknisk dokumentation","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/brought-the-quality-gate-code-under-a-linter-143/","url":"https://advisory.engineer.company/da/portfolio/brought-the-quality-gate-code-under-a-linter-143/","title":"Har bragt 10.242 linjer kvalitetsgate‑JavaScript under en formatter og en linter efter at have fastslået, at det var kodebasens største kodemængde og den eneste, intet læste, og har rettet 13 fund uden at undertrykke nogen.","summary":"Den største og mest bærende kode i repositoryet er nu formateret, lintet og typetjekket, med tretten fund rettet og nul undertrykkelser.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Sitets kvalitetsgate er toogtredive scripts på i alt 10.242 linjer JavaScript. Den var med god margin den største kodemængde i repositoryet, og den var den eneste kodemængde, intet læste — ingen formatter, ingen linter, ingen typetjek. De programmer der håndhævede hver regel i projektet, var de eneste programmer, der var underlagt ingen af dem.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Tjekkerne skulle holdes til den standard, de findes for at håndhæve, og formatteren skulle tilpasses dem frem for omvendt.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Formatteren kom først, og indrykningsbredden var den interessante beslutning. Repositoryets standard er fire mellemrum; ved fire mellemrum ville formatteren have omskrevet 2.173 linjer af den største tjekker. En overstyring til to mellemrum for de filer reducerede det til 38 linjers ægte drift. Princippet noteret sammen med den er, at formatteren tilpasses koden, ikke koden formatteren — at omformatere to tusind linjer for at tilfredsstille en præference ødelægger evnen til at læse filens historik. Derefter linteren, som frembragte tretten reelle fund, alle rettet og ingen undertrykt. Python‑tjekkerne fik den samme behandling gennem et typetjek konfigureret på et mellemniveau af stringens med tredive enkeltstående regler fra det strengeste niveau slået til ovenpå, valgt ved måling: ved den indstilling er træet tavst, og af de tredive kandidater var niogtyve allerede tavse, og én udløste — og den blev rettet frem for undtaget. Typetjekket fandt to reelle defekter, som linteren havde ladet bestå rent, begge om en værdis form frem for dens syntaks.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Den største og mest bærende kode i repositoryet er nu formateret, lintet og typetjekket, med tretten fund rettet og nul undertrykkelser. Grunden til at det betyder mere, end linjeantallet antyder, står i planen: en defekt i sitets stylesheet viser sig som en side der ser forkert ud, og en defekt i en tjekker viser sig som et tjek der består, når det ikke burde.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Dokumentation","Frontend‑udvikling","Python","Test \u0026 QA","DevOps \u0026 CI/CD‑automatisering","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/held-the-generator-to-964-tests-and-a-coverage-floor-145/","url":"https://advisory.engineer.company/da/portfolio/held-the-generator-to-964-tests-and-a-coverage-floor-145/","title":"Har holdt generatoren til 981 testtilfælde med et dækningsgulv på 92 % grendækning og advarsler behandlet som fejl, og har hævdet idempotens ved at køre hele build‑pipelinen to gange fra en tom fil og kræve, at anden gennemløb intet ændrer.","summary":"Pipelinen kan køres igen mod en levende database uden frygt, hvilket er det der overhovedet gør trinvist indholdsarbejde muligt.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e En generator der samler en database fra bunden, har en særlig slags fejl: den virker første gang og korrumperer anden gang. Trin der indsætter uden at tjekke, trin der afhænger af rækkefølgen i et tidligere trins output, trin der er sikre alene og ikke sammen. Intet af det viser sig i en test, der starter fra ingenting og kører én gang.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Bygningen skulle bevises gentagelig frem for blot fungerende, og testsuiten skulle være stor nok og streng nok til, at en regression ikke kunne slippe tavst igennem den.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Idempotenstesten er den stumpe og den mest nyttige: byg hele databasen fra en tom fil, tag et øjebliksbillede, kør hele pipelinen i nitten trin igen over resultatet, og kræv at anden gennemløb ikke ændrer noget. Rækketal, indhold og identifikatorer skal alle stemme. Omkring den ligger 383 testfunktioner — 981 tilfælde når de parametriserede folder sig ud — fordelt på femogfyrre filer og 7.944 linjer, der dækker pipelinen, gengiverne, indholdsindlæserne, målretningslogikken og tjekkerne. Grendækning bærer et gulv på tooghalvfems procent håndhævet i bygningen frem for rapporteret i et sammendrag, og suiten måler i øjeblikket omkring 95 procent, så gulvet har luft uden at være dekorativt. Advarsler er konfigureret som fejl, hvilket er den indstilling der betyder mest i praksis — en udfasningsmeddelelse der udskrives i to år, er en udfasningsmeddelelse ingen læser, og den kørsel der forvandler den til en rød test, er den kørsel der får den rettet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Pipelinen kan køres igen mod en levende database uden frygt, hvilket er det der overhovedet gør trinvist indholdsarbejde muligt. Gulvet er et gulv, ikke et mål, og det er værd at sige, at tooghalvfems procent grendækning stadig efterlader grene, intet nogensinde har taget — tallet afgrænser risikoen, det fjerner den ikke, og to af de defekter der senere blev fundet i projektet, lå i kode, dækningsrapporten viste som dækket.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Databaser","DevOps","Drift \u0026 backup","Python","Test \u0026 QA","Backend- \u0026 API‑udvikling","DevOps \u0026 CI/CD‑automatisering","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/established-pdf-ua-1-conformance-across-nine-documents-146/","url":"https://advisory.engineer.company/da/portfolio/established-pdf-ua-1-conformance-across-nine-documents-146/","title":"Har etableret PDF/UA‑1‑konformitet på tværs af ni dokumenter ved 106 af 106 regler og har fundet arkivvarianten fejle én regel ud af 146 — et nærved‑resultat, der læses som bestået af enhver, der ikke kører validatoren.","summary":"Tilgængelighedsoverholdelse er bevist med fuldt hus, og arkivpåstanden er oplyst ærligt som en nærved-fejl med det konkrete hul navngivet.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e En PDF der ser rigtig ud på skærmen, fortæller intet om, hvorvidt en skærmlæser kan læse den, om dens overskrifter danner en struktur, om dens sprog er erklæret, eller om den stadig kan åbnes om tyve år. Tilgængelig PDF og arkiv‑PDF er begge maskintjekbare standarder, og et dokument der aldrig er kørt gennem validatoren, er et dokument der fremsætter en uverificeret påstand.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e De genererede dokumenter skulle måles mod begge standarder, med resultatet noteret som et tal frem for som en hensigt.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Ni dokumenter — CV\u0026rsquo;et i sine varianter, referencearket, porteføljen og ansøgningen, på tværs af sprog — blev kørt gennem en uafhængig validator for tilgængelighedsprofilen og arkivprofilen hver for sig. Tilgængelighedsprofilen består med 106 af 106 regler, hvilket krævede tagget struktur, erklæret dokumentsprog, alternativ tekst på hver ikke‑dekorativ grafik, en rigtig titel i metadataene og en eksplicit læserækkefølge frem for den, layoutet tilfældigvis frembringer. Arkivprofilen er det mere interessante resultat: den fejler præcis én regel af 146. Det er den slags resultat, der er let at fejlrapportere. Hundrede og femogfyrre beståede læser som overholdelse i et sammendrag, og det er ikke overholdelse; det er et dokument der vil blive afvist af et system, der håndhæver standarden. Den fejlende regel er noteret med hvad den er, og hvorfor den ikke er lukket, frem for rundet væk.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Tilgængelighedsoverholdelse er bevist med fuldt hus, og arkivpåstanden er oplyst ærligt som en nærved‑fejl med det konkrete hul navngivet. Den grænse der er værd at være direkte om, er at begge tal kommer fra én validator; en anden implementering kan være uenig, og en regel der består, er kun bevis for, at denne tjekker intet havde at sige om den.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Dokumentation","Python","Test \u0026 QA","UX/UI‑design","Webudvikling","Teknisk dokumentation","UI/UX‑design \u0026 designsystemer","Webstedsudvikling \u0026 CMS"]},{"id":"https://advisory.engineer.company/da/portfolio/enabled-every-python-linter-rule-as-an-error-147/","url":"https://advisory.engineer.company/da/portfolio/enabled-every-python-linter-rule-as-an-error-147/","title":"Har valgt hver eneste regel, Python‑linteren har, som fejl og har arbejdet 1.815 fund ned til nul, hvor hver af de få undtagelser bærer en skreven begrundelse og to af dem er understøttet af et tjek frem for en kommentar.","summary":"Linteren kører ved fuld styrke med nul fund, og hver afvigelse er dokumenteret på den linje, hvor den tages.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e De fleste projekter vælger en behagelig delmængde af deres linters regler, og delmængden vælges af hvilke regler der var tavse den dag, den blev konfigureret. Det gør konfigurationen til en optegnelse over kodens eksisterende vaner frem for en standard koden holdes til, og hver regel der er slået fra, er en defektklasse, ingen nogensinde får besked om.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Standarden skulle vendes om — hver regel værktøjet implementerer slået til som en fejl — og den resulterende efterslæb arbejdes ned til nul frem for forhandlet ned ved at slå regler fra igen.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e At vælge det komplette regelsæt frembragte 1.815 fund ved første kørsel. De blev arbejdet igennem efter kategori frem for efter fil, for kategorierne fortæller noget: ubrugte argumenter og skyggede indbyggede navne er støj, men sikkerhedskategorien, kategorien for foranderlige standardværdier og kategorien for undtagelseshåndtering pegede hver især på reel adfærd. Der findes ægte uforeneligheder — en formatter og en linter kan være uenige om den samme linje, og nogle få regler modsiger projektets egne bevidste valg — og hver af det lille antal undtagelser bærer en skreven begrundelse dér hvor undtagelsen tages, som siger hvad reglen ville, og hvorfor denne kode gør noget andet. To af dem går videre og er understøttet af et tjek frem for en kommentar, så undtagelsen ikke tavst kan udvide sig: reglen er slået fra, og en test efterprøver netop den egenskab, reglen ville have håndhævet. Typetjek kører i streng tilstand ved siden af, hvilket er en særskilt og hårdere standard, og det er den, der fangede defekter, linteren ikke kunne se, fordi de handler om hvad en værdi er frem for hvordan den er skrevet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Linteren kører ved fuld styrke med nul fund, og hver afvigelse er dokumenteret på den linje, hvor den tages. Prisen er reel og værd at nævne: den strengeste indstilling frembringer fund, der oprigtigt ikke er værd at handle på, og nogen skal træffe den vurdering 1.815 gange frem for én gang.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Dokumentation","Python","Test \u0026 QA","Backend- \u0026 API‑udvikling","DevOps \u0026 CI/CD‑automatisering","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/wrote-tests-for-the-checkers-themselves-149/","url":"https://advisory.engineer.company/da/portfolio/wrote-tests-for-the-checkers-themselves-149/","title":"Har skrevet tests af selve tjekkene efter at have fastslået, at et tjek, der kun fodres med rent input, en dag melder rent, fordi det intet læste — ved at plante en stavefejl for at bekræfte, at stavekontrollen finder den, og ved at tage et id‑interval fra databasen frem for fra et tal i testen.","summary":"Hvert tjek i projektet har nu en test, der beviser, at det fejler på dårlige inddata, og områdeforventningerne læses fra sandhedskilden.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Projektet kører en række egne tjek over sit eget indhold — en stavekontrol, et tjek af identifikatorernes talområde, et stemmetjek, et tjek af taloverensstemmelse. Hvert af dem havde kørt grønt i månedsvis. Et tjek, der kun nogensinde har set rene inddata og kun nogensinde har meldt rent, kan ikke skelnes fra et tjek, der slet intet læser, og der fandtes ingen test i suiten, som kunne kende forskel på de to.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Tjekkene skulle bringes til at bevise, at de kan fejle, og de fikstursdata, de tjekker imod, skulle holde op med at være håndholdte kopier af det, de beskriver.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Mønsteret, der er anvendt hele vejen igennem, er at plante netop den defekt, tjekket findes for at fange, og kræve at tjekket finder den. Stavekontrollen fodres med et bevidst fejlstavet ord, og testen fejler, hvis kørslen kommer rent tilbage. Stemmetjekket fodres med prosa i første person og skal afvise den. Buzzword‑tjekket fodres med et forbudt ord. Hvert af disse er en lille test, og hver af dem lukkede en reel blind vinkel, for to af tjekkene viste sig at læse et snævrere sæt filer end deres dokumentation påstod og havde tavst sprunget indhold over. Den anden ændring handler om, hvor en test henter sine forventninger: tjekket af identifikatorernes talområde sammenlignede før med et tal skrevet i testfilen, hvilket betød, at enhver tilføjelse af indhold krævede en redigering af en test, og en redaktør, der opdaterede tallet uden at se efter, havde slået tjekket fra. Det udleder nu området fra databasen, så tjekket beskriver dataene frem for en forældet erindring om dem.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Hvert tjek i projektet har nu en test, der beviser, at det fejler på dårlige inddata, og områdeforventningerne læses fra sandhedskilden. Det ubehagelige er, hvad dette blotlagde: et grønt tjek havde været meningsløst mindst to steder i et ukendt tidsrum, og der er ingen måde at finde ud af med tilbagevirkende kraft, hvad der slap igennem.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Data governance","Databaser","Python","Test \u0026 QA","Data governance \u0026 datakvalitet","DevOps \u0026 CI/CD‑automatisering","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/found-the-commit-hooks-and-the-gate-disagreeing-150/","url":"https://advisory.engineer.company/da/portfolio/found-the-commit-hooks-and-the-gate-disagreeing-150/","title":"Har fundet commit‑hooks og kvalitetsgaten køre forskellige tjek, mens et dokument lovede, at de var de samme, ved at sammenligne de to lister i en test — de fem, der kun nogensinde kørte i hånden, var dem, der læste CV‑prosaen.","summary":"Hooken og porten kører beviseligt de samme tjek, og prosatjekkene kører nu ved hver commit. Afvejningen er commit-hookens køretid, som voksede og vil blive ved…","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Projektet havde en commit‑hook, der kører tjek, før en commit accepteres, og en fuld kvalitetsport kørt efter behov. Et dokument angav, at hooken kører porten, så intet kunne nå historikken uden at bestå alt. Begge lister blev vedligeholdt i hånden, i to forskellige filer, og intet sammenlignede dem.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Påstanden skulle gøres til en efterprøvning, hvilket betød at opregne begge mængder programmatisk og fejle, når de afviger.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Testen læser hook‑konfigurationen og portens opgavedefinitioner, opløser hver af dem til den mængde tjek, den faktisk kalder, og sammenligner. De stemte ikke. Fem tjek fandtes kun i porten og kørte aldrig ved commit, og de fem var ikke tilfældige — det var dem, der læser selve CV\u0026rsquo;ets prosa: stemmetjekket, der holder anmeldelser upersonlige, buzzword‑tjekket, tjekket af taloverensstemmelse på tværs af sprog, notationstjekket og stavekontrollen over indhold. Med andre ord kørte hvert tjek, der beskytter kode, automatisk, og hvert tjek, der beskytter skriften, kørte kun, når nogen huskede det. Da skriften er hele produktet, var udsattheden vendt om i forhold til, hvor nogen ville have gættet. Rettelsen var at bringe de fem ind i hooken, hvilket krævede at gøre to af dem hurtige nok til at overleve et budget før commit, og derefter at holde sammenligningstesten på plads, så de to lister ikke kan glide fra hinanden igen. Dokumentet, der havde beskrevet en hensigt, beskriver nu noget håndhævet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Hooken og porten kører beviseligt de samme tjek, og prosatjekkene kører nu ved hver commit. Afvejningen er commit‑hookens køretid, som voksede og vil blive ved med at vokse, efterhånden som indholdet vokser, og der findes et punkt, hvor en langsom hook bliver omgået — så denne rettelse har en holdbarhed målt i, hvor længe tjekkene forbliver hurtige.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Dokumentation","Python","Test \u0026 QA","DevOps \u0026 CI/CD‑automatisering","Teknisk dokumentation","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/built-a-cross-language-figure-and-notation-check-153/","url":"https://advisory.engineer.company/da/portfolio/built-a-cross-language-figure-and-notation-check-153/","title":"Har bygget et tværsprogligt indholdstjek, der fejler, når en oversættelse taber et tal, det engelske angiver, og når et sprog bruger notation, det ikke bruger — og har fundet to danske beskrivelser, der manglede en metrik, og seksten ukrainske spænd, der citerede på engelsk vis.","summary":"Atten reelle defekter lukket og klassen lukket med dem, da hver fremtidig oversættelse sammenlignes med sin engelske kilde, før den kan committes.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Den mest skadelige slags oversættelsesfejl i et CV er ikke en kejtet vending. Det er et tal, der forsvinder. En engelsk sætning, der hævder en halvtredsindstyvedobbelt forbedring, oversat til en sætning, der siger \u0026ldquo;betydeligt\u0026rdquo;, er en påstand stille trukket tilbage på ét marked og fastholdt på et andet — og ingen stavekontrol, grammatikkontrol eller menneskelig læsning af målsproget alene vil nogensinde bemærke det, for den oversatte sætning er fuldkommen god prosa.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Der var brug for et tjek, som læser sprogene mod hinanden frem for hvert enkelt for sig, på de to ting, der skal overleve oversættelse: tallene og den notation, hvert sprog bruger til at skrive dem.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Taltjekket udtrækker hvert tal, hver procentdel, hver multiplikator og hver enhed fra den engelske streng og kræver, at hver af dem optræder i hver oversættelse af den streng, med multiplikatorformerne kortlagt pr. sprog frem for matchet ordret — den engelske halvtredsindstyve‑gange‑form svarer til en bestemt dansk vending og en bestemt ukrainsk vending, og tjekket kender kortlægningen frem for at kræve cifrene alene. Notationstjekket er spejlbilledet af det: hvert sprog har konventioner, det skal bruge, og konventioner, det ikke må bruge, herunder decimalskilletegn, tusindgruppering og anførselstegn. Ukrainsk bruger vinkelanførselstegn; engelske dobbelte anførselstegn i en ukrainsk sætning er lige så forkerte som et manglende tal og langt lettere at indføre ved kopiering. Den første fulde kørsel fandt to danske beskrivelser, hvor et måltal til stede på engelsk var faldet ud, og seksten ukrainske spænd med anførsel i engelsk stil.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Atten reelle defekter lukket og klassen lukket med dem, da hver fremtidig oversættelse sammenlignes med sin engelske kilde, før den kan committes. Hvad tjekket ikke kan, er at bedømme mening: det beviser, at tallet overlevede, og at tegnsætningen er hjemmevant, og en oversættelse, der bevarer hvert tal, mens den vender påstanden om, består det uden videre.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","Data governance","Dokumentation","Internationalisering","Python","Test \u0026 QA","Data governance \u0026 datakvalitet","Internationalisering \u0026 lokalisering","Teknisk dokumentation"]},{"id":"https://advisory.engineer.company/da/portfolio/adopted-swift-6-strict-concurrency-over-a-c-event-loop-156/","url":"https://advisory.engineer.company/da/portfolio/adopted-swift-6-strict-concurrency-over-a-c-event-loop-156/","title":"Har taget Swift 6 fuldstændig streng samtidighed i brug uden aktører og har bygget bro fra en blokerende C‑hændelsesløkke til hovedaktøren gennem én producent, én forbruger og én rækkefølge — efter at have fastslået, at en opgave pr. hændelse mister den rækkefølge, grænsefladen afhænger af.","summary":"Programmet oversættes under fuldstændigt strengt samtidighedstjek uden undertrykkelser, og hændelsesrækkefølgen er en strukturel egenskab frem for et håb.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Swift 6\u0026rsquo;s fuldstændige strenge samtidighedstjek gør datakapløb til oversættelsesfejl i stedet for lejlighedsvise nedbrud. At indføre det over for et C‑bibliotek er der, hvor det bliver svært: kernens hændelsesløkke er et blokerende kald, der skal køre uden for hovedtråden for altid, og de værdier, den leverer tilbage, er pegepinde uden nogen som helst samtidighedsgarantier. Oversætteren kan ikke ræsonnere om noget af det og vil afvise alt, indtil grænsen er beskrevet udtrykkeligt.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Fuldstændigt tjek skulle slås til uden nogen nødudgange, hvilket betød at udforme overgangen fra en blokerende C‑løkke til hovedaktøren frem for at sætte påtegninger uden om den.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Den nærliggende fremgangsmåde er en aktør pr. delsystem, og den blev forkastet på måling frem for smag. At starte en opgave pr. indkommende hændelse lader køretiden planlægge dem i vilkårlig rækkefølge, og kernens hændelsesstrøm er ordnet — en besked‑ændret‑hændelse, der overhaler den besked‑oprettet‑hændelse, den henviser til, frembringer en grænseflade, der viser en redigering af noget, der endnu ikke findes. Aktørers genindtræden gør dette værre, ikke bedre, for en aktør kan afbryde midt i en metode og behandle et andet kald. Det, der erstattede den, er bevidst enkelt: én producenttråd, der ejer den blokerende løkke, én forbruger, én kø imellem dem og et enkelt hop over på hovedaktøren til sidst. Rækkefølgen bevares, fordi der er præcis én vej, og intet overhaler noget. De usikre typer, der krydser den grænse, er pakket ind i typer, hvis trådsikkerhed efterprøves ved indpakningen frem for antages, og efterprøvningen er dokumenteret med hvorfor den holder — pegepinden ejes af én tråd og kopieres, før den overdrages.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Programmet oversættes under fuldstændigt strengt samtidighedstjek uden undertrykkelser, og hændelsesrækkefølgen er en strukturel egenskab frem for et håb. Prisen er, at udformningen er mindre parallel, end den kunne være: alt ledes gennem én forbruger, og hvis den forbruger nogensinde bliver en flaskehals, vil rettelsen kræve, at man på ny udleder, hvilke hændelser der trygt kan omordnes, hvilket er præcis den analyse, dette undgik.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Backend‑udvikling","Drift \u0026 backup","Frontend‑udvikling","Løsningsarkitektur","Performanceoptimering","Test \u0026 QA","Backend- \u0026 API‑udvikling","Platform- \u0026 løsningsarkitektur","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/wrote-a-parser-that-verifies-every-ffi-call-site-157/","url":"https://advisory.engineer.company/da/portfolio/wrote-a-parser-that-verifies-every-ffi-call-site-157/","title":"Har skrevet en parser, der læser den rigtige C‑header på 7.308 linjer og verificerer hvert kaldssted, hver enum‑konstant og at hver pegerejende klasse er final, efter at en håndskrevet pladsholder‑header lod kald til tre fjernede funktioner kompilere, linke og crashe.","summary":"Den defektklasse, der frembragte det oprindelige nedbrud, kan ikke gentage sig, for en forældet henvisning er nu en bygningsfejl frem for en kørselsfejl.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Tidligt i projektet blev C‑grænsefladen repræsenteret af en håndskrevet header, der beskrev de funktioner, programmet forventede. Den header oversatte, programmet blev sammenkædet, og kald til tre funktioner, der ikke længere fandtes i kernen, nåede frem til at blive kaldt og brød ned. Både oversætteren og sammenkæderen var blevet tilfredsstillet af en beskrivelse af biblioteket frem for af biblioteket, og kløften viste sig først ved kørsel.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Den rigtige header — 7.308 linjer og 268 erklæringer — skulle blive myndigheden, og hver anvendelse af den i Swift‑koden skulle efterprøves mod den automatisk frem for ved gennemgang.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Tjekket er en parser, der læser den faktiske opstrøms‑header og opbygger mængden af funktioner, enum‑konstanter og typer, den erklærer, og derefter læser Swift‑kildekoden og opløser hvert kaldested og hver konstanthenvisning mod den mængde. Et kald til en funktion, headeren ikke erklærer, fejler bygningen. En henvisning til en enum‑konstant, der er blevet omdøbt, fejler bygningen. Det nuværende tal er 132 af de 268 erklæringer henvist til, og at vide hvilke 136 der er ubrugte, er i sig selv nyttigt, for det siger præcis, hvor meget af kernen klienten ikke har nået. Parseren håndhæver også en regel, oversætteren ikke kan: hver Swift‑klasse, der ejer en pegepind ind i kernen, skal være endelig. En ikke‑endelig klasse, der ejer en pegepind, kan nedarves, og en underklasse, der tilsidesætter deinitialisering eller tilføjer sin egen levetid, ændrer, hvornår pegepinden frigives — en brug efter frigivelse uden noget usikkert nøgleord i nærheden. Reglen tjekkes ved navn på tværs af hele træet.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Den defektklasse, der frembragte det oprindelige nedbrud, kan ikke gentage sig, for en forældet henvisning er nu en bygningsfejl frem for en kørselsfejl. Begrænsningen er, at parseren forstår headerens erklæringer og ikke dens betydning: den beviser, at en funktion findes med et matchende navn, og en funktion, hvis betydning eller ejerskabsregel ændrede sig opstrøms, mens signaturen blev bevaret, slipper igennem uden bemærkning.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["API'er \u0026 integration","Automatisering \u0026 CI/CD","Backend‑udvikling","Dokumentation","Sikkerhed","Test \u0026 QA","Backend- \u0026 API‑udvikling","DevOps \u0026 CI/CD‑automatisering","Teknisk dokumentation"]},{"id":"https://advisory.engineer.company/da/portfolio/took-the-test-suite-under-nine-seconds-158/","url":"https://advisory.engineer.company/da/portfolio/took-the-test-suite-under-nine-seconds-158/","title":"Har taget testsuiten fra seks tests over en grænse på tres sekunder til 135 beståede på 8,9 sekunder ved at profilere hovedtråden og fjerne de to kald, den sad inde i i 3.989 ud af 4.017 stikprøver.","summary":"Suiten gik fra seks test over tres sekunder — 74 sekunders vægur — til 135 test bestået på 8,9, hvilket bringer den inden for det vindue, hvor den kører ved…","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Testsuiten havde en tidsgrænse på tres sekunder, og seks test lå over den. En testsuite, der tager over et minut, holder op med at blive kørt før hver ændring, og en suite, der ikke køres før hver ændring, er en rapport om fortiden. Instinktet i den situation er at hæve grænsen, og at hæve grænsen er, hvordan en suite når ti minutter.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Tiden skulle findes frem for budgetteres til, hvilket betød at profilere suiten i stedet for at ræsonnere om, hvilke test der så dyre ud.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Profilen blev taget på hovedtråden, mens suiten kørte, og resultatet modsagde gættet. Hovedtråden sad inde i to kald i 3.989 stikprøver ud af 4.017 — så de langsomme test var ikke dem, der udførte mest arbejde, og næsten hver eneste test kom gennem de samme to steder. Det første var en fast ventetid brugt til at lade asynkront arbejde falde til ro før efterprøvning — reelt en søvn, betalt af hver test, der rørte hændelsesvejen, uanset om arbejdet allerede var færdigt. Den blev erstattet af at vente på den faktiske betingelse med en tidsfrist, så en test, der er klar på fem millisekunder, tager fem millisekunder, og kun en test, der reelt sidder fast, betaler den fulde ventetid. Det andet var opsætning pr. test, der genopbyggede et dyrt fikstur hver gang, hvor fiksturet var skrivebeskyttet og kunne bygges én gang for suiten. Ingen af dem lå i en test, nogen ville have udpeget som langsom; begge lå i den fælles vej, hvilket er grunden til, at hele suiten var ensartet langsom frem for at nogle få test var afvigere.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Suiten gik fra seks test over tres sekunder — 74 sekunders vægur — til 135 test bestået på 8,9, hvilket bringer den inden for det vindue, hvor den kører ved hver gemning. Forbeholdet er, at det fælles skrivebeskyttede fikstur nu er et koblingspunkt — en test, der ændrer det, vil frembringe en fejl i en anden test, og suitens hastighed afhænger af en disciplin, oversætteren ikke håndhæver.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Automatisering \u0026 CI/CD","DevOps","Performanceoptimering","Test \u0026 QA","DevOps \u0026 CI/CD‑automatisering","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/portfolio/rewrote-the-error-messages-against-a-tone-standard-162/","url":"https://advisory.engineer.company/da/portfolio/rewrote-the-error-messages-against-a-tone-standard-162/","title":"Har omskrevet applikationens fejlbeskeder efter en skreven tonestandard, efter at et afvist login gav brugeren skylden for at have tastet forkert, mens udbyderen i virkeligheden krævede en applikationsspecifik adgangskode, og har dækket det med en test, der nævner udbyderen.","summary":"Fejlfladen følger en angivet standard, og det tilfælde, der foranledigede den, er dækket af en test, der fejler på den gamle tekst.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e En indlogning mod en stor mailudbyder mislykkedes, og programmet fortalte brugeren, at adgangskoden var forkert. Den var ikke forkert. Den udbyder kræver en programspecifik adgangskode til tredjepartsklienter og afviser kontoens adgangskode uanset hvor omhyggeligt den tastes. Beskeden sendte brugeren ud i at genindtaste noget, der aldrig kunne virke, og den faktiske anvisning — gå hen og frembring en anden slags adgangskode — optrådte intetsteds.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Fejlbeskederne skulle omskrives efter en skreven standard frem for lappes én ad gangen, eftersom denne var det synlige tilfælde af en vane, der løb gennem dem alle.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Standarden har tre krav: sig hvad der skete, antyd aldrig at brugeren gjorde noget forkert, når årsagen ligger andetsteds, og giv den næste handling, når der findes en. Anvendt på tværs af fejlfladen overtrådte de fleste beskeder mindst ét — flere var det underliggende biblioteks fejlstreng ført videre, hvilket beskriver en tilstand for en programmør frem for en situation for et menneske. Udbydertilfældet blev omskrevet til at navngive udbyderen, angive at den kræver en programspecifik adgangskode til andre klienter, og sige hvor man opretter en. Testen er det, der forhindrer tilbagefald, og den er bevidst konkret: den driver en mislykket indlogning mod den udbyder og efterprøver, at beskeden indeholder udbyderens navn og den vending, der beskriver den krævede legitimationstype. En test, der kun efterprøvede at en fejl viste sig, ville bestå på den oprindelige forkerte besked, så efterprøvningen ligger på indholdet, hvilket er den eneste del, der nogensinde var i stykker.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Fejlfladen følger en angivet standard, og det tilfælde, der foranledigede den, er dækket af en test, der fejler på den gamle tekst. Det, der forbliver uafklaret, er omfanget: standarden håndhæves ved gennemgang og ved én test på én besked, og de øvrige udbydere med deres egne særlige krav har ingen tilsvarende test, så klassen er dokumenteret frem for lukket.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Dokumentation","Frontend‑udvikling","Produkt \u0026 krav","Sikkerhed","Test \u0026 QA","UX/UI‑design","Produktstrategi \u0026 kravspecifikation","Teknisk dokumentation","UI/UX‑design \u0026 designsystemer"]},{"id":"https://advisory.engineer.company/da/portfolio/held-five-repositories-to-one-history-standard-165/","url":"https://advisory.engineer.company/da/portfolio/held-five-repositories-to-one-history-standard-165/","title":"Har holdt fire kodebaser til én historikstandard — konventionel, uden emojis, uden attributionslinjer, håndhævet af en commit‑message‑hook — sammen med 46 instruktionsdokumenter, der styrer, hvordan arbejdet udføres.","summary":"Fem lagre deler ét historikformat og én anvisningsstruktur, begge håndhævet af hooks frem for af disciplin.","content_html":"\u003cp\u003e\u003cstrong\u003eSituation.\u003c/strong\u003e Fem lagre bygget over atten måneder af én person er den situation, hvor proces er lettest at springe over, for der er ingen at koordinere med, og prisen for en ulæselig historik betales helt af et fremtidigt jeg, der endnu ikke har beklaget sig. Det er også den situation, hvor en usammenhængende historik er mest sandsynlig, eftersom hvert lager kan glide ind i sine egne vaner uden noget, der trækker dem sammen.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpgave.\u003c/strong\u003e Én standard for historik og én standard for anvisninger skulle gælde på tværs af hvert lager, arbejdet skrives i, og den skulle håndhæves maskinelt frem for huskes.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHandling.\u003c/strong\u003e Commit‑standarden er et konventionelt præfiks, der navngiver ændringens art, og et virkefelt, en emnelinje under en fast længde, ingen emojis og ingen tilskrivningslinjer af nogen art — det sidste fordi en linje, der krediterer et værktøj, ikke er en kendsgerning om ændringen, og historik er til kendsgerninger om ændringer. En hook på commit‑beskeden afviser alt, der ikke retter sig efter det, i hvert lager, der bærer arbejde, så standarden er en egenskab ved lageret frem for ved den, der committer. Fordelingen i det største lager viser, hvad arbejdet faktisk var: 156 funktions‑commits, 133 rettelser, 128 dokumentation, 81 husholdning, 26 omskrivninger, 20 stil, 5 ydeevne og 3 test. Dokumentation ligger tæt nok på rettelser til at være værd at bemærke, og det er en følge af den anden halvdel af dette — 46 anvisningsdokumenter på tværs af de fire, hvert dækkende ét område, hvert skrevet som regler frem for beskrivelse, alle nåelige fra ét indgangsdokument pr. lager, så der er ét sted at begynde. En dokumentationslinter håndhæver størrelsesbudgetter pr. fil og medlemskab af indekset, så mængden forbliver overskuelig frem for at vokse til et arkiv.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eResultat.\u003c/strong\u003e Fem lagre deler ét historikformat og én anvisningsstruktur, begge håndhævet af hooks frem for af disciplin. Hvad dette ikke gør, er at gøre historikken god: formatet tjekkes, og indholdet gør ikke, så en emnelinje, der retter sig efter formatet og beskriver intet, slipper igennem præcis lige så godt som en, der forklarer ændringen.\u003c/p\u003e\n","date_published":"2026-09-13T01:45:50+02:00","date_modified":"2026-09-13T01:45:50+02:00","language":"da","tags":["Agile \u0026 Scrum","Automatisering \u0026 CI/CD","DevOps","Dokumentation","Projektledelse","Teknisk ledelse","DevOps \u0026 CI/CD‑automatisering","Projektledelse (Agile)","Teknisk dokumentation","Teknisk ledelse \u0026 rådgivning"]},{"id":"https://advisory.engineer.company/da/notes/solana-mobile-wallet-deeplinks/","url":"https://advisory.engineer.company/da/notes/solana-mobile-wallet-deeplinks/","title":"Sådan åbner man en dApp i Solana-mobilwallets","summary":"Hvorfor browse-deeplinks til Phantom, Solflare og Backpack fejler på mobilen — og de formater, regler og rettelser, der får dem til at virke.","content_html":"\u003cp\u003eEn React-dApp bygget på \u003ccode\u003e@solana/wallet-adapter-react\u003c/code\u003e forbinder\ndesktop-wallets uden problemer, men på en telefon falder det samme flow fra\nhinanden: wallet\u0026rsquo;en skal åbne dApp\u0026rsquo;en i sin egen indbyggede browser, og de\ndeeplinks, der skulle klare det, virker bare ikke. Backpack lander på en \u0026ldquo;hent\nappen\u0026rdquo;-side; Solflare åbner appen, men aldrig sitet; alle varianter ser ud til\nat fejle. Vi skilte problemet ad, og det viste sig at være fire adskilte\nproblemer med ét fælles symptom.\u003c/p\u003e\n\u003ch2 id=\"de-fire-problemer\"\u003eDe fire problemer\u003c/h2\u003e\n\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eBackpack-linket var forkert bygget.\u003c/strong\u003e Det eneste dokumenterede format er\n\u003ccode\u003ehttps://backpack.app/ul/v1/browse/\u0026lt;url\u0026gt;?ref=\u0026lt;ref\u0026gt;\u003c/code\u003e — et universelt link med\nmål-URL\u0026rsquo;en i stien og et påkrævet \u003ccode\u003eref\u003c/code\u003e. Et gæt med eget skema som\n\u003ccode\u003ebackpack://ul/v1/browse?url=...\u003c/code\u003e matcher ingen rute i appen, så brugeren\nender på wallet\u0026rsquo;ens installationsside.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSolflare skal også bruge sit universelle link:\u003c/strong\u003e\n\u003ccode\u003ehttps://solflare.com/ul/v1/browse/\u0026lt;url\u0026gt;?ref=\u0026lt;ref\u0026gt;\u003c/code\u003e — ikke det rå\n\u003ccode\u003esolflare://\u003c/code\u003e-skema. Et råt skema kan starte appen uden at dirigere den —\nhvilket er præcis \u0026ldquo;appen åbner, men site-fanen må åbnes med hånden\u0026rdquo;.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBegge parametre skal være kodet.\u003c/strong\u003e \u003ccode\u003eurl\u003c/code\u003e er dApp\u0026rsquo;ens fulde absolutte\nadresse, og \u003ccode\u003eref\u003c/code\u003e er den kaldende origin, hver især gennem\n\u003ccode\u003eencodeURIComponent\u003c/code\u003e. Et ukodet \u003ccode\u003e?\u003c/code\u003e eller \u003ccode\u003e\u0026amp;\u003c/code\u003e i målet ødelægger\nfortolkningen, og wallet\u0026rsquo;en åbner på sin forside i stedet for browserfanen.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUdløsningen betyder lige så meget som linket.\u003c/strong\u003e Universelle links skifter\nkun app ved en navigation, styresystemet stoler på — og de gør med vilje\ningenting, når de indsættes i adresselinjen, hvilket også er sådan, et helt\nkorrekt link \u0026ldquo;fejler\u0026rdquo; under test.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"de-dokumenterede-formater\"\u003eDe dokumenterede formater\u003c/h2\u003e\n\n\u003cul\u003e\n\u003cli\u003ePhantom: \u003ccode\u003ehttps://phantom.app/ul/browse/\u0026lt;url\u0026gt;?ref=\u0026lt;ref\u0026gt;\u003c/code\u003e — uden \u003ccode\u003e/v1\u003c/code\u003e i\nnetop dette.\u003c/li\u003e\n\u003cli\u003eSolflare: \u003ccode\u003ehttps://solflare.com/ul/v1/browse/\u0026lt;url\u0026gt;?ref=\u0026lt;ref\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eBackpack: \u003ccode\u003ehttps://backpack.app/ul/v1/browse/\u0026lt;url\u0026gt;?ref=\u0026lt;ref\u0026gt;\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eÉt mønster dækker alle tre:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003econst WALLET_BROWSE = {\n  phantom: (url, ref) =\u0026gt;\n    `https://phantom.app/ul/browse/${url}?ref=${ref}`,\n  solflare: (url, ref) =\u0026gt;\n    `https://solflare.com/ul/v1/browse/${url}?ref=${ref}`,\n  backpack: (url, ref) =\u0026gt;\n    `https://backpack.app/ul/v1/browse/${url}?ref=${ref}`,\n};\n\nfunction walletBrowseLink(\n  walletName,\n  targetUrl = window.location.href,\n) {\n  const build = WALLET_BROWSE[walletName.toLowerCase()];\n  if (!build) return null;\n  return build(\n    encodeURIComponent(targetUrl),\n    encodeURIComponent(window.location.origin),\n  );\n}\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"udløs-linket-så-ios-og-android-accepterer-det\"\u003eUdløs linket, så iOS og Android accepterer det\u003c/h2\u003e\n\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eRender et rigtigt anker, beregnet på forhånd.\u003c/strong\u003e Et almindeligt\n\u003ccode\u003e\u0026lt;a href={walletBrowseLink('phantom')}\u0026gt;\u003c/code\u003e er den mest pålidelige udløser på\nbegge platforme.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSkal det ske programmatisk\u003c/strong\u003e, så tildel \u003ccode\u003ewindow.location.href\u003c/code\u003e synkront\ninde i tryk-handleren — ingen \u003ccode\u003eawait\u003c/code\u003e, ingen \u003ccode\u003efetch\u003c/code\u003e, ingen \u003ccode\u003esetTimeout\u003c/code\u003e\nførst. Efter asynkront arbejde er gestus-konteksten væk, og iOS falder\ntilbage til wallet\u0026rsquo;ens websted. Aldrig \u003ccode\u003ewindow.open\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTest aldrig ved at indsætte i adresselinjen.\u003c/strong\u003e Universelle links udløses\nmed vilje ikke dér; test med et link, der trykkes på, eller en QR-kode, som\nkameraet scanner.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePas på messenger-webviews.\u003c/strong\u003e Åbnet i Telegrams eller Instagrams indbyggede\nbrowser bliver universelle links ofte slugt, og wallet\u0026rsquo;ens almindelige\nwebsted indlæses i stedet. User-agent-detektion er i bedste fald et gæt, så\ngiv også brugerne en synlig nødudgang: \u0026ldquo;åbn i Safari eller Chrome, og\nforbind derefter\u0026rdquo;.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"den-større-løsning-på-android\"\u003eDen større løsning på Android\u003c/h2\u003e\n\n\u003cp\u003eHåndbyggede deeplinks er iOS-historien. På Android lader Solana Mobiles Mobile\nWallet Adapter en dApp i mobilbrowseren forbinde direkte til den installerede\nwallet-app, helt uden omvejen om den indbyggede browser. Nyere versioner af\n\u003ccode\u003e@solana/wallet-adapter-react\u003c/code\u003e registrerer mobiladapteren automatisk, så en\nopgradering af wallet-adapter-pakkerne kan løse Android alene. Målarkitekturen:\nMobile Wallet Adapter på Android, universelle browse-links på iOS, hvor Apple\nikke tillader en tilsvarende løsning.\u003c/p\u003e\n\u003ch2 id=\"efterprøv-på-en-enhed\"\u003eEfterprøv på en enhed\u003c/h2\u003e\n\n\u003col\u003e\n\u003cli\u003eRigtig enhed, wallet installeret, link åbnet fra systembrowseren — ikke fra\nen messenger.\u003c/li\u003e\n\u003cli\u003eTryk på et renderet link, eller scan en QR-kode; indsæt aldrig i\nadresselinjen.\u003c/li\u003e\n\u003cli\u003eBekræft, at wallet\u0026rsquo;en åbner, og at dApp\u0026rsquo;en indlæses i dens indbyggede\nbrowserfane — anden halvdel er den, der fejler.\u003c/li\u003e\n\u003cli\u003eGentag uden wallet\u0026rsquo;en installeret: det universelle link skal falde tilbage\ntil wallet\u0026rsquo;ens websted. Ser du dén side, mens appen er installeret, er\nlinket eller udløsningen stadig forkert.\u003c/li\u003e\n\u003cli\u003eTest derefter messenger-vejen, og tilføj \u0026ldquo;åbn i browser\u0026rdquo;-hjælpen, hvis den\nfejler dér.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"kilder\"\u003eKilder\u003c/h2\u003e\n\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://docs.phantom.com/phantom-deeplinks/deeplinks-ios-and-android\"\u003ePhantom: deeplinks på iOS og Android\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.solflare.com/solflare/technical/deeplinks/other-methods/browse\"\u003eSolflare: Browse-deeplinket\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.backpack.app/deeplinks/other-methods/browse\"\u003eBackpack: Browse-deeplinket\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://docs.solanamobile.com/mobile-wallet-adapter/mobile-apps\"\u003eSolana Mobile: Mobile Wallet Adapter\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","date_published":"2026-08-10T00:00:00Z","date_modified":"2026-09-13T01:45:50+02:00","language":"da"}]}