Files
boc/AAMOS_INFRASTRUCTURE_ANALYSIS_PART2.md
T
Bernt 05ed037fe8 pilot.landvex.com: HTTPS + Full Stack Verified
- DNS: pilot.landvex.com -> 16.170.83.169
- TLS: Let's Encrypt certificate (expires 2026-09-30)
- Nginx: reverse proxy with SSL termination
- API: https://pilot.landvex.com/api/v1/missions
- UI: https://pilot.landvex.com/
- Upload: POST /api/v1/missions/import (multipart/form-data)

Verified:
 https://pilot.landvex.com/health
 https://pilot.landvex.com/version
 https://pilot.landvex.com/api/v1/missions (list)
 https://pilot.landvex.com/api/v1/missions/:id (get)
 POST /api/v1/missions/import (video upload)
 UI loads with title 'LandveX Intelligence Lab'

Next: Pilot 001 — Break the system!
2026-07-02 17:34:19 +00:00

394 lines
15 KiB
Markdown

# 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/<service>/`
### Återanvändningsbarhet: ⭐⭐⭐⭐⭐ (5/5)
**Varför hög återanvändningsbarhet:**
1. **Standardiserat mönster** — Varje tjänst följer samma konvention: `/api/svc/<namn>/``<namn>.wavult.com:<port>`
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