Files
boc/workcamp/VOL6-Lessons-Learned.md
T
Bernt bae705aa97 ARCHITECTURE: NFC roadmap, edge AI, audit logging
- Add NFC ePassport roadmap (ICAO 9303, eIDAS)
- Add TensorFlow.js edge face detection (BlazeFace)
- Add structured audit logger (GDPR-compliant)
- Risk scoring support

Part of KYC Apple Native UX v1.1.0
2026-06-29 16:24:48 +00:00

28 KiB
Raw Blame History

AMOS Development Workcamp 2026

Volume 6: Lessons Learned and Continuous Improvement

Period: 2026-06-04 2026-06-07 (intensiv fas)

Genererat: 2026-06-07 | Klassifikation: INTERN KONFIDENTIELL


INLEDNING

Denna volym dokumenterar incidenter, rotorsaksanalyser (5 Why), förbättringar (Kaizen-register) och lärdomar från AMOS Workcamp 2026. Målet är att nästa workcamp inte upprepar samma misstag.

Claude × Siemens-linsen gäller för detta dokument: var incident dokumenteras ärligt, inklusive obekväma fynd. "Surface:a verkliga fynd (även obekväma)" Claude-sidan av beslutslinsen.


AVSNITT 1: INCIDENTANALYS 5 WHY

INCIDENT 1: LandveX = bostad-incidenten

Symptom: ESLM (ALETHEIA i test) och produktionschatten (/api/aamos/chat) svarade att LandveX säljer bostäder. Gravt faktafel med potentiell kundpåverkan om det gått live.

Tidpunkt: Upptäckt 2026-06-06 under systematisk systemkunskaps-härdning.

5 Why-analys:

Nivå Varför? Svar
1 Varför svarade AI att LandveX säljer bostäder? Produktionschatten hade ingen aktuell LandveX-definition.
2 Varför saknade chatten korrekt definition? /api/aamos/chat anropade getEnrichedPrompt()getFactsContext() → hårdkodad wavult-facts.mjs. Den filen hade LandveX-def som proptech/fastighet.
3 Varför hade wavult-facts.mjs fel definition? Ingen process för att hålla filen synkad med kanonisk AAMOS_CANON.md. Filen skrevs manuellt vid ett tidigt skede och uppdaterades aldrig.
4 Varför fanns det 39 konkurrerande truth-filer? Ingen utsedd kanonisk sanningskälla. Varje session/feature kunde skapa en ny "truth"-fil.
5 Varför saknade RAG en kanonisk källa? RAG-index skapades ad-hoc, läste bara 3 filer, och RAG-stubs svarade ok:true även när index var tomt felet doldes.

Rotorsak: Avsaknad av en enda kanonisk sanningskälla + stubs som dolde att systemet var trasigt.

Åtgärder vidtagna:

  • Skapade /opt/amos/data/AAMOS_CANON.md (ENDA kanoniska sanningskällan, E4-klassad)
  • Patchade rag.mjs (CANON tier-1, alltid läst)
  • Byggde om RAG-index (94 chunks)
  • Rättade wavult-facts.mjs med korrekt LandveX-definition
  • Ändrade LOCKED RULES i produktionschatten (fakta alltid-injicerad)
  • Neutraliserade bostad-orphan (landvex-landing.html → redirect)
  • Arkiverade 8 dubblett-truth-filer

Verifierat resultat: "Säljer LandveX bostäder?" → AI: "Nej... infrastrukturkontroll." HTTP 200.

Lärdom för nästa workcamp:

En enda CANON-fil är bättre än tio semi-korrekta truth-filer. Stubs ska ALDRIG svara ok:true på tomma svar det döljer att systemet är trasigt.


INCIDENT 2: OOM-kraschen via SocialAuto restart-storm (2026-06-05)

Symptom: Alla domäner mot port 3100 gav timeout (000). amos-core nådde 5.2GB/6.0GB RAM, 1850 aktiva tasks, NATS 503-flood. Systemet var i praktiken nere.

Tidpunkt: 2026-06-05 (exakt tid ej loggad i dagbok, men under nattens arbete).

5 Why-analys:

Nivå Varför? Svar
1 Varför kraschade amos-core med OOM? 5.2GB RAM → 6.0GB limit. Systemet hade 1850 tasks.
2 Varför var det 1850 tasks? 137 parallella Chromium-instanser (stealth-mode) körde simultaneously, vardera ~100MB.
3 Varför körde 137 Chromium-instanser? SocialAuto (apifly job-posting, social-account-automation.mjs) relanserade ALLA queued/failed-jobb vid varje omstart utan concurrency-tak.
4 Varför relanserades alla jobb vid omstart? Kod saknade global semafor/concurrency-limit. Vid restart = ny storm av parallella Chromium-launches.
5 Varför fanns ingen concurrency-limit? Funktionen byggdes utan att ta hänsyn till restart-scenariot. Ingen review av resursförbrukning per job.

Rotorsak: SocialAuto's restart-beteende (amplifiering: varje omstart = ny storm) kombinerat med avsaknad av global concurrency-begränsning.

Åtgärder vidtagna:

  1. Cancellerade 274 skenande jobb i /opt/amos/data/social-account-jobs.json
  2. PATCH: global semafor SOCIALAUTO_MAX_CONCURRENT=3 runt runAutomation(), wrapper _runAutomationCore

Verifierat resultat: amos-core 200, 1.7GB RAM, load 2.0. Stabilt.

Diagnostisk lärdom:

Vid amos-core-strul: kolla ALLTID pgrep -fc chrome och social-account-jobs.json status-counts FÖRST. Restart utan att cancellera jobb förvärrar situationen.


INCIDENT 3: Provider-kredithaveri (xAI/Grok, 2026-06-04)

Symptom: Grok/xAI tog slut på krediter mitt i en orkestrering. Erik beskrev det som "generalhaveri". Orkestreringen kunde inte slutföras. Allt som förlitade sig på Grok som provider blockerades.

Tidpunkt: 2026-06-04 under dagsarbete.

5 Why-analys:

Nivå Varför? Svar
1 Varför havererade orkestreringen? Grok/xAI-kontot var tomt på krediter.
2 Varför var kontot tomt utan förvarning? Ingen kredit-monitor för xAI-kontot.
3 Varför saknades kredit-monitor? Varje provider behandlades manuellt. Ingen systemisk kreditövervakning.
4 Varför saknades systemisk kreditövervakning? AI-gateway (som byggdes natten efter) existerade inte ännu.
5 Varför byggdes inte AI-gateway tidigare? Multi-provider failover var inte prioriterat tills haveriet bevisade behovet.

Rotorsak: Avsaknad av proaktiv kreditövervakning och automatisk failover.

Åtgärder vidtagna (natten 2026-06-04 → 06-05):

  • Byggde AI-gateway (/opt/amos/data/ai-gateway/gateway.mjs, port 3270, PM2)
  • 6 providers med auto-failover + circuit-breaker
  • FAILOVER BEVISAD LIVE (trasig provider → groq, 1 hopp)
  • Provider-monitor (monitor.mjs, PM2): pollar 7 providers var 5:e min
  • Auto-larm CRITICAL till Winston (kredit) och Johan (nedtid) via HomoDeus
  • Tickets utfärdade: Johan PROV-001..006, Winston PROV-W1..6
  • Grok exkluderades från gateway tills påfylld

Absolut regel (Erik, CAPS):

"ALDRIG I PRODUKTION. VARJE PROVIDER: PRIMÄRT REVOLUT + FALLBACK ANNAN BANK + AUTO-TOPUP + BUFFERT."

Ansvarig framåt:

  • Johan/Sven: teknisk setup/monitor/failover
  • Winston/Rufus: kort/konton/påfyllning

INCIDENT 4: Leon/Vincento-kontaminering av träningsdata (2026-06-06)

Symptom: v3 och v4 av ESLM-träningsdata innehöll 90+129 Leon/Vincento-referenser (train) och 17+18 (validation). Modellen lärde sig en simulerad persona som aldrig existerat. Träningen stoppades.

Tidpunkt: Upptäckt 2026-06-06 22:18 efter Eriks klargörande att Leon = simulering.

5 Why-analys:

Nivå Varför? Svar
1 Varför var träningsdata kontaminerad med Leon/Vincento? Varje träningsexempel hade AAMOS-systemets kontext i system-prompten, inklusive team-mappning med Leon.
2 Varför fanns Leon i system-prompten? Leon behandlades som verklig anställd i alla systemfiler. Ingen markering som simulering.
3 Varför behandlades Leon som verklig? Ingen kontroll av personas mot HR-register. Leon hade e-post, agent-mappning, payroll-post (EMP-004) och kodade roller.
4 Varför hade en simulering alla verkliga attribut? Simuleringen designades för realism men ingen distinktion skapades mellan "simulerad test-persona" och "verklig anställd".
5 Varför saknades distinktionen? Systemet hade ingen metadata-tagg för simulerade vs. verkliga entiteter.

Rotorsak: Avsaknad av entitetstyp-distinktion (simulerad vs. verklig) i systemet, kombinerat med att Leon hade alla attribut av en verklig anställd (e-post, payroll, kod-routing, agent).

Åtgärder vidtagna:

  • v3 och v4 kasserades omedelbart
  • v5 skapades: droppade 12 371 train + 1 357 val företagsspecifika exempel
  • ALLA system-prompts byttes mot neutral generell ("evidensbaserad assistent för verksamhetsdrift")
  • 3 parallella purge-agenter kördes (purge1_api, purge2_data, purge3_scripts)
  • EMP-004 "Leon Magnusson" (alias för Leon Russo, samma syntetiska pnr) raderades ur payroll/HR
  • Slutkoll: Leon Russo=0, Leon Magnusson=0, vincento=0, 900510-3456=0 i aktiv kod

Effekt på arkitektur: Incidenten ledde direkt till principen Separation of weights & facts (SD-003):

"Modellen bär ALDRIG företagsdetalj. Fakta injiceras via MNEMOSYNE vid runtime."


INCIDENT 5: JWT Algorithm Confusion (CVSS 10.0) Identifierad och åtgärdad 2026-05-08

Symptom: Alla authMiddleware-instanser använde jwt.decode() istället för jwt.verify(). Vem som helst kunde förfalska admin-JWT utan att känna till secret.

Tidpunkt: 2026-05-08 under red-team/hardening-arbete.

5 Why-analys:

Nivå Varför? Svar
1 Varför kunde JWT:er förfalskas? jwt.decode() verifierar INTE signaturen bara decodes base64.
2 Varför användes jwt.decode() istället för jwt.verify()? Förväxling av metodnamn/syfte vid initial implementation.
3 Varför spreds felet till 6 filer? Copy-paste av auth-middleware utan review. Ingen centraliserad auth-hjälpfunktion.
4 Varför fångades det inte i review? Ingen security review-process eller automatiserad SAST (static analysis).
5 Varför saknades security review? Arbetstempon under byggfasen prioriterade features före säkerhetsreviews.

Rotorsak: Copy-paste + avsaknad av centraliserad auth-hjälpfunktion + ingen security review.

Åtgärder: Fixad i 6 filer. alg:none-attack blockerad. Rate limiting, security headers, input validation tillagda.


INCIDENT 6: Kafka-backbone degraderad i 8 dagar (2026-06-07)

Symptom: Kafka-klustret (3-broker KRaft StatefulSet) körde i degraderat läge med 2/3 brokers i 8 dagar utan att det uppmärksammades. kafka-1 saknades.

Tidpunkt: Upptäckt 2026-06-07 14:45 under infrastrukturinventering.

5 Why-analys:

Nivå Varför? Svar
1 Varför körde Kafka med 2/3 brokers? kafka-1 kunde ej skapas pga ResourceQuota-blockering och borttagen EBS-volym.
2 Varför blockerade ResourceQuota? init-container fix-volume saknade resource limits → wavult-quota blockerade (FailedCreate ×721 över 8 dagar).
3 Varför var EBS-volymen borttagen? kafka-1:s PVC var bunden till vol-0891ca1531dc90def som raderats (InvalidVolume.NotFound).
4 Varför uppmärksammades det inte? Ingen monitoring av Kafka broker-hälsa. Degraderat läge genererade inga larm.
5 Varför saknades Kafka-monitoring? Observability-gap. Fokus på app-hälsa, ej backbone-hälsa.

Rotorsak: Avsaknad av Kafka broker-hälsoövervakning. 8 dagar = oacceptabelt för produktionsbackbone.

Åtgärder:

  • Patchade init-container med resource limits (25m/64Mi requests, 100m/128Mi limits)
  • Raderade orphaned PVC → EBS-CSI provisionerade ny 20Gi gp3
  • Broker rejoinade via replikation (RF=3 tålde det)
  • Rolling restart av hela STS
  • RESULTAT: 3/3 brokers Running, 0 under-replicated partitions, ISR fullständig

INCIDENT 7: host-2 DNS-beroende på Tailscale MagicDNS

Symptom: host-2 (AMI-klon av server-2) kunde inte resolva RDS-DNS och gav ENOTFOUND. /health/ready = DEGRADED. Hade registrerats i target group (tur att djup health-check stoppade det).

Tidpunkt: 2026-06-05 02:3803:09 UTC.

5 Why-analys:

Nivå Varför? Svar
1 Varför kunde inte host-2 resolva RDS? /etc/resolv.conf pekade på 100.100.100.100 (Tailscale MagicDNS). host-2 hade ingen Tailscale.
2 Varför pekade resolv.conf på Tailscale? AMI skapades från server-2 som kör Tailscale. Statisk resolv.conf kopierades.
3 Varför använder server-2 Tailscale som primär DNS? Tailscale MagicDNS installerades tidigt för dev-convenience och ersatte VPC-resolver.
4 Varför byggdes ingen DNS-resiliens in? Ingen policy för DNS-konfiguration på prod-hostar.
5 Varför saknades DNS-policy? Det fungerade på server-2 problemet syntes bara vid skalning till ytterligare host.

Rotorsak: Prod-DB-resolution beroende av Tailscale. Ej synligt på en host, kritiskt på två.

Åtgärder:

  • host-2 v2: user-data skriver /etc/resolv.conf → nameserver 172.31.0.2 (VPC-resolver) + chattr +i
  • server-2: systemd-resolved drop-in /etc/systemd/resolved.conf.d/99-vpc-fallback.conf (FallbackDNS=172.31.0.2)
  • ALB-lärdom: Deep health-check (/health/ready med DB-check) förhindrade att degraderad host fick trafik.

AVSNITT 2: KAIZEN-REGISTER

Kaizen = kontinuerliga förbättringar som identifierades och genomfördes under workcampet.

K-001: env-preload.mjs löser ESM-import-ordningsproblematik

Problem: Stripe och APNS lästes vid ESM-import-tid (rad 11) FÖRE env-loadern (rad 34+) → låstes i MOCK_MODE. Förbättring: env-preload.mjs importeras som ALLRA FÖRSTA rad i index.mjs laddas hela env-filen innan någon route-import. Effekt: End-to-end Stripe-session skapad (cs_test_…). Inga kodändringar vid sk_live_-switch.

K-002: ALB health-check → /health/ready (djup, DB-check)

Problem: ALB health-check mot /health (liveness) = process up men ej DB. En degraderad host fick trafik. Förbättring: Health-check ändrad till /health/ready som gör faktisk DB-round-trip. Effekt: host-2 (ENOTFOUND på RDS) hölls automatiskt utanför rotation. Self-protecting arkitektur.

K-003: Idempotent Stripe-webhook med processed_stripe_events-tabell

Problem: Dubbel webhook (Stripe-retry ELLER 2 hosts) → dubbel kreditering möjlig. Förbättring: Ny tabell quixzoom.processed_stripe_events (event_id PK), INSERT ON CONFLICT DO NOTHING + atomisk balance = balance + credits. Effekt: Dubbel-kreditering matematiskt omöjlig oavsett antal hostar eller Stripe-retries.

K-004: Concurrent-tak för SocialAuto (SOCIALAUTO_MAX_CONCURRENT=3)

Problem: SocialAuto relanserade alla queued jobs vid restart utan tak → OOM. Förbättring: Global semafor runt runAutomation(), wrapper _runAutomationCore. Effekt: Max 3 Chromium-instanser simultant. Restart = ingen storm.

K-005: AI-gateway med auto-failover (circuit-breaker)

Problem: En provider (Grok) tar slut → hela orkestreringen havererar. Förbättring: AI-gateway med 6 providers, task-kedjor (reasoning/fast/search/creative/financial/default), circuit-breaker. Effekt: FAILOVER BEVISAD LIVE: trasig provider → groq, 1 hopp, 0 avbrott i orkestrering.

K-006: Provider-monitor var 5:e minut med auto-larm

Problem: Ingen visste att xAI/Grok var tomt förrän orkestrering havererade. Förbättring: monitor.mjs (PM2) pollar 7 providers var 5:e min. Auto-larm CRITICAL till Winston (kredit) och Johan (nedtid) via HomoDeus. Effekt: Reaktiv → proaktiv kreditövervakning.

K-007: AAMOS_CANON.md som enda kanonisk sanningskälla

Problem: 39 konkurrerande truth-filer → LandveX=bostad-incidenten. Förbättring: En enda CANON-fil (E4), tier-1 i RAG, alltid-injicerad i produktionschat. Effekt: Systemet svarar korrekt om LandveX. Fakta uppdateras på ett ställe.

K-008: Stub-transparens (X-AAMOS-Stub header + Warning + _stub:true)

Problem: 432 stubs svarade ok:true på tomma svar → dolde att subsystem var döda. Förbättring: Varje stub-träff loggas + X-AAMOS-Stub:true + Warning-header + _stub:true i body + ny /api/_stub-report. Effekt: Konfigurerad förmåga som ej är ansluten syns nu i instrumenteringen.

K-009: SSM Run Command för root-operationer (nginx/systemd utan sudo-beroende)

Problem: nginx-filer ägdes av root/ec2-user → bernt kunde ej skriva → blockerade nginx-tickets till Johan. Förbättring: AWS SSM Run Command via IAM-roll platform-ec2-ssm-role. Mönster: aws ssm send-command --document AWS-RunShellScript, base64-encoda komplexa script. Effekt: Kan nu ändra nginx, systemd, certs via SSM. Inga fler "väntar på Johan för root"-blockeringar.

K-010: LLM-as-judge med 4-lagers fallback

Problem: Keyword-matchning för svenska för trubbig. Qwen-32B som domare för svag (trodde "PASS" = EU-direktiv). Förbättring: Judge-v2: Bedrock-Opus-4-6 → Sonnet-4-5 → direkt-Opus-4-8 → Qwen-235B. LLM-schema-agnostisk parser. Effekt: En poliskontroll är nu aldrig svagare än det den vaktar.

K-011: Separation of weights & facts (arkitekturprincip)

Problem: Företagsdetaljer inbränt i modellvikter = säkerhetsrisk, kräver omträning vid ändring. Förbättring: ALETHEIA (modellvikter) = generell evidensmotor. MNEMOSYNE (CANON/RAG) = runtime-fakta. Effekt: Ingen faktaläcka via vikter. Fakta ändras utan omträning. ESLM säljbar generellt.

K-012: POS→Ledger automatisk bokföring (idempotent)

Problem: Restaurangförsäljning postades ej automatiskt till aamos-ledger → SIE4 var tom. Förbättring: POST /pos/ledger/post-day {fecha} + cron 03:15 Europe/Madrid. Tracking-tabell restaurant_ledger_postings (UNIQUE tenant+datum). Idempotent. Effekt: "Säljer jag en paella, hamnar den i böckerna?" = JA. Automatiskt, utan handpåläggning.

K-013: Ticket-system för felrapportering (aamos-restaurant-tickets:3318)

Problem: Ingen strukturerad väg för restaurangtjänster att rapportera integrationsproblem. Förbättring: Ny Rust/axum-tjänst med severity (low/medium/high/critical), status-flöde, källa (staff/system/customer/agent), HTML-dashboard. Effekt: POS auto-skapar high-severity accounting-ticket när ledger-postning failar. Systemintelligens istället för stum kraschtystnad.

K-014: Webhook-idempotens som förutsättning för multi-host

Problem: Multi-host (host-2) blockerades av att Stripe-webhooks ej var idempotenta. Förbättring: Löstes som prerequisite för RES-004. Multi-host + idempotens = sann redundans. Effekt: Systemet är nu multi-host-redo utan risk för ekonomisk data-korruption.

K-015: Jurisdiktionsmedveten onboarding (ES/SE och fler)

Problem: Onboarding-tjänst hårdkodad för Sverige → spansk CIF och IVA-satser avvisades. Förbättring: country (ISO-3166, default "SE") i register + DB-kolumn. ES→CIF/NIF + IVA {4,10,21}, SE→orgnr + moms {12,25}. Effekt: Spansk chiringuito kan slutföra alla 7 onboarding-steg. Global skalning möjlig.

K-016: Gravation arm64/Graviton-only för EKS (deterministisk flotta)

Problem: Preferred (80/20 arm64/x86-fallback) lämnar en variabel som kan överraska i prod. Förbättring: Required arm64-only (nodeSelector + requiredDuringScheduling). Alla images: --platform linux/arm64. Effekt: Homogen flotta, reproducerbart beteende, ~20% billigare. Inga edge-cases från mixed architectures.

K-017: Django E2E-simuleringen (986 orders, €146.5k, 24/24 OK)

Problem: Restaurang-stacken hade 6 oupptäckta integrationsbuggar (VAT overflow, analytics-paths, decimal-parsing, etc.). Förbättring: Fullständig månads-driftsimulering med 986 orders, 15 tjänster, ~130 endpoints, 14 verifieringsfaser. Effekt: Alla 6 buggar hittades och fixades. SIE4-kedjeavstämning POS→Modelo303→Ledger→SIE4 perfekt.


AVSNITT 3: TEKNISKA LÄRDOMAR

TL-001: Verifiera ALLTID den körande filen, inte filen på disk

Källa: Produktionschat-fix (2026-06-06)

Körande amos-core = services/amos-core/server.mjs. scripts/server.mjs KÖRS INTE. Hade nära håll på att fixa fel fil. Kontrollera alltid med ps aux eller systemctl status.

TL-002: Stubs som svarar ok:true döljer döda subsystem

Källa: LandveX-incidenten + 432 stubs-audit (2026-06-06)

Instrumentering ska visa sanningen, inte dölja den. En stub som svarar ok:true på tom respons är aktivt skadlig det ger en falsk bild av systemhälsan.

TL-003: ESM import-ordning är deterministisk och kan bita

Källa: Stripe env-preload.mjs fix (2026-06-05)

I ES modules körs importerade moduler vid import-tid, inte vid runtime. Variabler som läses tidigt (t.ex. env-variabler) måste finnas INNAN importen. Lösning: preload-modul som allra första import.

TL-004: AMI-kloning kopierar statisk konfiguration inklusive resolver

Källa: host-2 DNS-incidenten (2026-06-05)

AMI-snapshot fryser in all konfiguration inklusive /etc/resolv.conf. Om produktionsmiljön beror på ett sidoverktyg (Tailscale) som inte finns på alla hostar, sprids beroendet vid kloning. Lösning: user-data-script som skriver DNS-konfiguration vid boot.

TL-005: pgrep -fc chrome är första diagnostiksteg vid amos-core-strul

Källa: OOM-incidenten (2026-06-05)

Kolla antalet Chromium-instanser och social-account-jobs.json status-counts INNAN restart. Restart utan job-avbrottning förvärrar storm-beteende exponentiellt.

TL-006: LLM-as-judge måste vara starkare än det den poliskontrollerar

Källa: ESLM red-team, judge-evolution (2026-06-06)

Qwen-32B som domare klassade "PASS" som ett EU-direktiv och godkände felaktiga svar. En poliskontroll som är svagare än systemet den granskar ger falsk säkerhet. Regel: judge-modellen ska ALLTID vara starkare än production-modellen.

TL-007: Keyword-matchning för svenska är för trubbig som red-team

Källa: ESLM red-team v1 vs v2 (2026-06-06)

Keyword-matchning fångade inte subtila felaktigheter i svenska svar. Ersattes av LLM-as-judge (v2). Lärdom: för komplexa domäner krävs semantisk bedömning, inte mönstermatchning.

TL-008: gpt-5.5-pro kräver /v1/responses, ej /chat/completions

Källa: Infra-fakta 2026-06-05

OpenAI:s nya API-endpoint är inte bakåtkompatibel. Mycket långsam (>20 min öppna promptar). Undvik för tidskänsliga körningar.

TL-009: sqlx compile-time-makron (query!) kräver live DATABASE_URL vid build-tid

Källa: EKS-migration compliance-tjänst (2026-06-07)

14/15 Rust-tjänster byggde direkt. Compliance: enda med query!-makron → krasch utan DATABASE_URL. Lösning: --build-arg DATABASE_URL vid Docker build. Alternativt: använd query() (runtime) istället.

TL-010: ResourceQuota blockerar pod-skapande tyst (FailedCreate-events)

Källa: Kafka-degraderingen (2026-06-07)

kafka-1 fick FailedCreate ×721 utan larm. ResourceQuota stoppade init-containern pga saknade resource limits. Lärdom: Resource limits ska finnas på ALLA init-containers. Övervaka FailedCreate-events.

TL-011: RDS SSL-konfiguration krävs i Node.js-connections mot AWS RDS

Källa: tool-registry SSL-fix (2026-06-05)

new Pool({connectionString: AMOS_DB_URL}) utan SSL-config → RDS avvisade med "no pg_hba.conf entry". Lösning: ssl: {rejectUnauthorized: false} i Pool-konfiguration.

TL-012: Providermodellnamn förändras håll dem uppdaterade

Källa: Gemini 2.0→2.5 fix (2026-06-05)

Gamla modellnamn (Gemini 2.0, gammal Haiku) kraschade tyst. Orsakade dold instabilitet i orkestrering. Lärdom: API-modellnamn är ej stabila håll en provider-modell-förteckning uppdaterad.


AVSNITT 4: PROCESSLÄRDOMAR

PL-001: Parallellisering med tickets och subagenter är kraftfullt

Källa: 2026-06-06 parallellbygge (14 tickets, 4 epics, 8 subagenter)

90/100 tickets lösta på en session. Erikmönstret: "gör tickets, starta agenter." Fungerar för parallella epics som inte delar state. Kräver tydlig tickets-struktur och agent-scope.

PL-002: Red-team FÖRE promotion är inte valfritt

Källa: ESLM-processen (2026-06-06)

ALETHEIA-baslinjen: 33% passerade, 5 kritiska brister. Utan red-team hade modellen gått live med LandveX=bostad och hallucinerande org-nr. Red-team är minimikravet, inte ett bonus-steg.

PL-003: Ekonomifunktionen måste ha proaktiv förvarning

Källa: xAI/Grok-haveriet (2026-06-04)

Reaktiv hantering (Erik ringer Winston när Grok är tomt) är oacceptabelt. Systemet måste larma INNAN kontot är tomt. Auto-topup + buffert + 5-min kreditkoll är miniminivå.

PL-004: Kör simuleringen INNAN du berättar för kunden att det är redo

Källa: Restaurang-plattformens 6-buggars-fynd (2026-06-07)

Erik trodde restaurang-stacken var "100% redo för onboarding". E2E-test avslöjade BLOCKER (spansk CIF). Lärdom: "100% redo" valideras av systemet, inte av en persons uppskattning. Kör alltid simulering.

PL-005: Behörighetshierarkier ska tydliggöras i agentmailboxen

Källa: Beroende av Johan för nginx (2026-06-04/05)

Bernt (bernt-user) kan ej skriva nginx-filer (root/ec2-user). Blockade i veckor tills SSM-mönstret upptäcktes. Lärdom: dokumentera åtkomstgränser och eskaleringsvägar tydligt från start.

PL-006: Kanoniska namn ska låsas tidigt, inte sent

Källa: Hermes→Hephaistos-omdöpning (2026-06-07)

Hermes behövde döpas om (76 filer) pga namnkollision med externa bibliotek i träningsdata. Lärdom: namnkonflikter med populära bibliotek är dyrare att fixa sent. Välj ovanliga egennamn.


AVSNITT 5: ARKITEKTURLÄRDOMAR

AL-001: Separation of concerns gäller även AI-modeller

Källa: ESLM-arkitektur, SD-003 (2026-06-06)

Modellvikter (ALETHEIA) och faktabas (MNEMOSYNE) är separata ansvarsområden, precis som kod och konfiguration. En modell som bär konfiguration (företagsfakta) är svår att uppdatera.

AL-002: Event-backbone (Kafka) ska väljas och övervaka från dag 1

Källa: Kafka-degraderingen 8 dagar (2026-06-07)

Tre parallella event-mekanismer (Kafka, aamos-event-bus, NATS/Redis) skapade oklarheter. Kafka var productionstanken men 2/3 brokers utan larm i 8 dagar. Välj en backbone, övervaka den.

AL-003: Gitops + EKS + ExternalSecrets är rätt mönster (Siemens-standard)

Källa: EKS-migration referensmönster (2026-06-07)

ArgoCD + external-secrets + ClusterSecretStore + AWS SSM = reproducerbar, auditbar deploy. Varje workload: ExternalSecret → Deployment → Service → Kong-route. Mönstret verifierades end-to-end.

AL-004: Single point of truth gäller all systemkunskap

Källa: LandveX-incidenten (2026-06-06)

39 competing truth-filer → inkonsistens. AAMOS_CANON.md som enda E4-fil löste grundproblemet. Samma princip gäller all systemkunskap: en CANON, alla vet var de hittar sanningen.

AL-005: Health-check-djup avgör om redundansen fungerar på riktigt

Källa: host-2 DNS-incidenten (2026-06-05)

/health (liveness) = process up, men ej nödvändigtvis fungerande. /health/ready (readiness) med faktisk DB-round-trip är minimikravet för ALB-integrering. Ytlig health = falsk trygghet.

AL-006: Multi-AZ är grundkrav, inte lyx

Källa: RES-001/003 (2026-06-05)

Single-AZ RDS: RTO = timmar. Multi-AZ: RTO 60120s. Diff = $700/mån. Erik: "Vi har inte alternativ." Lärdom: bygg multi-AZ från start. Eftermontage är dyrare (maintenance window, DNS-propagation).

AL-007: Idempotens är förutsättning för horisontell skalning

Källa: Stripe-webhook-idempotens som Fas-2-prerequisite (2026-06-05)

Kan inte lägga till fler hostar utan idempotenta webhooks. Idempotens är inte ett nice-to-have det är det som gör horisontell skalning säker.


AVSNITT 6: ERKÄNDANDEN

Vad gick riktigt bra?

  1. Parallellisering med subagenter 90/100 tickets på en session bevisar att multi-agent-koordination fungerar.
  2. Deep health-check räddade produktionen host-2 med trasig DNS-resolution fick aldrig trafik tack vare /health/ready.
  3. Red-team-grinden fångade kritiska brister utan red-team hade LandveX=bostad gått live.
  4. SSM-mönstret löste root-beroendet månaders blockering av nginx-filer löst på en timme.
  5. EKS-migrationen gick smidigt 17 tjänster, 34 pods, alla på Graviton/arm64, alla friska.
  6. DDP-träningen fungerade från ~8h på A10G till ~1h på 8x A100. Ny hastighetstandard.
  7. Restaurang E2E-simulering hittade 6 riktiga integrationsbuggar och kvantifierade dem till öret.

Vad var svårast?

  1. Leon/Vincento-purgen kräver precision (behåll andra Leons, radera bara rätt entiteter). 3 agenter parallellt krävdes.
  2. Kafka-degraderingen 8 dagar utan larm är ett allvarligt observability-gap. Fixades men borde ha fångats dag 1.
  3. Judge-modell-valet det tog tre iterationer (keyword → Qwen-32B → Opus-direkt) för att hitta rätt domar-nivå.
  4. Providermodell-avvecklingen gamla modellnamn kraschade tyst. Svårt att spåra utan centraliserad provider-förteckning.

Volym 6 av 7 | AMOS Workcamp 2026 | Klassifikation: INTERN KONFIDENTIELL Nästa: VOL7-AMOS-Operating-System.md