# AAMOS Infrastrukturanalys — Del 2 ## LandveX Enterprise Platform — Återanvändningsbarhet & Anpassningskostnad **Datum:** 2026-07-02 **Analytiker:** Subagent (AAMOS Infrastructure Analysis) **Status:** Fortsättning på Del 1 (Auth/Identity Service: 5/5 ⭐, Låg anpassningskostnad) --- ## Sammanfattning | Komponent | Nuvarande användning | Återanvändningsbarhet | Anpassningskostnad | |-----------|---------------------|----------------------|-------------------| | **1. API-gateway** | Nginx reverse proxy + Rust-tjänster | ⭐⭐⭐⭐⭐ (5/5) | **Låg** | | **2. Databaslager** | PostgreSQL + Redis + PostGIS | ⭐⭐⭐⭐ (4/5) | **Låg** | | **3. Event-buss** | Hermes (Redis pub/sub + JSONL fallback) | ⭐⭐⭐⭐⭐ (5/5) | **Låg** | | **4. Frontend-ramverk** | React 19 + Vite + Tailwind (Ouroboros) | ⭐⭐⭐ (3/5) | **Medium** | --- ## 1. API-gateway ### Nuvarande användning AAMOS använder **Nginx** som central reverse proxy och API-gateway för alla 28+ Rust-tjänster: ``` Nginx (amos.wavult.com) ├── /api/svc/rule-engine/ → port 3201 ├── /api/svc/api-gateway/ → port 3206 (intern gateway) ├── /api/svc/ledger/ → port 3250 ├── /api/svc/bank-import/ → port 3253 ├── /api/svc/sie-import/ → port 3254 ├── /api/svc/people-core/ → port 3271 ├── /api/svc/operations-core/ → port 3272 ├── /api/svc/commerce-rust/ → port 3280 ├── /api/svc/analytics-rust/ → port 3281 ├── /api/svc/crm-rust/ → port 3282 ├── /api/svc/campaign-rust/ → port 3283 ├── /api/svc/hr-rust/ → port 3284 ├── /api/svc/payroll-rust/ → port 3285 ├── /api/svc/invoice-rust/ → port 3286 ├── /api/svc/compliance-rust/ → port 3287 ├── /api/svc/landvex-engine/ → port 3391 ├── /api/svc/quixzoom-engine/ → port 3390 └── ... (28 tjänster totalt) ``` **Konfigurationsfiler:** - `/etc/nginx/conf.d/aamos-upstreams.conf` — upstream-blocks - `/etc/nginx/snippets/rust-services.conf` — location-blocks - URL-prefix: `/api/svc//` ### Återanvändningsbarhet: ⭐⭐⭐⭐⭐ (5/5) **Varför hög återanvändningsbarhet:** 1. **Standardiserat mönster** — Varje tjänst följer samma konvention: `/api/svc//` → `.wavult.com:` 2. **Ingen affärslogik i gateway** — Nginx gör endast routing, SSL-terminering och rate limiting. All affärslogik finns i tjänsterna. 3. **Deklarativ konfiguration** — Nya tjänster läggs till med två rader (upstream + location) 4. **Health checks** — Varje tjänst exponerar `/health` som Nginx kan använda 5. **TLS/SSL centraliserat** — Certifikat hanteras på ett ställe **Exempel på återanvändning:** ```nginx # Lägg till ny tjänst (2 rader) upstream rust_new_service { server localhost:3400; } location /api/svc/new-service/ { proxy_pass http://rust_new_service/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } ``` ### Anpassningskostnad: **Låg** | Aspekt | Kostnad | Kommentar | |--------|---------|-----------| | **Ny tjänst** | ~5 min | Kopiera befintligt block, ändra port | | **Ny domän** | ~15 min | SSL-cert + server block | | **Rate limiting** | ~10 min | Nginx `limit_req_zone` | | **Auth** | ~30 min | JWT-validering i Nginx (lua) eller i tjänsterna | | **Load balancing** | ~20 min | Flera instanser i upstream | **Risker:** - Nginx-konfigurationen växer med varje tjänst (28+ redan) - Ingen service discovery — alla tjänster är hårdkodade - Ingen centraliserad API-dokumentation (Swagger/OpenAPI) **Rekommendation:** Behåll nuvarande lösning. Vid >50 tjänster, överväg en dynamisk service registry (Consul/Etcd). --- ## 2. Databaslager ### Nuvarande användning AAMOS använder en **polyglot persistence**-strategi: | Databas | Användning | Tjänster | |---------|-----------|----------| | **PostgreSQL** | Primär transaktionsdatabas | aamos-ledger, people-core, operations-core | | **Redis** | Cache + Event bus (Hermes) | Alla tjänster | | **PostGIS** | Geografisk data (implicit via PostgreSQL) | quixzoom-engine, landvex-engine | | **ClickHouse** | Analys och rapportering | aamos-analytics-engine | **PostgreSQL-schema (aamos-ledger):** ```sql -- Kärntabeller ledger_accounts -- Kontoplan (BAS 2024) ledger_journal_entries -- Verifikationer (IMMUTABLE) ledger_journal_lines -- Kontolinjer (dubbel bokföring) ledger_periods -- Perioder (open/closed) ledger_audit_log -- Audit trail (append-only) ledger_reconciliation_items -- Kontoavstämning ``` ### Återanvändningsbarhet: ⭐⭐⭐⭐ (4/5) **Varför hög återanvändningsbarhet:** 1. **Standardiserat schema** — Alla tjänster följer samma mönster: `tenant_id`, `trace_id`, `created_at` 2. **Multi-tenant design** — `tenant_id` på varje rad möjliggör SaaS-modell 3. **Audit-first** — Varje operation loggas i `ledger_audit_log` 4. **JSONB för flexibilitet** — `metadata`-fält möjliggör utökning utan migrationer 5. **BAS 2024 standard** — Svensk kontoplan kan bytas mot IFRS/US GAAP **Exempel på återanvändning (ny tjänst):** ```sql -- Samma mönster för ny tjänst CREATE TABLE new_service_entities ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id TEXT NOT NULL, trace_id TEXT NOT NULL, user_id TEXT NOT NULL, data JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` ### Anpassningskostnad: **Låg** | Aspekt | Kostnad | Kommentar | |--------|---------|-----------| | **Ny tenant** | ~1 min | `INSERT INTO tenants ...` | | **Ny kontoplan** | ~2 timmar | Kopiera BAS 2024, anpassa | | **Ny tabell** | ~15 min | Följ befintligt mönster | | **Migration** | ~30 min | `ALTER TABLE` eller ny tabell | | **Backup/restore** | ~10 min | `pg_dump` / `pg_restore` | | **PostGIS** | ~1 timme | Aktivera extension, spatiala index | **Risker:** - PostgreSQL är single-node (ingen replikering dokumenterad) - ClickHouse är separat — data dupliceras potentiellt - Ingen connection pooling (PgBouncer) dokumenterad - `ledger_journal_entries` växer obegränsat — partitionering behövs vid skala **Rekommendation:** - Sätt upp PostgreSQL-replikering (primary-replica) för läs-skala - Överväg PgBouncer vid >100 samtidiga anslutningar - Partitionera `ledger_journal_entries` per `fiscal_year` --- ## 3. Event-buss (Hermes) ### Nuvarande användning **Hermes** är AAMOS event fabric — en thin adapter mellan tjänster: ``` ┌─────────────────────────────────────────────────────────────┐ │ HERMES EVENT FABRIC │ ├─────────────────────────────────────────────────────────────┤ │ Transport: Redis pub/sub (primär) │ │ Fallback: JSONL-fil (/tmp/hermes/events.jsonl) │ │ Kanal: aamos:hermes │ ├─────────────────────────────────────────────────────────────┤ │ Event envelope: │ │ { id, trace_id, correlation_id, event_type, source, │ │ tenant_id, user_id, entity_type, entity_id, │ │ decision_source, payload, ts, schema_version } │ └─────────────────────────────────────────────────────────────┘ ``` **Användning i aamos-ledger:** ```javascript // Vid varje operation await hermes.emit('finance.journal.posted', ctx, { entry_id: id, entry_number, period, fiscal_year }); await hermes.emit('finance.account.created', ctx, { account_number, name, coa_standard }); await hermes.emit('finance.period.closed', ctx, { period, fiscal_year, closed_by }); ``` ### Återanvändningsbarhet: ⭐⭐⭐⭐⭐ (5/5) **Varför maximal återanvändningsbarhet:** 1. **Universal event envelope** — Samma schema för ALLA händelser oavsett tjänst 2. **Trace propagation** — `trace_id` och `correlation_id` följer genom hela systemet 3. **Tenant isolation** — `tenant_id` i varje event säkerställer multi-tenant 4. **Decision source** — `'user'|'system'|'agent'` möjliggör audit och AI-spårning 5. **Fallback-arkitektur** — Redis nere? JSONL-fil garanterar durabilitet 6. **Schema versioning** — `schema_version: '1.0'` möjliggör evolution **Exempel på återanvändning (ny tjänst):** ```javascript import hermes from './hermes.mjs'; // Publicera await hermes.emit('crm.deal.won', ctx, { deal_id, value, customer }); // Prenumerera await hermes.subscribe((event) => { if (event.event_type === 'finance.journal.posted') { // Uppdatera CRM med betalningsstatus } }); ``` ### Anpassningskostnad: **Låg** | Aspekt | Kostnad | Kommentar | |--------|---------|-----------| | **Nytt event** | ~2 min | `hermes.emit('domain.action', ctx, payload)` | | **Ny prenumerant** | ~5 min | `hermes.subscribe(handler)` | | **Ny kanal** | ~5 min | Ändra `HERMES_CHANNEL` env-var | | **Redis-cluster** | ~1 timme | Konfigurera sentinel/cluster | | **Kafka-migrering** | ~1 dag | Byta transport, behålla envelope | **Risker:** - Redis pub/sub är fire-and-forget (ingen persistens utanför JSONL) - Inga dead-letter queues dokumenterade - Ingen event replay-mekanism - JSONL-filen växer obegränsat — rotation behövs **Rekommendation:** - Sätt upp log rotation för JSONL-filen - Överväg Redis Streams (istället för pub/sub) för persistens - Dokumentera event-katalog (alla event_type som används) --- ## 4. Frontend-ramverk (Ouroboros) ### Nuvarande användning **Ouroboros** är LandveX Fortnox-klon — ett React-baserat webbgränssnitt: ``` Ouroboros Frontend ├── React 19.2.7 ├── Vite 8.1.0 (build tool) ├── TypeScript 6.0.2 ├── Tailwind CSS 4.3.1 ├── React Router 7.18.0 ├── Recharts 3.9.0 (diagram) ├── Lucide React 1.21.0 (ikoner) └── API-client: Fetch + localStorage JWT ``` **Struktur:** ``` src/ ├── App.tsx # Huvudkomponent (just nu: Vite-default) ├── main.tsx # Entry point ├── index.css # Tailwind + global styles ├── components/ │ └── Layout.tsx # Sidebar + navigation ├── contexts/ │ └── AuthContext.tsx # JWT auth (mock just nu) ├── types/ │ └── index.ts # TypeScript interfaces └── utils/ └── api.ts # API client (ej kopplad till backend) ``` **Nuvarande status:** - ✅ Byggt med modern stack (React 19, Vite, Tailwind) - ✅ TypeScript för typsäkerhet - ✅ Layout-komponent med navigation - ✅ AuthContext med JWT-hantering - ⚠️ **App.tsx är fortfarande Vite-default** (räknare, loggor) - ⚠️ **API-klienten är ej kopplad till aamos-ledger** (localhost:3000) - ⚠️ **Auth är mock** (hardkodad användare) - ⚠️ **Inga sidor implementerade** (endast Layout) ### Återanvändningsbarhet: ⭐⭐⭐ (3/5) **Varför medelhög återanvändningsbarhet:** 1. **Modern stack** — React 19 + Vite + Tailwind är branschstandard 2. **Komponentbaserad** — Layout, AuthContext kan återanvändas 3. **TypeScript** — Typer definierade för alla domänobjekt 4. **API-abstraktion** — `api.ts` ger ett lager ovanpå fetch **Begränsningar:** 1. **Ej kopplad till backend** — API-klienten pekar på fel URL (`localhost:3000` istället för `amos.wavult.com:3250`) 2. **Mock-auth** — Ingen riktig JWT-flöde implementerat 3. **Ingen state management** — Ingen Zustand/Redux/React Query 4. **Inga formulär** — Ingen react-hook-form eller liknande 5. **Inga tester** — Inget test-ramverk konfigurerat ### Anpassningskostnad: **Medium** | Aspekt | Kostnad | Kommentar | |--------|---------|-----------| | **Koppla till backend** | ~2 timmar | Uppdatera API_BASE_URL, anpassa endpoints | | **Implementera sidor** | ~2-3 dagar | Dashboard, verifikat, kontoplan, rapporter | | **JWT-auth** | ~4 timmar | Integrera med aamos-ledger auth.mjs | | **State management** | ~1 dag | Zustand eller React Query för server-state | | **Formulär** | ~1 dag | react-hook-form för verifikat-inmatning | | **Tester** | ~2 dagar | Vitest + React Testing Library | | **Mobilanpassning** | ~1 dag | Tailwind responsive (redan delvis) | **Risker:** - Stor gap mellan design (Layout.tsx) och implementation (App.tsx) - API-klienten har typer som inte matchar backend (Voucher vs journal_entry) - Ingen error handling eller loading states - Ingen pagination för stora listor (verifikat, konton) **Rekommendation:** 1. **Omedelbart:** Uppdatera `API_BASE_URL` till `https://amos.wavult.com/api/ledger` 2. **Sprint 1:** Implementera Dashboard-sida med riktig data 3. **Sprint 2:** Verifikat-lista och detaljvy 4. **Sprint 3:** Verifikat-inmatning med formulär 5. **Sprint 4:** Rapporter (P&L, balansräkning) --- ## Jämförelse med Auth/Identity Service (Del 1) | Komponent | Återanvändningsbarhet | Anpassningskostnad | Nyckelskillnad | |-----------|----------------------|-------------------|----------------| | **Auth/Identity** | ⭐⭐⭐⭐⭐ | Låg | Redan abstraherad, tenant-aware | | **API-gateway** | ⭐⭐⭐⭐⭐ | Låg | Samma mönster, deklarativ config | | **Databaslager** | ⭐⭐⭐⭐ | Låg | Standardiserat schema, men skalning behövs | | **Event-buss** | ⭐⭐⭐⭐⭐ | Låg | Universal envelope, fallback-arkitektur | | **Frontend** | ⭐⭐⭐ | Medium | Modern stack men ej kopplad till backend | --- ## Rekommendationer per komponent ### API-gateway: ✅ Behåll - Nginx är beprövad, stabil och kräver minimal anpassning - Överväg endast dynamisk service registry vid >50 tjänster ### Databaslager: ⚠️ Förbättra - Sätt upp PostgreSQL-replikering - Partitionera `ledger_journal_entries` - Överväg PgBouncer för connection pooling ### Event-buss: ✅ Behåll, förbättra - Hermes-envelopen är utmärkt - Lägg till log rotation för JSONL - Dokumentera event-katalog ### Frontend: 🔴 Prioritera - Största gapet mellan design och implementation - Koppla till backend omedelbart - Implementera sidor i prioritetsordning: Dashboard → Verifikat → Rapporter --- ## Nästa steg 1. **Omedelbart:** Koppla Ouroboros frontend till aamos-ledger backend 2. **Vecka 1:** Implementera Dashboard med riktig data 3. **Vecka 2:** Implementera verifikat-lista och detaljvy 4. **Vecka 3:** PostgreSQL-replikering och partitionering 5. **Vecka 4:** Hermes event-katalog och log rotation --- *Analys baserad på:* - `aamos-ledger/index.mjs` — Ledger Engine API - `aamos-ledger/hermes.mjs` — Event fabric - `aamos-ledger/schema.sql` — Databasschema - `ouroboros-frontend/` — React frontend - `memory/nginx-upstreams-result.md` — Nginx konfiguration - `landvex-plugin-architecture.md` — Plugin-arkitektur