Commit Graph

7 Commits

Author SHA1 Message Date
Claude 3ec25dea9c ALVA: analysvy, sammanfattning och integrationsgränssnitt
---- Statistiken är ett produktbeslut ----------------------------------

Vilka siffror som visas avgör vad organisationen optimerar, så tre mått
är uteslutna med avsikt och låsta av test: ärenden per tekniker,
genomsnittlig ledtid och aktivitet. Alla tre belönar den som hoppar över
kontroller, och ett svårt fel SKA ta längre tid.

Medtagna, var och en handlingsbar:

  VERIFIERINGSGRAD   Andel avslut med fastställd orsak. Det enda mått
                     ett försäkringsbolag egentligen bryr sig om. Att
                     den inte är 100 % är friskt.
  REPRODUKTIONSGRAD  Låg siffra förutsäger återkommande fordon — man kan
                     inte åtgärda det man inte sett.
  OMARBETNING        Samma fordon tillbaka med samma orsakskategori inom
                     ett fönster. Det dyraste felet i en verkstad och det
                     enda ingen mäter, eftersom det kräver att två
                     ärenden kopplas ihop. Här är kopplingen gratis.
  UNDANTAGSFREKVENS  Vilka kontroller som hoppas över, per steg och fas.
                     Ett steg högt i listan är antingen felskrivet eller
                     kräver utrustning som saknas — bägge åtgärdbara.

Ett mått utan underlag visas som NOT APPLICABLE, aldrig som noll.
Skillnaden avgör om någon fattar beslut på en siffra som inte finns.

---- Sammanfattningen är härledd, inte genererad -----------------------

Frestelsen är att låta modellen skriva den. Det vore fel av tre skäl:
den blir en del av ett beslutsunderlag och måste därför gå att lita på
utan att granskas mot loggen varje gång; samma ärende måste ge samma
text om två år; och verkstadsgolvet har dålig täckning.

Den är alltså en projektion som briefen och rapporten. Den innehåller
inget som inte står i loggen och säger uttryckligen när något saknas i
stället för att utelämna det. Ett test kräver att den aldrig skriver
"felet konstaterat" när orsaken inte fastställts.

---- Integration utan påhittade endpoints ------------------------------

Jag känner inte Beonodes, ServiceCams eller CABAS faktiska gränssnitt.
En uppfunnen endpoint som ser färdig ut är sämre än en tom: den ser ut
att fungera tills någon försöker.

Därför ett profildrivet gränssnitt. En profil beskriver vad en KATEGORI
av system förväntar sig, och märks validated först efter att den körts
mot leverantören. Tills dess står den som draft, och det syns i
gränssnittet — en integrationslista där allt ser färdigt ut är den
snabbaste vägen till ett misslyckat införande, eftersom verkstaden
planerar efter den.

Kategorier: diagnosprotokoll, DMS, videooffert, fordonsdata,
skadekalkyl (CABAS är nordisk standard), garanti och försäkring.

Skadekalkyl går åt båda håll. Det ALVA tillför en kalkyl är inte fler
poster utan beviskedjan bakom dem: vad som kontrollerades, vad som
uteslöts och varför. Det är den enda del av en kalkyl som i dag inte går
att granska i efterhand.

Inkommande protokoll blir evidens, inte bilagor, med härkomsten bevarad
i varje post — ett värde som kommit utifrån får aldrig se ut som något
teknikern själv mätt. Saknas instrumentets identitet nedgraderas värdet
till E1 enligt samma regel som gäller manuella mätningar.

Utgående leveranser signeras med HMAC över tidsstämpel och kropp;
tidsstämpeln ligger inne i signaturen så en fångad leverans inte går att
spela upp i morgon. Verifieringsfunktionen exporteras så mottagaren kan
använda exakt samma kod — de flesta integrationsfel uppstår i glappet
mellan två implementationer av samma signatur.

Prenumerationer går genom samma SSRF-gräns som leverantörsuppslagen, och
leverans sker efter att loggen skrivits: en mottagare ska aldrig kunna
se en händelse som inte finns i loggen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
2026-08-05 15:51:30 +00:00
Claude fbc034a280 Revisionen: C-3, C-4, M-1, M-4, M-5, M-6, m-3, m-5 och m-7 åtgärdade
C-3 · Dataskydd genom krypto-shredding. Identifierande fält krypteras
med en nyckel per ärende; radering sker genom att nyckeln förstörs.
Loggen förblir intakt och hashverifierbar — det som blir oåtkomligt är
identifieringen, inte protokollet över vad som kontrollerades. Ett
raderat ärende visar fortfarande att lufttrycket mättes till 2,4 bar
klockan 08:42, bara inte längre vems bil det gällde.

Vad som inte krypteras är lika viktigt: mätvärden, observationer och
kontrollresultat är verksamhetsdata. Krypteras allt raderas beviset
tillsammans med personuppgiften.

En raderingsbegäran gäller ett fordon, inte ett ärende — men
identifieraren är krypterad och går inte att söka på. Därför ett blindat
index: HMAC av den normaliserade identifieraren, samma fordon ger alltid
samma värde, värdet går inte att vända tillbaka utan nyckeln.

Gallringsdatum sätts vid avslut utifrån ärendetypen. Ett ärende utan
datum gallras aldrig — för tidig gallring går inte att ångra.

C-4 · Modellanropen kan stängas av per organisation. Flaggan bärs i
token så orkestern kan neka utan databasåtkomst. Metodikmotorn fungerar
ensam; en verkstad som inte kan acceptera överföringen till
modelleverantören kan ändå använda produkten.

M-1 · Mätvärden bär vilket mätdon som användes och när det var
kalibrerat. Utan spårbart instrument nedgraderas värdet från E4 till E1
— det är teknikerns observation av en siffra, inte en mätning.
Kalibreringen bedöms vid mättillfället, inte i dag. Demoärendet fick
kalibrerade instrument: det ska visa den praxis produkten kräver.

M-4 · Läslogg. Varje skrivning loggades redan; ingen läsning gjorde det.
M-5 · Återställningstest i CI. Larmet visade att backup sker, inte att
den går att återställa. Testet kontrollerar det som faktiskt brukar
tappas: att append-only-triggarna följde med och fortfarande biter.
M-6 · Regelpaketet verifieras mot HMAC. Ogiltig signatur spärrar avslut;
saknad nyckel ger granskningsläge i stället för driftavbrott — det är så
säkerhetsfunktioner blir avstängda.
m-3 · EXIF-borttagningen är nu avsiktlig och låst av test. Den höll av
en slump, och en ändring i stil med "bevara originalkvaliteten" hade
tyst börjat publicera var kundens bil stod.
m-5 · SBOM och sårbarhetsskanning i CI.
m-7 · Promptversionen binds till varje svar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
2026-08-05 13:44:37 +00:00
Claude 69a519be75 Observation: se var tiden går, utan ett enda nytt beroende
CloudWatch gav loggar och mätvärden men svarade inte på frågan man
faktiskt har när något är långsamt: var tog tiden vägen.

Tjänsterna har medvetet nästan inga beroenden — plattformen har
pg-drivrutinen, orkestern har Claude-klienten. Att dra in ett
OpenTelemetry-SDK med trettio paket för att mäta fyra saker vore fel
avvägning. I stället två standarder som båda bara är text på stdout:

W3C Trace Context. Klienten startar spåret och traceparent följer med
genom plattformen till orkestern, så en teknikers handling går att följa
hela vägen till modellsvaret i stället för att bli två orelaterade spår.

CloudWatch EMF. Strukturerad JSON som CloudWatch själv extraherar
mätvärden ur — ingen agent, ingen SDK, inget som kan sluta fungera tyst.

Varje anrop ger en loggrad med nedbrytning av tiden per del: databasen,
modellanropet, objektlagringen, kundens leverantör. Det svarar direkt på
om ett långsamt ärende beror på S3 eller på Opus-granskningen, i stället
för att någon ska korrelera fem loggrader.

Vägen normaliseras innan den blir dimension, och organisation, ärende-id
och spår-id blir aldrig dimensioner — varje unik kombination är en egen
tidsserie som kostar. De ligger som vanliga fält, sökbara i Logs
Insights. Ett test låser det, eftersom det är precis den sortens sak som
smyger in senare.

Tre larm på det teknikern märker: svarstid p95 över tre sekunder
(medelvärdet döljer att var tjugonde tekniker väntar orimligt länge),
serverfel med spår-id i loggraden, och att modellen avböjer — det senare
tyder på att underlaget innehåller något oväntat, inte på ett driftfel.

Modulen är delad mellan tjänsterna i stället för duplicerad.
Byggkontexten flyttas därför till felsokning/services, och en symlänk gör
att testerna och integrationstestet kör mot samma fil som bilderna.

Verifierat: 106 vitest-tester (10 nya för spårning, EMF-format och att
dimensionerna hålls få), typkontroll, eslint på klient och tjänster,
rotens CI, terraform fmt och referenskontroll på båda lagren, samt
integrationstest mot riktig Postgres där spårraderna syns live.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
2026-08-04 13:36:47 +00:00
Claude a5e276534c Arbetslasten kopplad till AWS — kedjan är helt egen
Andra lagret läser nu basens utdata i stället för att upprepa någonting.
05-aws.tf hämtar klustret, domänen, certifikatet, registret, rollerna,
hinken och hemligheternas namn — ändras något i basen slår det igenom
här utan att en rad ändras. Autentiseringen mot klustret sker med en
färsk EKS-token i stället för en kubeconfig på disk: inget att
distribuera, inget som går ut.

Hemligheterna bor i Secrets Manager och speglas in av External Secrets
var timme. Terraform ser aldrig värdena, och det är själva poängen — en
hemlighet som passerar Terraform hamnar i tillståndsfilen. Roteras en
hemlighet följer klustret efter av sig självt.

Plattformstjänsten kör som ett tjänstekonto med IRSA. Rollen är bunden
till exakt det kontot i den namnrymden, så grannpodden på samma nod får
ingenting på köpet. Bilagorna signeras mot S3 med samma roll — inga
nycklar existerar att läcka.

Postgres-podden är borta. Händelseloggen ligger i Aurora utanför
klustret, i ett subnätlager utan routing ut, med automatisk
säkerhetskopiering och PITR. Ingressen är en ALB med ACM-certifikat i
stället för nginx, och alla tre tjänsterna delar den genom samma
gruppnamn.

Gitea med egna Actions-runners kör i samma kluster. Därmed finns inget
externt beroende kvar: källkod, bygge, register och driftsättning ligger
allt i vår AWS-miljö. Runnern och driftsättningen har varsitt
tjänstekonto med skilda roller — bygget får publicera till ECR men inte
röra klustret, driften tvärtom. Ett komprometterat bygge kan inte
driftsätta.

Gitea kör SQLite på en EBS-volym i stället för en egen Aurora-databas.
En verkstadsinstallation har en handfull utvecklare, och ytterligare en
databas att säkerhetskopiera och övervaka är kostnad utan motsvarande
nytta.

Verifierat: 96 vitest-tester, rotens lint och format:check, terraform fmt
på båda lagren och statisk referenskontroll av vardera (88 respektive 35
resurser, inga dinglande referenser, alla count-resurser indexerade).
terraform validate kunde inte köras här — registry.terraform.io är
blockerad av sessionens egress-policy — så CI-jobbet kör den.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
2026-08-04 12:53:08 +00:00
Claude ac24938108 AWS-basen: allt eget, inget GitHub
Guidad Felsökning får en egen AWS-grund i felsokning/infra/aws — nät,
kluster, databas, objektlagring, register, hemligheter, domän och
observation. Inget GHCR, ingen extern byggtjänst.

Två lager i ordning, och uppdelningen är inte smak: en enda apply som
både skapar ett EKS-kluster och schemalägger in i det är en känd fälla,
eftersom kubernetes-leverantören måste konfigureras med uppgifter som
inte finns förrän klustret existerar.

Nätet ligger i tre lager. Publikt bara för lastbalanserare och NAT,
privat för noderna, och ett eget datalager för Aurora utan routing ut
alls — att databasen inte kan nå internet hänger då inte på att en
säkerhetsgrupp är rätt konfigurerad. VPC-endpoints för S3, ECR, loggar,
Secrets Manager, STS och ELB gör att bilddragningar och loggar aldrig
lämnar nätet, vilket både är säkrare och sänker NAT-notan rejält.

IRSA i stället för nodroller: plattformens tjänstekonto har en roll
bunden till exakt en namnrymd och ett tjänstekonto, så grannpodden på
samma nod får ingenting på köpet. IMDSv2 med hoppgräns 1 hindrar
dessutom en pod från att låna nodens roll via metadatatjänsten.

Bygge och drift har delade rättigheter. Byggrollen får publicera till
ECR men inte röra klustret; driftrollen tvärtom. Ett komprometterat
bygge kan därför inte driftsätta.

Aurora PostgreSQL Serverless v2 med 30 dagars säkerhetskopiering och
PITR ned till sekunden — det som gör den duglig för händelseloggen är
inte prestandan utan att förlorad logg annars hade tagit varje ärendes
bevisvärde med sig. S3-hinken för bilagor har versionshantering,
SSE-KMS, TLS-krav och blockerad publik åtkomst; plattformens roll får
läsa och skriva men aldrig radera, eftersom bilagorna hör till en
append-only logg.

Larmen är fyra och ett av dem larmar på saknad data: uteblir mätvärdet
för säkerhetskopiering finns ingen backup, och en backup man tror finns
är värre än ingen.

Verifierat: terraform fmt och en statisk referenskontroll (88 resurser,
5 datakällor, inga dinglande referenser). terraform validate kunde inte
köras här — registry.terraform.io är blockerad av sessionens
egress-policy — så CI-jobbet kör den i stället.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
2026-08-04 12:39:42 +00:00
Claude c407aad58a Varje produkt äger sitt eget träd — och GitHub-flödena bort
Rot-CI:n föll med 107 lint-fel efter merge:n. Orsaken var inte kod som
blivit sämre: Semantikas rot-eslint började granska felsokning/, ett
träd med egen verktygskedja och andra regler. Felen låg i värdappens
befintliga Supabase-funktioner, oförändrade sedan innan.

Rätt åtgärd är att låta varje produkt äga sitt eget träd, inte att lätta
på någons regler. felsokning/ ignoreras därför av Semantikas eslint och
prettier — den har egen eslint-konfiguration, egna prettier-regler och
eget CI-flöde. Ingen regel är försvagad för någon av produkterna.

Samtidigt: mina GitHub-workflows för publicering och driftsättning är
borttagna. Guidad Felsökning ska inte längre bero på GitHub Actions eller
GHCR — bygge, publicering till eget ECR och terraform apply mot EKS
ligger nu i .gitea/workflows/felsokning.yml och körs av egna runners.
Driftsättningen är fortsatt ett eget, manuellt steg med en bildtagg;
rollback är att köra igen med en tidigare tagg.

.github/workflows/ci.yml är Semantikas och lämnas orörd.

Verifierat: rotens lint, format:check, typecheck och test går igenom, och
Guidad Felsöknings egna 96 tester, typkontroll, bygge och integrationstest
mot riktig Postgres likaså.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
2026-08-04 12:27:33 +00:00
Claude 301c477e25 Merge main: Guidad Felsökning flyttar ur roten till felsokning/
Main är sedan den här grenen skapades en helt annan produkt — Semantika,
en mobilapp med egen CDK-infrastruktur. Den äger nu repots rot: en
npm-workspaces-monorepo med apps/mobile, services/api och infra.

För att båda ska rymmas i samma repo flyttar Guidad Felsökning in i en
egen katalog i stället för att göra anspråk på roten:

  felsokning/app        webbklienten (Vite, egen package.json och
                        eslint-/vitest-konfiguration)
  felsokning/services   plattformstjänsten och AI-orkestern
  felsokning/infra      Terraform och databasschemat
  felsokning/docs       vision, moduler, drift
  felsokning/supabase   edge-funktion och migrationer

Merge:n hade tagit bort 128 filer som Guidad Felsökning bygger på —
värdapplikationens komponenter, Supabase-klienten, tillgångar — eftersom
main raderat dem och den här grenen inte råkat ändra just dem. De är
återställda på sin nya plats. Utan dem gick varken bygget eller
testerna: ai.ts och synk.ts importerar Supabase-klienten.

Semantikas rotfiler är orörda: package.json, eslint.config.js och
.github/workflows/ är deras. Guidad Felsökning har egna motsvarigheter i
sin katalog.

CI flyttar samtidigt från GitHub Actions till .gitea/workflows — samma
syntax, egna runners. .github/workflows/ tillhör Semantika härefter.

Verifierat på den nya platsen: 96 vitest-tester, typkontroll, eslint på
både klient och tjänster, bygge, och integrationstest mot riktig Postgres.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
2026-08-04 12:22:49 +00:00