v1.0.0
55 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
04e0a1e8ec |
ALVA deployment config
Guidad Felsökning / test-och-bygg (push) Has been cancelled
Guidad Felsökning / tjanster (push) Has been cancelled
Guidad Felsökning / terraform (push) Has been cancelled
Guidad Felsökning / leverantorskedja (push) Has been cancelled
Guidad Felsökning / aterstallning (push) Has been cancelled
Guidad Felsökning / publicera (push) Has been cancelled
Guidad Felsökning / driftsatt (push) Has been cancelled
|
||
|
|
e502de8276 |
Portalmenyn i två nivåer: arbetet synligt, administrationen under Settings
Tio länkar i tre brutna rader var ingen meny. Nivå ett är nu arbetet — Dashboard, Analysis, Warranty, Insurance, Diagnostics — plus Settings, som samlar det som konfigurerar organisationen: kunskapskällor, integration, abonnemang, fakturor och supportärenden mot plattformen. Settings har en översiktssida där varje område är en hel klickbar rad med en mening om vad man uträttar där, och inne i inställningarna visas områdena som en egen, alltid synlig rad med det aktiva markerat — ingen fällmeny. Områdeslistan ligger i en egen modul och bär huvudmenyns markering, inställningsraden och översiktssidan ur samma data. Nya vyn står bakom portalvakten och ingår i genomgångens telefonmätning och portalspärrens kontroll. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
6c5af03abe |
Utläsningen på en rad på smal skärm
Startsidans utläsning bröt sig på två rader på mobil. Den sätts nu i sidhuvudets 10 px med tätare spärrning under sm-brytpunkten, ordinarie grad därutöver. Enradighet verifierad vid 430/390/360/344 px utan horisontellt överflöde. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
28bfc29a5c |
Betalarspåret: beviskraven följer den som betalar — ALVA 3.6
Garantistandarden FGS-1.0 (fabriksgaranti, vagnskadegaranti, försäkring, extern garantigivare, leasing/fleet, goodwill) inarbetad i regelmotorn och bokförd i docs/GARANTISTANDARD-FGS.md (ALVA-DOC-0011): vad som redan var uppfyllt, vad som införs nu, och den ärliga gränsen — ODIS/DISS/SAGA2 är tillverkarsystem; ALVA bär bevispaketet och eskaleringsspåret, den ersätter dem inte. Tre nya händelsetyper i det stängda schemat: betalare (spår, namn, claim-/skadereferens, godkännande), eskalering (öppnad/besvarad, kanal, referens) och reservdel (artikelnummer, serienummer, batch, sparad del). Grinden kräver fastställd betalare för de ärendetyper där någon annan än kunden betalar, godkännande för goodwill och externa garantigivare, och spärrar avslut när en eskalering är öppnad utan dokumenterat svar — matchad per referens. Claim- och skadenummer kan komma ur betalaren, inte bara ur skannad arbetsorder. Tre nya ärendetyper med regelpaketskrav: Body damage warranty, Extended warranty, Leasing or fleet. Betalare, eskalering och reservdel är interna i delningsfiltret — kunden ser åtgärden, inte förhandlingen. Fyndet på vägen, åtgärdat med regressionstest: serverns ärendetypskrav var en tyst no-op. Servern matade den distribuerade paketformen (arendetypRegler) in i en grindfunktion som bara läste den slimmade (arendetyper[typ].krav) — garanti- och försäkringskraven upprätthölls bara som råd i klienten. C-2-mönstret, återuppstånden genom ett filformat. Grinden läser nu båda formerna, och regressionstestet låser att den distribuerade formen spärrar på servern. UI: betalar- och eskaleringspaneler i ärendevyn (panelen visas när ärendetypen kräver den), grindnyckeln grind.eskalering på alla tio språken, regelpaket 2.1 speglat klient/server med likhetstestet intakt. 781 enhetstester, genomgång 4/4 inom budget, portalspärr, integrationstest mot Postgres, typkontroll, lint på baslinjen, artefaktmätning och språkrunda gröna. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
4dea6d2818 |
Fackgranskning av metodikinnehållet — ALVA 3.5
Sex oberoende domängranskningar av metodikbiblioteket, den enda text i systemet som säger åt en tekniker vad den ska göra med ett fordon: chassi, elsystem, högvolt, motor/drivlina, övriga system, plus en maskinell granskning av bibliotekets egna tre regler. Varje fynd verifierat före åtgärd, varje ersättning applicerad med träffkrav. Bokfört i docs/FACKGRANSKNING-2026-08.md (ALVA-DOC-0009); protokollet som gör den mänskliga granskningen per marknad utförbar i docs/FACKGRANSKNINGSPROTOKOLL.md (ALVA-DOC-0010). Granskat-flaggorna är oförändrade — detta höjer golvet, marknadens fackman sätter flaggan. Tio kritiska fynd åtgärdade. Tyngst: högvoltens skyddsutrustning och avspärrning låg SIST i säkerhetssekvensen — efter spänningsfrihets- mätningen — och står nu först med EN 60903/60900-krav; mätningen kräver CAT III och prova–mät–prova; frånskiljaren låses mot återinkoppling; metodiken säger nu vad som är förbjudet utan behörighet. Därtill: klimatets saknade f-gasgrind (nytt säkerhetssteg, högvoltens mönster), ADAS-provkörningen som instruerade att provocera nödbromsingrepp i trafik, öppna-aldrig-varmt för kylsystemet, trycksänkning och högtrycksförbud för bränsle, deaktiverad tändning/ insprutning före kompressionsprov, avgasutsug, provkörningsförbud vid bränsle-/bromsvätskeläckage, SRS-mätförbud — och klistringsfelet som lät engelska styrningsklagomål matcha högvoltsmetodiken (styrningens nyckelord låg i högvoltens lista; bekräftat av fyra granskare oberoende av varandra). Därutöver: referensvärden och villkor på mätningarna (startspänning, spänningsfall, laddspänning med smart laddning-reservation, vilostrom, CAN-terminering med gateway-reservation, AC-tryck vid föreskrivet varvtal), rätt metod där fel stod (säkringar mäts under last, krypström via mV-fall, spolskifte i stället för resistans, glappkontroll med avlastning efter fjädringstyp), och 23 nya kontroller där granskningen fann diagnostiska hål. 153 → 176 kontroller, samtliga med evidenskrav. Fasmodellen fick sista ordet där den och en granskare drog åt olika håll: vibrationens provkörning står kvar sist (Action går inte före Localization) och kör-först-substansen bor i symptomsteget; bromsarnas nya vägprov heter reproduktion och klassas som lokalisering — temperaturjämförelsen per hjul är avgränsning, inte åtgärd. Grindtexten för spänningslöshet kräver nu uttryckligen verifiering genom mätning, på alla tio språken. Grindfixturen fick sitt tredje foto när skyddsnätets felkodskontroll kom till — fixturen följer regeln, inte tvärtom (jfr T-13). 775 enhetstester, genomgång 4/4 inom interaktionsbudgeten (vibration 81/90 med de nya kontrollerna), portalspärr, integrationstest, typkontroll, lint på baslinjen, artefaktmätning och språkrunda gröna. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
c334786bb3 |
Språkrevision, del 2: källtexten, ordlistorna och sju kataloger
Tio parallella granskningar (nio språk plus engelska källtexten), varje
fynd verifierat innan åtgärd. Detta är de första sju katalogerna plus
det tvärgående; pl, nl och ro följer i nästa commit, och hela
revisionen bokförs i ALVA-DOC-0008.
Källtexten (en): ett kritiskt fynd — grind.kvalitetskontroll sa
"symptom verified", vilket på verkstadsengelska betyder att symtomet
BEKRÄFTATS FÖREKOMMA (som i grind.reproducering), medan grinden avser
kontrollen efter åtgärd. Nu "symptom verified as resolved", speglat i
ECM-regelmotorns rubrik och propagerat till alla översättningar. Två
större ellipser rättade: "history checked or justified" och "action
documented or justified" band "justified" till fel led — det är den
uteblivna kontrollen respektive frånvaron som motiveras. Därtill:
enhetlig amerikansk stavning, "instrument cluster" i stället för
"instrument panel" om mätarhuset (även i ärendevyn och genomgångens
selektor), "Assigned to", "Calibration valid until", artikel- och
kommateringsfel, terminologin application/registration enhetlig.
Ordlistorna (ord.mjs): luckor som släppte igenom icke-svar ("faulty",
"fertig", "jw.", "hors service", "boh", "defect" på rumänska) och
luckor som nekade korrekt skrivna resonemang ("gdyż", "ya que",
"waardoor", "se datorează", "zurückzuführen", "donc") — det senare är
falsklarmsriktningen och väger tyngst. Svenska EVIDENSORD tappade
trebokstavsdelsträngen "mat" som träffade inuti "information".
Stammar i stället för enstaka böjningsformer där jämförelsen är
delsträng; jämförelsen mot hela fältet fick formvarianter.
Katalogerna: per språk rättade betydelseskiften (slutsats.ickesvar sa
"inte en slutsats" där källan säger "inte ett svar" — i sex språk),
kongruens runt {falt}-hållaren (fem språk), räkneordsgrammatik (pl,
ro), kalkeringar ("intake", "Endlich", "napisał wiersz", "dépannage"),
terminologisk konsekvens (expediente/pratica/processo/Vorgang/dossier
genomgående, punkter-av-kontroll enhetligt, clôturer/encerrar), och
fransk typografi med hårt mellanslag före ?!:; och i «».
Avvisade fynd bokförs i dokumentet — bl.a. it webb.kallor.rubrik
(familjegemensam läsning av "Operational Knowledge Infrastructure")
och omdöpning av mätarställnings-nycklarna (hade brutit synk med
ärendevyns paneltitlar utan språklig vinst).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
|
||
|
|
0068ef9844 |
Webbplatsen på alla tio språken
Sajten var hårdkodad engelska medan diagnostikytan redan talade tio språk. Nu hämtar hela den publika webben — startsidan, ansökan, inloggningen, språksidan, navigationen och sidfoten — sin text ur samma katalog som resten av produkten, under nytt prefix webb. (153 nycklar × 10 språk). Språkval på webben: besökarens eget val (väljare i sidfoten, sparat i localStorage med minnesfallback för privat läge) → webbläsarens språk → engelska. Rangordningen bor kvar i valjSprak; ny modul alva/webbsprak.ts bär bara lagring och React-kroken. Portalens länkar står medvetet kvar på engelska — portalen är produkten och styrs av konto och organisation, inte av ett besöksval i en sidfot. Gränsen håller: ordmärket, utläsningen och fasnamnen är ALVA:s struktur och står likadant i varje språk; lang-attributet följer valet; språksidans förhandsvisning behåller egen väljare och utgår från besökarens språk. Test: startsidans hjälterad och faskort låses mot systemdefinitionen (två källor för samma mening driver isär tyst), webbnycklarna krävs i varje språk, och designtesterna jämför nu katalognycklar i stället för strängar — starkare, eftersom samma nyckel är samma ord på alla språk. Ny språkrunda mot den bakade artefakten: väljare, sidbyte, webbläsarspråk och engelsk fallback, 11/11. 775 enhetstester, genomgång 4/4, portalspärr, integrationstest, artefaktmätning, typkontroll och lint gröna. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
83944f4962 |
Telefonen fastnade i inzoomat läge efter inloggning
Rapporterat med skärmdump: portalens första sida möttes kraftigt inzoomad efter inloggning på iPhone. Orsaken är iOS Safaris beteende, inte vår layout: ett formulärfält vars text är mindre än 16 px får webbläsaren att zooma in vid fokus — och den zoomar aldrig ut igen efter navigeringen. Inloggningens fält är 14 px och arbetsvyns 13 px, båda under tröskeln. Botemedlet är fältets textstorlek, inte viewport-metataggen. `maximum-scale=1` hade också stoppat inzoomningen men samtidigt tagit ifrån användaren nypzoomen, och ett tillgänglighetsverktyg offras inte för att slippa en CSS-rad. Regeln ligger i kaskaden på .alva-yta och gäller bara pekskärmar (hover: none, pointer: coarse) — på skrivbordet finns ingen autozoom och 13 px är designens täthet. Verifierat mot den bakade artefakten med pekskärmsemulering: inloggningen och arbetsvyns namnfält mäter 16 px på telefon, 14 respektive 13 px på skrivbord. Regeln låst i designtestet, som redan läser index.css. 769 tester, typkontroll, lint och artefaktmätning gröna. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
c1c56e60b5 |
TÜV-revision 2: fyra nya fynd — två Major med samma rot
Uppföljning först: alla tolv fynd från första ronden omprövade utan regression. T-4 noteras med gillande — gallringen förstör nycklar, inte rader, och kolliderar därför varken med append-only-triggarna eller den nya kedjan. Mekanismerna komponerar utan specialfall. T-13, MAJOR. Säkerhetstaket räknade varje mätvärde med matdonId som spårbart. Registeruppslaget härleder kalibreringsdatumet men stämplade aldrig OM kalibreringen gällde vid mottagandet. Ett instrument vars kalibrering gick ut 2019 kunde alltså bära taket "hög" — samtidigt som evidensmodellen graderar samma mätning E1, "kalibrering saknas eller utgången". Systemets två omdömen om samma faktum motsade varandra, och det generösare styrde grinden. Den uppenbara fixen — jämföra datumet mot klockan vid grindprövning — är fel: samma logg ska ge samma utfall om tio år. Faktumet fryses i stället när det fortfarande är ett faktum: mätdonsFakta stämplar kalibreradVidMatning vid mottagandet, taket kräver stämpeln, och klientens eget påstående skrivs alltid över. Strikt bakåt: ett ostämplat mätvärde räknas inte — det som inte kan styrkas bär inte hög. T-14, MAJOR. Leverantörsprotokollet gick förbi mätdonsregistret. T-2 stängde teknikerns väg; en leverantörsprofil kunde fortfarande stämpla in vilket matdonId som helst — T-2 återuppstånden genom sidodörren, och efter T-13 hade det opverifierade påståendet dessutom matat taket. Granskarens mönsternotering: kontrollen infördes vid grinden där fyndet gjordes, inte vid resursen den skyddar — andra gången i kodbasen (grinden själv var en gång enbart klient). Åtgärd: varje protokollmätvärde passerar registret. Okänt instrument NEDGRADERAS i stället för att avvisas — en webhook kan inte registrera instrumentet på plats, och att kasta evidensen vore värre än att gradera den ärligt. Värdet behålls, matdonspåståendena stryks, nedgraderingen redovisas i svaret. T-15, minor. Oförseglad drift syntes bara som en loggrad per avslut. Nu varnar tjänsten vid start — en rad vid boot är ett beslut någon fattat, en rad per avslut är brus — och miljövariabeln är dokumenterad. T-16, minor. Återställningsprovet var skrivet före kedjan: det bevisade att rader överlever en dump, ingenting om sekvens, kedjehash eller försegling — en backup som tappar kedjan återställer en logg som aldrig mer verifierar. Provet var grönt medan det mätte fel sak, vilket första ronden två gånger utpekade som den farligaste sortens grönt. Utökat: länkar, ordning och försegling överlever, och omförsegling avvisas även i den återställda databasen. Under arbetet: en sökväg i patchskriptet matchade aldrig därför att avtryckets avskiljare är NUL-bytes — ersättningen rapporterade ok utan att ha gjort något, och bara integrationstestet avslöjade det. Fixen applicerades om med assert på träff. Samma läxa som T-16, i verktygen. 768 enhetstester, 213 integrationskontroller, återställningsprov, genomgång 4/4, typkontroll, lint gröna. docs/TUV-AUDIT-2.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
1ba5aaaefa |
Härdning efter panelgranskningen: kedjad logg, förseglat avslut, härledd säkerhetsnivå
Fyra av granskningens fynd åtgärdade, i bevisvärdesordning. HASHKEDJAN (ALVA-SPEC-070). Triggrar skyddar loggen mot applikationen, inte mot den som äger databasen — det var granskningens allvarligaste invändning mot ett system vars hela värde är bevisvärde. Varje händelse bär nu en hash av sitt innehåll och föregående händelses hash, beräknad av servern vid insättningen. All skrivning går genom en enda kedjande funktion; en händelse vid sidan av kedjan är ett hål i beviset, så den bekväma vägen förbi finns inte. Digest tas över den LAGRADE händelsen, efter kryptering: verifieringen ska kunna räkna om den ur databasen för all framtid, och krypto-shredding förstör nycklar, inte rader, så kedjan överlever en radering. Radlås per ärende hindrar att två samtidiga batchar forkar kedjan — en falsk larmande verifiering avfärdas snart som trasig, och då är den värdelös. Integrationstestet provar hotmodellen ordagrant: triggern släpps, en rad ändras med full databasbehörighet, triggern återskapas. Verifieringen pekar ut raden — inte bara att något är fel, utan vilken. FÖRSEGLINGEN. Avslut skriver kedjans rot och en HMAC med en nyckel som aldrig finns i databasen, i samma transaktion som avslutshändelsen. Den som räknar om hela kedjan efter sin ändring stoppas av att förseglingen inte går att räkna om utan nyckeln. Engångs: triggern vägrar ändra en satt försegling. Svaret säger vad det bevisar och inte — innehållet är oförändrat sedan mottagandet, ingenting om tiden före, ingenting om sanningshalten. Den texten följer med in i varje rapport som citerar svaret, för det är precis den skillnad en motpartsjurist annars hittar. SIGNATUREN. Fältet hette signatur men var teknikerns egen text — det inbjöd en jurist att tro något som inte gällde. Det skrivs nu ur verifierad token som övriga härkomstfält och intygar exakt vad det kan intyga: vem som var inloggad när avslutet togs emot. SÄKERHETSNIVÅN (ALVA-SPEC-071). Var teknikerns fria val — ett självskattat värde som ser ut som en mätning. Nu ett tak härlett ur underlaget: hög kräver reproducerat symptom OCH spårbart mätvärde ur mätdonsregistret; enbart observationer bär inte ens medel. Teknikern kan sänka men aldrig höja — asymmetrin är poängen, ärlig osäkerhet är information. Grinden spärrar påståenden över taket på alla tio språken, och gränssnittet visar taket medan arbetet pågår i stället för att spara beskedet till avslutsknappen. "Delvis reproducerat" bär inte hög: delvis är ett annat ord för att felet inte är förstått. Taket bet direkt i två av våra egna testfixturer som påstod hög utan spårbart mätdon — vilket är regeln som fungerar, inte testet som är fel. Genomgången avslöjade följdkravet: vid medel/låg kräver panelen att teknikern anger vilka ytterligare kontroller som skulle stärka bedömningen, och det fältet fylls nu i som en tekniker skulle. Kvar ur granskningens lista, medvetet: extern förankring (RFC 3161), klienthashat foto vid upptagning, gränsvärden som data, OIDC/SAML. 766 tester, 200 integrationskontroller mot riktig Postgres — inklusive sabotage som databasägare — genomgång 4/4, portalspärr, typkontroll, lint och artefaktmätning gröna. Utgåva 3.3, API-specen uppdaterad, åtgärderna bokförda i panelrapportens bilaga A. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
b72048e40b |
Ett designsystem, inte två
Portalen höll åtta färger. Arbetsvyn höll fyrtiosju. Det var inte ett slarv utan två system: ui.tsx bar en egen designfilosofi i sitt filhuvud — "industriellt verkstadsverktyg i ETKA-tradition", egen palett, eget snitt, egen rytm — vid sidan av ALVA-SPEC-001. Två beskrivningar av hur en produkt ska se ut blir aldrig lika. Värst syntes det i typsnittet. Arbetsvyn låg utanför `.alva-yta` och ärvde därför värdapplikationens antikva — exakt samma fynd som en gång gjordes om portalen, fast här hade det stått kvar. En tekniker som klickade från portalen in i ett ärende bytte både färg och bokstavsform. De fyrtiosju färgerna avbildas nu på ALVA:s åtta. Tonade fyllningar avskaffas helt: allvarlighet bärs i linje och text, aldrig i en fylld yta. En gul varningsruta drar mer uppmärksamhet än sitt innehåll, och när tre ligger på samma skärm bär ingen av dem något. Grönt finns inte i paletten — blått bär "verifierat", vilket STATUSFARG redan sa. Skuggor och övergångar bort. Panelen är samma form som portalens Block, verktygsraden samma vita rad med en linje under, och ordmärket står först i den precis som i portalens sidhuvud. 176 avståndsklasser snäpptes till 8 px-rutnätet. Knapparna är gemener nu, i BÅDA ytorna. Etiketter och rubriker är versala i ALVA — de är uppmärkning. En knapp är en uppmaning, och i arbetsvyn är uppmaningen ofta en hel mening: "Photograph the instrument panel". Versal sats läses långsammare och bryts sämre, och just den knappen trycks med handskar bredvid ett fordon. Att låta portalen behålla versaler hade gett två knappspråk i samma produkt, vilket var det som skulle bort. Designtestet omfattar nu hela ytan — marknadswebb, portal OCH arbetsvy. Att det bara gällde halva produkten var själva orsaken till att de kunde glida isär: ett designsystem som gäller halva ytan är en stilguide. Mutationsprövat: en enda återinförd blå utanför paletten fäller det. Två fel som bara en skärmdump från en telefon kunde hitta, båda samma sak — text som var vit eller ljusgrå mot den gamla mörkblå raden och blev osynlig mot den vita: tiden i ärendehuvudet och användarnamnet i listan. Tjugo svenska strängar till, alla i mall-literaler och därför osynliga för de tidigare sveparna: loggens radtexter, överlämningsrapporten, AI-promptens fältnamn och "1 tim 37 min". 750 tester, 186 integrationskontroller, genomgång, portalspärr, typkontroll och lint gröna. Artefakten mätt på 390 och 1280 px över femton vyer: inget spill, inga externa begäranden. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
15328c6380 |
Sista svenska raden i arbetsvyn
En hjälptext under felbeskrivningen stod kvar på svenska: den var bruten över två källrader och syntes därför inte för något av mönstren som sveparna använde. Den hittades genom att titta på den byggda sidan i en telefonbredd, vilket är den enda kontroll som ser vad användaren ser. 609 tester, typkontroll och lint rena, artefakten mätt och ren. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
aba9b50c52 |
Metodikerna på engelska — och nyckelorden på båda språken
Sexton metodiker: fasnamn, steg, frågor, svarsalternativ, kontroller och de notiser som säger varför ett steg finns. Cirka 390 strängar, plus demoärendets underlag och evidensmotorns poster. Det här är den enda text i systemet som säger åt någon vad den ska göra med ett fordon. "Mät och dokumentera spänningsfrihet före ingrepp" är inte en etikett, och därför står granskningsstatusen nu i modulhuvudet: texten är skriven på svenska och ÖVERSATT till engelska, alltså inte läst av en fackman på målspråket. Samma krav som ställs på de nio andra språken ställs på den — språksidan säger det rakt ut i stället för att tyst undanta källspråket. Att göra undantaget hade varit precis det sidan varnar för. NYCKELORDEN är avsiktligt tvåspråkiga och blev en union, inte en översättning. De matchas mot teknikerns egen fritext; att byta ut de svenska hade gjort metodikvalet blint för allt en svensk verkstad skriver. 155 engelska nyckelord tillagda, inga svenska borttagna — fler nyckelord kan bara ge fler träffar, aldrig färre. Genomgången är beviset: fyra ärenden drivs genom hela flödet i det byggda gränssnittet — identifiering, pre-diagnostik, metodik, reproducering, felorsak, åtgärd, kvalitetskontroll, slutsats, avslut — och alla fyra stängs. Rubrikerna i utskriften läser nu VIBRATION WHILE DRIVING och HIGH-VOLTAGE SYSTEM — ELECTRIC AND HYBRID. 609 tester, 186 integrationskontroller mot riktig Postgres, genomgång, portalspärr, typkontroll och lint gröna. Artefakten byggd och mätt på 390 och 1280 px: inget spill, inga externa begäranden. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
8aae3a2a97 |
Regelverk, ärendetyper och säkerhetssvar på engelska — med arv där data byter språk
ecm.ts bar regelverkets rådtexter: undantagsorsaker, orsakskategorier, underlagskällor, evidensgrader och de meningar som säger vad som fattas. Cirka hundra strängar, nu på engelska tillsammans med serverns ecm-regler.json — klienten och regelpaketet måste säga samma sak, annars är det inte samma regel. Tre av dem var inte text utan DATA, och där gjordes bytet med arv i stället för rakt av. ÄRENDETYPEN ligger i loggen och slår upp regelpaketets extra krav. Ett gammalt garantiärende vars typ heter "Garanti" hade inte matchat "Warranty", fått noll extra krav, och släppts igenom grinden med FÄRRE krav än när det öppnades — utan att någonting i gränssnittet visade det. ARENDETYP_ARV normaliserar typen vid uppslaget, aldrig i loggen. GALLRINGSTIDEN slås upp på samma nyckel, och det var värre. Ett garantiärende hade fallit ur tabellen och tagit standardtiden 36 månader i stället för 120 — alltså raderat garantiunderlaget sju år i förtid, tyst och oåterkalleligt. Ett uppslag som missar ska ge det försiktigaste utfallet; här gav det det farligaste. Två tester låser det. SÄKERHETSSPÄRREN avgörs av en textsträng. När knappen bytte från "Ja" till "Yes" gick klient och server isär: klienten skrev "Yes", servern jämförde mot "Ja". Utfallet blev fail-closed — högvoltsärenden gick inte att avsluta alls — vilket är rätt riktning för ett fel att falla åt, men det var en slump och inte en konstruktion. `arJakande` känner igen ett ja på alla språken. Att en säkerhetsspärr avgörs av fritext är i sig felet; rätt lösning är ett booleskt fält, och att arvet står synligt i koden är en påminnelse om det. Pre-diagnostikens kvitteringar känns igen på sin text och har fått samma behandling: gamla ärenden hade annars visat en ogjord kontroll för arbete som faktiskt utförts, och teknikern hade kvitterat en gång till — två kvitteringar för samma sak i en append-only logg. Genomgången drev gränssnittet på svenska knappnamn och gick sönder på rätt sätt: den hittade "+ Dokumentera felorsak", "Registrera besked" och kundkanalerna "Telefon"/"E-post", som alla missats av de tidigare svepen. Fyra av fyra ärenden avslutas igen. 609 tester, 186 integrationskontroller mot riktig Postgres, genomgång, portalspärr, typkontroll och lint gröna. Mutationsprövat: utan ARENDETYP_ARV faller två tester, utan `arJakande` ett. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
3ea14575f1 |
Diagnostikgränssnittet på engelska
Portalen var engelsk, men själva arbetsverktyget — det tekniker faktiskt
använder — var svenskt rakt igenom. "Engelska som standard" gällde alltså
skyltfönstret och inte produkten.
Omkring 400 användarsynliga strängar är översatta: etiketter, knappar,
frågor, felmeddelanden, platshållare och de härledda projektionerna
(brief, tidrapport, kundrapport).
Bytet gjordes med en karta och ett skript som bara byter EXAKTA träffar
inom citattecken eller mellan JSX-taggar, aldrig delsträngar. Skriptet
rapporterar dessutom vilka poster som inte fick någon träff — fem
strängar stod som JSX-text efter ett element och syntes därför inte för
mönstret. Utan den rapporten hade de blivit kvar tysta.
Typsystemet fångade det som var farligt. Åtta anrop skickade händelsen
typ: "kommentar" och hade blivit typ: "comment" — en händelsetyp är DATA
i en append-only logg, inte text. Samma sak för `krav === "kommentar"`
och för ArbetsorderGrupp. Det är precis den sortens fel en
massöversättning gör, och precis därför den ska göras i ett projekt som
kompilerar.
Skillnaden mellan etikett och värde är genomgående kodad i domänmodellen
— nycklarna är `godkant`, `hog`, `symptomet_borta`, och det översatta är
_LABEL-posterna. Det var det som gjorde bytet möjligt att göra maskinellt
utan att röra loggen.
En regression från förra commiten är rättad: Slutsats.tsx sållade bort
hypotesbristerna med `text.includes("bemöts inte")`. När granskningen
började svara på engelska slutade jämförelsen tyst att matcha. Den går nu
på nyckeln, som inte byter språk.
Två saker att veta om befintliga installationer: en organisation som
sparat egna objekttyper eller identifieringsmetoder på svenska får
standardlistan tillbaka, eftersom okända värden filtreras bort, och
streckkodsläsarens `typ` matchar nu de engelska metodnamnen. Båda
degraderar till standard i stället för att gå sönder.
Datumen står kvar i ISO-format (sv-SE ger YYYY-MM-DD). Det är inte en
kvarlämnad svenskhet utan det entydiga formatet — en verkstadsrapport
ska inte kunna läsas som 03/04 åt två håll.
Kvar: ecm.ts (regelverkets rådtexter) och metodiker.mjs (metodikernas
steg och kontroller). De tas härnäst.
602 tester, typkontroll och lint rena.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
|
||
|
|
b2c2ce72a3 |
Språksidan: vad som är översatt, vad som är granskat, och skillnaden
En vanlig språkmeny påstår att produkten finns på tio språk och slutar där. Sidan i foten redovisar i stället skillnaden mellan att en text ÄR översatt och att den är GRANSKAD av någon som kan yrket — och visar det på de strängar där skillnaden betyder något: grindens hinder, alltså de meningar som nekar en tekniker att avsluta ett ärende. Att välja just dem är avsiktligt. En spärr ingen förstår är en spärr utan väg förbi, så det är rätt strängar att döma en översättning efter. Väljaren byter språk direkt i provet; åtta av tio språk möts därefter av beskedet att metodiken inte är fackgranskad på språket. Det är ett obekvämt sätt att presentera sin egen produkt och hela poängen med sidan: en verkstadschef i Rumänien som får veta det i förväg kan planera för det, samma chef som får veta det av en tekniker som missförstått en säkerhetsinstruktion kan inte. Varningen står UNDER provet, inte över. Den som just läst fem meningar på sitt eget språk ska mötas av vad de inte garanterar — inte varnas i förväg och sedan lugnas av att texten ser bra ut. Sidan ligger i foten och inte i portalens navigation. Den är dokumentation snarare än ett arbetsverktyg, och portalraden har redan tio poster. Språkknapparna ligger i rutnät, inte flexradbrytning. Tio språk bröts av flex till nio plus ett ensamt, och den ensamma knappen läste sig som en eftertanke i stället för som ett språk bland tio. Två kolumner på telefon och fem på skärm gör tio jämnt i båda riktningarna. Utgåva 3.2 dokumenterad. 602 tester, typkontroll och lint rena. Artefakten byggd och mätt på 390 och 1280 px över femton vyer: inget spill, inga externa begäranden. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
322d228c80 |
ALVA-RULE-200 gällde bara på svenska — nu på tio språk
Slutsatsgranskningen avvisar icke-svar med en ordlista: "klart", "ok", "trasig". Listan var enbart svensk. En tysk tekniker som skrev "erledigt" i motiveringsfältet passerade filtret — inte därför att texten dög, utan därför att filtret bara kände igen "klart". Grinden släppte igenom avslutet och rapporten såg fullständig ut. Det var alltså inte en översättningsbrist utan ett hål i den regel som är hela produktens värde, och hålet fanns på varje marknad utom en. Samma sak åt andra hållet: orsaksorden som visar att en text innehåller ett resonemang var svenska, liksom evidensorden. Engelskans "photo" innehåller inte "foto", så "the photo shows the arcing at pin 14" räknades inte som en hänvisning till underlag. Följden hade varit värre än ett släppt avslut — en korrekt skriven motivering hade nekats, och en spärr som nekar rätt svar är en spärr man lär sig kringgå. Listorna ligger nu i sprak/ord.mjs, per språk, och slås ihop till en union i stället för att väljas efter inställning. Ett icke-svar är ett icke-svar oavsett språk — jämförelsen görs mot hela fältet, så en tekniker som skriver på ett annat språk än organisationens ska inte kunna passera på den vägen. Orsaks- och evidensorden går åt motsatt håll: unionen gör kontrollen mer tillåtande, aldrig strängare, och det är rätt riktning att fela åt. Medvetet utanför listorna: "inget", "keine", "none". Att ingenting kvarstår osäkert är ett giltigt och ofta korrekt svar; att göra det till ett icke-svar hade tvingat fram utfyllnad, och utfyllnad är sämre än ett kort sant svar. Ett test låser det. Bristernas texter kommer nu ur katalogen och bär sin nyckel, precis som grindens hinder. Fältnamnet översätts med resten av meningen — "Begründung fehlt.", inte "Motivering fehlt.". Mutationsprövat: med listan återställd till enbart svenska föll nio tester, ett per språk. Svenska och engelska är genomgångna; övriga listor är en första uppsättning och står som ogranskade i filhuvudet, av samma skäl som `granskat` i SPRAK — de är metodik, inte gränssnitt. 597 tester, 186 integrationskontroller, typkontroll, lint och genomgång gröna. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
be10704349 |
Grinden talar organisationens språk — engelska som standard
Kvalitetsgrinden formulerade sina hinder på svenska, hårdkodat. I en produkt där engelska är standardspråket betyder det att en spärr kan neka ett avslut på ett språk teknikern inte läser. Det är en spärr utan väg förbi: teknikern ser att systemet vägrar men inte varför, och den enda utvägen blir att ringa någon. Det är då regeln slutar vara en regel och blir ett hinder man lär sig kringgå. Varje hinder bär nu både nyckel och färdig text. Nyckeln därför att en klient som byter språk ska kunna rendera om utan att fråga servern; texten därför att ett hinder som hamnar i en logg eller en PDF måste gå att läsa utan katalogen. Hindrets id och nyckel är språkoberoende — det är bara texten som byter. Språket är organisationens, inte användarens. En verkstad i Tyskland med en polsk tekniker ska ha ett gemensamt dokumentationsspråk; rapporten ska inte byta språk beroende på vem som råkade stänga ärendet. Det lagras i organisationens inställningar, och en felstavad landskod blir engelska i stället för ett fel — språkinställningen är en etikett och ska inte hindra någon från att spara sina objekttyper. SPARRFRAGOR bär nu nycklar i stället för svensk text. Testet som jämför serverns lista med klientens jämför nycklar, så listorna kan fortfarande inte glida isär. Två tester prövade svenska ord i grindens utdata och gick sönder, vilket var rätt av dem. De prövar nu nyckeln — texten är översatt och byter språk med organisationen, och att pröva svenska ord hade gjort dem till tester av vilket språk som råkar vara standard. Ett nytt test prövar det som faktiskt betyder något: samma id, samma nyckel, olika text. Integrationstestet följer språket hela vägen — organisationens inställning, genom servern, ut i det 409-svar som nekar avslutet: engelska som standard, tyska efter byte, engelska igen vid okänd kod. 582 tester, 186 integrationskontroller mot riktig Postgres, genomgång och portalspärr gröna. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
995858174d |
Språk: engelska som källa, tio EU-språk, och en struktur som inte får översättas
Engelska är standard- och källspråk. Nio översättningar till: tyska,
franska, spanska, italienska, polska, nederländska, portugisiska,
rumänska och svenska.
Två sorters text, behandlade olika. GRÄNSSNITTSTEXT faller tillbaka på
engelska tyst — en engelsk knapp hos en tysk användare är irriterande
men ofarlig. METODIKINNEHÅLL gör det aldrig tyst: det märks som
ogranskat, med språket namngivet. Skälet står i modulhuvudet och är hela
poängen med uppdelningen: engelska SYNS som ett annat språk, medan en
felaktig översättning ser ut som en instruktion. En maskinöversatt
säkerhetsanvisning som ingen fackman läst är därför sämre än en engelsk.
Bara engelska och svenska är `granskat: true`.
Strukturen översätts inte. ALVA-SPEC-001 §2 slår fast att fasnamn och
statusord skrivs likadant i varje land — en revisor ska kunna läsa en
rumänsk och en tysk rapport utan att veta vilket språk verkstaden
arbetar på. Det hade gått att skriva in dem oöversatta i varje katalog
och låsa dem med ett test; det är svagare, för en översättare som ser
"Passed" i den polska filen översätter den, och testet blir en tvist i
stället för en regel. Nycklarna saknas i stället helt i
översättningarna och `t()` hämtar dem alltid ur engelskan. Då finns
ingenting att översätta fel.
Testet räknar inte bara nycklar — det går att få grönt genom att
kopiera engelskan till tio filer. Det prövar fyra saker: att katalogen
är komplett, att strukturen inte är översatt, att inget språk är
engelska i förklädnad (tak på 25 % identiska strängar), och att
variabelhållarna överlevde. {procent} som blir {percent} i den franska
filen ger inget fel — den ger "{percent} % de l'interface" på skärmen,
för alltid.
Mutationsprövat: en borttagen nyckel, en översatt statussträng, en
trasig variabelhållare och en polsk fil som var en kopia av engelskan
gav sex röda tester. Polskan har dessutom en egen anmärkning i
filhuvudet: {sprak} sätter in "Polski" i nominativ, och "w języku
Polski" är fel — meningarna är därför omskrivna så att namnet står som
etikett i parentes.
581 tester, typkontroll och lint rena.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
|
||
|
|
0566ddadc6 |
Startsidan: bort med färdplanen, och rapportens frågor i stället för dess disposition
Färdplanen är borttagen. Fyra faser med "Planned" och "Specified" säger inget om vad man får i dag — den lovar framtid på en sida där läsaren försöker avgöra om nuet duger. Kvartalsrapporten stod som en tabell med kolumnerna Section, Content och Basis: alltså en beskrivning av rapportens DISPOSITION. Det är dokumentation, inte en startsida — läsaren fick veta hur rapporten är uppbyggd innan den fått veta vad den svarar på, och "SECTION" upprepat sex gånger var det mest framträdande på skärmen. Nu står frågorna. Vilka fel diagnosticerar vi rätt första gången? Hur ofta visar sig en misstänkt orsak vara den verkliga? Vilka fel kommer tillbaka? Vilka steg hoppas över, och varför? En verkstadschef känner igen sina egna frågor; ingen känner igen en innehållsförteckning. Verifierat mot den byggda artefakten: ROADMAP borta, SECTION-etiketten borta, 491 tester, artefakten ren. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
934bc2e4bc |
Staplade tabeller: rubrik i stället för arton etiketter
Den staplade formen upprepade kolumnnamnet före VARJE cell. Sex rader gånger tre kolumner blev arton etiketter av samma vikt, och innehållet drunknade i dem — kvartalsrapporten på startsidan var en vägg av SECTION / CONTENT / BASIS där själva texten var det minst framträdande. Etiketten för första kolumnen var dessutom rent brus. Den cellen ÄR radens identitet, och att skriva "SEKTION" ovanför "New validated diagnostic patterns" säger ingenting som inte redan står där. Första cellen är därför rubrik utan etikett, resten etiketteras, och blocken skiljs med ram och bakgrund i stället för med en hårstreckslinje — ögat ska se var en post börjar utan att läsa. Arton etiketter blev sex rubriker och tolv små etiketter. Ändringen ligger i Tabell och gäller därmed varje staplad tabell i portalen: garantier, försäkring, support, abonnemang, fakturor, Impressum och utgåvor. 491 tester · genomgången 4/4 · artefakten ren. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
5579006e79 |
Abonnemang: gratis start, månadsfaktura, och en låsning som aldrig rör historiken
Kontot startar på Free och stannar där tills någon väljer annat. En provperiod som tyst börjar kosta är samma sorts fälla produkten finns för att undvika. Fakturan skapas ändå vid registreringen — på noll kronor — därför att den etablerar serien och visar kunden exakt vad den inte betalar för. Fyra nivåer: Free (hela metoden, två konton), Standard, Premium, Enterprise. Enterprise har inget listpris i stället för ett påhittat. Basavgift plus per aktiv användare, och nivån är en HÄNDELSE — vilken nivå som gällde när en faktura utfärdades måste gå att svara på i efterhand, och en kolumn som skrivits över kan inte svara. Månadsjobbet är idempotent på perioden: kör det två gånger samma dygn och den andra körningen fakturerar ingenting. Ett fakturajobb som dubbelfakturerar vid en omstart är värre än ett som inte kör alls. Perioden räknas från registreringsdagen, inte från den första i månaden — den som registrerar sig den 20:e ska inte få en faktura på elva dagar som sin första upplevelse av produkten. PDF utan beroenden. Kravet var inga beroenden, och ett PDF-bibliotek drar in fem till för att rita text i två spalter. PDF är ett textformat; generatorn är tvåhundra rader som går att läsa. Renderad och verifierad i Chromium. Kunden hämtar fakturan själv eller anger en adress — bägge vägar leder till samma dokument, och e-post är ett tillägg, inte den enda vägen till sitt eget underlag. ---- Låsningen och dess gräns ------------------------------------------ Vi litar på kunden: inget kort, ingen förskottsbetalning, ingen spärr innan någon fått veta. Förfallen faktura ger synlig nedräkning i 14 dagar och sedan stopp för nya ärenden. Men läsning och export är sanna i ALLA tillstånd, och det är inte generositet. Ärendeloggen är verkstadens underlag i en garanti- eller försäkringstvist som gäller DERAS kund — en tredje part utan del i vår obetalda faktura. Att göra det oåtkomligt vore att använda någon annans rättsliga ställning som påtryckningsmedel. Prövat från flera håll, eftersom det är en regel som är lätt att tumma på under press. En nollfaktura kan aldrig låsa någon. Free fakturerar noll, och en obetald nollfaktura är en bokföringspost, inte en skuld. ---- Tre fynd som testerna grävde fram ---------------------------------- 1. En kuverterad nyckel gjorde HELA organisationens övriga ärenden oläsbara när huvudnyckeln saknades — nycklarFor laddar alla nycklar, och en enda som inte gick att öppna kastade. En delvis migrerad organisation blev alltså helt stum av ett fel som gällde ett ärende. Nu hoppas den över, med varning i loggen, och fälten maskeras — vilket dessutom är rätt utfall i sak: det är precis vad krypto-shredding lämnar efter sig. 2. Integrationstestet försökte backdatera abonnemangets registrering och stoppades av min egen trigger. Att testet fick böja sig för regeln och inte tvärtom är poängen med regeln. 3. Palettestet räknade upp färgerna som en andra lista — samma dubblering som M-7 handlade om. Det läser dem nu ur FARG, med ett tak på åtta värden som motvikt: en palett som växer förbi det är en färglåda. 491 enhetstester · 179 integrationskontroller · genomgången 4/4 · portalspärren 18/18. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
ae5acbed92 |
Fotograferad mätarställning, versionshistorik och tysk kravbild i foten
---- Mätarställningen ska fotograferas ---------------------------------- Klienten krävde redan fotot: värdefältet visas först efter bilden. Men GRINDEN gjorde det inte, och en regel som bara finns i gränssnittet är en vana — inte en spärr. Det är samma förhållande som QUALITET C-2 gällde, fast åt andra hållet: här var servern svagare, vilket är värre, eftersom servern är den auktoritativa. Skillnaden är hela uppgiftens bevisvärde. En inskriven siffra är teknikerns påstående om vad som stod på mätaren; ett foto visar vad som stod där. Mätarställningen avgör garanti- och försäkringsfrågor i efterhand och är den enda uppgift i ärendet någon kan ha ett intresse av att skriva fel. Evidensgraderingen följer nu med: fotograferad ger E2, inskriven ger E1 och märks som inskriven i rapporten. Undantag finns och måste finnas — slocknad display, oåtkomlig timräknare — men kräver motivering, som det nekade historiksvaret. ---- Versionen räknades aldrig upp -------------------------------------- Systemet påstod "ALVA 1.0" efter tre revisioner, en fakturamodul och en stängd portal. Versionen sa alltså ingenting om vad man fick. Historiken är HÄRLEDD UR VAD SOM FAKTISKT LEVERERATS och varje post pekar på sin commit. En utgåva som inte går att peka på hör inte hemma i listan — en påhittad ändringslogg är samma obefogade säkerhet som produkten finns för att undvika. Första siffran höjs bara när GARANTIERNA ändras, vilket hänt två gånger: 2.0 när fakturan blev ett härlett dokument, 3.0 när TÜV-härdningen ändrade vad loggen garanterar. Nuvarande: 3.1. Och ett fynd på vägen: ritningsstämpeln läste versionen ur den AKTUELLA konstanten, så ett ärende stängt under 1.0 visade 3.1 — precis det stämpelns egen beskrivning säger att den inte ska göra. Avslutshändelsen bär numera versionen, och stämpeln läser den därifrån. Äldre ärenden säger uttryckligen "ej registrerad" i stället för att låna dagens siffra. ---- Tysk kravbild i foten ---------------------------------------------- Listan är tysk därför att § 5 DDG är den strängaste och mest utkrävbara i EU: klarar man den klarar man de andra marknaderna på köpet. Två fällor som är aktuella just nu, och bägge ser fortfarande ut som upplysningar: ODR-LÄNKEN SKA BORT. Förordning 524/2013 upphävdes genom förordning (EU) 2024/3228 och plattformen stängdes 20 juli 2025. Länken har legat i tiotusentals fotnoter sedan 2016 och pekar numera ingenstans. Foten saknar den medvetet. § 5 TMG HETER § 5 DDG sedan 14 maj 2024. Modulen hittar inte på uppgifter. Ett Impressum med påhittad adress är inte ett halvfärdigt Impressum utan ett vilseledande, och skadan större än den tomma rutans. Osatta fält redovisas som en åtgärdslista med rättslig grund, så driften kan spärra en driftsättning på listan i stället för att upptäcka bristen när brevet kommer. 460 enhetstester · genomgången 4/4 · typkontroll ren. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
a94c228cab |
Garantiregimer, försäkringsvillkor och felanmälan i ärendet
---- Garantier (ALVA-SPEC-040) ----------------------------------------- Skiljelinjen mellan LAGSTADGAT och AVTALAT bär allt annat, och den förväxlas dagligen åt bägge håll. Överraskande lite av det verkstaden kallar garanti är lagstadgat: nybilsgaranti avtalad. Ingen lag i EU eller USA kräver den. rostskyddsgaranti avtalad. Ingen lag kräver den, någonstans. lackgaranti avtalad. drivlinegaranti avtalad. avgasgaranti LAGSTADGAD i bägge, och den enda som är det. Att kalla rostskyddet lagstadgat är fel; att kalla avgasgarantin en tillverkarutfästelse är fel åt andra hållet, och det andra felet kostar kunden pengar — en katalysator på en sexårig bil offereras rutinmässigt som en betald reparation när den inte är det. Varje lagstadgad post bär källa och kontrolldatum: 2019/771 (2 år, säljaren — inte tillverkaren), MVBER 461/2010 förlängd till 2028, 715/2007 (5 år/100 000 km), 2024/1257 (8 år/160 000 km, batteri 80 % vid 5 år och 72 % vid 8), CAA § 207 (2/24 000 och 8/80 000 miles), Magnuson–Moss § 2302(c), CARB (3/50 000 och 7/70 000), ACC II (70 % SoH vid 8 år/100 000 miles). Bedömningen skiljer INOM, UTANFÖR och OKLART. Saknas underlag blir det oklart, aldrig utanför — att påstå att en garanti gått ut när underlaget inte räcker är det enda felet här som kostar kunden pengar. ---- Försäkring (ALVA-SPEC-041) ---------------------------------------- Modulen avgör ingenting och kan inte avgöra något. Vad som gäller bestäms av kundens eget försäkringsbrev och villkoren vid tecknandet — inte av vad ett bolag skriver i dag och inte av vad vi noterat. Testerna låser att resultatet inte innehåller något fält som liknar ett utfall, och att ett fordon utanför samtliga noterade gränser ändå inte får ett nej: registret kan vara ofullständigt och produkten en annan. Det som står överst är de sju villkoren som avgör en maskinskadefråga. Ålder och sträcka är två av dem; de fem andra avgör oftare. Registret med If, Folksam, Trygg-Hansa, Svedea, WaterCircles och Hedvig ligger under, med källa och avläsningsdatum per post, och märks som föråldrat efter 180 dagar i stället för att se aktuellt ut. ---- Felanmälan i ärendet (ALVA-PROC-0050) ----------------------------- En anmälningsknapp som bara finns i en portalvy nås aldrig av den som står med händerna i en bil. Den ligger därför i varje ärende, och tar med sitt sammanhang självt: ärende, metodik, plattformsversion och spår-id. Teknikern minns inte plattformsversionen, och att fråga efter den är att lägga över vårt problem på verkstaden. Sammanhanget HÄRLEDS och kan inte smugglas: ett regnr i anropet släpps inte igenom. En supportanmälan är inte ett skäl att flytta personuppgifter till ett annat system. Bevisat i integrationstestet. Anmälan är oföränderlig och statusen en projektion av inläggen — samma skäl som för fakturan: en anmälan vars historia kan skrivas om är inte ett underlag när någon frågar hur länge felet var känt. Verkstaden svarar i sitt eget ärende; status sätts av supporten med egen nyckel. ---- Historikkontrollen ------------------------------------------------- Kravet fanns redan: klienten öppnar inte metodiken förrän pre-diagnostiken är besvarad, och ett nej kräver skriven motivering. Det var dock aldrig BEVISAT att spärren håller. Genomgången prövar nu att metodiken inte går att nå medan historikfrågan står obesvarad — i det enda ögonblick det går att pröva, eftersom svaret därefter redan är avgivet. 429 enhetstester · 157 integrationskontroller mot riktig Postgres · genomgången 4/4 · portalspärren 16/16. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
6790b60182 |
Symmetri i huvudet och i knapparna
Navigationen trycktes ihop mot högerkanten med ett tomrum efter ordmärket. På smal skärm ligger den nu på egen rad och fördelas över hela måttet — samma fördelning som sidfoten redan använder. Raden får sin balans av marginalerna i stället för av att posterna klumpas ihop. Mätt: noll pixlar kvar på bägge sidor. Portalens sex länkar blir på 360 px en tvåkolumnsindex, vilket läser sig som avsikt och inte som spill. Knapparna var innehållsbreda, så REQUEST ACCOUNT blev dubbelt så bred som LOGIN. Två knappar bredvid varandra där den ena är dubbelt så bred läser sig som en huvudåtgärd och en eftertanke, oavsett vad de heter — och det är inte förhållandet mellan dem. Rutnätet ger dem samma bredd; vikten skiljs av fyllning mot kontur, som resten av systemet gör. Lika bredd räckte inte: REQUEST ACCOUNT bryts till två rader och knapparna blev då olika HÖGA, vilket är samma obalans en rad ned. Bägge fyller nu sin cell. Mätt: 163x57 mot 163x57. ---- Och ett test som slutade mäta ------------------------------------- Namntestet från förra ändringen matchade markup-formen, inte invarianten. När <Link> fick en className hittade mönstret noll knappar — testet slutade mäta i stället för att falla. Det enda som avslöjade det var kravet att det ska hitta NÅGOT, och det är därför kravet står där i stället för att tas för givet. Mutationstestat igen efter rättelsen: bägge testen faller när "Customer login" läggs tillbaka. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
0cc4f1578c |
Inloggningen heter Login, inte Customer login
Startsidans knapp hette "Customer login" medan navigationen kallade samma sida "Login". Två namn på samma destination är förvirrande i sig, men det här var värre än så: "customer" är i det här systemet FORDONETS ÄGARE — den som får delningslänken och godkänner en åtgärd. Verkstaden som loggar in är inte den. Knappen lovade alltså en ingång för fel person, med produktens eget ord för någon annan. Två test låser det: varje länk till inloggningen bär navigationens namn på destinationen, och ingen ingång kallar verkstaden för kund. Mutationstestade — bägge faller när "Customer login" läggs tillbaka. Övriga "customer" på ytan står kvar. De handlar om fordonets ägare, och där är ordet rätt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
b147694e31 |
Härdning av hela TÜV-revisionen
Tio av tolv fynd stängda, två reducerade med skälen utskrivna. Varje
stängning prövas av integrationssviten mot riktig Postgres — 144
kontroller, upp från 100.
T-1 Händelsenyckeln är nu (arende_id, id). Det finns inget delat
namnrum kvar att ockupera, så attacken saknar yta i stället för att
vara mildrad. Inom ett ärende bedöms en kollision på klientens
avtryck — en hash av det kanoniserade innehåll klienten skickade,
taget före serverns egna fält och före krypteringen, eftersom
varken raden eller nyttolasten går att jämföra. Identiskt innehåll
är fortfarande idempotent; samma id med annat innehåll ger 409 och
skriver ingenting alls, inte heller resten av satsen. Samma attack
en nivå upp — ärende-id är lika förutsägbart — stängs separat: ett
id som ägs av en annan organisation ger 409 i stället för att tyst
låta bli, vilket tidigare lämnade offrets ärende oskapat och varje
senare synk svarande 404.
T-2 Mätdonet slås upp i registret. Beteckning och kalibrering HÄRLEDS
därifrån och skriver över det klienten skickade. Okänt mätdon ger
400. Utgånget avvisas inte — mätningen gjordes — men registrets
datum följer med, så graderingen faller på registrets uppgift. Ett
mätvärde utan mätdon får sina påstådda uppgifter borttagna.
T-3 Reducerad, inte stängd. Personnycklarna kuverteras under en
huvudnyckel utanför databasen. En återställd dump ger nycklar som
inte öppnas — verifierat genom att starta om utan huvudnyckeln. Vad
som återstår står utskrivet: en backup tagen FÖRE en radering, plus
huvudnyckeln, återställer fortfarande uppgifterna.
Därtill: gallringen verkställs nu av ett eget jobb och grupperar på det
blindade fordonsindexet så att en delad nyckel inte gallras för tidigt
(T-4) · AI-avlästa mätvärden bär härkomst (T-5) · bcrypt kostnad 12
(T-6) · åtkomstloggen och raderingsregistret är append-only, med en
smalare regel för personnycklarna som måste kunna förstöras (T-7) ·
åtkomstloggen dokumenterad (T-8) · ett externt regelpaket utan signatur
spärrar avslut (T-9) · CORS faller inte längre öppet (T-10) · exp krävs
i token (T-11) · react-router 7 (T-12, med den kvarvarande avvikelsen
motiverad).
Den motspelande hyresgästen som revisionen efterlyste finns nu som
testform och körs i CI.
---- Vad härdningen själv avslöjade -----------------------------------
Två av rättelserna var kortvarigt fel på samma sätt som fynden, och
bägge fångades bara av att jag försökte bevisa dem:
T-7-testet var grönt mot en TOM tabell. En radnivåtrigger har inga
rader att fyra på, så delete lyckades och kontrollen mätte ingenting.
T-6-testet påstod anropet, inte kostnaden. toContain("gen_salt('bf')")
hade accepterat kostnad 6 för evigt — och gjorde det, så länge det
fanns.
Bägge är mönstret revisionen namngav: en kontroll som är riktig i sina
egna termer och oprövad vid sin gräns. Det gäller tester lika mycket som
kod.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
|
||
|
|
3b83fc94e9 |
Portalen är stängd på riktigt — m-9 stängd
Anmärkningen var att en inloggning som SER ut att autentisera ger portalen bakom den en auktoritet den inte har. Rättelsen är inte att ta bort skylten utan att göra spärren verklig där det finns något att spärra mot. Med plattformen konfigurerad autentiserar inloggningen mot /api/auth/logga-in, varje portalväg går genom Portalvakt, och fakturavyn läser organisationens egna fakturor ur GET /api/fakturor. Misslyckas hämtningen visas felet — inte exemplet: data som ser äkta ut men inte är det är värre än ett synligt fel. Utloggningen finns i portalhuvudet och rensar sessionen på riktigt. Utan konfigurerad plattform finns ingen session att kräva, och demonstrationsmärkningen visas exakt i det läget. ---- Varför garantin inte är ett källkodstest ------------------------ Sviten kan bara läsa koden och se att vakten är inkopplad. Släpper den igenom ändå — fel villkor, fel ordning, ett <Navigate> som aldrig hinner rendera — ser koden likadan ut. Och en spärr som inte spärrar är precis det m-9 handlade om. e2e/portalsparr.mjs bygger därför med plattformen konfigurerad och tittar var besökaren faktiskt hamnar: fem vägar spärrade utan session, fem öppna med, utloggning som rensar token och stänger portalen igen. Mutationstestad — att plocka bort vakten från en enda route fäller den. Bevisad: 374 enhetstester, typkontroll, genomgången 4/4 ärenden, portalspärren 14/14. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
d1b361573e |
Faktureringens serverdel — och två fel den grävde fram
Fakturering fanns som modell, vy och tester men aldrig som något en
server kunde utfärda. Nu finns tabellerna, vägarna och gränsen mellan
kund och utfärdare.
Beloppet tas aldrig emot. Det härleds ur organisationens faktiska
tillstånd — de konton som verkligen kan logga in, de moduler som
verkligen är påslagna — och ett anrop som ändå skickar rader eller
totalt avvisas med 400 i stället för att tigas ihjäl. Samma hållning som
mot okända fält i händelseschemat.
Fakturaraden är oföränderlig, skyddad av samma trigger som loggen. Det
får en följd som är lätt att missa: "betald" kan då inte vara en kolumn
som uppdateras. Betalningen är en egen händelse och statusen en
projektion av händelserna. En felaktig faktura rättas inte heller — den
bemöts av en kreditfaktura med omvänt tecken och ett granskbart skäl.
Utfärdaren är inte en användare. Ingen av rollerna i en verkstad är
motpart i avtalet, så en kunds administratör kan varken utfärda sin egen
faktura eller bokföra den som betald; utfärdandet kräver en egen nyckel,
och utan den i miljön utfärdas ingenting alls. Nummerserien är utan
luckor — en sequence hade varit billigare men lämnar hål vid rollback,
och ett underlag med hål i är en lista.
---- Vad som föll ut när sviten faktiskt kördes ------------------------
integrationstest.sh fanns men låg utanför CI, och den föll på andra
raden — i kod som inte hade med fakturering att göra:
C-7 Append-only-triggern på felsokning_arenden förbjöd ALL update. Två
av radens kolumner är härledda efteråt: gallringsdatumet vid avslut
och det blindade fordonsindexet. Alltså föll varje avslut med 500,
efter att kvalitetsgrinden redan godkänt ärendet. Skyddet är nu
kolumnvis: identitet och ursprung är fortfarande låsta, radering
fortfarande omöjlig, men de fält systemet självt härleder får
skrivas.
C-8 Fordonshistoriken sökte i klartext efter en identifierare som
krypteras i vila. Jämförelsen kunde aldrig träffa: historiken
svarade tomt på varje fordon, med 200. Det blindade indexet fanns
just för den frågan och var aldrig inkopplat.
Bägge ligger i backenden till produktens centrala löfte — att ett
avslutat ärende är ett varaktigt underlag — och ingen av dem kunde synas
i en grön enhetssvit, eftersom ingen av dem kan falla utan en databas.
Sviten är därför ett eget CI-jobb nu.
Bevisad: 364 enhetstester, 100+ integrationskontroller mot riktig
Postgres, genomgången 4/4 ärenden. Spärren mot angivet belopp
mutationstestad — borttagen ger den 201 i stället för 400.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
|
||
|
|
c9fdef27c9 |
Text som lade sig ovanpå text — och kontrollen som inte såg det
Etiketten AUTHENTICATION är bredare än 96 px och kan inte brytas. Den staplade mobilformen gav den `w-[96px]`, så texten rann ut ur sin ruta medan värdet började vid 96 px. Bokstäverna hamnade ovanpå varandra. `min-w` låter korta etiketter hålla kolumnen och långa knuffa värdet till nästa rad i stället. Det allvarligare var att breddmätningen i genomgången inte kunde ha hittat det här: överspill gör inte dokumentet bredare. Ett första försök att jämföra elementens rutor rapporterade noll krockar med felet återinlagt — rutorna skar aldrig varandra, bara bokstäverna gjorde det. Mätningen jämför därför nu elementets textbredd med dess egen ruta, och görs över portalens åtta vyer i telefonbredd. Bevisad: med `w-[96px]` återinlagt faller genomgången med exitkod 1 och pekar på kunskapskällor och Authentication. Med `min-w` grön igen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
b457543ede |
Fakturering i systemet — och ingen betalleverantör
ALVA säljs inte över disk. Aktiveringssekvensen på webbplatsen har hela tiden sagt det: ansökan granskas, faktura utfärdas, betalning registreras, organisationen aktiveras. Ändå laddade sidan Stripe. Stripe. `@stripe/stripe-js` injicerar sitt skript redan vid import, inte när någon ska betala, så ALVA hämtade en betalleverantör vid varje sidvisning trots att produkten aldrig tar emot en betalning. Bakom artefaktens CSP blockerades anropet och syntes som ett fel i konsolen på ett system som inte har en kassa. Importen går nu mot `/pure`, som är samma modul utan sidoeffekten. Butikens kassa fungerar som förut, men bara när någon faktiskt öppnar den. Externa begäranden på ALVA-ytan: noll. Faktureringen. Beloppet måste komma någonstans ifrån, och det enda hållbara stället är organisationens faktiska tillstånd: aktiva konton, licensperiod, påslagna moduler. En summa någon skriver in kan säga emot verkligheten — en härledd kan inte det. Samma resonemang som sammanfattningen. Varje rad bär sitt underlag, så en granskare ser varför summan blev den den blev utan att fråga någon. Beloppen räknas i öre, momsen på nettot och inte per rad, och en utfärdad faktura ändras aldrig: en felaktig faktura krediteras med en post som pekar tillbaka och kräver ett skäl. Samma regel som för händelseloggen. Prislistan ligger på ett ställe och är märkt som platshållare — den ska sättas per marknad. Mekanismen är oberoende av siffrorna. Ingen betalningshantering, inga kortuppgifter, ingen extern tjänst. Betalning registreras av en administratör när pengarna kommit in; systemet påstår aldrig att något är betalt utan att en människa sagt det. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
9533a90b7b |
Skriv om demonstrationsmärkningen så den inte går att missförstå
Första formuleringen sa "Applications are handled outside this demonstration". Det läses lika gärna som att ansökningar tas emot någon annanstans, av ett riktigt system. Det gör de inte — det finns ingen mottagning alls. En läsare frågade vad meningen betydde, vilket är svaret på om den var tydlig. Värre var att produktens beskrivning av avsedd handläggning stod direkt under: två meningar bredvid varandra där den ena säger att ingenting händer och den andra beskriver en granskningsprocess. De upphävde varandra. Den senare är nu märkt "Intended operation:". Inloggningens ruta hänvisade till att den riktiga autentiseringen finns i plattformstjänsten, vilket inte hjälper någon som står på sidan. Den säger nu vad besökaren ska göra: skriv vad som helst, lösenordet kontrolleras inte, inget konto behövs. En märkning som inte går att missförstå säger två saker — att ingenting sker, och vad läsaren ska göra i stället. Fyra tester låser båda. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
3ffedcd78e |
Märk de ytor som inte gör något (QUALITY-AUDIT-2 · m-9)
Inloggningen autentiserar ingenting: vilken organisation och vilket användarnamn som helst släpps in, och lösenordet kontrolleras inte. Kontoansökan skickar ingenting, och referensen på kvittenssidan bildas i webbläsaren. Portalens siffror är fasta exempelvärden. Bägge ser ändå ut som att de gör något, och två personer i rad har försökt använda dem på riktigt innan de frågade. Det är precis vad fyndet förutsade: en yta som ser färdig ut planerar man efter. Integrationssidan tillämpar redan den här måttstocken på sig själv — en profil står `draft` tills den körts mot leverantören, med motiveringen att en lista där allt ser färdigt ut är den snabbaste vägen till ett misslyckat införande. Samma regel gäller nu resten av ytan. Rutan säger vad som INTE sker, inte vad som ska komma. Ett löfte om framtida funktion vore samma fel i ny form, och ett test avvisar formuleringar av den sorten. Det här stänger inte m-9 helt. Den ärliga slutfixen är att låsa portalrutten bakom den riktiga plattformssessionen, vilket är ett beslut om vad portalen ska vara — men tills dess vilseleder den inte. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
66762629df |
Bäddad typografi, tätare spärrning, räta hörn och ritningsstämpel
Fyra saker som alla svarar på samma sak: ALVA såg fortfarande inte ut som det den påstår sig vara. Snittet som fil. Fallkedjan säkrade ordningen men inte utfallet — utan DIN installerad föll ytan ned till vad enheten råkade ha, Helvetica på en iPhone och Roboto på en Android. Ett system som beskriver sig som en standard får inte se olika ut beroende på var det öppnas. IBM Plex Sans, specens tredje tillåtna snitt, bakas därför in: latinsk delmängd, tre textvikter och två för monospace, drygt 100 kB. Licensen följer med. Vite bakar in woff2 som data-URI. Det är inte en optimering utan ett krav: ALVA publiceras bland annat som en självbärande sida bakom en CSP där varje extern begäran blockeras, och en @font-face mot en assetfil hade tyst fallit tillbaka till enhetens eget snitt — alltså precis det inbäddningen ska avskaffa. Bara woff2; värdapplikationens bilder är megabyte stora och förblir egna filer. Spärrningen ett steg tätare genomgående. DIN-satta OEM-dokument är tätare än vad ytan var, och med rätt bokstavsform tål den det. Räta hörn i felsökningen. 69 förekomster av rundad radie, alla ur Lovable-arvet. Ett verkstadssystem har räta hörn. Ritningsstämpel sist i rapporten: beteckning, regelpaket, evidensmodell, plattformsversion, status och utgåvedatum. En granskare måste kunna se vilka versioner som gällde när ärendet stängdes, inte vilka som gäller den dag rapporten läses. Fyra tester låser inbäddningen, inklusive att ingen @font-face pekar mot en extern värd. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
9668cc256b |
Ge ALVA-ytan sin egen typografi enligt ALVA-SPEC-001
ALVA satte inget eget snitt och ärvde därför värdapplikationens `Crimson Text` — en antikva. Specens paragraf 6 föreskriver DIN 2014, med FF DIN och IBM Plex Sans som tillåtna alternativ. Skillnaden är inte kosmetisk. Bokstavsformen är det första som säger vilken tradition ett verktyg tillhör, och dokumentet beskrev ett tyskt industrisystem medan skärmen visade en bokstavsform ur en helt annan. På en telefon, där ingenting annat konkurrerar om intrycket, var det i praktiken allt man såg. Fallkedjan är därför inte godtycklig: en organisation som licensierat DIN får DIN, övriga faller ned genom grotesker som delar dess karaktär, och aldrig till en antikva. Beteckningar och mätvärden sätts med fast teckenbredd och tabellsiffror — en beteckning jämförs oftare än den läses. Reglerna gäller bara ALVA-ytan; butiken lämnas som den är. Fyra tester låser snittet, kaskaden och siffrorna, inklusive att fallkedjan aldrig slutar i en antikva. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
07b6713245 |
Gör ALVA läsbart på telefon
Portalens tabeller sköt ut dokumentet till 842 px på en 390 px-skärm. Sidan gick att dra i sidled och texten kapades i högerkanten. Tre orsaker, tre olika svar. Tabellerna. En sexkolumnstabell på en telefon har två utfall och bägge är dåliga: antingen tvingas hela sidan i sidled, eller så scrollar tabellen inuti sig själv och läsaren ser tre tecken av varje kolumn. Under 640 px blir varje rad därför en grupp namngivna fält — kolumnrubriken som etikett, cellen som värde. Samma form som Falt redan använder, och samma princip som resten av ytan: ett instrumentpanelsblad läses uppifrån och ner. Bägge formerna renderas och växlas med bredd, inte med JavaScript. Navigationen. Portalens fem länkar bröts inte utan breddade dokumentet. Raden bryts nu, med tätare mellanrum på smal skärm. Fasindikatorn. Kolumnerna saknade min-w-0 och kunde därför inte krympa under sitt innehåll. Ett första försök lät namnen brytas, men "LOCALIZA/TION" mitt i ordet är inte tydligare än inget namn. Under 640 px bär bokstaven och statussymbolen informationen — vilket är precis vad A·L·V·A är till för — medan raden ovanför namnger den aktiva fasen och dess syfte i klartext. Namnet finns kvar för skärmläsare. Mätt vid 390 och 360 px: samtliga sju ALVA-vyer, ansökans kvittens, ärendelistan och ärendesidans tre flikar håller sig nu inom skärmbredden. Fyra tester låser konstruktionerna. Designtestet fångade förresten mitt eget brott mot 8-px-rutnätet på vägen — py-1 — och koden rättades, inte testet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
86d553b639 |
Kör ALVA:s tester i CI, och genomgången som incheckat test
CI körde `npm test` i roten, som delegerar till workspaces. Listan är apps/mobile, services/api och infra — felsokning/app står inte där. Pipelinen körde alltså 30 tester från en orelaterad tjänst och inte ett enda av ALVA:s 311. Varken lint eller typkontroll nådde produkten heller. Det är inte att testerna föll. Det är att ingenting upprätthöll dem. Varje garanti som de två revisionerna skrivit som "låst av ett test" — härkomsten, kvalitetsgrinden, raderingen, mätdonsspårbarheten, högvoltsspärren, det stängda schemat, driftskydden mellan klient och grind — låstes av tester som ingen pipeline körde. De höll därför att en person körde dem för hand före varje commit. Det är en person, inte en spärr. Två nya jobb. `alva` kör produktens lint, typkontroll och hela sviten mot sin egen lockfil. `genomgang` installerar Chromium och kör fyra ärenden genom det byggda gränssnittet. Genomgången kontrollerar tre saker: att varje ärende når avslutat läge, att varje händelse klienten faktiskt producerar passerar det stängda schemat, och att interaktionerna per ärende håller sig under 90. Bägge felvägarna är provade, inte antagna — sänkt budget fäller tre fall, och ett schemafilter som avvisar allt fäller fyra. En kontroll som inte kan falla är dekoration. Skriptet bygger appen själv med de två miljövariabler bygget kräver. Lämnas det åt den som startar kommandot testar genomgången tyst en annan applikation: utan hash-routing matchar ingen route, och utan platshållare för den gamla butiksklienten kastar den innan routern monteras så att sidan blir tom. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
31727a4ea0 |
Härda enligt revision 2: stäng schemat, ta bort dubbelregeln
C-5. granskaHändelse itererade schemats nycklar och aldrig händelsens, så okända fält accepterades och sparades ordagrant. Två garantier vilade på motsatsen: krypto-shreddingen skyddar en fast lista av fältnamn, så personuppgifter på en vanlig observation krypterades aldrig och överlevde raderingen — och delningsfiltret är typnivå, så samma fält gick ut i kundens delningslänk. Schemat är nu stängt, med varje valfritt fält deklarerat. Det gäller även `kalla`: protokollinläsningen fungerade bara därför att schemat var öppet. Avslaget är hårt, inte en tyst strykning. Verifierat mot riktig trafik — samtliga händelser som klienten faktiskt producerar passerar. M-7. Klienten upprepar inte längre grindens regel utan anropar grinda() och visar dess egna hinder. Villkoret hade glidit isär två gånger utan att något test märkte det. Det avslöjade omedelbart ett verkligt fel i grinden: den krävde textresultat även på kontroller vars krav är foto — trots att gränssnittet märker fältet "Observation (valfritt)". Servern hade alltså nekat avslut på nästan varje riktigt ärende, och det syntes inte så länge klienten hade ett eget och mildare villkor. Evidens graderas nu efter kontrollens eget krav. M-8. Protokollinläsningen svarar med utfall per händelse i stället för en siffra, 207 vid delvis lyckad inläsning, innehållshärledda id:n i stället för klockan, och en transaktion runt hela importen. M-9. En genererad webhookhemlighet lämnas ut en gång vid skapandet. m-8. Profilens vägslagning begränsas till egna egenskaper. m-10. Ett mätvärde som kommer ur en kontroll redovisas en gång. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
45967d086e |
Lås inte in ärenden där åtgärden dokumenterades före förslaget
När kundbeskedet blev ett avslutsvillkor i klienten uppstod en fälla: knappen "Lämna åtgärdsförslag till kund" visades bara när ingen åtgärd var dokumenterad, och beskedsrutan bara när ett förslag fanns. En tekniker som skrev åtgärden först hade därmed ingen väg att registrera beskedet, och ärendet gick inte att stänga. Grinden avvisade redan sådana ärenden vid synk — villkoret i klienten flyttade bara upptäckten. Men ett spärrvillkor utan väg ut är ett fel även när spärren i sig är riktig. Förslagsknappen står kvar tills ett förslag faktiskt lämnats. Ordningen förslag → besked → arbete är fortfarande den panelen föreskriver, och loggen är append-only med tidsstämplar, så ett besked som registreras i efterhand syns som just det. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
8daeb41ba1 |
Kräv kundens besked även i klienten innan avslut
Grinden på servern har alltid krävt kundbeskedet när arbete faktiskt utförts. Klientens kanAvslutas gjorde inte det, och glappet syntes först när tio ärenden av olika karaktär kördes hela vägen genom gränssnittet: samtliga tio gick att stänga på skärmen med utfört arbete och utan att kunden hade sagt ja. Det är samma sorts fel som slutsatsen hade, på ett annat villkor — och det värre av de två, eftersom ett utfört arbete utan registrerat besked är precis vad en tvist handlar om. Hindertexten namnger nu kundbeskedet, och ett test speglar klientens avslutsvillkor mot grindens hela åtgärdskedja så att nästa villkor som läggs till i grinden inte kan glömmas i klienten. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
6fa7953012 |
Logga metodikens mätkontroller som mätvärden
En kontroll vars krav är "matvarde" loggade bara kontroll_utford. Det gällde 56 av metodikernas 153 kontroller — drygt en tredjedel — och fick två följder som bägge upptäcktes när tio ärenden kördes igenom gränssnittet: Felorsaksanalysen nekade "Mätresultat" som underlag med motiveringen att underlaget inte finns i loggen, trots att teknikern just hade matat in mätvärdet som kontrollen krävde. Enda vägen förbi var att mata in samma siffra en gång till via dokumentationspanelen. Evidensprofilen i analysvyn underskattade systematiskt hur mycket som faktiskt mäts, eftersom mätningarna aldrig fanns som mätvärden. Mätningen loggas nu som det den är. Utan känt mätdon graderas den E1 och inte E4 (QUALITY-AUDIT M-1) — ett avläst tal utan spårbart instrument är inte en spårbar mätning. Tre tester låser förhållandet mellan metodikernas kravtyper och den evidens de producerar, så att en ny kravtyp inte kan införas utan att någon tar ställning till vad den ska ge för evidens. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
f0f5cc670e |
Håll ALVA-ytan fri från butikens driftmeddelanden
Betalningsbannern satt i App och undantog bara /felsokning, så den renderades ovanför ALVA-huvudet: "Skarpa betalningar är inte konfigurerade." En verkstad som ser ett driftmeddelande från en annan produkt läser det som att den tittar på något halvfärdigt. Det är ett trovärdighetsproblem, inte ett kosmetiskt. Undantaget jämför nu hela sökvägssegment i stället för prefix, så att /alvarlig inte råkar räknas som ALVA. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
590fab3a70 |
Spärra avslut utan slutsats även i klienten (ALVA-RULE-200)
Kvalitetsgrinden på servern krävde en slutsats, men klientens avslutsknapp gjorde inte det. Ett ärende gick därför att stänga på skärmen utan ett varför, och teknikern fick beskedet först vid synk — den sämsta tänkbara tidpunkten, eftersom bilen då har lämnat verkstaden. Klienten anropar nu granskaSlutsats() — samma funktion som grinden, inte en klientkopia av regeln — och avslutsknappen är spärrad tills den är ren. Slutsatspanelen visas så fort underlaget är helt, inte bara när metodikens sista steg är avbockat, så att frågan kommer när den går att besvara och inte som ett hinder efteråt. Hindret säger vad som fattas i stället för att bara konstatera att kraven inte är uppfyllda: först underlaget, sedan de enskilda bristerna i slutsatsen. Fyra tester jämför verdikt mellan klient och grind för samma logg, så att de två ändarna inte kan glida isär igen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
cd6b2caca5 |
Sammanfattning och slutsats i rapport och Live Share; API dokumenterat
Sammanfattningen ligger först i både kundrapporten och Live Share. Mottagaren är oftast inte tekniker — det är kunden, en försäkringshandläggare eller en flottansvarig — och de ska få bilden på fem sekunder och sedan kunna gå djupare, inte tvärtom. I Live Share härleds den ur det NIVÅFILTRERADE underlaget. Det betyder att sammanfattningen aldrig kan avslöja något som delningsnivån döljer: filtret ligger före projektionen, inte efter. Slutsatsen visas som ett eget avsnitt före underlaget. En handläggare läser skälet först och kontrollerar det sedan — den ordningen är hela poängen med att fältet finns. Sju nya vägar dokumenterade i OpenAPI och låsta av paritetstestet: sammanfattning, protokollinläsning, statistik, integrationskategorier, prenumerationer, radering och mätdon. Ett API som inte är dokumenterat är inte ett API någon kan koppla in sig mot — och specen valideras maskinellt så dokumentationen inte kan glida från servern. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
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
|
||
|
|
01189ae42a |
ALVA-RULE-200: ett ärende stängs aldrig utan ett varför
Kravet är enkelt att formulera och lätt att bygga fel. En obligatorisk
fritextruta blir "klart" på tredje ärendet, och då har vi bara gjort
dokumentationen långsammare utan att göra den bättre.
Därför fyra frågor med olika adressat i stället för ett fält:
MOTIVERING Varför följer slutsatsen av evidensen? Detta är raden som
saknas i varje verkstadsprotokoll. Underlaget säger vad
som mättes, slutsatsen vad som är fel — ingenting säger
varför det ena medför det andra, och det är precis det
steget en försäkringsbedömare granskar.
UTESLUTET Vad övervägdes och varför föll det bort?
ÅTGÄRDSVAL Varför denna åtgärd och inte en annan?
KVARSTÅENDE Vad är fortfarande osäkert? Får vara "inget" — men aktivt.
Kvalitetsgranskningen är riktad mot hur någon med bråttom faktiskt
skriver: en katalog över icke-svar (klart, åtgärdat, trasig, se ovan,
vet ej), minsta längd, och kravet att texten bär ett orsakssamband eller
refererar konkret evidens. Den som skriver "12,4 V vid stift 14"
hänvisar till en mätning utan att säga ordet — regeln får inte tvinga
fram ett språkbruk som inte är teknikerns.
Den regel som gör underlaget användbart för ett försäkringsbolag härleds
ur loggen: en hypotes som dokumenterats och inte blivit slutsatsen MÅSTE
bemötas. Utan den är en felsökning en gissning som råkade stämma.
Den ärliga vägen finns: orsaken kunde inte fastställas är ett giltigt
utfall, ofta mer användbart än en påhittad orsak — men varför den inte
kunde det är fortfarande ett varför.
Slutsatsen är kunddelbar. Den besvarar "varför kostade det här vad det
kostade" och är den enda rad en bedömare behöver. Att bygga funktionen
och sedan hålla den intern vore att bygga den förgäves.
I gränssnittet granskas fälten medan man skriver, inte efter Spara, och
obemötta hypoteser listas — teknikern ska aldrig behöva gissa vad som
fattas. Det är skillnaden mellan ett krav som respekteras och ett som
kringgås.
---
Typkontrollen avslöjade under arbetet en riktig bugg i mitt eget
grindarbete: schemat och grinden skrevs mot antagna fältnamn i stället
för mot domänmodellen. atgard_utford heter beskrivning och utford, inte
text. Följden var värre än ett typfel — grinden såg utförd åtgärd som
utebliven och krävde därför aldrig kundbesked eller kvalitetskontroll.
Det syntes inte, eftersom testfixturerna hade samma antagande.
Rättat i schema, grind och fixturer, och låst av två nya test: varje
fält i schemat måste finnas i domänmodellen, och varje händelse
demoärendet producerar måste passera serverns validering. Ett schema som
avvisar riktig trafik är värre än inget schema.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt
|
||
|
|
baa5288add |
ALVA-modellen synlig i guiden
Fasindikatorn ovanför metodikpanelen: var i metoden arbetet befinner sig, vilken fas det aktuella steget hör till, och vad fasen uttryckligen inte gör. Fasen härleds ur steget via den delade klassificeringen, så indikatorn kan aldrig visa något annat än vad metodiken faktiskt gör. En indikator som sätts separat blir förr eller senare fel, och då är den värre än ingen — den påstår att arbetet är i verifiering när det fortfarande lokaliserar. Ärendets beteckning står i samma rad. Ett id ur loggen är en ogenomskinlig sträng; ALVA-CASE-00007 är det som sägs i telefon och skrivs i ett protokoll. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
a8fdc9ebcc |
ALVA: webbplats, portal och kunskapskällor
Webbplatsen och plattformen är ett system. Samma komponentbibliotek, samma rutnät, samma ord — besökaren lämnar aldrig marknadswebben när den loggar in, eftersom den inte gör det. När apparna kommer återanvänder de samma bibliotek. Det som saknas på startsidan är lika avsiktligt som det som finns: ingen hjältebild, ingen gradient, ingen animation, inga kundlogotyper, ingen uppmaning att boka demo. En sida som försöker övertyga läser som marknadsföring; en sida som redovisar läser som dokumentation. Den senare är vad en teknisk chef fattar beslut utifrån. Kunskapskällorna är byggda som Operational Knowledge Infrastructure: leverantörsoberoende gränssnitt där organisationen ansluter det den har licens till. Det gör att produkten aldrig behöver marknadsföras med "vi stödjer X". En betainstallation fungerar på enbart egna dokument. Livscykeln har fem tillstånd med avsikt. Configured och Connected är inte samma sak — en nyckel kan vara ifylld och ändå fel — och Validated skiljer sig från Connected: anslutningen svarar, men har den data för de fordon organisationen faktiskt arbetar med? Det är den frågan som avgör om källan är till nytta. Portalens nyckeltal visas som NOT APPLICABLE i stället för som tomma grafer. Att visa noll vore att lova något som inte finns; att dölja raderna vore att dölja riktningen. Ett test läser den faktiska källkoden och låser disciplinen: inga gradienter, ingen animation, inga emojier utanför ✓ ○ □ →, ingen färg utanför paletten, inga marknadsföringsord. Ett designsystem som bara finns i ett dokument blir urvattnat på tredje sidan någon lägger till. Testet avslöjade att min egen kod använde py-3 — 12 px — och alltså bröt 8 px-rutnätet på sju ställen. Jag rättade koden, inte testet. Ett rutnät med undantag är inget rutnät. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
610bb9eca6 |
ALVA: metoden i kod — faser, nomenklatur, statusspråk, komponenter
ALVA är inte en omdöpning utan en annan produktklass. Skillnaden mellan en assistent och en metod är att metoden går att granska, och därför ligger den i kod och i test, inte i marknadsföringen. Språkgränsen är den bärande avgränsningen: ALVA:s STRUKTUR är engelsk och oföränderlig — fasnamn, statusord, dokumenttyper, identifierare skrivs likadant i varje land, precis som DIN 2014 heter DIN 2014 på svenska. ALVA:s INNEHÅLL är på arbetsspråket: frågan till teknikern och kontrollpunktens text är svenska i en svensk verkstad. Att översätta VERIFICATION till Verifiering hade gjort ALVA till ett ord för samma sak i varje land i stället för samma sak i varje land. Faserna är tillämpade på metodikbiblioteket, inte påklistrade: alla 31 steg-id i de 16 metodikerna är klassificerade i data. Gränsen mellan L och V är den enda svåra och bär hela metoden — att mäta spänning vid en komponent avgränsar var felet finns, att mäta spänningsfall under last fastställer varför. Regeln: ett steg är Verification när det kan avfärda en kandidatorsak. Ett test kräver att faserna kommer i ALVA-ordning inom varje metodik. Ett annat slår fast att en metodik inte behöver innehålla alla fyra — läckagemetodiken slutar med lokalisering, och att fylla ut modellen med ett konstruerat Action-steg hade varit att tillämpa den slarvigt. Statusspråket är en uttömmande katalog, låst av test: inga utropstecken, inget tilltal, varje rad slutar med punkt. Bedömning uttrycks som ett tal — Confidence level: 92% — aldrig som Jag tror. Skillnaden är produktens existensberättigande: det ena är en person som gissar, det andra ett mätvärde som går att ifrågasätta. Komponentbiblioteket är ett, för både webbplats och portal. 8 px-rutnät utan undantag, nästan monokromt, ALVA Blue bara för aktivt steg och verifierad status. Fyra ikoner: ✓ ○ □ →. Ingen animation — rörelse som inte bär information är brus i ett utrymme där teknikern redan har för mycket. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |
||
|
|
03fbea8fac |
Revisionen: m-4 och m-6 — de två som bara går att stänga delvis
m-6 · Tillgänglighetstester med axe på verkstadsgränssnittets grundkomponenter: knapp, textfält, panel och bild. Gränssnittet var genomtänkt för handskar, buller och solljus men obevisat — ingenting kontrollerade att en knapp har ett tillgängligt namn eller att ett formulärfält har en etikett. Att bilder bär alternativtext är i den här produkten inte bara ett tillgänglighetskrav: bilden *är* bevisningen, och beskrivningen är det som säger vad den visar. Ungefär en tredjedel av WCAG går att kontrollera maskinellt. Testet säger det rakt ut, och den manuella granskningen står kvar som öppen — automatik hittar inte om ett gränssnitt är användbart, bara om det är felformat. m-4 · Paritetstestet mellan orkesterkopiorna jämför nu innehåll i stället för att kontrollera att strängar förekommer: grundreglerna ord för ord, metodikkatalogens id i ordning, och modellvalet per uppgift. Ett substrängtest hade inte fångat att en grundregel ändrats i ena kopian. Den riktiga åtgärden är att avveckla Supabase-vägen. Det är ett driftbeslut, inte en kodändring, och står kvar som öppet. Revisionsdokumentet har fått en avdelning med utfall per fynd, så att en omgranskning kan verifiera i stället för att lita på ordet. Två punkter är ärligt öppna och ingen av dem är kod: personuppgiftsbiträdesavtalet med konsekvensbedömning, och avvecklingen av den äldre orkestern. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012EQg3rJsrQ1ZNTvkzmQAtt |