Skip to content
@Hackaton-FIAP-Andressa-Silva

Hackaton FIAP - Andressa Silva

Architecture Diagram Analyzer

Sistema de análise automática de diagramas de arquitetura de software utilizando IA generativa (Gemini 2.5 Flash Lite via LangChain), desenvolvido como projeto integrado do Hackathon FIAP — trilhas SOAT e IADT.


Aluna: Andressa Silva — RM 359660

Vídeo Apresentação: > Abrir no YouTube

Repositórios:

Serviço Repositório
Upload Service Hackaton-FIAP-Andressa-Silva/upload-service
Report Service Hackaton-FIAP-Andressa-Silva/report-service
AI Processing Service Hackaton-FIAP-Andressa-Silva/ai-processing-service
API Gateway Hackaton-FIAP-Andressa-Silva/api-gateway
Infrastructure (Terraform) Hackaton-FIAP-Andressa-Silva/infrastructure

Problema e Solução

Equipes de engenharia perdem horas revisando manualmente diagramas de arquitetura para identificar riscos e gargalos. Este sistema automatiza essa análise: o usuário faz upload de um diagrama (PNG, JPEG ou PDF) e recebe em segundos um relatório técnico estruturado com componentes identificados, riscos classificados por severidade e recomendações priorizadas, produzidos por um modelo de IA com guardrails de validação de saída.


Arquitetura do Sistema

Arquitetura da Solução

Diagrama de Arquitetura

Diagrama de Sequência — Fluxo Completo

Diagrama de Sequência

Ver código-fonte Mermaid do diagrama de sequência
sequenceDiagram
    autonumber

    actor Cliente
    participant GW as API Gateway<br/>(Nginx)
    participant US as Upload Service<br/>(FastAPI + PostgreSQL)
    participant S3 as AWS S3
    participant SQS as AWS SQS
    participant AI as AI Processing Worker<br/>(LangChain + Gemini)
    participant Gemini as Gemini 2.5 Flash Lite<br/>(Google API)
    participant RS as Report Service<br/>(FastAPI + MongoDB)

    rect rgb(220, 235, 255)
        Note over Cliente,SQS: Fase 1 — Upload e Enfileiramento
        Cliente->>GW: POST /api/v1/uploads<br/>X-API-Key: ***<br/>body: multipart/form-data (arquivo)
        GW->>GW: Valida X-API-Key<br/>Rate limit (10 req/s, burst 20)
        GW->>US: POST /api/v1/uploads (proxy)
        US->>US: Valida MIME type (whitelist PNG/JPEG/PDF)
        US->>US: Valida magic bytes (assinatura binária)
        US->>US: Valida tamanho ≤ 20 MB
        US->>S3: PUT s3://bucket/{uuid}/{filename}
        S3-->>US: 200 OK
        US->>US: INSERT upload (id, filename, s3_key,<br/>status=RECEIVED) → PostgreSQL
        US->>SQS: SendMessage<br/>{upload_id, s3_key, content_type}
        SQS-->>US: MessageId
        US-->>GW: 202 {upload_id, status: "RECEIVED"}
        GW-->>Cliente: 202 {upload_id, status: "RECEIVED"}
    end

    rect rgb(240, 240, 240)
        Note over Cliente,US: Fase 2 — Polling de Status (assíncrono)
        loop Até status = ANALYZED ou ERROR
            Cliente->>GW: GET /api/v1/uploads/{upload_id}/status<br/>X-API-Key: ***
            GW->>US: GET /uploads/{upload_id}/status (proxy)
            US->>US: SELECT upload WHERE id = upload_id → PostgreSQL
            US-->>GW: 200 {upload_id, status, updated_at}
            GW-->>Cliente: 200 {upload_id, status, updated_at}
        end
    end

    rect rgb(255, 240, 220)
        Note over SQS,RS: Fase 3 — Processamento Assíncrono (Worker)
        AI->>SQS: ReceiveMessage (long polling)
        SQS-->>AI: {upload_id, s3_key, content_type}
        AI->>US: PATCH /uploads/{upload_id}/status<br/>X-Internal-Token: ***<br/>body: {status: "PROCESSING"}
        US->>US: UPDATE upload SET status=PROCESSING → PostgreSQL
        US-->>AI: 200 OK
        AI->>S3: GetObject s3://bucket/{s3_key}
        S3-->>AI: bytes do arquivo
        alt content_type = application/pdf
            AI->>AI: pdf2image → converte PDF para PNG
        end
        AI->>AI: base64.encode(image_bytes)
        AI->>Gemini: ChatMessage [SystemPrompt + UserPrompt + image_base64]<br/>response_mime_type: application/json
        Gemini-->>AI: JSON {summary, components[], risks[], recommendations[]}
        AI->>AI: Guardrail 1: Pydantic schema validation<br/>(campos obrigatórios, enums HIGH/MEDIUM/LOW)
        AI->>AI: Guardrail 2: sanitize strings<br/>(strip + truncate 2000 chars)
        alt Guardrails OK
            AI->>RS: POST /reports<br/>X-Internal-Token: ***<br/>body: {upload_id, summary, components,<br/>risks, recommendations, ai_model,<br/>processing_time_seconds}
            RS->>RS: INSERT report → MongoDB
            RS-->>AI: 201 {report_id, upload_id}
            AI->>US: PATCH /uploads/{upload_id}/status<br/>X-Internal-Token: ***<br/>body: {status: "ANALYZED"}
            US->>US: UPDATE upload SET status=ANALYZED → PostgreSQL
            US-->>AI: 200 OK
        else Guardrails FALHOU
            AI->>US: PATCH /uploads/{upload_id}/status<br/>X-Internal-Token: ***<br/>body: {status: "ERROR", error_message: "..."}
            US->>US: UPDATE upload SET status=ERROR → PostgreSQL
            US-->>AI: 200 OK
        end
        AI->>SQS: DeleteMessage (remove da fila)
    end

    rect rgb(220, 255, 230)
        Note over Cliente,RS: Fase 4 — Consulta do Relatório
        Cliente->>GW: GET /api/v1/reports/{upload_id}<br/>X-API-Key: ***
        GW->>GW: Valida X-API-Key<br/>Rate limit
        GW->>RS: GET /reports/{upload_id} (proxy)
        RS->>RS: db.reports.findOne({upload_id}) → MongoDB
        RS-->>GW: 200 {report_id, summary, components[],<br/>risks[], recommendations[],<br/>ai_model, processing_time_seconds}
        GW-->>Cliente: 200 {relatório completo}
    end
Loading

Fluxo de Dados

1. Cliente  →  API Gateway (valida X-API-Key, rate limit)
2. Gateway  →  Upload Service (valida MIME, magic bytes, tamanho ≤ 20 MB)
3. Upload Service  →  S3 (persiste arquivo) + PostgreSQL (metadados: status RECEIVED)
4. Upload Service  →  SQS (mensagem com upload_id, s3_key, content_type)
5. AI Worker  ←  SQS (long polling)
6. AI Worker  →  S3 (download do arquivo)  [converte PDF→PNG se necessário]
7. AI Worker  →  Gemini 2.5 Flash Lite (análise multimodal via LangChain)
8. AI Worker  →  Guardrails Pydantic (valida + sanitiza output do LLM)
9. AI Worker  →  Upload Service PATCH status → ANALYZED (ou ERROR)
10. AI Worker →  Report Service POST /reports (persiste relatório no MongoDB)
11. Cliente  →  GET /reports/{upload_id} (resultado disponível)

Serviços

Serviço Porta Stack Responsabilidade
api-gateway 8080 Nginx Reverse proxy, autenticação X-API-Key, rate limiting (10 req/s, burst 20), headers de segurança, CORS
upload-service 8001 FastAPI · Python 3.12 · PostgreSQL Recebe uploads, valida tipo/tamanho/magic bytes, persiste no S3, publica em SQS, expõe status
ai-processing-service Python 3.12 · LangChain · Gemini 2.5 Flash Lite Worker SQS: baixa arquivo, analisa com IA, valida output com guardrails, salva relatório
report-service 8003 FastAPI · Python 3.12 · MongoDB Atlas Armazena e serve relatórios gerados pela IA

Modelo de Dados

Upload (PostgreSQL — upload-service)

Campo Tipo Descrição
id UUID v4 Identificador único
filename string Nome original do arquivo
content_type string image/png, image/jpeg, application/pdf
s3_key string Chave do objeto no S3
file_size int Tamanho em bytes
status enum RECEIVEDPROCESSINGANALYZED / ERROR
error_message string Mensagem de erro se status = ERROR
created_at / updated_at datetime Timestamps

Report (MongoDB — report-service)

{
  "id": "uuid",
  "upload_id": "uuid",
  "summary": "Descrição geral da arquitetura...",
  "components": [
    { "name": "API Gateway", "type": "Gateway", "description": "...", "technology": "Nginx" }
  ],
  "risks": [
    { "title": "Single point of failure", "severity": "HIGH", "description": "...", "impact": "...", "affected_components": ["API Gateway"] }
  ],
  "recommendations": [
    { "title": "Adicionar redundância", "priority": "HIGH", "description": "...", "rationale": "..." }
  ],
  "ai_model": "gemini-2.5-flash-lite",
  "processing_time_seconds": 4.32,
  "created_at": "2026-05-14T23:00:00Z"
}

Pipeline de IA

Modelo

Gemini 2.5 Flash Lite via langchain-google-genai, com:

  • Temperatura 0.1 (determinístico)
  • response_mime_type: application/json (JSON mode nativo)
  • Timeout de 30 s por requisição
  • Até 2 retentativas em caso de falha

Guardrails (validação de saída)

O output do LLM passa por validação obrigatória antes de ser persistido:

  1. Schema Pydantic — verifica estrutura e tipos (campos obrigatórios, enums HIGH/MEDIUM/LOW)
  2. Sanitização de strings — strip de whitespace + truncamento em 2.000 caracteres por campo
  3. Em caso de violação → status ERROR no upload, nenhum dado inválido é salvo

Prompt

  • System prompt: define o papel de arquiteto sênior e exige resposta exclusivamente em JSON
  • User prompt: estrutura exata do JSON esperado com regras (identificar todos os componentes visíveis, severidade em maiúsculas, mínimo 1 risco e 1 recomendação)
  • PDFs são convertidos para PNG antes de serem enviados ao modelo (multimodal)

Segurança

Controle Implementação
Autenticação externa X-API-Key header validado no Nginx (comparação com variável de ambiente injetada)
Autenticação interna X-Internal-Token header validado nos endpoints /uploads/{id}/status e /reports
Rate limiting 10 req/s por IP, burst 20 — resposta 429 (Nginx limit_req)
Validação de tipo de arquivo Whitelist de MIME types + verificação de magic bytes (assinatura binária real do arquivo)
Tamanho máximo 20 MB por upload (validado no Upload Service e no Nginx client_max_body_size 25M)
Validação de saída LLM Guardrails Pydantic + sanitização — nenhum output do modelo é salvo sem validação
Princípio do menor privilégio IAM roles separados por serviço no ECS (upload-service acessa S3+SQS; ai-processing acessa S3+SQS)
Segredos AWS Secrets Manager (produção) / variáveis de ambiente (desenvolvimento local)
Criptografia em repouso S3 (KMS), RDS PostgreSQL (AES-256)
Imagens Docker Usuário não-root, multi-stage builds
Headers de segurança X-Content-Type-Options, X-Frame-Options: DENY, X-XSS-Protection em todas as respostas

Infraestrutura AWS (Terraform)

Todos os recursos são provisionados via Terraform (infrastructure/terraform/) com estado remoto no S3.

terraform/
├── main.tf          # Orchestração dos módulos + secrets globais
├── variables.tf     # environment, aws_region, api_key, google_api_key, internal_token, mongodb_url
├── outputs.tf       # ALB DNS, S3 bucket, SQS URL, ECR repos
└── modules/
    ├── networking/  # VPC, subnets públicas/privadas, Internet Gateway, NAT
    ├── s3/          # Bucket de diagramas (criptografia KMS)
    ├── sqs/         # Fila principal + Dead Letter Queue
    ├── rds/         # PostgreSQL (RDS) para upload-service
    ├── documentdb/  # MongoDB URL secret (MongoDB Atlas via Secrets Manager)
    ├── ecr/         # Repositórios de imagens Docker (4 serviços)
    ├── iam/         # Roles ECS com least privilege por serviço
    └── ecs/         # Cluster ECS Fargate + ALB + Task Definitions (4 serviços)

Recursos AWS provisionados

Recurso Descrição
VPC Subnets públicas (ALB) e privadas (ECS tasks, RDS)
ECS Fargate Cluster com tasks para os 4 serviços
ALB Application Load Balancer na frente do api-gateway
RDS PostgreSQL Banco do upload-service (subnet privada)
S3 Bucket para armazenar diagramas enviados
SQS Fila de processamento + DLQ
ECR 4 repositórios Docker privados
Secrets Manager api-key, google-api-key, internal-token, mongodb-url
IAM Roles Roles separados para upload-service e ai-processing-service

CI/CD (GitHub Actions)

Cada serviço tem seu próprio pipeline em .github/workflows/ci-cd.yml:

push to main
    ├── test          → pytest + coverage ≥ 80% (threshold obrigatório)
    └── build-push    → docker build → ECR push → ECS deploy (rolling update)

O repositório infrastructure tem pipeline separado:

push to main (paths: terraform/**)
    ├── plan    → terraform plan (sem environment)
    └── apply   → terraform apply (environment: production, requer aprovação)

Secrets necessários por repositório

Secret upload report ai-proc api-gw infra
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_SESSION_TOKEN
GOOGLE_API_KEY
INTERNAL_SERVICE_TOKEN
API_KEY

Nota AWS Academy: as credenciais são temporárias (STS) e expiram a cada 4 horas. Os três campos (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) precisam ser atualizados conjuntamente.


Quick Start (desenvolvimento local com LocalStack)

Pré-requisitos

Subindo o ambiente

# 1. Clone e configure variáveis
git clone <repo-url> && cd hackaton-fiap
cp infrastructure/.env.local infrastructure/.env
# Edite infrastructure/.env e preencha GOOGLE_API_KEY

# 2. Suba toda a stack (LocalStack + todos os serviços)
cd infrastructure
docker compose --env-file .env up --build

# 3. Verifique os health checks
curl http://localhost:8080/health
# → {"status":"healthy","service":"api-gateway"}

A stack local usa LocalStack para simular S3 e SQS sem custos de nuvem. As filas e buckets são criados automaticamente pelo script scripts/init-localstack.sh.


Uso da API

1. Enviar diagrama para análise

curl -X POST http://localhost:8080/api/v1/uploads \
  -H "X-API-Key: dev-api-key-change-me" \
  -F "file=@meu-diagrama.png"
{
  "upload_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "RECEIVED",
  "filename": "meu-diagrama.png",
  "created_at": "2026-05-14T23:00:00Z"
}

2. Consultar status do processamento

curl http://localhost:8080/api/v1/uploads/550e8400-e29b-41d4-a716-446655440000/status \
  -H "X-API-Key: dev-api-key-change-me"
{ "upload_id": "...", "status": "ANALYZED", "updated_at": "..." }

Ciclo de status: RECEIVEDPROCESSINGANALYZED (ou ERROR)

3. Obter relatório

curl http://localhost:8080/api/v1/reports/550e8400-e29b-41d4-a716-446655440000 \
  -H "X-API-Key: dev-api-key-change-me"
{
  "report_id": "uuid",
  "upload_id": "uuid",
  "summary": "Arquitetura de microserviços com 4 serviços...",
  "components": [
    { "name": "API Gateway", "type": "Gateway", "description": "...", "technology": "Nginx" }
  ],
  "risks": [
    { "title": "Ausência de circuit breaker", "severity": "HIGH", "description": "...", "impact": "...", "affected_components": ["Upload Service"] }
  ],
  "recommendations": [
    { "title": "Implementar Resilience4j", "priority": "HIGH", "description": "...", "rationale": "..." }
  ],
  "ai_model": "gemini-2.5-flash-lite",
  "processing_time_seconds": 4.32
}

Formatos aceitos

Formato MIME Type Observação
PNG image/png Recomendado
JPEG / JPG image/jpeg
PDF application/pdf Convertido para PNG antes da análise

Tamanho máximo: 20 MB


Deploy na AWS

cd infrastructure/terraform

terraform init

terraform plan \
  -var="environment=prod" \
  -var="google_api_key=AIza..." \
  -var="internal_service_token=$(openssl rand -hex 32)" \
  -var="api_key=$(openssl rand -hex 16)" \
  -var="mongodb_url=mongodb+srv://..."

terraform apply

Após o apply, as imagens ECR são publicadas automaticamente pelo CI/CD ao fazer push para main em cada repositório de serviço.

Outputs do Terraform:

  • alb_dns_name — endpoint público da aplicação
  • ecr_repositories — URLs dos repositórios Docker
  • s3_bucket_name — bucket de diagramas
  • sqs_queue_url — URL da fila de processamento

Estrutura do Monorepo

hackaton-fiap/
├── api-gateway/               # Nginx — proxy, auth, rate limit
│   ├── nginx.conf
│   └── Dockerfile
├── upload-service/            # FastAPI + PostgreSQL
│   ├── src/
│   │   ├── domain/            # Entidades (Upload, UploadStatus) e repositórios
│   │   ├── application/       # Use cases: CreateUpload, GetStatus, UpdateStatus
│   │   ├── api/               # Routers FastAPI + schemas Pydantic
│   │   └── infrastructure/    # PostgreSQL, S3, SQS, config
│   └── tests/
├── ai-processing-service/     # Worker SQS + LangChain + Gemini
│   ├── src/
│   │   ├── domain/            # Entidades (AnalysisResult, Component, Risk, Recommendation)
│   │   ├── application/       # Use case: ProcessDiagram
│   │   └── infrastructure/    # SQS consumer, S3 client, OpenAI/Gemini analyzer, guardrails, prompts
│   └── tests/
├── report-service/            # FastAPI + MongoDB
│   ├── src/
│   │   ├── domain/            # Entidade Report
│   │   ├── application/       # Use cases: CreateReport, GetReport
│   │   ├── api/               # Routers + schemas
│   │   └── infrastructure/    # MongoDB (Motor async), config
│   └── tests/
├── infrastructure/
│   ├── docker-compose.yml     # Stack local completa (LocalStack, PostgreSQL, MongoDB, todos os serviços)
│   ├── .env.local             # Template de variáveis de ambiente
│   ├── scripts/
│   │   └── init-localstack.sh # Cria bucket S3 e fila SQS no LocalStack
│   └── terraform/             # Infraestrutura AWS completa (módulos: VPC, ECS, RDS, S3, SQS, ECR, IAM)
└── docs/
    ├── refinamento-tecnico-negocial.md
    └── backlog-epicos.md

Padrões de Arquitetura de Software

  • Arquitetura Hexagonal (Ports & Adapters) em todos os serviços Python: domínio isolado de infraestrutura via interfaces abstratas
  • Clean Architecture: separação em camadas domainapplicationinfrastructure
  • Event-driven: desacoplamento entre upload e processamento via SQS (produtor/consumidor assíncrono)
  • CQRS simplificado: separação de escrita (Upload Service + AI Worker) e leitura (Report Service)

Popular repositories Loading

  1. ai-processing-service ai-processing-service Public

    Worker service that consumes SQS messages, analyzes architecture diagrams with Gemini 2.0 Flash Vision, and sends structured reports to the report service.

    Python 1

  2. api-gateway api-gateway Public

    Nginx-based reverse proxy that acts as the single entry point for the FIAP Secure Systems architecture analyzer.

    Dockerfile 1

  3. infrastructure infrastructure Public

    Infrastructure-as-code and local development stack for the FIAP Architecture Analyzer — a microservices system that accepts architecture diagrams, analyzes them with Google Gemini Vision, and retur…

    HCL 1

  4. report-service report-service Public

    Microservice responsible for storing and serving AI-generated architecture analysis reports.

    Python 1

  5. upload-service upload-service Public

    Microservice responsible for receiving architecture diagrams, storing them in S3, and publishing analysis jobs to SQS.

    Python 1

  6. .github .github Public

Repositories

Showing 6 of 6 repositories

Top languages

Loading…

Most used topics

Loading…