bae705aa97
- 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
344 lines
12 KiB
Markdown
344 lines
12 KiB
Markdown
# LandveX Finance
|
|
|
|
> Banking-grade bokföringsgränssnitt för LandveX AB
|
|
> Byggt på Ouroboros Ledger API med realtidsintegration mot Revolut, Nordea och SIE4-export.
|
|
|
|
---
|
|
|
|
## Arkitekturöversikt
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ LANDVEX FINANCE │
|
|
│ (Single-Page Application) │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────┐ │
|
|
│ │ Översikt │ │Transaktioner│ │ Fakturor │ │ Moms │ │
|
|
│ │ (KPI) │ │ (Journal) │ │ (Invoice) │ │ (VAT) │ │
|
|
│ └─────────────┘ └─────────────┘ └─────────────┘ └────────┘ │
|
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────┐ │
|
|
│ │ Löner │ │ Period │ │ Tasks │ │ Prognos│ │
|
|
│ │ (Payroll) │ │ (Close) │ │(Onboarding) │ │(Forecast)│
|
|
│ └─────────────┘ └─────────────┘ └─────────────┘ └────────┘ │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ UI: Vanilla JS ES Modules + CSS Custom Properties │
|
|
│ State: In-memory med localStorage-persistens │
|
|
│ API: Fetch → LandveX Ledger Proxy → Ouroboros Ledger (port 3250)│
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ LANDVEX LEDGER PROXY │
|
|
│ (/opt/amos/api/landvex/ledger-proxy.mjs) │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ • Server-side auth (JWT → ledger token) │
|
|
│ • Trial balance beräknas server-side (prestanda) │
|
|
│ • Revolut integration (JWT assertion + refresh token) │
|
|
│ • SIE4-export │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
│
|
|
┌───────────────┼───────────────┐
|
|
▼ ▼ ▼
|
|
┌─────────┐ ┌──────────┐ ┌──────────┐
|
|
│Ledger │ │ Revolut │ │ Nordea │
|
|
│(3250) │ │ (B2B) │ │ (API) │
|
|
└─────────┘ └──────────┘ └──────────┘
|
|
```
|
|
|
|
### Teknisk Stack
|
|
|
|
| Lager | Teknik |
|
|
|-------|--------|
|
|
| Frontend | Vanilla JS (ES2022), CSS Custom Properties, inget framework |
|
|
| Backend Proxy | Node.js + Express (ES modules) |
|
|
| Ledger API | Ouroboros Ledger (port 3250) |
|
|
| Bankintegration | Revolut B2B API, Nordea Open Banking |
|
|
| Datalagring | PostgreSQL (ledger), JSONL-filer (backup) |
|
|
| Cache | Redis |
|
|
| Auth | JWT (wavult_token cookie) |
|
|
|
|
---
|
|
|
|
## Deployment-guide
|
|
|
|
### Förutsättningar
|
|
|
|
- Node.js ≥ 20
|
|
- PostgreSQL ≥ 15
|
|
- Redis ≥ 7
|
|
- Nginx (reverse proxy + SSL)
|
|
|
|
### Miljövariabler
|
|
|
|
```bash
|
|
# Databas
|
|
DATABASE_URL=postgresql://user:pass@host:5432/wavult_identity
|
|
LEDGER_DB_URL=postgresql://user:pass@host:5432/ledger
|
|
|
|
# Redis
|
|
REDIS_URL=redis://localhost:6379
|
|
|
|
# Auth
|
|
AMOS_JWT_SECRET=your-jwt-secret-here
|
|
|
|
# Revolut (B2B)
|
|
REVOLUT_CLIENT_ID=your-client-id
|
|
REVOLUT_REFRESH_TOKEN=your-refresh-token
|
|
REVOLUT_PRIVATE_KEY_PATH=/opt/amos/data/revolut_private_prod.pem
|
|
|
|
# Intern kommunikation
|
|
LEDGER_BASE=http://localhost:3250
|
|
LEDGER_TOKEN=wavult-amos-internal-2026
|
|
|
|
# Server
|
|
PORT=3100
|
|
BIND_HOST=0.0.0.0
|
|
NODE_ENV=production
|
|
```
|
|
|
|
### Installation
|
|
|
|
```bash
|
|
# 1. Klona repo (om separat)
|
|
cd /opt/amos
|
|
|
|
# 2. Installera beroenden
|
|
npm install
|
|
|
|
# 3. Verifiera miljövariabler
|
|
cp .env.example .env
|
|
nano .env
|
|
|
|
# 4. Starta ledger-tjänsten (om separat)
|
|
cd /opt/amos/services/ledger
|
|
npm start # port 3250
|
|
|
|
# 5. Starta huvudservern
|
|
npm start # port 3100
|
|
|
|
# 6. Verifiera health checks
|
|
curl http://localhost:3100/health
|
|
curl http://localhost:3100/health/finance
|
|
curl http://localhost:3100/prom-metrics
|
|
```
|
|
|
|
### PM2 (produktion)
|
|
|
|
```bash
|
|
# ecosystem.config.cjs
|
|
module.exports = {
|
|
apps: [{
|
|
name: 'amos-finance',
|
|
script: './scripts/server.mjs',
|
|
instances: 1,
|
|
exec_mode: 'fork',
|
|
env: { NODE_ENV: 'production' },
|
|
log_file: '/var/log/amos/finance.log',
|
|
error_file: '/var/log/amos/finance-error.log',
|
|
out_file: '/var/log/amos/finance-out.log',
|
|
merge_logs: true,
|
|
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
|
|
}]
|
|
};
|
|
```
|
|
|
|
### Nginx-konfiguration
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name finance.wavult.com;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/wavult.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/wavult.com/privkey.pem;
|
|
|
|
location / {
|
|
root /opt/amos/public/ouroboros/finance;
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
|
|
location /api/ {
|
|
proxy_pass http://localhost:3100;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
|
|
location /prom-metrics {
|
|
proxy_pass http://localhost:3100;
|
|
allow 10.0.0.0/8; # Interna nätverk endast
|
|
deny all;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## API-endpoints
|
|
|
|
### Finance Proxy (`/api/landvex/*`)
|
|
|
|
| Metod | Endpoint | Beskrivning |
|
|
|-------|----------|-------------|
|
|
| GET | `/api/landvex/ledger/journal` | Journal (verifikat) |
|
|
| GET | `/api/landvex/ledger/trial-balance` | Saldobalans (server-side) |
|
|
| POST | `/api/landvex/ledger/journal` | Skapa verifikat |
|
|
| POST | `/api/landvex/ledger/journal/:id/post` | Bokför verifikat |
|
|
| GET | `/api/landvex/ledger/accounts` | Kontoplan |
|
|
| GET | `/api/landvex/ledger/periods` | Räkenskapsperioder |
|
|
| GET | `/api/landvex/ledger/invoices` | Fakturor |
|
|
| POST | `/api/landvex/ledger/invoices` | Skapa faktura |
|
|
| GET | `/api/landvex/ledger/export/sie4` | SIE4-export |
|
|
| POST | `/api/landvex/ledger/journal/:id/upload` | Ladda upp kvitto |
|
|
| GET | `/api/landvex/ledger/journal/:id/receipts` | Hämta kvitton |
|
|
|
|
### Health & Metrics
|
|
|
|
| Endpoint | Beskrivning |
|
|
|----------|-------------|
|
|
| `GET /health` | Simpel health check |
|
|
| `GET /health/detailed` | Vault + OPA status |
|
|
| `GET /health/finance` | DB + Redis + disk + ledger + Revolut |
|
|
| `GET /prom-metrics` | Prometheus metrics (intern) |
|
|
| `GET /metrics` | JSON metrics (legacy) |
|
|
|
|
---
|
|
|
|
## Miljövariabler (komplett lista)
|
|
|
|
### Obligatoriska
|
|
|
|
| Variabel | Beskrivning | Exempel |
|
|
|----------|-------------|---------|
|
|
| `DATABASE_URL` | PostgreSQL för identity/tenant | `postgresql://.../wavult_identity` |
|
|
| `AMOS_JWT_SECRET` | JWT-signering | `super-secret-key` |
|
|
| `LEDGER_BASE` | Ouroboros Ledger URL | `http://localhost:3250` |
|
|
| `LEDGER_TOKEN` | Intern token för ledger | `wavult-amos-internal-2026` |
|
|
|
|
### Bankintegration (valfria)
|
|
|
|
| Variabel | Beskrivning |
|
|
|----------|-------------|
|
|
| `REVOLUT_CLIENT_ID` | Revolut B2B client ID |
|
|
| `REVOLUT_REFRESH_TOKEN` | Refresh token för Revolut |
|
|
| `REVOLUT_PRIVATE_KEY_PATH` | Sökväg till RSA-nyckel |
|
|
| `NORDEA_CLIENT_ID` | Nordea Open Banking |
|
|
| `NORDEA_CLIENT_SECRET` | Nordea secret |
|
|
|
|
### Operativa
|
|
|
|
| Variabel | Beskrivning | Standard |
|
|
|----------|-------------|----------|
|
|
| `PORT` | Serverport | `3100` |
|
|
| `BIND_HOST` | Bind-adress | `0.0.0.0` |
|
|
| `NODE_ENV` | Miljö | `development` |
|
|
| `REDIS_URL` | Redis-anslutning | `redis://localhost:6379` |
|
|
| `LOG_LEVEL` | Loggnivå | `info` |
|
|
|
|
---
|
|
|
|
## Utveckling
|
|
|
|
### Lokal utveckling
|
|
|
|
```bash
|
|
# 1. Starta med utvecklingsläge
|
|
NODE_ENV=development npm start
|
|
|
|
# 2. UI-filer serveras från /public/ouroboros/finance/
|
|
# Ändringar i index.html syns direkt (ingen build)
|
|
|
|
# 3. Testa API
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
|
http://localhost:3100/api/landvex/ledger/journal?limit=5
|
|
```
|
|
|
|
### Filstruktur (frontend)
|
|
|
|
```
|
|
public/ouroboros/finance/
|
|
├── index.html # Huvudfil (177KB, ska brytas ner)
|
|
├── ledger.html # Äldre ledger-vy
|
|
└── docs/
|
|
├── UI-REFACTOR-PLAN.md # Refaktoreringsplan
|
|
└── ARCHITECTURE.md # Arkitekturbeskrivning
|
|
```
|
|
|
|
### Filstruktur (backend)
|
|
|
|
```
|
|
api/
|
|
├── finance/ # Finance-specifika moduler (nya)
|
|
│ ├── metrics.mjs # Prometheus metrics
|
|
│ ├── logger.mjs # Strukturerad loggning
|
|
│ └── health.mjs # Health checks
|
|
├── landvex/
|
|
│ └── ledger-proxy.mjs # Huvud-proxy för LandveX
|
|
├── finance/ # Generella finance-routes
|
|
│ ├── ledger.mjs
|
|
│ ├── invoices.mjs
|
|
│ └── ...
|
|
└── ...
|
|
```
|
|
|
|
---
|
|
|
|
## Övervakning
|
|
|
|
### Prometheus Metrics
|
|
|
|
```bash
|
|
# Scrape-config för Prometheus
|
|
scrape_configs:
|
|
- job_name: 'landvex-finance'
|
|
static_configs:
|
|
- targets: ['localhost:3100']
|
|
metrics_path: '/prom-metrics'
|
|
```
|
|
|
|
### Viktiga metrics
|
|
|
|
| Metric | Typ | Beskrivning |
|
|
|--------|-----|-------------|
|
|
| `finance_journal_entries_total` | Counter | Antal verifikat |
|
|
| `finance_invoices_total` | Gauge | Fakturor per status |
|
|
| `finance_vat_payable` | Gauge | Moms att betala |
|
|
| `finance_api_duration_seconds` | Histogram | API-svarstider |
|
|
| `amos_http_requests_total` | Counter | HTTP-requests |
|
|
|
|
### Larm (förslag)
|
|
|
|
| Larm | Condition | Åtgärd |
|
|
|------|-----------|--------|
|
|
| DB nere | `health/finance` != 200 | PagerDuty |
|
|
| Disk full | `disk.free_gb < 1` | Rensa loggar |
|
|
| Revolut auth fail | `revolut.authenticated == false` | Rotera token |
|
|
| API-latens | `p95 > 2s` | Skala upp |
|
|
|
|
---
|
|
|
|
## Säkerhet
|
|
|
|
- **Auth:** JWT i httpOnly-cookie, Bearer-token i header
|
|
- **CORS:** Endast `*.wavult.com`
|
|
- **Rate limiting:** 100 req/min per IP
|
|
- **Input validation:** Alla POST/PUT valideras
|
|
- **SQL injection:** Parameteriserade queries (pg)
|
|
- **XSS:** `esc()`-funktion i UI, CSP-headers
|
|
- **CSRF:** SameSite=Lax på cookies
|
|
|
|
---
|
|
|
|
## Support
|
|
|
|
- **Slack:** #finance-dev
|
|
- **On-call:** finance-oncall@wavult.com
|
|
- **Runbook:** [Confluence/Runbooks/Finance](https://wiki.wavult.com)
|
|
|
|
---
|
|
|
|
*Senast uppdaterad: 2026-06-24*
|
|
*Version: Sprint 3 (UI & Observability)*
|