BC02 - TEKNISK ARKITEKTUR

BC02 - AI-Dokumentanalys för Offerter (Optimate Core)

Projektkod: AIDA-2025-BC2
Version: 1.0
Datum: 2025-11-01
Arkitekt: Lars Diethelm
Status: För godkännande


Sammanfattning

Arkitekturval

Plattform: Optimate Core - Hub-and-Spoke Architecture

  • Motivering: Modularitet och separation av capability (core engines) från configuration (n8n workflows för BC02). Beprövad arkitektur med återanvändbara komponenter.

AI-plattform: Anthropic Claude Sonnet 4 (primär) + Ollama (lokal backup/embeddings)

  • Motivering: Claude excellent för multi-document analysis, teknisk dokumentförståelse och svensk text. Vision API för ritningsanalys. Ollama för embeddings och fallback.

Orkestrering (Hub): n8n

  • Motivering: BC02-specifika workflows för dokumenthantering, beslutspunkter, CRM-integration. Visuell design för enkel anpassning.

Capability Layer (Spokes): Optimate Core Engines (FastAPI Microservices)

  • Ingestion Engine: ZIP-fil parsing, dokumentidentifiering, ritningsanalys
  • Agentic Engine: Multi-document RAG, krav-extrahering, motstridighetsdetektering, Go/No-go rekommendation

Deployment: Render (Cloud) - REKOMMENDERAT

  • Motivering: Snabb setup för Fas 4. Managed infrastructure. Auto-scaling för varierande offertvolym (550/år = ~10-12/vecka, ojämnt fördelat).

Säkerhet: Render Private Network + Keycloak SSO (future)

  • Motivering: Säker kommunikation mellan services. Multi-user access (Mattias, Karin, Emil, Liza).

Klassificering: Konfidentiell affärsdata + Kunddokument

  • Kryptering: TLS 1.3 för transit, AES-256 för lagring. GDPR-compliance för kunddata.

Huvudkomponenter (Optimate Core)

Hub Layer:

  • n8n: BC02-specifika workflows (dokumentintag, analys-pipeline, CRM-uppdatering)

Capability Layer (Core Spokes):

  • Ingestion Engine (FastAPI): ZIP-parsing, PDF-extrahering, ritningsanalys (Blue Beam integration)
  • Agentic Engine (FastAPI): Multi-document RAG, krav-extrahering, motstridighetsdetektering, Go/No-go AI
  • PostgreSQL (Render Managed): Förfrågningslog, AI-beslut, historiska projekt, kunddata-cache
  • Qdrant: Vektordatabas för semantisk sökning i dokumentation och historiska offerter
  • Ollama: Lokal LLM för embeddings och backup-inferens
  • Django HIL Portal: Mattias/Karins gränssnitt för granskning av AI-analys och beslutsstöd

External Integrations:

  • WorkCloud CRM API (registrering av affärsmöjlighet)
  • UC API (kreditkontroll)
  • Email (mottagande och utskick av offerter)
  • Blue Beam (future: direktintegration för ritningsanalys)

1. Arkitekturöversikt

Konceptuell arkitektur (Optimate Core - Hub-and-Spoke)

┌──────────────────────────────────────────────────────────┐
│              PRESENTATION LAYER                           │
│      Django HIL Portal (Mattias, Karin, Emil)            │
│   - Förfrågningslista med AI-rekommendationer            │
│   - Dokumentvisning med AI-highlights                    │
│   - Go/No-go beslutsstöd med motivering                  │
│   - Historisk projektjämförelse                          │
└─────────────────┬────────────────────────────────────────┘
                  │ HTTPS (Render Private Network)
                  │
┌─────────────────▼────────────────────────────────────────┐
│            HUB LAYER (BC02 Configuration)                 │
│                        n8n                                │
│                                                           │
│  BC02-specifika workflows:                               │
│  1. Förfrågningsmottagning (Email → ZIP-parsing)         │
│  2. Dokumentanalys-pipeline (orchestration)              │
│  3. Go/No-go beslutsstöd                                 │
│  4. CRM-registrering (WorkCloud)                         │
│  5. Kreditkontroll (UC API)                              │
│  6. Offertgenerering och utskick                         │
└──┬────────┬─────────┬──────────┬──────────────────────────┘
   │        │         │          │
   │ API    │ API     │ API      │ API
   │        │         │          │
┌──▼────────▼─────────▼──────────▼──────────────────────────┐
│       CAPABILITY LAYER (Core Spokes)                      │
│          Optimate Core Engines                            │
│                                                           │
│  ┌────────────────────┐      ┌──────────────────────┐   │
│  │ Ingestion Engine   │      │  Agentic Engine      │   │
│  │   (FastAPI)        │      │    (FastAPI)         │   │
│  │                    │      │                      │   │
│  │ • ZIP parsing      │      │ • Multi-doc RAG      │   │
│  │ • PDF extraction   │      │ • Krav-extrahering   │   │
│  │ • Dokumenttyp ID   │      │ • Motstridigheter    │   │
│  │ • Ritningsanalys   │      │ • Go/No-go AI        │   │
│  │ • OCR (Claude)     │      │ • Historisk jämför.  │   │
│  └────────────────────┘      └──────────────────────┘   │
│                                                           │
│  ┌──────────────┐  ┌──────────────┐  ┌────────────┐    │
│  │   Claude API │  │    Ollama    │  │   Qdrant   │    │
│  │              │  │              │  │            │    │
│  │ • Doc analys │  │ • Embeddings │  │ • Historik │    │
│  │ • Vision API │  │ • Backup AI  │  │ • Semantisk│    │
│  │ • Multi-doc  │  │              │  │   sökning  │    │
│  └──────────────┘  └──────────────┘  └────────────┘    │
│                                                           │
│  ┌──────────────────────────────────────────────────┐   │
│  │      PostgreSQL (Render Managed)                 │   │
│  │  • Förfrågningslog (550/år)                      │   │
│  │  • AI-beslut och rekommendationer                │   │
│  │  • Historiska projekt (vunna/förlorade)          │   │
│  │  • Kunddata-cache (WorkCloud sync)               │   │
│  │  • Dokument-metadata                             │   │
│  └──────────────────────────────────────────────────┘   │
└───────────────────┬─────────────────────────────────────┘
                    │
┌───────────────────▼─────────────────────────────────────┐
│            EXTERNAL INTEGRATIONS                         │
│  (anropas via Ingestion/Agentic Engines)                │
│                                                          │
│  WorkCloud CRM  │  UC Kreditkontroll  │  Email (SMTP)  │
└──────────────────────────────────────────────────────────┘

Dataflöde - Komplett offertprocess:

[1. Email med ZIP-länk] 
    ↓
[n8n: Ladda ner ZIP] → [Ingestion Engine: Extrahera filer]
    ↓
[Ingestion Engine: Identifiera dokumenttyper]
    → AF-del, AFD-1, AFD.472, K-ritningar, A-ritningar, 
      teknisk beskrivning (25-60 sidor)
    ↓
[Agentic Engine: Multi-document RAG-analys]
    → Extrahera: Omfattning, garantitider, entreprenadform,
      tekniska krav, motstridigheter
    → Jämför med Qdrant: 5 liknande historiska projekt
    ↓
[Agentic Engine: Go/No-go AI-rekommendation]
    Input: Projektstorlek, kund, geografi, komplexitet, historik
    Output: Rekommendation (Go/No-go) + konfidensgrad + motivering
    ↓
[Django Portal: Mattias/Emil ser AI-sammanfattning]
    - 1-sida sammanfattning (från 25-60 sidor)
    - Kritiska krav highlighted
    - Motstridigheter flaggade
    - Go/No-go rekommendation med motivering
    - Jämförelse med historiska projekt
    ↓
[Manuellt beslut: Go/No-go]
    ↓
IF Go:
    ├─► [n8n → UC API: Kreditkontroll]
    ├─► [n8n → WorkCloud: Registrera affärsmöjlighet]
    ├─► [n8n → OneNote: Uppdatera]
    └─► [Fortsätt med mängdning och kalkyl]
ELSE No-go:
    └─► [n8n → CRM: Markera som avböjd + skäl]

Teknisk stack (Optimate Core)

Lager Teknologi Produkt/Ramverk Version Motivering
Hub (Configuration)
Orkestrering n8n n8n Latest Visuell workflow för BC02-specifik offertprocess
Capability (Core Spokes)
Core Engines FastAPI Optimate Ingestion Engine 1.x ZIP-parsing, dokumentidentifiering, ritningsanalys
Core Engines FastAPI Optimate Agentic Engine 1.x Multi-doc RAG, krav-extrahering, Go/No-go AI
AI - Primär Claude API Anthropic Sonnet 4 Latest Multi-document analysis, Vision för ritningar
AI - Lokal Ollama Llama 3.1/Mistral Latest Embeddings för Qdrant, backup-inferens
Vektordatabas Qdrant Qdrant Latest Semantisk sökning i historik + dokumentation
Databas (Cloud) PostgreSQL Render Managed 15.x Förfrågningslog, AI-beslut, kundcache
Presentation
Frontend Django Django HIL Portal 4.x Mattias/Karin/Emils gränssnitt för beslutsstöd
Infrastructure
Cloud Deployment Render Render - Managed infrastructure, private network
Identity Keycloak Keycloak Latest SSO för multi-user (Mattias, Karin, Emil, Liza)
Observability LangSmith LangSmith Latest AI decision tracking, quality monitoring
Containerisering Docker Docker Compose Latest Local dev + on-premise option
Version Control Git GitHub Latest Three-repo strategy (core, template, customer)

2. AI-komponenter (Optimate Core)

Capability Architecture för BC02

BC02 använder följande Optimate Core engines:

1. Ingestion Engine - BC02-specifika endpoints

Ansvar: Förfrågningsintag, dokumentparsing, initial klassificering

BC02-funktioner:

  • ZIP-fil hantering: Ladda ner från email-länk, extrahera alla filer
  • Dokumenttyp-identifiering: Känna igen AF, AFD, K-ritningar, A-ritningar, teknisk beskrivning
  • PDF-extrahering: Text + struktur från multi-page dokument (25-60 sidor)
  • Ritningsanalys: OCR via Claude Vision för littrering, ytor, detaljer
  • Metadata-extrahering: Projektstorlek, byggare, plats, typ från dokumentnamn och innehåll

API-endpoints för BC02:

POST /api/v1/ingest/tender-zip
  Input: {url: "https://port.se/download/xxx.zip"}
  Output: {
    files: [
      {filename: "AF-del.pdf", type: "af", pages: 28, ...},
      {filename: "AFD-1.pdf", type: "afd1", pages: 3, ...},
      {filename: "K-ritning_01.pdf", type: "k_drawing", ...},
      ...
    ],
    metadata: {
      project_name: "Stender VB 1966",
      builder: "Stender Fastigheter",
      location: "Uppsala",
      estimated_size: "2.5 MSEK"
    }
  }

POST /api/v1/ingest/identify-document-type
  Input: {filename: "...", content_sample: "first 1000 chars"}
  Output: {type: "afd472", confidence: 0.95, reasoning: "..."}

POST /api/v1/ingest/extract-drawing-info
  Input: {drawing_pdf_base64: "..."}
  Output: {
    area_sqm: 1250,
    material_distribution: {"plåt": 800, "papp": 450},
    littering: ["A1", "A2", "B3"],
    complexity: "medium"
  }

Prestanda:

  • ZIP-extrahering: <30s för typisk förfrågan (10-30 filer)
  • Dokumenttyp-ID: <2s per dokument (95%+ accuracy)
  • Ritningsanalys: <10s per ritning med Claude Vision

2. Agentic Engine - BC02-specifika endpoints

Ansvar: Intelligent dokumentanalys, RAG-pipeline, beslutsstöd

BC02-funktioner:

  • Multi-document RAG: Läsa och förstå 10-30 dokument tillsammans (totalt 25-60 sidor)
  • Krav-extrahering: AFD-1 Omfattning, AFD.472 Garantitider, tekniska krav från teknisk beskrivning
  • Motstridighetsdetektering: Jämföra AFD, teknisk beskrivning, ritningar - flagga konflikter
  • Entreprenadform-identifiering: AB vs ABT + implikationer för risk och ansvar
  • Historisk jämförelse: Söka i Qdrant för 5 liknande projekt baserat på typ, storlek, kund
  • Go/No-go AI: Rekommendera baserat på prioriteringsmatris + historik

API-endpoints för BC02:

POST /api/v1/agent/analyze-tender
  Input: {
    documents: [
      {type: "af", content: "...", metadata: {...}},
      {type: "afd1", content: "...", metadata: {...}},
      {type: "technical_description", content: "...", pages: 52},
      ...
    ],
    project_metadata: {...}
  }
  Output: {
    summary: "1-page executive summary",
    scope: {
      extracted_from: "AFD-1 page 2",
      requirements: ["Takarbeten 1250 kvm", "Plåt + papp", ...],
      exclusions: ["Ställning ingår ej", ...]
    },
    guarantees: {
      standard: "2 år",
      special: ["Täthet 10 år", "Färg 5 år"],
      source: "AFD.472 section 3.2"
    },
    contract_form: {
      type: "ABT",
      implications: ["Byggherren ansvarar för...", ...],
      source: "AF-del page 1"
    },
    conflicts: [
      {
        description: "Teknisk beskrivning säger 'plåt endast', ritning visar papp",
        documents: ["technical_description p.15", "drawing_02.pdf"],
        severity: "high"
      }
    ],
    technical_requirements: [
      "Brandklass REI 60",
      "U-värde max 0.15",
      ...
    ],
    confidence: 0.88,
    processing_time_ms: 25000
  }

POST /api/v1/agent/go-no-go-recommendation
  Input: {
    project_summary: {...},  # From analyze-tender
    customer_info: {name: "...", history: [...], credit_rating: ...},
    prioritization_matrix: {
      size_threshold: 500000,  # SEK
      margin_min: 0.15,
      geography_max_km: 200,
      customer_tier: "A/B/C"
    }
  }
  Output: {
    recommendation: "GO",
    confidence: 0.87,
    reasoning: [
      "Project size 2.5 MSEK exceeds threshold (500k)",
      "Customer A-tier with good payment history",
      "Within 150km (Uppsala)",
      "Similar project won 3 months ago with 22% margin"
    ],
    similar_projects: [
      {
        name: "Stender AB 2024-08",
        won: true,
        margin: 0.22,
        similarity_score: 0.91
      },
      ...
    ],
    risk_factors: [
      "AFD.472 guarantees 10 years (above standard 2y)",
      "ABT contract form (more responsibility)"
    ],
    sources: [
      "Historical project DB: 5 matches",
      "Customer tier from WorkCloud",
      "AFD.472 from tender documents"
    ]
  }

POST /api/v1/agent/summarize-requirements
  Input: {technical_description_pdf: "...", page_count: 52}
  Output: {
    one_page_summary: "Markdown formatted, ~500 words",
    critical_requirements: [
      {requirement: "...", source: "page 15", priority: "high"},
      ...
    ],
    materials: ["Plåt Prelaq Nova", "Papp SBS", ...],
    estimated_complexity: "medium-high"
  }

Prestanda:

  • Multi-document analysis: <30s för 25-60 sidor
  • Go/No-go recommendation: <5s (efter dokumentanalys)
  • Motstridighetsdetektering: <10s
  • Historisk jämförelse (Qdrant): <2s

AI-modeller och strategi

Modell 1: Claude Sonnet 4 (Primär för dokumentanalys)

Användning i BC02:

  • Multi-document understanding (AF, AFD, teknisk beskrivning tillsammans)
  • Svensk textförståelse (byggdokumentation är på svenska)
  • Vision API för ritningsanalys (K-ritningar, takplaner)
  • Sammanfattning av långa dokument (52 sidor → 1 sida)
  • Motstridighetsdetektering mellan dokument

Prompt-strategi:

System: Du är en expert på svensk byggdokumentation och offertkalkylering 
för tak- och fasadarbeten. Din uppgift är att analysera förfrågningsunderlag
och extrahera kritisk information för kalkylering.

Context: [10-30 dokument i full-text eller excerpts]

Task: Analysera samtliga dokument och:
1. Extrahera omfattning från AFD-1
2. Identifiera speciella garantikrav från AFD.472
3. Lista alla tekniska krav från teknisk beskrivning
4. Flagga motstridigheter mellan dokument
5. Sammanfatta i max 1 sida

Format: JSON enligt schema {...}

Träningsdata:

  • 10 kompletta förfrågningsunderlag från Mattias
  • 50+ historiska projekt med outcome (vunna/förlorade)
  • Dokumentation av common pitfalls (missade krav)

Prestanda target:

  • Krav-extrahering: >95% accuracy
  • Motstridighetsdetektering: >85% recall
  • Sammanfattning: Läsbar och användbar för Mattias/Karin

Modell 2: Ollama (Lokal LLM för embeddings + backup)

Modeller:

  • nomic-embed-text: Embeddings för Qdrant
  • Llama 3.1 8B: Backup-inferens vid Claude API-fel

Användning i BC02:

  • Embeddings av historiska projekt (typ, krav, outcome)
  • Embeddings av tekniska krav för semantisk matching
  • Backup om Claude API är nere (lägre quality men operational continuity)

Prestanda:

  • Embeddings: <500ms per document
  • Inference: 5-10s per request (CPU), <2s med GPU

RAG-pipeline för BC02

Vad lagras i Qdrant:

  1. Historiska projekt (550/år = 2750 projekt över 5 år)
    • Projektnamn, typ, storlek, kund
    • Tekniska krav (embedded)
    • Outcome (vunnet/förlorat, marginal)
    • Kalkylatorns anteckningar
  2. Dokumentation och kunskapsbas
    • AFF och AMA-definitioner (svenska byggstandarder)
    • Tidigare feltolkningar och "lessons learned"
    • Materialspecifikationer och priser

Retrieval-strategi:

Query: Nytt projekt "Stender VB 1966, tak 1250 kvm, plåt + papp"

Qdrant search:
  - Embedding av projektsummary
  - Metadata filter: type="tak", size_range=[1000, 1500]
  - Return: Top 5 most similar projects

For each returned project:
  - Margin, outcome, customer, challenges
  - Feed to Claude as context for Go/No-go decision

3. Systemintegration

Integrationspunkter

System Typ Protokoll Frekvens Datavolym Kritikalitet
Email (inbound) Källa IMAP/POP3 Continuous 550 emails/år Hög
WorkCloud CRM Mål REST API Per offert 550 updates/år Hög
UC Kreditkontroll Tjänst REST API Per Go-beslut ~400/år Medium
Email (outbound) Mål SMTP Per offert ~220/år Medium
Blue Beam Future Plugin/API Optional - Låg

API-specifikationer

API 1: WorkCloud CRM - Registrera affärsmöjlighet

endpoint: /api/opportunities
method: POST
authentication: API Key (Header)
request body:
  {
    "customer_id": "12345",
    "project_name": "Stender VB 1966",
    "estimated_value": 2500000,
    "probability": 0.5,
    "stage": "tender_analysis",
    "responsible": "Mattias Svensson",
    "notes": "AI-analyserad, Go-beslut, ABT-kontrakt",
    "documents": ["af_del.pdf", "technical_desc.pdf"],
    "source": "BC02_AI_System"
  }
response: 200 OK
  {
    "opportunity_id": "OPP-2025-1234",
    "created_at": "2025-11-01T10:30:00Z"
  }

API 2: UC Kreditkontroll

endpoint: /api/v1/creditcheck
method: POST
authentication: API Key
request body:
  {
    "org_number": "556789-1234",
    "company_name": "Stender Fastigheter AB"
  }
response:
  {
    "rating": "AAA",
    "credit_limit": 5000000,
    "payment_remarks": 0,
    "recommendation": "approve",
    "report_url": "https://uc.se/report/..."
  }

API 3: Email Integration (via n8n)

n8n har inbyggda Email-nodes:

  • Email Trigger: Poll IMAP inbox var 5:e minut för nya förfrågningar
  • Email Send: SMTP för utskick av offerter

4. Dataarkitektur

Datamodell

Tabell 1: tender_requests

Attribut Typ Beskrivning Constraint
id UUID Unik identifierare PRIMARY KEY
received_at TIMESTAMP Mottagen tidpunkt NOT NULL
email_from VARCHAR(255) Avsändare NOT NULL
email_subject VARCHAR(500) Ämnesrad
zip_url TEXT Länk till ZIP-fil
project_name VARCHAR(255) Projektnamn (AI-extraherat)
customer_name VARCHAR(255) Kundnamn
estimated_value DECIMAL(12,2) Uppskattat projektvärde
complexity ENUM simple, medium, complex
status ENUM received, analyzing, decided, calculating, sent NOT NULL
decision ENUM go, no_go, pending
decided_by VARCHAR(100) Mattias, Karin, Emil
decided_at TIMESTAMP Beslutstidpunkt
workcloud_opp_id VARCHAR(50) WorkCloud opportunity ID

Tabell 2: tender_documents

Attribut Typ Beskrivning Constraint
id UUID Unik identifierare PRIMARY KEY
tender_id UUID Referens till tender_requests FOREIGN KEY
filename VARCHAR(255) Originalfilnamn NOT NULL
document_type ENUM af, afd1, afd472, k_drawing, a_drawing, technical_desc, other NOT NULL
page_count INTEGER Antal sidor
file_size_kb INTEGER Filstorlek
content_text TEXT Extraherad text (för RAG)
metadata JSONB PDF metadata, AI-extraherad info
storage_path TEXT S3/Supabase path

Tabell 3: ai_analysis

Attribut Typ Beskrivning Constraint
id UUID Unik identifierare PRIMARY KEY
tender_id UUID Referens till tender_requests FOREIGN KEY
analysis_type ENUM full, scope, guarantees, conflicts, summary NOT NULL
result JSONB AI output (strukturerad JSON) NOT NULL
confidence DECIMAL(3,2) AI confidence (0.00-1.00)
processing_time_ms INTEGER Tid för analys
model_used VARCHAR(50) claude-sonnet-4, llama-3.1, etc
prompt_version VARCHAR(20) Prompt version för reproducerbarhet
created_at TIMESTAMP Analystidpunkt DEFAULT NOW()

Tabell 4: go_no_go_decisions

Attribut Typ Beskrivning Constraint
id UUID Unik identifierare PRIMARY KEY
tender_id UUID Referens till tender_requests FOREIGN KEY
ai_recommendation ENUM go, no_go NOT NULL
ai_confidence DECIMAL(3,2) AI confidence NOT NULL
ai_reasoning TEXT AI:s motivering
similar_projects JSONB Array av liknande historiska projekt
risk_factors JSONB Array av identifierade risker
human_decision ENUM go, no_go, NULL
human_decided_by VARCHAR(100) Mattias, Emil, etc
human_decision_at TIMESTAMP Beslutstidpunkt
override_reason TEXT Om skiljer från AI-rekommendation

Tabell 5: historical_projects

Attribut Typ Beskrivning Constraint
id UUID Unik identifierare PRIMARY KEY
project_name VARCHAR(255) Projektnamn NOT NULL
customer_name VARCHAR(255) Kund NOT NULL
project_type VARCHAR(100) Tak, fasad, etc
project_value DECIMAL(12,2) Värde i SEK
won BOOLEAN Vunnet eller förlorat NOT NULL
margin DECIMAL(4,3) Marginal (0.15 = 15%)
completion_date DATE Färdigställt
key_requirements JSONB Tekniska krav
challenges TEXT Utmaningar och lärdomar
embedding VECTOR(768) Qdrant embedding

Tabell 6: credit_checks

Attribut Typ Beskrivning Constraint
id UUID Unik identifierare PRIMARY KEY
tender_id UUID Referens till tender_requests FOREIGN KEY
org_number VARCHAR(20) Organisationsnummer NOT NULL
uc_rating VARCHAR(10) UC-rating
credit_limit DECIMAL(12,2) Kreditlimit
approved BOOLEAN Godkänd eller ej NOT NULL
checked_at TIMESTAMP Kontrolltidpunkt DEFAULT NOW()
checked_by VARCHAR(100) Liza, etc

Datalagring

Datatyp Lagring Retention Backup Kryptering
Tender requests PostgreSQL 7 år Daglig AES-256 at rest
PDF-dokument Supabase Storage / S3 7 år Veckovis TLS + AES-256
AI-beslut PostgreSQL 7 år Daglig AES-256
Historiska projekt PostgreSQL + Qdrant Permanent Daglig AES-256
Qdrant vectors Qdrant (disk) Permanent Veckovis snapshot TLS in transit

5. Säkerhetsarkitektur

Säkerhetslager

Render Cloud:

[Internet] → [Render Load Balancer + TLS] → [Private Network]
                                                    ↓
    [n8n] ← Private → [Ingestion Engine] ← Private → [Agentic Engine]
      ↓                       ↓                              ↓
    [Django Portal]      [PostgreSQL]                   [Qdrant]

On-Premise (future):

[Internet] → [Cloudflare Tunnel] → [Docker Network]

Autentisering och auktorisering

Fas 4: Basic auth i n8n + Django Fas 5: Keycloak SSO

Roller:

  • Kalkylator (Mattias, Karin): Full åtkomst, beslut på standardprojekt
  • Projektchef (Emil): Full åtkomst, beslut på stora/strategiska projekt
  • Ekonomi (Liza): Read-only + kreditkontroll-beslut
  • Admin (Rebecka, Lars): Systemadministration

Datasäkerhet

Aspekt Implementation Standard
Kryptering i vila AES-256 för Postgres/Qdrant FIPS 140-2
Kryptering i transit TLS 1.3 för alla API-calls RFC 8446
Nyckelhantering Render Secrets / .env (encrypted) Principle of least privilege
GDPR Compliance Kunddata pseudonymiserad vid behov GDPR Article 25
Access logs All AI-access loggad i PostgreSQL ISO 27001

6. Infrastruktur (Optimate Core - Render Deployment)

Deployment Model: Render (Cloud) - REKOMMENDERAT FAS 4

Arkitektur (Render):

# render.yaml - BC02 AI-Dokumentanalys
services:
  # n8n - Workflow Hub
  - type: web
    name: bc02-n8n
    env: docker
    dockerfilePath: ./Dockerfile.n8n
    envVars:
      - key: N8N_ENCRYPTION_KEY
        sync: false
      - key: DATABASE_URL
        fromDatabase:
          name: bc02-postgres
          property: connectionString
    plan: standard  # $25/mån
    
  # Ingestion Engine (Core)
  - type: web
    name: bc02-ingestion-engine
    env: docker
    dockerCommand: uvicorn ingestion_engine.main:app --host 0.0.0.0 --port 8000
    envVars:
      - key: WORKCLOUD_API_KEY
        sync: false
      - key: UC_API_KEY
        sync: false
      - key: DATABASE_URL
        fromDatabase:
          name: bc02-postgres
          property: connectionString
    plan: standard  # $25/mån
    
  # Agentic Engine (Core)
  - type: web
    name: bc02-agentic-engine
    env: docker
    dockerCommand: uvicorn agentic_engine.main:app --host 0.0.0.0 --port 8000
    envVars:
      - key: ANTHROPIC_API_KEY
        sync: false
      - key: QDRANT_URL
        value: http://bc02-qdrant:6333
      - key: DATABASE_URL
        fromDatabase:
          name: bc02-postgres
          property: connectionString
      - key: LANGSMITH_API_KEY
        sync: false
    plan: standard  # $25/mån
    
  # Qdrant Vector Database
  - type: web
    name: bc02-qdrant
    env: docker
    disk:
      name: bc02-qdrant-data
      mountPath: /qdrant/storage
      sizeGB: 10
    plan: starter  # $7/mån
    
  # Django HIL Portal
  - type: web
    name: bc02-django-portal
    env: python
    buildCommand: pip install -r requirements.txt && python manage.py migrate
    startCommand: gunicorn bc02_portal.wsgi:application
    envVars:
      - key: DATABASE_URL
        fromDatabase:
          name: bc02-postgres
          property: connectionString
      - key: N8N_WEBHOOK_URL
        value: http://bc02-n8n:5678/webhook
    plan: starter  # $7/mån

databases:
  - name: bc02-postgres
    databaseName: dokumentanalys
    user: bc02_user
    plan: starter  # $7/mån

Kostnad Render (Fas 4):

  • n8n: $25/mån
  • Ingestion Engine: $25/mån
  • Agentic Engine: $25/mån
  • Qdrant: $7/mån
  • Django Portal: $7/mån
  • PostgreSQL: $7/mån
  • Total production: ~$96/mån (~$1150/år = 13 450 SEK/år)
  • Med staging: ~$150/mån (~$1800/år = 21 000 SEK/år)

Cost-benefit:

  • Årlig besparing BC02: 340 490 kr
  • Render-kostnad År 1: 21 000 kr (6% av besparing)
  • Nettobesparing: 319 490 kr/år

Miljöer

Miljö Deployment Användning Användare
Development Lokal Docker Compose Lars utveckling Lars
Staging Render (separate services) Test med real data Mattias, Lars
Production Render Live offerthantering Mattias, Karin, Emil, Liza

Skalbarhet

Komponent Start Max Skalningsstrategi
Ingestion Engine Standard Pro Horizontal scaling vid >20 offerter/vecka
Agentic Engine Standard Pro + GPU GPU för Ollama om Claude-kostnad hög
Qdrant Starter Standard RAM upgrade för >10k historiska projekt
PostgreSQL Starter Pro Storage + connection pool vid >1000 offerter/år

7. Prestanda och SLA

Prestandakrav

Metrik Krav Mätmetod Frekvens
ZIP-extraction <30s Backend timer Per request
Document analysis <45s för 25-60 sidor Backend timer Per request
Go/No-go recommendation <5s Backend timer Per request
Portal response time <500ms p95 Browser metrics Kontinuerlig
System availability >99% Render uptime monitor Kontinuerlig

Service Level Agreement (SLA)

Tillgänglighet: 99% (43.8h downtime/år acceptabelt)

  • Underhållsfönster: Lördagar 06:00-08:00

Response tider:

  • Email → ZIP-download → Analys klar: <2 minuter
  • Mattias ser AI-sammanfattning: <3 minuter från mottagande
  • Total tid steg 2-8: <45 minuter (från 100-255 min)

Dataförlust:

  • RPO (Recovery Point Objective): 24h (dagliga backups)
  • RTO (Recovery Time Objective): 4h (restore från Render backup)

Support:

  • Kontorstid (08:00-17:00): Rebecka primär, Lars sekundär
  • Utanför kontorstid: Email-support, 24h respons
  • Kritiska fel: 4h responstid

8. Monitoring och observability

LangSmith Integration (AI Observability)

Vad trackas:

  • Varje Claude API-anrop (prompt + response)
  • Processing time och cost per request
  • Confidence scores per AI-beslut
  • User feedback (Mattias override av AI-rekommendation)

Dashboard KPI:er:

  • AI träffsäkerhet Go/No-go: Target >85%
  • Krav-extrahering accuracy: Target >95%
  • Motstridighetsdetektering recall: Target >85%
  • Average processing time: <45s
  • Cost per offert: <$5

Alert Workflows (n8n)

[n8n Schedule: Var 5:e minut]
  ↓
[Check AI error rate senaste timmen]
  ↓
IF error_rate > 10%:
  → Email alert till Lars + Rebecka
  
[n8n Schedule: Daglig 08:00]
  ↓
[Query PostgreSQL: AI-decisions senaste 24h]
  ↓
[Generate performance report]
  ↓
[Email till Mattias + Emil]:
    - Antal förfrågningar analyzerade
    - AI Go/No-go träffsäkerhet
    - Genomsnittlig processing time
    - Identifierade motstridigheter

9. Disaster Recovery

Backup-strategi (Render Managed)

Automatiska backups:

  • PostgreSQL: Daglig automatisk backup (Render managed)
  • Qdrant: Veckovis snapshot via n8n workflow
  • n8n workflows: Daglig export till GitHub

n8n Backup Workflow:

[Schedule: 03:00 daglig]
  ↓
[n8n API: Export all workflows → JSON]
  ↓
[Qdrant API: Create snapshot]
  ↓
[Git: Commit + push to customer-site repo]
  ↓
[Email notification: Backup completed]

DR-plan

Scenario RTO RPO Procedur
Render region failure 4h 24h Restore från backup till annan region
Database corruption 4h 24h Restore från Render automatic backup
Qdrant data loss 2h 7 dagar Re-import från veckovis snapshot
Accidental workflow deletion 1h 1 dag Restore från Git history

10. Utvecklingsmiljö

Development Setup

# Klona customer site repository
git clone https://github.com/optimate/customer-prolux-bc02-site.git
cd customer-prolux-bc02-site

# Setup environment
cp .env.example .env
# Edit .env med API-nycklar

# Starta full stack lokalt
docker-compose up -d

# Services tillgängliga:
# n8n: http://localhost:5678
# Django Portal: http://localhost:8000
# Ingestion Engine: http://localhost:8001
# Agentic Engine: http://localhost:8002
# Qdrant: http://localhost:6333
# PostgreSQL: localhost:5432

CI/CD Pipeline

GitHub Actions - Deploy to Render:

name: Deploy BC02 to Production

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Deploy to Render
        run: |
          curl -X POST "https://api.render.com/deploy/srv-xxx" \
            -H "Authorization: Bearer ${{ secrets.RENDER_API_KEY }}"

Bilagor

Bilaga A: BC02 Site Repository Struktur

customer-prolux-bc02-site/
├── infra/
│   ├── render.yaml                 # Render deployment config
│   └── docker-compose.yml          # Local dev setup
├── n8n/
│   ├── workflows/
│   │   ├── 01-email-intake.json
│   │   ├── 02-document-analysis-pipeline.json
│   │   ├── 03-go-no-go-decision.json
│   │   ├── 04-crm-registration.json
│   │   ├── 05-credit-check.json
│   │   └── 06-backup-workflow.json
│   └── credentials/                # Encrypted credentials
├── django_portal/
│   ├── bc02_app/
│   │   ├── views.py                # Tender list, detail, decision
│   │   ├── models.py               # Django ORM models
│   │   ├── templates/
│   │   │   ├── tender_list.html
│   │   │   ├── tender_detail.html
│   │   │   └── go_no_go_decision.html
│   │   └── api.py                  # REST API for n8n webhooks
│   ├── requirements.txt
│   └── manage.py
├── config/
│   ├── ingestion-engine.yml        # BC02-specific endpoints config
│   ├── agentic-engine.yml          # RAG settings, prompts
│   ├── document-types.json         # AF, AFD, K, A definitions
│   └── prioritization-matrix.json  # Go/No-go criteria from Emil
├── data/
│   ├── training_tenders/           # 10 example tenders from Mattias
│   │   ├── stender_vb_1966/
│   │   ├── nibbleskolan_2024/
│   │   └── ...
│   └── historical_projects.csv     # Historical project data for Qdrant
├── prompts/
│   ├── analyze_tender.txt          # Claude prompt for full analysis
│   ├── extract_scope_afd1.txt
│   ├── detect_conflicts.txt
│   └── go_no_go_recommendation.txt
├── backup/
│   ├── postgres/
│   ├── qdrant/
│   └── n8n/
├── site-docs/
│   ├── BC02-Setup.md
│   ├── BC02-User-Guide-Mattias.md
│   └── BC02-Teknisk-Arkitektur.md  # This document
└── .env                            # Secrets (not in Git)

Bilaga B: Kostnadsanalys

Initial Investering (År 1):

Post Kostnad
Core Engine Development (BC02 endpoints) 80 000 kr
n8n Workflows Development 40 000 kr
Django Portal Development 30 000 kr
Data prep + Training (10 examples) 20 000 kr
Testing + Deployment 15 000 kr
Total År 1 185 000 kr

Årlig Drift (År 2+):

Post Kostnad
Render Cloud Hosting 21 000 kr
Claude API (550 × $3) 19 200 kr
LangSmith Observability 7 200 kr
Maintenance (20h/år) 40 000 kr
Total År 2+ 87 400 kr

ROI-kalkyl (uppdaterad):

  • Årlig besparing BC02: 340 490 kr
  • Investering År 1: 185 000 kr
  • Drift År 2+: 87 400 kr
  • Nettobesparing År 1: 155 490 kr
  • Nettobesparing År 2+: 253 090 kr/år
  • ROI: 6,5 månader
  • NPV 3 år (5% diskontering): ~540 000 kr

Dokumentinformation

Version: 1.0
Arkitekt: Lars Diethelm
Platform: Optimate Core (Hub-and-Spoke Architecture)
Deployment: Render (Cloud) primär
Granskad av: Rebecka Englund (IT), Mattias Svensson (Process)
Godkänd av: Emil Gråberg (Processägare)
Datum: 2025-11-01
Nästa revision: Efter BP3 (vecka 43)

Repositories:

  • Core: github.com/optimate/optimate-core (Ingestion + Agentic Engines)
  • Template: github.com/optimate/optimate-customer-template
  • Customer Site: github.com/optimate/customer-prolux-bc02-site

Signering och Godkännande

Detta dokument utgör den tekniska grunden för implementation av BC02 Fas 4.

Roll Namn Signatur Datum
Processägare Emil Gråberg ____________ ______
Processexpert Mattias Svensson ____________ ______
Kalkylator Karin Asp ____________ ______
IT-ansvarig Rebecka Englund ____________ ______
Arkitekt/Utvecklare Lars Diethelm ____________ ______

Nästa steg:

  1. Godkännande av detta dokument (Vecka 43)
  2. Uppföljningsmöte med Emil: Prioriteringsmatris + KPI:er (1 timme)
  3. Setup Render deployment + customer-site repository (Vecka 43)
  4. Utveckling av BC02-endpoints i Core Engines (Vecka 43-44)
  5. Import av 10 träningsexempel till Qdrant (Vecka 44)
  6. BP3-beslut (Vecka 43)
  7. Pilot med 5 förfrågningar (Vecka 45-46)
  8. Full utrullning (Vecka 47+)