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
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
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
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
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