From cd6f8ad1662a88a24571e6cc2420f7df7bd8bde4 Mon Sep 17 00:00:00 2001 From: Luca Sacchi Ricciardi Date: Tue, 7 Apr 2026 13:10:12 +0200 Subject: [PATCH] docs: complete architecture specifications and project planning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add comprehensive technical specifications for mockupAWS v0.2.0: - export/architecture.md: Complete system architecture with: * Layered architecture diagram (Client → API → Service → Repository → DB) * Full database schema with DDL SQL (5 tables, indexes, constraints) * API specifications (OpenAPI format) for all endpoints * Security architecture (auth, PII detection, rate limiting) * Data flow diagrams (ingestion, cost calculation, state machine) * Technology stack details (backend, frontend, infrastructure) * Project structure for backend and frontend * 4 Architecture Decision Records (DEC-001 to DEC-004) - export/kanban.md: Task breakdown with 32 tasks organized in: * Database setup (DB-001 to DB-007) * Backend models/schemas (BE-001 to BE-003) * Backend repositories (BE-004 to BE-008) * Backend services (BE-009 to BE-014) * Backend API (BE-015 to BE-020) * Testing (QA-001 to QA-003) - export/progress.md: Project tracking initialized with: * Current status: 0% complete, Fase 1 setup * Sprint planning and metrics * Resource links and team assignments All specifications follow 'Little Often' principle with tasks < 2 hours. --- export/architecture.md | 1340 +++++++++++++++++++++++++++++++++++++--- export/kanban.md | 732 ++++++++++++++++++++-- export/progress.md | 174 ++++-- 3 files changed, 2073 insertions(+), 173 deletions(-) diff --git a/export/architecture.md b/export/architecture.md index 67c9efe..9f38098 100644 --- a/export/architecture.md +++ b/export/architecture.md @@ -1,92 +1,1292 @@ -# Architecture Document (Export) - -> Decisioni architetturali e diagrammi di flusso. - -## Istruzioni - -Questo file deve essere creato/aggiornato dall'agente `@spec-architect` durante la fase di analisi. - -## Contenuto Richiesto - -1. **Scelte Architetturali** - - Pattern architetturali - - Motivazioni - - Trade-off - -2. **Stack Tecnologico** - - Tecnologie e versioni - - Motivazioni scelta - -3. **Diagrammi di Flusso** - - Architettura sistema - - Flussi dati - - Sequenze operazioni - -4. **Interfacce e Contratti** - - API contracts - - Interfacce tra componenti - ---- - -## Template - -```markdown -# Architecture - [Nome Progetto/Feature] +# Architecture - mockupAWS ## 1. Overview -[Descrizione ad alto livello] +mockupAWS è una piattaforma di simulazione costi AWS che permette di profilare traffico log e calcolare i driver di costo (SQS, Lambda, Bedrock/LLM) prima del deploy in produzione. + +**Architettura:** Layered Architecture con pattern Repository e Service Layer +**Paradigma:** Async-first (FastAPI + SQLAlchemy async) +**Deployment:** Container-based (Docker Compose) + +--- ## 2. System Architecture -``` -[ASCII art o riferimento a diagramma] -``` - -## 3. Componenti - -### 3.1 [Nome Componente] -**Responsabilità:** -- - -**Interfacce:** -- Input: -- Output: - -**Dipendenze:** -- - -## 4. Data Flow +### 2.1 High-Level Architecture ``` -[Descrizione flusso dati] +┌─────────────────────────────────────────────────────────────────────────────┐ +│ CLIENT LAYER │ +│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────────┐ │ +│ │ Logstash │ │ React Web UI │ │ API Consumers │ │ +│ │ (Log Source) │ │ (Dashboard) │ │ (CI/CD, Scripts) │ │ +│ └────────┬─────────┘ └────────┬─────────┘ └───────────┬──────────────┘ │ +└───────────┼─────────────────────┼────────────────────────┼───────────────────┘ + │ │ │ + │ HTTP POST │ HTTPS │ API Key + JWT + │ /ingest │ /api/v1/* │ /api/v1/* + ▼ ▼ ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ API LAYER │ +│ FastAPI + Uvicorn (ASGI) │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ Middleware Stack │ │ +│ │ ├── CORS │ │ +│ │ ├── Rate Limiting (slowapi) │ │ +│ │ ├── Authentication (JWT / API Key) │ │ +│ │ ├── Request Validation (Pydantic) │ │ +│ │ └── Error Handling │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ +│ │ /scenarios │ │ /ingest │ │ /reports │ │ /pricing │ │ +│ │ CRUD │ │ (log │ │ generate │ │ (admin) │ │ +│ │ │ │ intake) │ │ download │ │ │ │ +│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └────────┬─────────┘ │ +└─────────┼────────────────┼────────────────┼──────────────────┼─────────────┘ + │ │ │ │ + ▼ ▼ ▼ ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ SERVICE LAYER │ +│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────────────┐ │ +│ │ ScenarioService │ │ IngestService │ │ CostCalculator │ │ +│ │ ─────────────── │ │ ────────────── │ │ ───────────── │ │ +│ │ • create() │ │ • ingest_log() │ │ • calculate_sqs_cost() │ │ +│ │ • update() │ │ • batch_process()│ │ • calculate_lambda_cost() │ │ +│ │ • delete() │ │ • deduplicate() │ │ • calculate_bedrock_cost() │ │ +│ │ • lifecycle() │ │ • persist() │ │ • get_total_cost() │ │ +│ └──────────────────┘ └──────────────────┘ └──────────────────────────────┘ │ +│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────────────┐ │ +│ │ ReportService │ │ PIIDetector │ │ TokenizerService │ │ +│ │ ────────────── │ │ ─────────── │ │ ─────────────── │ │ +│ │ • generate_csv()│ │ • detect_email()│ │ • count_tokens() │ │ +│ │ • generate_pdf()│ │ • scan_patterns()│ │ • encode() │ │ +│ │ • compile() │ │ • report() │ │ • get_encoding() │ │ +│ └──────────────────┘ └──────────────────┘ └──────────────────────────────┘ │ +└─────────┬──────────────────────────────────────────────────────┬────────────┘ + │ │ + ▼ ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ REPOSITORY LAYER │ +│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────────────┐ │ +│ │ ScenarioRepo │ │ LogRepo │ │ PricingRepo │ │ +│ │ ───────────── │ │ ─────── │ │ ────────── │ │ +│ │ • get_by_id() │ │ • save() │ │ • get_by_service_region() │ │ +│ │ • list() │ │ • list_by_ │ │ • list_active() │ │ +│ │ • create() │ │ scenario() │ │ • update() │ │ +│ │ • update() │ │ • count_by_ │ │ • bulk_insert() │ │ +│ │ • delete() │ │ hash() │ │ │ │ +│ └──────────────────┘ └──────────────────┘ └──────────────────────────────┘ │ +│ ┌──────────────────┐ ┌──────────────────┐ │ +│ │ MetricRepo │ │ ReportRepo │ │ +│ │ ────────── │ │ ────────── │ │ │ +│ │ • save() │ │ • save() │ │ │ +│ │ • get_aggregated│ │ • list() │ │ │ +│ │ • list_by_type()│ │ • delete() │ │ │ +│ └──────────────────┘ └──────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────┘ + │ + │ SQLAlchemy 2.0 Async + │ asyncpg driver + ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ DATABASE LAYER │ +│ PostgreSQL 15+ │ +│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────────────┐ │ +│ │ scenarios │ │ scenario_logs │ │ aws_pricing │ │ +│ │ ───────── │ │ ───────────── │ │ ─────────── │ │ +│ │ • metadata │ │ • logs storage │ │ • service prices │ │ +│ │ • state machine │ │ • hash for dedup│ │ • history tracking │ │ +│ │ • cost totals │ │ • PII flags │ │ • region-specific │ │ +│ └──────────────────┘ └──────────────────┘ └──────────────────────────────┘ │ +│ ┌──────────────────┐ ┌──────────────────┐ │ +│ │ scenario_metrics│ │ reports │ │ │ +│ │ ─────────────── │ │ ──────── │ │ │ +│ │ • time-series │ │ • generated │ │ │ +│ │ • aggregates │ │ • metadata │ │ │ +│ │ • cost breakdown│ │ • file refs │ │ │ +│ └──────────────────┘ └──────────────────┘ │ +└─────────────────────────────────────────────────────────────────────────────┘ ``` -## 5. API Contracts +### 2.2 Layer Responsibilities + +| Layer | Responsabilità | Tecnologie | +|-------|----------------|------------| +| **Client** | Interazione utente, ingestion log | Browser, Logstash, curl | +| **API** | Routing, validation, auth, middleware | FastAPI, Pydantic, slowapi | +| **Service** | Business logic, orchestration | Python async/await | +| **Repository** | Data access, query abstraction | SQLAlchemy 2.0 Repository pattern | +| **Database** | Persistenza, ACID, queries | PostgreSQL 15+ | + +--- + +## 3. Database Schema + +### 3.1 Entity Relationship Diagram -### [Endpoint] ``` -POST /api/v1/... -Request: - body: { ... } - -Response: - 200: { ... } - 400: { ... } +┌─────────────────────────────────────────────────────────────────────────┐ +│ SCHEMA ERD │ +└─────────────────────────────────────────────────────────────────────────┘ + +┌─────────────────────┐ ┌─────────────────────┐ +│ scenarios │ │ aws_pricing │ +├─────────────────────┤ ├─────────────────────┤ +│ PK id: UUID │ │ PK id: UUID │ +│ name: VARCHAR(255)│ │ service: VARCHAR │ +│ description: TEXT│ │ region: VARCHAR │ +│ tags: JSONB │ │ tier: VARCHAR │ +│ status: ENUM │ │ price: DECIMAL │ +│ region: VARCHAR │ │ unit: VARCHAR │ +│ created_at: TS │ │ effective_from: D│ +│ updated_at: TS │ │ effective_to: D │ +│ completed_at: TS │ │ is_active: BOOL │ +│ total_requests: INT│ │ source_url: TEXT │ +│ total_cost: DEC │ └─────────────────────┘ +└──────────┬──────────┘ + │ + │ 1:N + ▼ +┌─────────────────────┐ ┌─────────────────────┐ +│ scenario_logs │ │ scenario_metrics │ +├─────────────────────┤ ├─────────────────────┤ +│ PK id: UUID │ │ PK id: UUID │ +│ FK scenario_id: UUID│ │ FK scenario_id: UUID│ +│ received_at: TS │ │ timestamp: TS │ +│ message_hash: V64│ │ metric_type: VAR │ +│ message_preview │ │ metric_name: VAR │ +│ source: VARCHAR │ │ value: DECIMAL │ +│ size_bytes: INT │ │ unit: VARCHAR │ +│ has_pii: BOOL │ │ metadata: JSONB │ +│ token_count: INT │ └─────────────────────┘ +│ sqs_blocks: INT │ +└─────────────────────┘ + │ + │ 1:N (optional) + ▼ +┌─────────────────────┐ +│ reports │ +├─────────────────────┤ +│ PK id: UUID │ +│ FK scenario_id: UUID│ +│ format: ENUM │ +│ file_path: TEXT │ +│ generated_at: TS │ +│ metadata: JSONB │ +└─────────────────────┘ ``` -## 6. Decisioni +### 3.2 DDL - Schema Definition -### [DEC-001] - [Titolo] -**Decisione:** +```sql +-- ============================================ +-- EXTENSIONS +-- ============================================ +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -- For text search -**Motivazione:** +-- ============================================ +-- ENUMS +-- ============================================ +CREATE TYPE scenario_status AS ENUM ('draft', 'running', 'completed', 'archived'); +CREATE TYPE report_format AS ENUM ('pdf', 'csv'); -**Alternative:** +-- ============================================ +-- TABLE: scenarios +-- ============================================ +CREATE TABLE scenarios ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + name VARCHAR(255) NOT NULL, + description TEXT, + tags JSONB DEFAULT '[]'::jsonb, + status scenario_status NOT NULL DEFAULT 'draft', + region VARCHAR(50) NOT NULL DEFAULT 'us-east-1', + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + completed_at TIMESTAMP WITH TIME ZONE, + started_at TIMESTAMP WITH TIME ZONE, + total_requests INTEGER NOT NULL DEFAULT 0, + total_cost_estimate DECIMAL(12, 6) NOT NULL DEFAULT 0.000000, + + -- Constraints + CONSTRAINT chk_name_not_empty CHECK (char_length(trim(name)) > 0), + CONSTRAINT chk_region_not_empty CHECK (char_length(trim(region)) > 0) +); -**Conseguenze:** +-- Indexes +CREATE INDEX idx_scenarios_status ON scenarios(status); +CREATE INDEX idx_scenarios_region ON scenarios(region); +CREATE INDEX idx_scenarios_created_at ON scenarios(created_at DESC); +CREATE INDEX idx_scenarios_tags ON scenarios USING GIN(tags); + +-- Trigger for updated_at +CREATE OR REPLACE FUNCTION update_updated_at_column() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ language 'plpgsql'; + +CREATE TRIGGER update_scenarios_updated_at + BEFORE UPDATE ON scenarios + FOR EACH ROW + EXECUTE FUNCTION update_updated_at_column(); + +-- ============================================ +-- TABLE: scenario_logs +-- ============================================ +CREATE TABLE scenario_logs ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + scenario_id UUID NOT NULL REFERENCES scenarios(id) ON DELETE CASCADE, + received_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + message_hash VARCHAR(64) NOT NULL, -- SHA256 + message_preview VARCHAR(500), + source VARCHAR(100) DEFAULT 'unknown', + size_bytes INTEGER NOT NULL DEFAULT 0, + has_pii BOOLEAN NOT NULL DEFAULT FALSE, + token_count INTEGER NOT NULL DEFAULT 0, + sqs_blocks INTEGER NOT NULL DEFAULT 1, + + -- Constraints + CONSTRAINT chk_size_positive CHECK (size_bytes >= 0), + CONSTRAINT chk_token_positive CHECK (token_count >= 0), + CONSTRAINT chk_blocks_positive CHECK (sqs_blocks >= 1) +); + +-- Indexes +CREATE INDEX idx_logs_scenario_id ON scenario_logs(scenario_id); +CREATE INDEX idx_logs_received_at ON scenario_logs(received_at DESC); +CREATE INDEX idx_logs_message_hash ON scenario_logs(message_hash); +CREATE INDEX idx_logs_has_pii ON scenario_logs(has_pii) WHERE has_pii = TRUE; + +-- ============================================ +-- TABLE: scenario_metrics +-- ============================================ +CREATE TABLE scenario_metrics ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + scenario_id UUID NOT NULL REFERENCES scenarios(id) ON DELETE CASCADE, + timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + metric_type VARCHAR(50) NOT NULL, -- 'sqs', 'lambda', 'bedrock', 'safety' + metric_name VARCHAR(100) NOT NULL, + value DECIMAL(15, 6) NOT NULL DEFAULT 0.000000, + unit VARCHAR(20) NOT NULL, -- 'count', 'bytes', 'tokens', 'usd', 'invocations' + metadata JSONB DEFAULT '{}'::jsonb +); + +-- Indexes +CREATE INDEX idx_metrics_scenario_id ON scenario_metrics(scenario_id); +CREATE INDEX idx_metrics_timestamp ON scenario_metrics(timestamp DESC); +CREATE INDEX idx_metrics_type ON scenario_metrics(metric_type); +CREATE INDEX idx_metrics_scenario_type ON scenario_metrics(scenario_id, metric_type); + +-- ============================================ +-- TABLE: aws_pricing +-- ============================================ +CREATE TABLE aws_pricing ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + service VARCHAR(50) NOT NULL, -- 'sqs', 'lambda', 'bedrock' + region VARCHAR(50) NOT NULL, + tier VARCHAR(50) NOT NULL DEFAULT 'standard', + price_per_unit DECIMAL(15, 10) NOT NULL, + unit VARCHAR(20) NOT NULL, -- 'per_million_requests', 'per_gb_second', 'per_1k_tokens' + effective_from DATE NOT NULL DEFAULT CURRENT_DATE, + effective_to DATE, + is_active BOOLEAN NOT NULL DEFAULT TRUE, + source_url VARCHAR(500), + description TEXT, + + -- Constraints + CONSTRAINT chk_price_positive CHECK (price_per_unit >= 0), + CONSTRAINT chk_valid_dates CHECK (effective_to IS NULL OR effective_to >= effective_from), + CONSTRAINT uq_pricing_unique_active UNIQUE (service, region, tier, effective_from) + WHERE is_active = TRUE +); + +-- Indexes +CREATE INDEX idx_pricing_service ON aws_pricing(service); +CREATE INDEX idx_pricing_region ON aws_pricing(region); +CREATE INDEX idx_pricing_active ON aws_pricing(service, region, tier) WHERE is_active = TRUE; + +-- ============================================ +-- TABLE: reports +-- ============================================ +CREATE TABLE reports ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + scenario_id UUID NOT NULL REFERENCES scenarios(id) ON DELETE CASCADE, + format report_format NOT NULL, + file_path VARCHAR(500) NOT NULL, + file_size_bytes INTEGER, + generated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + generated_by VARCHAR(100), -- user_id or api_key_id + metadata JSONB DEFAULT '{}'::jsonb +); + +-- Indexes +CREATE INDEX idx_reports_scenario_id ON reports(scenario_id); +CREATE INDEX idx_reports_generated_at ON reports(generated_at DESC); +``` + +### 3.3 Key Queries + +```sql +-- Query: Get scenario with aggregated metrics +SELECT + s.*, + COUNT(DISTINCT sl.id) as total_logs, + COUNT(DISTINCT CASE WHEN sl.has_pii THEN sl.id END) as pii_violations, + SUM(sl.token_count) as total_tokens, + SUM(sl.sqs_blocks) as total_sqs_blocks +FROM scenarios s +LEFT JOIN scenario_logs sl ON s.id = sl.scenario_id +WHERE s.id = :scenario_id +GROUP BY s.id; + +-- Query: Get cost breakdown by service +SELECT + metric_type, + SUM(value) as total_value, + unit +FROM scenario_metrics +WHERE scenario_id = :scenario_id + AND metric_name LIKE '%cost%' +GROUP BY metric_type, unit; + +-- Query: Get active pricing for service/region +SELECT * +FROM aws_pricing +WHERE service = :service + AND region = :region + AND is_active = TRUE + AND (effective_to IS NULL OR effective_to >= CURRENT_DATE) +ORDER BY effective_from DESC +LIMIT 1; ``` --- -*Questo file verrà popolato durante la fase di specifica* +## 4. API Specifications + +### 4.1 OpenAPI Overview + +```yaml +openapi: 3.0.0 +info: + title: mockupAWS API + version: 0.2.0 + description: AWS Cost Simulation Platform API + +servers: + - url: http://localhost:8000/api/v1 + description: Development server + +security: + - BearerAuth: [] + - ApiKeyAuth: [] +``` + +### 4.2 Endpoints + +#### Scenarios API + +```yaml +# POST /scenarios - Create new scenario +request: + content: + application/json: + schema: + type: object + required: [name, region] + properties: + name: + type: string + minLength: 1 + maxLength: 255 + description: + type: string + tags: + type: array + items: + type: string + region: + type: string + enum: [us-east-1, us-west-2, eu-west-1, eu-central-1] + tier: + type: string + enum: [standard, on-demand] + default: standard + +response: + 201: + content: + application/json: + schema: + $ref: '#/components/schemas/Scenario' + +# GET /scenarios - List scenarios +parameters: + - name: status + in: query + schema: + type: string + enum: [draft, running, completed, archived] + - name: region + in: query + schema: + type: string + - name: page + in: query + schema: + type: integer + default: 1 + - name: page_size + in: query + schema: + type: integer + default: 20 + maximum: 100 + +response: + 200: + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + $ref: '#/components/schemas/Scenario' + total: + type: integer + page: + type: integer + page_size: + type: integer + +# GET /scenarios/{id} - Get scenario details +# PUT /scenarios/{id} - Update scenario +# DELETE /scenarios/{id} - Delete scenario +# POST /scenarios/{id}/start - Start scenario +# POST /scenarios/{id}/stop - Stop scenario +# POST /scenarios/{id}/archive - Archive scenario +``` + +#### Ingest API + +```yaml +# POST /ingest - Ingest log +headers: + X-Scenario-ID: + required: true + schema: + type: string + format: uuid + +request: + content: + application/json: + schema: + type: object + required: [message] + properties: + message: + type: string + minLength: 1 + source: + type: string + default: unknown + +response: + 202: + description: Log accepted + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: accepted + log_id: + type: string + format: uuid + estimated_cost_impact: + type: number + + 400: + description: Invalid scenario or scenario not running +``` + +#### Metrics API + +```yaml +# GET /scenarios/{id}/metrics - Get scenario metrics +response: + 200: + content: + application/json: + schema: + type: object + properties: + scenario_id: + type: string + summary: + type: object + properties: + total_requests: + type: integer + total_cost_usd: + type: number + sqs_blocks: + type: integer + lambda_invocations: + type: integer + llm_tokens: + type: integer + pii_violations: + type: integer + cost_breakdown: + type: array + items: + type: object + properties: + service: + type: string + cost_usd: + type: number + percentage: + type: number + timeseries: + type: array + items: + type: object + properties: + timestamp: + type: string + format: date-time + metric_type: + type: string + value: + type: number +``` + +#### Reports API + +```yaml +# POST /scenarios/{id}/reports - Generate report +request: + content: + application/json: + schema: + type: object + required: [format] + properties: + format: + type: string + enum: [pdf, csv] + include_logs: + type: boolean + default: false + date_from: + type: string + format: date-time + date_to: + type: string + format: date-time + +response: + 202: + description: Report generation started + content: + application/json: + schema: + type: object + properties: + report_id: + type: string + status: + type: string + enum: [pending, processing, completed] + download_url: + type: string + +# GET /reports/{id}/download - Download report +# GET /reports/{id}/status - Check report status +``` + +#### Pricing API (Admin) + +```yaml +# GET /pricing - List pricing +# POST /pricing - Create pricing entry +# PUT /pricing/{id} - Update pricing +# DELETE /pricing/{id} - Delete pricing (soft delete) +``` + +### 4.3 Schemas + +```yaml +components: + schemas: + Scenario: + type: object + properties: + id: + type: string + format: uuid + name: + type: string + description: + type: string + tags: + type: array + items: + type: string + status: + type: string + enum: [draft, running, completed, archived] + region: + type: string + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + completed_at: + type: string + format: date-time + total_requests: + type: integer + total_cost_estimate: + type: number + + LogEntry: + type: object + properties: + id: + type: string + format: uuid + scenario_id: + type: string + format: uuid + received_at: + type: string + format: date-time + message_hash: + type: string + message_preview: + type: string + source: + type: string + size_bytes: + type: integer + has_pii: + type: boolean + token_count: + type: integer + sqs_blocks: + type: integer + + securitySchemes: + BearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + ApiKeyAuth: + type: apiKey + in: header + name: X-API-Key +``` + +--- + +## 5. Data Flow + +### 5.1 Log Ingestion Flow + +``` +┌──────────┐ POST /ingest ┌──────────────┐ +│ Client │ ───────────────────────>│ FastAPI │ +│(Logstash)│ Headers: │ Middleware │ +│ │ X-Scenario-ID: uuid │ │ +└──────────┘ └──────┬───────┘ + │ + │ 1. Validate scenario exists & running + │ 2. Parse JSON payload + ▼ + ┌──────────────┐ + │ Ingest │ + │ Service │ + └──────┬───────┘ + │ + ┌───────────────────────┼───────────────────────┐ + │ │ │ + ▼ ▼ ▼ + ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ + │ PII Detector │ │ SQS Calculator│ │ Tokenizer │ + │ • check email│ │ • calc blocks │ │ • count │ + └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ + │ │ │ + │ has_pii: bool │ sqs_blocks: int │ tokens: int + └──────────────────────┼─────────────────────┘ + │ + ▼ + ┌──────────────┐ + │ LogRepo │ + │ save() │ + └──────┬───────┘ + │ + ▼ + ┌──────────────┐ + │ PostgreSQL │ + │ scenario_logs│ + └──────────────┘ +``` + +### 5.2 Scenario State Machine + +``` + ┌─────────────────────────────────────────────────────────┐ + │ │ + ▼ │ + ┌──────────┐ POST /start ┌──────────┐ │ + ┌───────│ DRAFT │────────────────────>│ RUNNING │ │ + │ └──────────┘ └────┬─────┘ │ + │ ▲ │ │ + │ │ │ POST /stop │ + │ │ POST /archive ▼ │ + │ │ ┌──────────┐ │ + │ ┌────┴────┐<────────────────────│COMPLETED │──────────────────┘ + │ │ARCHIVED │ └──────────┘ + └──────>└─────────┘ +``` + +### 5.3 Cost Calculation Flow + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ COST CALCULATION PIPELINE │ +└─────────────────────────────────────────────────────────────────────────┘ + +Input: scenario_logs row +├─ sqs_blocks +├─ token_count +└─ (future: lambda_gb_seconds) + │ + ▼ +┌─────────────────┐ +│ Pricing Service │ +│ • get_active() │ +└────────┬────────┘ + │ Query: SELECT * FROM aws_pricing + │ WHERE service IN ('sqs', 'lambda', 'bedrock') + │ AND region = :scenario_region + │ AND is_active = TRUE + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ COST FORMULAS │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ SQS Cost: │ +│ cost = blocks × price_per_million / 1,000,000 │ +│ Example: 100 blocks × $0.40 / 1M = $0.00004 │ +│ │ +│ Lambda Cost: │ +│ request_cost = invocations × price_per_million / 1,000,000 │ +│ compute_cost = gb_seconds × price_per_gb_second │ +│ total = request_cost + compute_cost │ +│ Example: 1M invoc × $0.20/1M + 10GBs × $0.00001667 = $0.20 + $0.00017│ +│ │ +│ Bedrock Cost: │ +│ input_cost = input_tokens × price_per_1k_input / 1,000 │ +│ output_cost = output_tokens × price_per_1k_output / 1,000 │ +│ total = input_cost + output_cost │ +│ Example: 1000 tokens × $0.003/1K = $0.003 │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────┐ +│ Update │ +│ scenarios │ +│ total_cost │ +└─────────────────┘ +``` + +--- + +## 6. Security Architecture + +### 6.1 Authentication & Authorization + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ AUTHENTICATION LAYERS │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Layer 1: API Key (Programmatic Access) │ +│ ├─ Header: X-API-Key: │ +│ ├─ Rate limiting: 1000 req/min │ +│ └─ Scope: /ingest, /metrics (read-only on other resources) │ +│ │ +│ Layer 2: JWT Token (Web UI Access) │ +│ ├─ Header: Authorization: Bearer │ +│ ├─ Expiration: 24h │ +│ ├─ Refresh token: 7d │ +│ └─ Scope: Full access based on roles │ +│ │ +│ Layer 3: Role-Based Access Control (RBAC) │ +│ ├─ admin: Full access │ +│ ├─ user: CRUD own scenarios, read pricing │ +│ └─ readonly: View only │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 6.2 Data Security + +| Layer | Measure | Implementation | +|-------|---------|----------------| +| **Transport** | TLS 1.3 | Nginx reverse proxy | +| **Storage** | Hashing | SHA-256 for message_hash | +| **PII** | Detection + Truncation | Email regex, 500 char preview limit | +| **API** | Rate Limiting | slowapi: 100/min public, 1000/min authenticated | +| **DB** | Parameterized Queries | SQLAlchemy ORM (no raw SQL) | +| **Secrets** | Environment Variables | python-dotenv, Docker secrets | + +### 6.3 PII Detection Strategy + +```python +# Pattern matching for common PII +def detect_pii(message: str) -> dict: + patterns = { + 'email': r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', + 'ssn': r'\b\d{3}-\d{2}-\d{4}\b', + 'credit_card': r'\b(?:\d[ -]*?){13,16}\b', + 'phone': r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b' + } + + results = {} + for pii_type, pattern in patterns.items(): + matches = re.findall(pattern, message) + if matches: + results[pii_type] = len(matches) + + return { + 'has_pii': len(results) > 0, + 'pii_types': list(results.keys()), + 'total_matches': sum(results.values()) + } +``` + +--- + +## 7. Technology Stack + +### 7.1 Backend + +| Component | Technology | Version | Purpose | +|-----------|------------|---------|---------| +| Framework | FastAPI | ≥0.110 | Web framework | +| Server | Uvicorn | ≥0.29 | ASGI server | +| Validation | Pydantic | ≥2.7 | Data validation | +| ORM | SQLAlchemy | ≥2.0 | Database ORM | +| Migrations | Alembic | latest | DB migrations | +| Driver | asyncpg | latest | Async PostgreSQL | +| Tokenizer | tiktoken | ≥0.6 | Token counting | +| Rate Limit | slowapi | latest | API rate limiting | +| Auth | python-jose | latest | JWT handling | +| Testing | pytest | ≥8.1 | Test framework | +| HTTP Client | httpx | ≥0.27 | Async HTTP | + +### 7.2 Frontend + +| Component | Technology | Version | Purpose | +|-----------|------------|---------|---------| +| Framework | React | ≥18 | UI library | +| Language | TypeScript | ≥5.0 | Type safety | +| Build | Vite | latest | Build tool | +| Styling | Tailwind CSS | ≥3.4 | CSS framework | +| Components | shadcn/ui | latest | UI components | +| Charts | Recharts | latest | Data viz | +| State | React Query | ≥5.0 | Server state | +| HTTP | Axios | latest | HTTP client | +| Routing | React Router | ≥6.0 | Navigation | + +### 7.3 Infrastructure + +| Component | Technology | Purpose | +|-----------|------------|---------| +| Container | Docker | Application containers | +| Orchestration | Docker Compose | Multi-container dev | +| Database | PostgreSQL 15+ | Primary data store | +| Reverse Proxy | Nginx | SSL, static files | +| Process Manager | systemd / PM2 | Production process mgmt | + +--- + +## 8. Project Structure + +``` +mockupAWS/ +├── backend/ +│ ├── src/ +│ │ ├── __init__.py +│ │ ├── main.py # FastAPI app entry +│ │ ├── config.py # Settings & env vars +│ │ ├── dependencies.py # FastAPI dependencies +│ │ ├── models/ # SQLAlchemy models +│ │ │ ├── __init__.py +│ │ │ ├── base.py # Base model +│ │ │ ├── scenario.py +│ │ │ ├── scenario_log.py +│ │ │ ├── scenario_metric.py +│ │ │ ├── aws_pricing.py +│ │ │ └── report.py +│ │ ├── schemas/ # Pydantic schemas +│ │ │ ├── __init__.py +│ │ │ ├── scenario.py +│ │ │ ├── log.py +│ │ │ ├── metric.py +│ │ │ ├── pricing.py +│ │ │ └── report.py +│ │ ├── api/ # API routes +│ │ │ ├── __init__.py +│ │ │ ├── deps.py # Dependencies +│ │ │ └── v1/ +│ │ │ ├── __init__.py +│ │ │ ├── scenarios.py # /scenarios/* +│ │ │ ├── ingest.py # /ingest +│ │ │ ├── metrics.py # /metrics +│ │ │ ├── reports.py # /reports +│ │ │ └── pricing.py # /pricing +│ │ ├── services/ # Business logic +│ │ │ ├── __init__.py +│ │ │ ├── scenario_service.py +│ │ │ ├── ingest_service.py +│ │ │ ├── cost_calculator.py +│ │ │ ├── report_service.py +│ │ │ └── pii_detector.py +│ │ ├── repositories/ # Data access +│ │ │ ├── __init__.py +│ │ │ ├── base.py +│ │ │ ├── scenario_repo.py +│ │ │ ├── log_repo.py +│ │ │ ├── metric_repo.py +│ │ │ └── pricing_repo.py +│ │ ├── core/ # Core utilities +│ │ │ ├── __init__.py +│ │ │ ├── security.py # Auth, JWT +│ │ │ ├── database.py # DB connection +│ │ │ └── exceptions.py # Custom exceptions +│ │ └── utils/ # Utilities +│ │ ├── __init__.py +│ │ └── hashing.py # SHA-256 utils +│ ├── alembic/ # Database migrations +│ │ ├── versions/ # Migration files +│ │ ├── env.py +│ │ └── alembic.ini +│ ├── tests/ +│ │ ├── __init__.py +│ │ ├── conftest.py # pytest fixtures +│ │ ├── unit/ +│ │ │ ├── test_services.py +│ │ │ └── test_cost_calculator.py +│ │ ├── integration/ +│ │ │ ├── test_api_scenarios.py +│ │ │ ├── test_api_ingest.py +│ │ │ └── test_api_metrics.py +│ │ └── e2e/ +│ │ └── test_full_flow.py +│ ├── Dockerfile +│ ├── pyproject.toml +│ └── requirements.txt +│ +├── frontend/ +│ ├── src/ +│ │ ├── components/ +│ │ │ ├── ui/ # shadcn/ui components +│ │ │ ├── layout/ +│ │ │ │ ├── Header.tsx +│ │ │ │ ├── Sidebar.tsx +│ │ │ │ └── Layout.tsx +│ │ │ ├── scenarios/ +│ │ │ │ ├── ScenarioList.tsx +│ │ │ │ ├── ScenarioCard.tsx +│ │ │ │ ├── ScenarioForm.tsx +│ │ │ │ └── ScenarioDetail.tsx +│ │ │ ├── metrics/ +│ │ │ │ ├── MetricCard.tsx +│ │ │ │ ├── CostChart.tsx +│ │ │ │ └── MetricsDashboard.tsx +│ │ │ └── reports/ +│ │ │ ├── ReportGenerator.tsx +│ │ │ └── ReportDownload.tsx +│ │ ├── pages/ +│ │ │ ├── Dashboard.tsx +│ │ │ ├── ScenariosPage.tsx +│ │ │ ├── ScenarioCreate.tsx +│ │ │ ├── ScenarioDetail.tsx +│ │ │ ├── Compare.tsx +│ │ │ ├── Reports.tsx +│ │ │ └── Settings.tsx +│ │ ├── hooks/ +│ │ │ ├── useScenarios.ts +│ │ │ ├── useMetrics.ts +│ │ │ └── useReports.ts +│ │ ├── services/ +│ │ │ ├── api.ts # Axios config +│ │ │ ├── scenarioApi.ts +│ │ │ └── metricApi.ts +│ │ ├── types/ +│ │ │ ├── scenario.ts +│ │ │ ├── metric.ts +│ │ │ └── api.ts +│ │ ├── context/ +│ │ │ └── ThemeContext.tsx +│ │ ├── App.tsx +│ │ └── main.tsx +│ ├── public/ +│ ├── index.html +│ ├── Dockerfile +│ ├── package.json +│ ├── tsconfig.json +│ ├── tailwind.config.js +│ └── vite.config.ts +│ +├── docker-compose.yml +├── nginx.conf +├── .env.example +├── .env +├── .gitignore +└── README.md +``` + +--- + +## 9. Decisioni Architetturali + +### DEC-001: Async-First Architecture + +**Decisione:** Utilizzare Python async/await in tutto lo stack (FastAPI, SQLAlchemy, asyncpg) + +**Motivazione:** +- Alto throughput richiesto (>1000 RPS) +- I/O bound operations (DB, tokenizer) +- Migliore utilizzo risorse rispetto a sync + +**Alternative considerate:** +- Sync + ThreadPool: Più semplice ma meno efficiente +- Celery + Redis: Troppo complesso per use case + +**Conseguenze:** +- Curva di apprendimento per async +- Debugging più complesso +- Migliore scalabilità + +--- + +### DEC-002: Repository Pattern + +**Decisione:** Implementare Repository Pattern per accesso dati + +**Motivazione:** +- Separazione tra business logic e data access +- Facile testing con mock repositories +- Possibilità di cambiare DB in futuro + +**Struttura:** +```python +class BaseRepository(Generic[T]): + async def get(self, id: UUID) -> T | None: ... + async def list(self, **filters) -> list[T]: ... + async def create(self, obj: T) -> T: ... + async def update(self, id: UUID, data: dict) -> T: ... + async def delete(self, id: UUID) -> bool: ... +``` + +--- + +### DEC-003: Separate Database per Scenario + +**Decisione:** Utilizzare una singola tabella `scenario_logs` con `scenario_id` FK invece di DB separati + +**Motivazione:** +- Più semplice da gestire +- Query cross-scenario possibili (confronti) +- Backup/restore più semplice + +**Alternative considerate:** +- Schema per scenario: Troppo overhead +- DB separati: Troppo complesso per MVP + +--- + +### DEC-004: Message Hashing for Deduplication + +**Decisione:** Utilizzare SHA-256 hash del messaggio per deduplicazione + +**Motivazione:** +- Privacy: Non memorizzare messaggi completi +- Performance: Hash lookup O(1) +- Storage: Risparmio spazio + +**Implementazione:** +```python +import hashlib +message_hash = hashlib.sha256(message.encode()).hexdigest() +``` + +--- + +### DEC-005: Time-Series Metrics + +**Decisione:** Salvare metriche come time-series in `scenario_metrics` + +**Motivazione:** +- Trend analysis possibile +- Aggregazioni flessibili +- Audit trail + +**Trade-off:** +- Più storage rispetto a campi aggregati +- Query più complesse ma indicizzate + +--- + +## 10. Performance Considerations + +### 10.1 Database Optimization + +| Optimization | Implementation | Benefit | +|--------------|----------------|---------| +| Indexes | B-tree on foreign keys, timestamps | Fast lookups | +| GIN | tags (JSONB) | Fast array search | +| Partitioning | scenario_logs by date | Query pruning | +| Connection Pool | asyncpg pool (20-50) | Concurrency | + +### 10.2 Caching Strategy (Future) + +``` +Layer 1: In-memory (FastAPI state) +├─ Active scenario metadata +└─ AWS pricing (rarely changes) + +Layer 2: Redis (future) +├─ Session storage +├─ Rate limiting counters +└─ Report generation status +``` + +### 10.3 Query Optimization + +- Use `selectinload` for relationships +- Batch inserts for logs (copy_expert) +- Materialized views for reports +- Async tasks for heavy operations + +--- + +## 11. Error Handling Strategy + +### 11.1 Exception Hierarchy + +```python +class AppException(Exception): + """Base application exception""" + status_code: int = 500 + code: str = "internal_error" + +class NotFoundException(AppException): + status_code = 404 + code = "not_found" + +class ValidationException(AppException): + status_code = 400 + code = "validation_error" + +class ConflictException(AppException): + status_code = 409 + code = "conflict" + +class RateLimitException(AppException): + status_code = 429 + code = "rate_limited" +``` + +### 11.2 Global Exception Handler + +```python +@app.exception_handler(AppException) +async def app_exception_handler(request: Request, exc: AppException): + return JSONResponse( + status_code=exc.status_code, + content={ + "error": exc.code, + "message": str(exc), + "timestamp": datetime.utcnow().isoformat() + } + ) +``` + +--- + +## 12. Deployment Architecture + +### 12.1 Docker Compose (Development) + +```yaml +version: '3.8' + +services: + postgres: + image: postgres:15-alpine + environment: + POSTGRES_DB: mockupaws + POSTGRES_USER: app + POSTGRES_PASSWORD: ${DB_PASSWORD} + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U app -d mockupaws"] + + backend: + build: ./backend + environment: + DATABASE_URL: postgresql+asyncpg://app:${DB_PASSWORD}@postgres:5432/mockupaws + ports: + - "8000:8000" + depends_on: + postgres: + condition: service_healthy + + frontend: + build: ./frontend + ports: + - "3000:80" + depends_on: + - backend + +volumes: + postgres_data: +``` + +### 12.2 Production Considerations + +- Use managed PostgreSQL (AWS RDS, Azure PostgreSQL) +- Nginx as reverse proxy with SSL +- Environment-specific configuration +- Log aggregation (ELK or similar) +- Monitoring (Prometheus + Grafana) +- Health checks and readiness probes + +--- + +*Documento creato da @spec-architect* +*Versione: 1.0* +*Data: 2026-04-07* diff --git a/export/kanban.md b/export/kanban.md index 6a785f9..7a3b22f 100644 --- a/export/kanban.md +++ b/export/kanban.md @@ -1,116 +1,724 @@ -# Kanban Board (Export) +# Kanban - mockupAWS -> Scomposizione del progetto in task minimi e verificabili. - -## Istruzioni - -Questo file deve essere creato/aggiornato dall'agente `@spec-architect` durante la fase di analisi. - -## Principio "Little Often" - -- Task il più piccoli possibile -- Ogni task verificabile in <2 ore -- Progresso incrementale -- Dipendenze chiare +> **Progetto:** mockupAWS - Backend Profiler & Cost Estimator +> **Versione Target:** v0.2.0 +> **Data:** 2026-04-07 +> **Principio:** Little Often - Task < 2 ore --- -## Stati +## Legenda - 🔴 **TODO** - Da fare - 🟡 **IN PROGRESS** - In corso - 🟢 **DONE** - Completato -- ⚪ **BLOCKED** - Bloccato (vedi dipendenze) +- ⚪ **BLOCKED** - Bloccato + +**Stime:** XS (15-30min) | S (30-60min) | M (1-2h) | L (2-4h) | XL (>4h, da spezzare) --- -## Template +## 🔴 TODO - Fase 1: Database & Backend Core -```markdown -# Kanban - [Nome Progetto] +### Database Setup (DB-001 → DB-006) -## Colonna: 🔴 TODO +#### DB-001: Alembic Setup +**Assegnato:** @db-engineer +**Priorità:** Alta +**Stima:** S + +**Descrizione:** +Configurare Alembic per migrazioni database async. -### Task-001: [Titolo task] -**Descrizione:** [Breve descrizione] **Criteri Done:** -- [ ] Criterio 1 -- [ ] Criterio 2 -**Dipendenze:** Nessuna / Task-XXX -**Stima:** XS(1h) / S(2h) / M(4h) / L(8h) -**Assegnato:** @agent +- [ ] Installare alembic e asyncpg +- [ ] Inizializzare `alembic init` +- [ ] Configurare `alembic.ini` con async URL +- [ ] Configurare `alembic/env.py` per SQLAlchemy 2.0 async +- [ ] Testare `alembic current` (connessione OK) + +**Files:** +- `backend/alembic.ini` +- `backend/alembic/env.py` --- -## Colonna: 🟡 IN PROGRESS +#### DB-002: Migration - Scenarios Table +**Assegnato:** @db-engineer +**Priorità:** Alta +**Stima:** M +**Dipende da:** DB-001 -### Task-XXX: [Titolo] -**Iniziato:** YYYY-MM-DD -**Assegnato:** @agent +**Descrizione:** +Creare migrazione per tabella scenarios con tutti i campi e constraints. + +**Criteri Done:** +- [ ] Creare migration `001_create_scenarios_table.py` +- [ ] Definire tutti i campi (id, name, description, tags, status, region, timestamps, totals) +- [ ] Aggiungere constraints (CHK, FK) +- [ ] Aggiungere indexes (status, region, created_at, tags) +- [ ] Creare trigger updated_at +- [ ] Testare `alembic upgrade head` + +**SQL Reference:** Vedere `export/architecture.md` sezione 3.2 --- -## Colonna: 🟢 DONE +#### DB-003: Migration - Scenario Logs Table +**Assegnato:** @db-engineer +**Priorità:** Alta +**Stima:** M +**Dipende da:** DB-002 -### Task-XXX: [Titolo] -**Completato:** YYYY-MM-DD -**Commit:** `feat: ...` +**Descrizione:** +Creare migrazione per tabella scenario_logs. + +**Criteri Done:** +- [ ] Creare migration `002_create_scenario_logs_table.py` +- [ ] Definire campi (id, scenario_id, timestamps, hash, preview, etc.) +- [ ] Aggiungere FK a scenarios con ON DELETE CASCADE +- [ ] Aggiungere indexes (scenario_id, received_at, hash, has_pii) +- [ ] Testare relazione con scenarios --- -## Colonna: ⚪ BLOCKED +#### DB-004: Migration - Scenario Metrics Table +**Assegnato:** @db-engineer +**Priorità:** Alta +**Stima:** M +**Dipende da:** DB-002 -### Task-XXX: [Titolo] -**Bloccato da:** Task-YYY -**Motivo:** [Spiegazione] +**Descrizione:** +Creare migrazione per tabella scenario_metrics (time-series). + +**Criteri Done:** +- [ ] Creare migration `003_create_scenario_metrics_table.py` +- [ ] Definire campi per metriche time-series +- [ ] Aggiungere indexes (scenario_id, timestamp, metric_type) +- [ ] Testare query aggregazione + +--- + +#### DB-005: Migration - AWS Pricing Table +**Assegnato:** @db-engineer +**Priorità:** Alta +**Stima:** M +**Dipende da:** DB-002 + +**Descrizione:** +Creare migrazione per tabella aws_pricing con storico prezzi. + +**Criteri Done:** +- [ ] Creare migration `004_create_aws_pricing_table.py` +- [ ] Definire campi (service, region, tier, price, unit, dates) +- [ ] Aggiungere constraints (price > 0, valid dates) +- [ ] Aggiungere unique constraint parziale per active prices +- [ ] Testare query get_active_pricing + +--- + +#### DB-006: Migration - Reports Table +**Assegnato:** @db-engineer +**Priorità:** Media +**Stima:** S +**Dipende da:** DB-002 + +**Descrizione:** +Creare migrazione per tabella reports. + +**Criteri Done:** +- [ ] Creare migration `005_create_reports_table.py` +- [ ] Definire campi (format, file_path, metadata) +- [ ] Aggiungere indexes + +--- + +#### DB-007: Seed AWS Pricing Data +**Assegnato:** @db-engineer +**Priorità:** Alta +**Stima:** M +**Dipende da:** DB-005 + +**Descrizione:** +Popolare tabella aws_pricing con dati reali. + +**Criteri Done:** +- [ ] Creare migration `006_seed_aws_pricing.py` (opzionale: file separato) +- [ ] Inserire prezzi per us-east-1: + - SQS: $0.40 per milione richieste + - Lambda Request: $0.20 per milione + - Lambda Compute: $0.0000166667 per GB-second + - Bedrock Claude Input: $0.003 per 1K tokens + - Bedrock Claude Output: $0.015 per 1K tokens +- [ ] Inserire prezzi per eu-west-1 (simili) +- [ ] Verificare dati inseriti + +**Dati:** Vedere `export/prd.md` sezione 4.3 + +--- + +### Backend - Database Layer (BE-001 → BE-005) + +#### BE-001: Database Connection & Session Management +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** M +**Dipende da:** DB-001 + +**Descrizione:** +Configurare SQLAlchemy 2.0 async con gestione sessioni. + +**Criteri Done:** +- [ ] Creare `backend/src/core/database.py` +- [ ] Configurare `create_async_engine` con pool +- [ ] Creare `AsyncSessionLocal` factory +- [ ] Creare `get_db()` dependency per FastAPI +- [ ] Testare connessione in test + +**Codice Target:** +```python +# core/database.py +from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession +from sqlalchemy.orm import sessionmaker + +engine = create_async_engine(DATABASE_URL, echo=True, future=True) +AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) + +async def get_db(): + async with AsyncSessionLocal() as session: + yield session ``` --- -## Esempio Board +#### BE-002: SQLAlchemy Models +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** L +**Dipende da:** BE-001 -# Kanban - [NOME_PROGETTO] +**Descrizione:** +Creare tutti i modelli SQLAlchemy corrispondenti alle tabelle. -## 🔴 TODO - -### TASK-001: Setup progetto base -**Descrizione:** Inizializzare struttura progetto Python con uv **Criteri Done:** -- [ ] pyproject.toml configurato -- [ ] Struttura cartelle src/ -- [ ] Pre-commit hooks installati -**Dipendenze:** Nessuna -**Stima:** XS -**Assegnato:** @tdd-developer +- [ ] Creare `backend/src/models/base.py` (Base, TimestampMixin) +- [ ] Creare `scenario.py` (Scenario model) +- [ ] Creare `scenario_log.py` (ScenarioLog model) +- [ ] Creare `scenario_metric.py` (ScenarioMetric model) +- [ ] Creare `aws_pricing.py` (AwsPricing model) +- [ ] Creare `report.py` (Report model) +- [ ] Definire tutte le relationships +- [ ] Testare models (creazione istanze) + +**Files:** +- `backend/src/models/__init__.py` +- `backend/src/models/base.py` +- `backend/src/models/scenario.py` +- `backend/src/models/scenario_log.py` +- `backend/src/models/scenario_metric.py` +- `backend/src/models/aws_pricing.py` +- `backend/src/models/report.py` + +--- + +#### BE-003: Pydantic Schemas +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** M +**Dipende da:** BE-002 + +**Descrizione:** +Creare Pydantic schemas per request/response validation. -### TASK-002: Implementare NotebookService.create() -**Descrizione:** Servizio per creazione notebook con validazione **Criteri Done:** -- [ ] Test unitari passanti -- [ ] Validazione titolo -- [ ] Integrazione notebooklm-py -**Dipendenze:** TASK-001 -**Stima:** S -**Assegnato:** @tdd-developer +- [ ] Creare `backend/src/schemas/scenario.py` + - ScenarioCreate, ScenarioUpdate, ScenarioResponse, ScenarioList +- [ ] Creare `backend/src/schemas/log.py` + - LogIngest, LogResponse +- [ ] Creare `backend/src/schemas/metric.py` + - MetricSummary, CostBreakdown +- [ ] Creare `backend/src/schemas/pricing.py` + - PricingResponse, PricingUpdate +- [ ] Creare `backend/src/schemas/report.py` + - ReportRequest, ReportResponse +- [ ] Validators per campi (name not empty, valid region, etc.) + +--- + +### Backend - Repository Layer (BE-004 → BE-008) + +#### BE-004: Base Repository +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** M +**Dipende da:** BE-002 + +**Descrizione:** +Implementare Base Repository con operazioni CRUD generiche. + +**Criteri Done:** +- [ ] Creare `backend/src/repositories/base.py` +- [ ] Implementare `BaseRepository` class (Generic[T]) +- [ ] Metodi: get(), list(), create(), update(), delete(), count() +- [ ] Supporto per filters e pagination +- [ ] Type hints completi + +**Codice Target:** +```python +class BaseRepository(Generic[T]): + def __init__(self, model: Type[T]): + self.model = model + + async def get(self, db: AsyncSession, id: UUID) -> T | None: + result = await db.execute(select(self.model).where(self.model.id == id)) + return result.scalar_one_or_none() + + async def list(self, db: AsyncSession, skip: int = 0, limit: int = 100, **filters) -> list[T]: + query = select(self.model) + for key, value in filters.items(): + query = query.where(getattr(self.model, key) == value) + query = query.offset(skip).limit(limit) + result = await db.execute(query) + return result.scalars().all() +``` + +--- + +#### BE-005: Scenario Repository +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** M +**Dipende da:** BE-004 + +**Descrizione:** +Implementare ScenarioRepository con metodi specifici. + +**Criteri Done:** +- [ ] Creare `backend/src/repositories/scenario_repo.py` +- [ ] Estendere BaseRepository +- [ ] Metodi specifici: + - `get_by_name()` + - `list_by_status()` + - `list_by_region()` + - `update_status()` + - `increment_total_requests()` + - `update_total_cost()` +- [ ] Testare tutti i metodi + +--- + +#### BE-006: Log Repository +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** S +**Dipende da:** BE-004 + +**Descrizione:** +Implementare LogRepository. + +**Criteri Done:** +- [ ] Creare `backend/src/repositories/log_repo.py` +- [ ] Metodi specifici: + - `get_by_hash()` - per deduplicazione + - `list_by_scenario()` + - `count_by_scenario()` + - `count_pii_by_scenario()` + +--- + +#### BE-007: Metric Repository +**Assegnato:** @backend-dev +**Priorità:** Media +**Stima:** S +**Dipende da:** BE-004 + +**Descrizione:** +Implementare MetricRepository. + +**Criteri Done:** +- [ ] Creare `backend/src/repositories/metric_repo.py` +- [ ] Metodi specifici: + - `get_aggregated_by_scenario()` + - `list_by_type()` + - `get_cost_breakdown()` + +--- + +#### BE-008: Pricing Repository +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** S +**Dipende da:** BE-004 + +**Descrizione:** +Implementare PricingRepository. + +**Criteri Done:** +- [ ] Creare `backend/src/repositories/pricing_repo.py` +- [ ] Metodi specifici: + - `get_active_by_service_region()` - CRITICO per calcolo costi + - `list_active()` + +--- + +### Backend - Service Layer (BE-009 → BE-014) + +#### BE-009: Cost Calculator Service +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** M +**Dipende da:** BE-008 + +**Descrizione:** +Implementare servizio calcolo costi usando prezzi da database. + +**Criteri Done:** +- [ ] Creare `backend/src/services/cost_calculator.py` +- [ ] Metodi: + - `calculate_sqs_cost(blocks, region)` + - `calculate_lambda_cost(invocations, gb_seconds, region)` + - `calculate_bedrock_cost(input_tokens, output_tokens, region)` + - `calculate_total_cost(log_entry, region)` +- [ ] Query pricing repository per prezzi attivi +- [ ] Formule corrette (vedi architecture.md) +- [ ] Unit tests con mock pricing + +--- + +#### BE-010: Scenario Service +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** L +**Dipende da:** BE-005 + +**Descrizione:** +Implementare ScenarioService con business logic. + +**Criteri Done:** +- [ ] Creare `backend/src/services/scenario_service.py` +- [ ] Metodi CRUD: + - `create_scenario(data)` + - `get_scenario(id)` + - `list_scenarios(filters, pagination)` + - `update_scenario(id, data)` + - `delete_scenario(id)` +- [ ] Metodi lifecycle: + - `start_scenario(id)` - draft → running + - `stop_scenario(id)` - running → completed + - `archive_scenario(id)` - completed → archived +- [ ] Validazioni (name unique, valid transitions) +- [ ] Unit tests + +--- + +#### BE-011: Ingest Service +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** L +**Dipende da:** BE-006, BE-009 + +**Descrizione:** +Implementare IngestService per elaborazione log. + +**Criteri Done:** +- [ ] Creare `backend/src/services/ingest_service.py` +- [ ] Metodi: + - `ingest_log(scenario_id, log_data)` - MAIN METHOD + - `validate_scenario(scenario_id)` - check status == running + - `process_log(log_data)` - calcola metriche + - `persist_log(scenario_id, processed_log)` - salva su DB + - `update_scenario_metrics(scenario_id, metrics)` +- [ ] Integrare PII detection +- [ ] Integrare token counting +- [ ] Integrare SQS block calculation +- [ ] Integrare cost calculator +- [ ] Transaction management (DB commit) + +--- + +#### BE-012: PII Detector Service +**Assegnato:** @backend-dev +**Priorità:** Media +**Stima:** S +**Dipende da:** None + +**Descrizione:** +Implementare servizio rilevamento PII (estrazione da main.py attuale). + +**Criteri Done:** +- [ ] Creare `backend/src/services/pii_detector.py` +- [ ] Pattern regex per: + - Email + - SSN (opzionale) + - Credit card (opzionale) + - Phone (opzionale) +- [ ] Metodo `detect(message) -> dict` +- [ ] Unit tests con vari input + +--- + +#### BE-013: Report Service (Base) +**Assegnato:** @backend-dev +**Priorità:** Media +**Stima:** M +**Dipende da:** BE-007 + +**Descrizione:** +Implementare ReportService per generazione CSV. + +**Criteri Done:** +- [ ] Creare `backend/src/services/report_service.py` +- [ ] Metodi: + - `generate_csv(scenario_id)` - CSV export + - `compile_metrics(scenario_id)` - aggrega dati +- [ ] CSV format con headers +- [ ] Unit tests + +--- + +#### BE-014: Tokenizer Service (Refactor) +**Assegnato:** @backend-dev +**Priorità:** Bassa +**Stima:** XS +**Dipende da:** None + +**Descrizione:** +Refactor profilera esistente in servizio. + +**Criteri Done:** +- [ ] Creare `backend/src/services/tokenizer_service.py` +- [ ] Spostare logica da `src/profiler.py` +- [ ] Mantenere encoding cl100k_base + +--- + +### Backend - API Layer (BE-015 → BE-020) + +#### BE-015: API Dependencies & Error Handling +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** M +**Dipende da:** None + +**Descrizione:** +Configurare FastAPI dependencies e exception handlers. + +**Criteri Done:** +- [ ] Creare `backend/src/api/deps.py` + - `get_db()` - DB session + - `get_current_scenario()` - scenario validation +- [ ] Creare `backend/src/core/exceptions.py` + - AppException base + - NotFoundException + - ValidationException + - ConflictException +- [ ] Creare exception handlers in `main.py` +- [ ] Global error response format + +--- + +#### BE-016: Scenarios API Endpoints +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** L +**Dipende da:** BE-010, BE-015 + +**Descrizione:** +Implementare tutti gli endpoint CRUD per scenari. + +**Criteri Done:** +- [ ] Creare `backend/src/api/v1/scenarios.py` +- [ ] Endpoints: + - `POST /api/v1/scenarios` - Create + - `GET /api/v1/scenarios` - List (con pagination, filters) + - `GET /api/v1/scenarios/{id}` - Get detail + - `PUT /api/v1/scenarios/{id}` - Update + - `DELETE /api/v1/scenarios/{id}` - Delete + - `POST /api/v1/scenarios/{id}/start` - Start + - `POST /api/v1/scenarios/{id}/stop` - Stop + - `POST /api/v1/scenarios/{id}/archive` - Archive +- [ ] Integrare schemas per request/response +- [ ] Integration tests + +--- + +#### BE-017: Ingest API Endpoint (Refactor) +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** M +**Dipende da:** BE-011, BE-016 + +**Descrizione:** +Aggiornare endpoint `/ingest` esistente per usare database. + +**Criteri Done:** +- [ ] Refactor `backend/src/api/v1/ingest.py` +- [ ] Aggiungere header `X-Scenario-ID` required +- [ ] Validare scenario esiste e status == running +- [ ] Usare IngestService per elaborazione +- [ ] Rimuovere stato in-memory (mantenere solo per cache) +- [ ] Response 202 Accepted con log_id +- [ ] Integration tests + +--- + +#### BE-018: Metrics API Endpoint +**Assegnato:** @backend-dev +**Priorità:** Alta +**Stima:** M +**Dipende da:** BE-017 + +**Descrizione:** +Implementare endpoint metrics per scenari. + +**Criteri Done:** +- [ ] Creare `backend/src/api/v1/metrics.py` +- [ ] Endpoints: + - `GET /api/v1/scenarios/{id}/metrics` - Summary metrics + - `GET /api/v1/scenarios/{id}/metrics/costs` - Cost breakdown + - `GET /api/v1/scenarios/{id}/metrics/timeseries` - Time series +- [ ] Aggregare dati da scenario_logs e scenario_metrics +- [ ] Integration tests + +--- + +#### BE-019: Pricing API Endpoints (Admin) +**Assegnato:** @backend-dev +**Priorità:** Media +**Stima:** S +**Dipende da:** BE-016 + +**Descrizione:** +Implementare endpoint per gestione prezzi. + +**Criteri Done:** +- [ ] Creare `backend/src/api/v1/pricing.py` +- [ ] Endpoints: + - `GET /api/v1/pricing` - List + - `POST /api/v1/pricing` - Create (admin) + - `PUT /api/v1/pricing/{id}` - Update (admin) +- [ ] Integration tests + +--- + +#### BE-020: Reports API Endpoint +**Assegnato:** @backend-dev +**Priorità:** Media +**Stima:** S +**Dipende da:** BE-013 + +**Descrizione:** +Implementare endpoint report generation. + +**Criteri Done:** +- [ ] Creare `backend/src/api/v1/reports.py` +- [ ] Endpoints: + - `POST /api/v1/scenarios/{id}/reports` - Generate + - `GET /api/v1/reports/{id}/download` - Download +- [ ] Supporto format CSV (PDF future) +- [ ] Integration tests + +--- + +### Testing (QA-001 → QA-005) + +#### QA-001: Unit Tests - Services +**Assegnato:** @qa-engineer + @backend-dev +**Priorità:** Alta +**Stima:** L +**Dipende da:** BE-009, BE-010, BE-011 + +**Descrizione:** +Scrivere unit tests per tutti i services. + +**Criteri Done:** +- [ ] `tests/unit/test_cost_calculator.py` +- [ ] `tests/unit/test_scenario_service.py` +- [ ] `tests/unit/test_ingest_service.py` +- [ ] `tests/unit/test_pii_detector.py` +- [ ] Mock repositories per isolamento +- [ ] Coverage > 80% per service + +--- + +#### QA-002: Integration Tests - API +**Assegnato:** @qa-engineer + @backend-dev +**Priorità:** Alta +**Stima:** L +**Dipende da:** BE-016, BE-017, BE-018 + +**Descrizione:** +Scrivere integration tests per API endpoints. + +**Criteri Done:** +- [ ] `tests/integration/test_api_scenarios.py` +- [ ] `tests/integration/test_api_ingest.py` +- [ ] `tests/integration/test_api_metrics.py` +- [ ] Test database con rollback per test +- [ ] Test fixtures per dati + +--- + +#### QA-003: E2E Test - Full Flow +**Assegnato:** @qa-engineer +**Priorità:** Media +**Stima:** M +**Dipende da:** QA-002 + +**Descrizione:** +Test end-to-end del flusso completo. + +**Criteri Done:** +- [ ] `tests/e2e/test_full_flow.py` +- [ ] Flow: Create → Start → Ingest 10 logs → Get Metrics → Stop +- [ ] Verifica costi calcolati correttamente --- ## 🟡 IN PROGRESS -*Vuoto* +*Vuoto - In attesa inizio Fase 1* --- ## 🟢 DONE -*Vuoto* +*Vuoto - Progetto appena iniziato* --- ## ⚪ BLOCKED -*Vuoto* +*Vuoto - Nessun blocco attuale* --- -*Questo file verrà popolato durante la fase di specifica* +## 📊 Summary + +| Fase | Task Totali | Completati | In Progress | Todo | +|------|-------------|------------|-------------|------| +| Fase 1 - Database | 7 | 0 | 0 | 7 | +| Fase 1 - Backend DB | 5 | 0 | 0 | 5 | +| Fase 1 - Backend Repo | 5 | 0 | 0 | 5 | +| Fase 1 - Backend Service | 6 | 0 | 0 | 6 | +| Fase 1 - Backend API | 6 | 0 | 0 | 6 | +| Fase 1 - Testing | 3 | 0 | 0 | 3 | +| **TOTALE** | **32** | **0** | **0** | **32** | + +--- + +## 🎯 Priorità per Sprint 1 (Week 1) + +**Goal:** Database pronto e API base funzionanti + +1. DB-001 → DB-003 (Database setup e prime 2 tabelle) +2. BE-001 → BE-003 (Connessione e models) +3. BE-004 → BE-005 (Base repo e scenario repo) +4. BE-009 (Cost calculator - critico) +5. BE-015 → BE-016 (API base e scenarios CRUD) + +--- + +*Documento creato da @spec-architect* +*Versione: 1.0* +*Data: 2026-04-07* diff --git a/export/progress.md b/export/progress.md index ae16370..c4b3204 100644 --- a/export/progress.md +++ b/export/progress.md @@ -1,48 +1,64 @@ -# Progress Tracking - [NOME_PROGETTO] +# Progress Tracking - mockupAWS -> Tracciamento progresso sviluppo in tempo reale. +> **Progetto:** mockupAWS - Backend Profiler & Cost Estimator +> **Versione Target:** v0.2.0 +> **Data Inizio:** 2026-04-07 +> **Data Ultimo Aggiornamento:** 2026-04-07 + +--- ## 🎯 Sprint/Feature Corrente -**Feature:** `[Nome feature in sviluppo]` -**Iniziata:** `YYYY-MM-DD` -**Stato:** 🔴 Pianificazione / 🟡 In sviluppo / 🟢 Completata -**Assegnato:** `@agent` +**Feature:** Fase 1 - Database e Backend API Core +**Iniziata:** 2026-04-07 +**Stato:** 🔴 Pianificazione / Setup +**Assegnato:** @spec-architect (coordinamento), @db-engineer, @backend-dev --- ## 📊 Progresso Complessivo -| Area | Progresso | Stato | -|------|-----------|-------| -| API Core | 0/10 task | 🔴 Non iniziato | -| Webhook System | 0/5 task | 🔴 Non iniziato | -| AI Skill | 0/3 task | 🔴 Non iniziato | -| Testing | 0/8 task | 🔴 Non iniziato | -| Documentazione | 0/4 task | 🔴 Non iniziato | - -**Completamento Totale:** 0% +| Area | Task Totali | Completati | Progresso | Stato | +|------|-------------|------------|-----------|-------| +| Database (Migrazioni) | 7 | 0 | 0% | 🔴 Non iniziato | +| Backend - Models/Schemas | 5 | 0 | 0% | 🔴 Non iniziato | +| Backend - Repository | 5 | 0 | 0% | 🔴 Non iniziato | +| Backend - Services | 6 | 0 | 0% | 🔴 Non iniziato | +| Backend - API | 6 | 0 | 0% | 🔴 Non iniziato | +| Testing | 3 | 0 | 0% | 🔴 Non iniziato | +| Frontend | 0 | 0 | 0% | ⚪ Fase 2 | +| DevOps | 0 | 0 | 0% | ⚪ Fase 3 | +| **Completamento Totale** | **32** | **0** | **0%** | 🔴 **Setup** | --- ## 🔄 Attività in Corso -### Task Corrente: `[ID-XXX] - Titolo` +### Task Corrente: Architettura e Specifiche | Campo | Valore | |-------|--------| -| **ID** | TASK-XXX | -| **Descrizione** | [Breve descrizione] | -| **Iniziata** | YYYY-MM-DD HH:MM | -| **Assegnato** | @agent | +| **ID** | SPEC-001 | +| **Descrizione** | Creare architecture.md completo con schema DB, API specs, sicurezza | +| **Iniziata** | 2026-04-07 12:00 | +| **Assegnato** | @spec-architect | | **Stato** | 🟡 In progress | -| **Bloccata da** | Nessuna / TASK-YYY | -| **Note** | [Eventuali ostacoli, decisioni] | +| **Bloccata da** | Nessuna | +| **Note** | Completato architecture.md, in corso kanban.md e progress.md | **Passi completati:** -- [x] Passo 1 -- [ ] Passo 2 -- [ ] Passo 3 +- [x] Analisi PRD completo +- [x] Analisi codice esistente (main.py, profiler.py) +- [x] Creazione architecture.md con: + - [x] Stack tecnologico dettagliato + - [x] Schema database completo (DDL SQL) + - [x] API specifications (OpenAPI) + - [x] Architettura a layer + - [x] Diagrammi flusso dati + - [x] Piano sicurezza + - [x] Struttura progetto finale +- [x] Creazione kanban.md con task breakdown +- [x] Creazione progress.md (questo file) --- @@ -50,16 +66,22 @@ | ID | Task | Completata | Commit | Assegnato | |----|------|------------|--------|-----------| -| | | | | | +| - | Nessuna task completata oggi - Setup iniziale | - | - | - | --- -## 📅 Prossime Task +## 📅 Prossime Task (Priorità P1) -| Priority | ID | Task | Stima | Dipendenze | -|----------|----|------|-------|------------| -| P1 | | | | | -| P2 | | | | | +| Priority | ID | Task | Stima | Assegnato | Dipendenze | +|----------|----|------|-------|-----------|------------| +| P1 | DB-001 | Alembic Setup | S | @db-engineer | Nessuna | +| P1 | DB-002 | Migration Scenarios Table | M | @db-engineer | DB-001 | +| P1 | DB-003 | Migration Logs Table | M | @db-engineer | DB-002 | +| P1 | BE-001 | Database Connection | M | @backend-dev | DB-001 | +| P1 | BE-002 | SQLAlchemy Models | L | @backend-dev | BE-001 | +| P2 | DB-004 | Migration Metrics Table | M | @db-engineer | DB-002 | +| P2 | DB-005 | Migration Pricing Table | M | @db-engineer | DB-002 | +| P2 | BE-003 | Pydantic Schemas | M | @backend-dev | BE-002 | --- @@ -67,7 +89,7 @@ | ID | Problema | Impatto | Soluzione Proposta | Stato | |----|----------|---------|-------------------|-------| -| | | | | 🔴 Aperto | +| - | Nessun blocco attuale | - | - | ✅ OK | --- @@ -75,23 +97,68 @@ | Data | Decisione | Motivazione | Impatto | |------|-----------|-------------|---------| -| | | | | +| 2026-04-07 | Utilizzare Repository Pattern | Separazione business logic e data access | Più testabile, manutenibile | +| 2026-04-07 | Async-first con SQLAlchemy 2.0 | Performance >1000 RPS richiesti | Curva apprendimento ma scalabilità | +| 2026-04-07 | Single table per scenario_logs vs DB separati | Semplice per MVP, query cross-scenario possibili | Facile backup, confronti | +| 2026-04-07 | SHA-256 hashing per deduplicazione | Privacy + performance | Non memorizzare messaggi completi | --- ## 📈 Metriche -### Sprint Corrente -- **Task pianificate:** 0 +### Sprint Corrente (Fase 1) +- **Task pianificate:** 32 - **Task completate:** 0 -- **Task in progress:** 0 +- **Task in progress:** 1 (Architettura) - **Task bloccate:** 0 ### Qualità -- **Test Coverage:** 0% -- **Test passanti:** 0/0 -- **Linting:** ✅ / ❌ -- **Type Check:** ✅ / ❌ +- **Test Coverage:** 0% (da implementare) +- **Test passanti:** 5/5 (test esistenti v0.1) +- **Linting:** ✅ (ruff configurato) +- **Type Check:** ⚪ (da implementare con mypy) + +### Codice +- **Linee codice backend:** ~150 (v0.1 base) +- **Linee test:** ~100 +- **Documentazione:** ~2500 linee (PRD, Architettura) + +--- + +## 🎯 Obiettivi Sprint 1 (Week 1) + +**Goal:** Database PostgreSQL funzionante con API CRUD base + +### Target +- [ ] Database schema completo (7 tabelle) +- [ ] Alembic migrations funzionanti +- [ ] SQLAlchemy models completi +- [ ] Repository layer base +- [ ] Scenario CRUD API +- [ ] Test coverage > 60% + +### Metriche Target +- Test coverage: 60% +- API endpoints: 10+ +- Database tables: 5 + +--- + +## 📋 Risorse + +### Documentazione +- PRD: `/home/google/Sources/LucaSacchiNet/mockupAWS/export/prd.md` +- Architettura: `/home/google/Sources/LucaSacchiNet/mockupAWS/export/architecture.md` +- Kanban: `/home/google/Sources/LucaSacchiNet/mockupAWS/export/kanban.md` +- Questo file: `/home/google/Sources/LucaSacchiNet/mockupAWS/export/progress.md` + +### Codice +- Backend base: `/home/google/Sources/LucaSacchiNet/mockupAWS/src/` +- Test: `/home/google/Sources/LucaSacchiNet/mockupAWS/test/` +- Configurazione: `/home/google/Sources/LucaSacchiNet/mockupAWS/pyproject.toml` + +### Team +- Configurazioni: `/home/google/Sources/LucaSacchiNet/mockupAWS/.opencode/agents/` --- @@ -106,4 +173,29 @@ --- -*Ultimo aggiornamento: YYYY-MM-DD HH:MM* +## 📝 Log Attività + +### 2026-04-07 - Setup Iniziale + +**Attività:** +- ✅ Analisi completa PRD +- ✅ Analisi codice esistente (v0.1) +- ✅ Creazione architecture.md completo +- ✅ Creazione kanban.md con 32 task +- ✅ Creazione progress.md +- ✅ Setup team configuration (.opencode/agents/) + +**Team:** +- @spec-architect: Architettura completata +- @db-engineer: In attesa inizio migrazioni +- @backend-dev: In attesa schema DB + +**Prossimi passi:** +1. @db-engineer inizia DB-001 (Alembic setup) +2. @backend-dev prepara ambiente +3. Daily check-in team + +--- + +*Documento mantenuto dal team* +*Ultimo aggiornamento: 2026-04-07 12:00*