Files
TieMeasureFlow/PIANO_IMPLEMENTAZIONE.md
T
Adriano dbdbb77daf feat: FASE 0 - Setup progetto TieMeasureFlow
Struttura monorepo completa con server FastAPI e client Flask:
- Server: FastAPI + SQLAlchemy 2.0 async + Alembic migrations
- Client: Flask + blueprints (auth, measure, maker, statistics)
- Database: docker-compose MySQL 8.0 + Alembic async config
- Config: pydantic-settings, TailwindCSS, Flask-Babel i18n
- Piano implementazione completo (18 sezioni, 1600 righe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 00:16:54 +01:00

88 KiB

TieMeasureFlow - Piano di Implementazione Completo

TieMeasureFlow by Tielogic Sistema di gestione task per misurazioni con calibro manuale Data: 2026-02-06 | Versione Piano: 1.0


Indice

  1. Brand Identity
  2. Analisi Concorrenza
  3. Architettura Generale
  4. Stack Tecnologico e Motivazioni
  5. Struttura Monorepo
  6. Modello Dati MySQL
  7. API REST Endpoints
  8. Ruoli e Autorizzazioni
  9. UX Design e Wireframe
  10. Fasi di Sviluppo
  11. Dettaglio Task e Agenti
  12. Versioning Ricette
  13. Gestione File Server
  14. Tastierino Touch
  15. Internazionalizzazione e Temi
  16. Sicurezza e Rete
  17. Evoluzioni Future
  18. Decisioni Architetturali

0. Brand Identity

Elemento Valore
Nome prodotto TieMeasureFlow
Nome breve TMFlow
Azienda Tielogic
Claim "Tie" (da Tielogic) + "Measure" + "Flow" = collega le misure in un flusso guidato
Concept logo Calibro stilizzato + freccia fluida curva
Colore primario Blu industriale #2563EB
Colore secondario Grigio acciaio #64748B
Colore accent Blu scuro #1E40AF
Tema light Sfondo #F8FAFC, testo #0F172A
Tema dark Sfondo #0F172A, testo #F1F5F9
Feedback misura OK Verde #059669
Feedback misura WARNING Giallo #D97706
Feedback misura FAIL Rosso #DC2626
Font UI Inter
Font numeri/misure JetBrains Mono (monospace, ottimo per valori decimali)
Logo varianti Completo (icona+testo), icona sola, monocromo bianco, monocromo scuro
   ┌──────────────────────────────────────────────┐
   │                                              │
   │   ╔══╗                                       │
   │   ║  ║──────┐                               │
   │   ║  ║      │  ~~~>  (freccia fluida curva) │
   │   ║  ║──────┘                               │
   │   ╚══╝                                       │
   │   Calibro stilizzato    Flow                  │
   │                                              │
   │   TieMeasureFlow                              │
   │   by Tielogic                                 │
   │                                              │
   └──────────────────────────────────────────────┘

   Varianti necessarie:
   - Logo completo (icona + testo) per navbar e login
   - Icona sola (favicon 32x32, 16x16) per tab browser
   - Monocromo bianco (su sfondo scuro / dark theme)
   - Monocromo scuro (su sfondo chiaro / light theme)
   - Formato SVG (vettoriale) + PNG (raster)

Branding Configurabile

Il logo e il nome azienda sono configurabili dal server:

  • Ogni installazione del sistema puo caricare il proprio logo
  • Il nome azienda e visibile nella navbar e nei report PDF
  • Configurazione via system_settings nel database
  • Il branding "Powered by TieMeasureFlow - Tielogic" resta nel footer

1. Analisi Concorrenza

Prezzo: $1.680/licenza | Tipo: Desktop Windows

Analisi Screenshot Concorrente

Vista Classica (std1.jpg):

  • Grafici a barre per ogni caratteristica (Diametro Interno, Esterno, Lunghezza)
  • Zone colorate: rosso (fuori tolleranza), giallo (warning), verde (in specifica)
  • Foto del pezzo fisico + foto calibro che misura il pezzo
  • Prompt guidato in basso: "Next: Coupling 256-78 Inside Diameter"
  • Stato DAQ: "USB Input Tool" per acquisizione diretta

Carta di Controllo SPC (std2.jpg):

  • Grafico con limiti UTL/UWL/Target/LWL/LTL a zone colorate
  • Istogramma con indici Cp, Cpk, Pp, Ppk
  • Tabella dati: osservazione, sottogruppo, valore, timestamp
  • Tab per ogni caratteristica misurata

Vista Multi-caratteristica (std3.jpg):

  • 5 "Position Offset" affiancati, ciascuno con carta di controllo + istogramma
  • Indici di capability per ogni posizione
  • Confronto visivo immediato tra posizioni

Confronto Competitivo

Aspetto MeasurLink TieMeasureFlow (nostro) Vantaggio
Piattaforma Desktop Windows Web app (qualsiasi dispositivo) Nostro
Prezzo $1.680/licenza Da definire (piu accessibile) Nostro
Guida visuale Foto generica pezzo Immagine/PDF annotata con marker numerati Nostro
Dove misurare Lista piatta caratteristiche Frecce e indicatori posizionati sul disegno tecnico Nostro
Workflow Semi-guidato Task strutturati con subtask per marker Nostro
Selezione ricetta Manuale da lista Barcode + URL parametrico + manuale Nostro
Multilingua Solo inglese IT/EN configurabile per utente Nostro
Tema Un solo tema Dark/Light per utente Nostro
SPC Completo, maturo Completo (da implementare) MeasurLink
Integrazione HW Vasta gamma calibri Web Serial API (Chrome/Edge) MeasurLink
Storicita Prodotto consolidato Nuovo prodotto MeasurLink
Editor ricette Assente (setup tecnico) Editor drag-and-drop con Fabric.js Nostro
Feature Come la implementiamo
Zone colorate rosso/giallo/verde Feedback in tempo reale su ogni misura inserita
Prompt "Next" guidato Indicatore "Prossima misura: Marker #N - Descrizione"
Stato connessione DAQ Icona stato calibro USB nella status bar
Tolleranze UTL/UWL/Target/LWL/LTL Configurabili per ogni subtask nella ricetta
Timestamp automatico Ogni misura registrata con data/ora precisa
Istogrammi e Cp/Cpk Dashboard Metrologist con Plotly.js

2. Architettura Generale

┌──────────────────────────────────────────────────────────────┐
│               TABLET WINDOWS (Edge/Chrome)                    │
│                                                               │
│  ┌──────────────── FLASK CLIENT ──────────────────────────┐  │
│  │                                                         │  │
│  │  [Logo Azienda] TieMeasureFlow   [IT/EN] [Dark] [User] │  │
│  │  ─────────────────────────────────────────────────────  │  │
│  │                                                         │  │
│  │  ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐  │  │
│  │  │   /maker     │ │  /measure     │ │  /statistics     │  │  │
│  │  │             │ │              │ │                 │  │  │
│  │  │ Fabric.js   │ │ PDF.js       │ │ Plotly.js       │  │  │
│  │  │ Editor      │ │ Canvas       │ │ Carte controllo │  │  │
│  │  │ Ricette     │ │ Web Serial   │ │ Istogrammi      │  │  │
│  │  │ Upload file │ │ Numpad touch │ │ Trend/Cp/Cpk    │  │  │
│  │  │ Task/Sub    │ │ Barcode scan │ │ Report PDF      │  │  │
│  │  │ Versioning  │ │ CSV export   │ │ Filtri avanzati │  │  │
│  │  └──────┬──────┘ └──────┬───────┘ └───────┬─────────┘  │  │
│  │         └───────────────┼─────────────────┘             │  │
│  └─────────────────────────┼───────────────────────────────┘  │
│                             │                                  │
└─────────────────────────────┼──────────────────────────────────┘
                              │ HTTPS + API Key
                              │ ZeroTier Network
┌─────────────────────────────┼──────────────────────────────────┐
│                       FastAPI SERVER                            │
│                             │                                   │
│  ┌──────────────────────────┼────────────────────────────────┐ │
│  │  /api/auth       - Login, logout, profilo utente           │ │
│  │  /api/users      - CRUD utenti + ruoli + API keys          │ │
│  │  /api/recipes    - CRUD ricette + versioning immutabile    │ │
│  │  /api/tasks      - Task + subtask per versione ricetta     │ │
│  │  /api/measurements - Salvataggio + query misure            │ │
│  │  /api/statistics - Aggregazioni SPC, indici capability     │ │
│  │  /api/files      - Upload/download immagini/PDF            │ │
│  │  /api/reports    - Generazione PDF (WeasyPrint + Kaleido)  │ │
│  │  /api/settings   - Config sistema (logo, nome azienda)     │ │
│  └──────────────────────────┬────────────────────────────────┘ │
│                              │                                  │
│  ┌────────────────┐  ┌──────┴───────────────┐                  │
│  │  /uploads       │  │     MySQL 8.0+        │                  │
│  │  ├── images/    │  │                       │                  │
│  │  ├── pdfs/      │  │  users                │                  │
│  │  ├── logos/     │  │  recipes              │                  │
│  │  └── reports/   │  │  recipe_versions      │                  │
│  │                 │  │  recipe_tasks          │                  │
│  │  (disco locale) │  │  recipe_subtasks       │                  │
│  │                 │  │  measurements          │                  │
│  └────────────────┘  │  access_logs            │                  │
│                       │  system_settings        │                  │
│                       │  recipe_version_audit   │                  │
│                       └────────────────────────┘                  │
└───────────────────────────────────────────────────────────────────┘

3. Stack Tecnologico e Motivazioni

Backend

Tecnologia Versione Motivazione
FastAPI 0.110+ Async nativo, auto-docs OpenAPI, performance per tablet multipli
Uvicorn 0.30+ ASGI server, supporto HTTPS
SQLAlchemy 2.0 2.0+ ORM async first-class, type-safe, moderne best practice
asyncmy 0.2+ Driver MySQL async (non-blocking I/O)
MySQL 8.0+ Richiesto dal cliente, JSON support, buon ecosistema
Alembic 1.13+ Migration database versionato
Pydantic 2.0+ Validazione dati, serializzazione automatica
passlib + bcrypt - Hash password sicuro
Pillow 10+ Generazione miniature immagini
Plotly Python 5.x Generazione grafici SPC server-side per report
Kaleido 0.2+ Export grafici Plotly in SVG/PNG ad alta qualita
WeasyPrint 62+ HTML → PDF professionale, supporta CSS3 moderno

Frontend Client

Tecnologia Versione Motivazione
Flask 3.0+ Lightweight, Jinja2 integrato, blueprint routing
Jinja2 3.x Template engine server-side, i18n nativo
htmx 2.0 HTML-over-the-wire, aggiornamenti parziali senza SPA
Alpine.js 3.x Reattivita client-side leggera, stato locale
TailwindCSS 3.x Utility-first, personalizzazione tema, dark mode nativa
PDF.js 4.x Rendering PDF in canvas, worker-based, HiDPI
Fabric.js 6.x Editor annotazioni: frecce, cerchi, rettangoli, drag-and-drop
Plotly.js 5.x Grafici SPC interattivi (zoom, hover, filtri)
html5-qrcode 2.x Barcode scanner via camera, cross-browser
Web Serial API Browser Lettura calibri USB, nativo Chrome/Edge
Flask-Babel 4.x i18n server-side (estrazione stringhe, .po/.mo)
alpinejs-i18n 2.x i18n client-side (switch lingua dinamico)
Inter font - UI professionale, leggibilita ottimale
JetBrains Mono - Monospace per valori numerici/misure

Perche Queste Scelte

Scelta Alternative scartate Motivazione
FastAPI vs Django Django REST troppo pesante per API pura FastAPI e 3-5x piu veloce, async nativo
Flask vs React React = SPA complessa, overhead JS Flask + htmx = semplicita, SEO, meno bundle JS
TailwindCSS vs Bootstrap Bootstrap meno personalizzabile Tailwind: dark mode nativa, CSS variables, look moderno
Plotly vs Chart.js Chart.js meno potente per SPC Plotly: export SVG, piu tipi di grafici, hover ricchi
WeasyPrint vs wkhtmltopdf wkhtmltopdf non supporta CSS3 WeasyPrint: flexbox, grid, CSS moderno
Fabric.js vs marker.js marker.js licenza commerciale Fabric.js: MIT, oggetti ricchi, export JSON
MySQL vs PostgreSQL Richiesto MySQL dal cliente MySQL 8.0+ ha JSON, async, sufficiente

4. Struttura Monorepo

TieMeasureFlow/
├── PIANO_IMPLEMENTAZIONE.md          # Questo file
├── CLAUDE.md                          # Istruzioni progetto per Claude
├── docker-compose.yml                 # MySQL + servizi (opzionale)
├── .env.example                       # Template variabili ambiente
├── .gitignore
│
├── server/                            # FastAPI Backend
│   ├── main.py                        # Entry point FastAPI
│   ├── requirements.txt
│   ├── config.py                      # Configurazione (DB, paths, API keys)
│   ├── database.py                    # Engine SQLAlchemy async
│   │
│   ├── models/                        # SQLAlchemy Models
│   │   ├── __init__.py
│   │   ├── user.py                    # User + roles (JSON)
│   │   ├── recipe.py                  # Recipe + RecipeVersion (immutabile)
│   │   ├── task.py                    # RecipeTask + RecipeSubtask
│   │   ├── measurement.py            # Measurement records
│   │   ├── access_log.py             # Login/action logs
│   │   └── setting.py                # SystemSetting (logo, nome, config)
│   │
│   ├── schemas/                       # Pydantic Schemas (validazione I/O)
│   │   ├── __init__.py
│   │   ├── user.py
│   │   ├── recipe.py                  # Include version schemas
│   │   ├── task.py                    # Include subtask schemas
│   │   ├── measurement.py
│   │   └── statistics.py             # SPC response schemas
│   │
│   ├── routers/                       # API Routers (endpoint grouping)
│   │   ├── __init__.py
│   │   ├── auth.py                    # POST login, logout, GET/PUT me
│   │   ├── users.py                   # CRUD utenti (admin only)
│   │   ├── recipes.py                 # CRUD ricette + versioning
│   │   ├── tasks.py                   # CRUD task + subtask
│   │   ├── measurements.py            # POST misure, GET query
│   │   ├── statistics.py              # GET SPC data endpoints
│   │   ├── files.py                   # POST upload, GET download
│   │   ├── reports.py                 # GET genera PDF report
│   │   └── settings.py               # GET/PUT config sistema
│   │
│   ├── services/                      # Business Logic (separata dai router)
│   │   ├── __init__.py
│   │   ├── auth_service.py            # Login, password hash, API key validation
│   │   ├── recipe_service.py          # Versioning copy-on-write logic
│   │   ├── measurement_service.py     # Salvataggio, pass/fail calc, deviation
│   │   ├── spc_service.py             # Calcoli Cp, Cpk, Pp, Ppk, X-bar, R
│   │   └── report_service.py          # WeasyPrint + Plotly/Kaleido generation
│   │
│   ├── middleware/                     # Middleware FastAPI
│   │   ├── __init__.py
│   │   ├── api_key.py                 # Verifica API Key su ogni request
│   │   └── logging.py                # Access logging automatico
│   │
│   ├── templates/                     # Jinja2 template per report PDF server-side
│   │   └── reports/
│   │       ├── base_report.html       # Layout base report con logo
│   │       ├── spc_report.html        # Report SPC con grafici
│   │       └── measurement_report.html # Report misure tabulare
│   │
│   ├── uploads/                       # File uploadati (GITIGNORED)
│   │   ├── images/                    # {recipe_id}/{version_id}/
│   │   ├── pdfs/                      # {recipe_id}/{version_id}/
│   │   ├── logos/                     # Logo azienda configurabile
│   │   └── reports/                   # Report PDF temporanei (auto-pulizia 24h)
│   │
│   ├── migrations/                    # Alembic DB migrations
│   │   ├── env.py
│   │   ├── alembic.ini
│   │   └── versions/
│   │
│   └── tests/
│       ├── conftest.py                # Fixtures condivise (test DB, client)
│       ├── test_auth.py
│       ├── test_recipes.py            # Include test versioning
│       ├── test_measurements.py
│       └── test_spc.py               # Test calcoli statistici
│
├── client/                            # Flask Frontend (Tablet UI)
│   ├── app.py                         # Entry point Flask
│   ├── requirements.txt
│   ├── config.py                      # URL server API, API key, settings
│   │
│   ├── blueprints/                    # Flask Blueprints (routing per ruolo)
│   │   ├── __init__.py
│   │   ├── auth.py                    # Login/logout/profile pages
│   │   ├── measure.py                 # Pagine MeasurementTec
│   │   ├── maker.py                   # Pagine Maker (editor ricette)
│   │   └── statistics.py             # Pagine Metrologist (SPC)
│   │
│   ├── services/                      # API client helpers
│   │   ├── __init__.py
│   │   └── api_client.py             # Wrapper requests verso FastAPI server
│   │
│   ├── templates/                     # Jinja2 Templates
│   │   ├── base.html                  # Layout: navbar, footer, tema, lingua, logo
│   │   │
│   │   ├── components/                # Componenti riutilizzabili
│   │   │   ├── navbar.html            # Navbar dinamica per ruoli + logo + lingua + tema
│   │   │   ├── numpad.html            # Tastierino touch per misure manuali
│   │   │   ├── caliper_status.html    # Indicatore stato connessione calibro USB
│   │   │   ├── barcode_scanner.html   # Modal scanner barcode
│   │   │   ├── measurement_feedback.html # Feedback colore verde/giallo/rosso
│   │   │   └── next_measurement.html  # Indicatore "Prossima misura"
│   │   │
│   │   ├── auth/
│   │   │   ├── login.html             # Login con logo azienda
│   │   │   └── profile.html           # Modifica: nome display, lingua, tema
│   │   │
│   │   ├── measure/                   # Pagine ruolo MeasurementTec
│   │   │   ├── select_recipe.html     # Selezione ricetta (barcode/manual/URL param)
│   │   │   ├── task_list.html         # Lista task con miniature + progress
│   │   │   ├── task_execute.html      # Esecuzione: immagine annotata + numpad + misure
│   │   │   └── task_complete.html     # Riepilogo: pass/fail + export CSV
│   │   │
│   │   ├── maker/                     # Pagine ruolo Maker
│   │   │   ├── recipe_list.html       # Lista ricette con filtri + stato versione
│   │   │   ├── recipe_editor.html     # Editor: form + upload + Fabric.js canvas
│   │   │   ├── task_editor.html       # Editor task/subtask con tolleranze
│   │   │   ├── recipe_preview.html    # Anteprima come vista MeasurementTec
│   │   │   └── version_history.html   # Storico versioni con diff
│   │   │
│   │   └── statistics/                # Pagine ruolo Metrologist
│   │       ├── dashboard.html         # Dashboard SPC: overview + alert
│   │       ├── control_chart.html     # Carta X-bar / R interattiva
│   │       ├── histogram.html         # Istogramma + curva normale + distribuzione
│   │       ├── capability.html        # Gauge Cp/Cpk/Pp/Ppk con indicatori
│   │       ├── trend.html             # Trend temporali + confronto periodi
│   │       └── filters.html           # Componente filtri: date, ricetta, operatore, lotto, seriale
│   │
│   ├── static/
│   │   ├── css/
│   │   │   ├── tailwind.css           # TailwindCSS compilato
│   │   │   ├── themes.css             # CSS Variables per dark/light + brand colors
│   │   │   └── numpad.css             # Stili tastierino touch (bottoni grandi)
│   │   │
│   │   ├── js/
│   │   │   ├── alpine-init.js         # Alpine.js config + i18n + tema toggle
│   │   │   ├── caliper.js             # Web Serial API: connect, read, parse dati calibro
│   │   │   ├── barcode.js             # html5-qrcode: init camera, decode, callback
│   │   │   ├── numpad.js              # Logica numpad: cifre, punto, +/-, backspace, invio
│   │   │   ├── annotation-viewer.js   # Canvas overlay display-only (MeasurementTec)
│   │   │   ├── annotation-editor.js   # Fabric.js editor completo (Maker)
│   │   │   ├── csv-export.js          # Export misure in CSV (Blob API)
│   │   │   └── spc-charts.js          # Plotly.js: configurazioni grafici SPC
│   │   │
│   │   ├── img/
│   │   │   ├── tmflow-logo.svg        # Logo TieMeasureFlow (vettoriale)
│   │   │   ├── tmflow-icon.svg        # Icona sola (favicon source)
│   │   │   ├── favicon.ico            # Favicon 32x32
│   │   │   └── default-company-logo.png # Logo placeholder se non configurato
│   │   │
│   │   └── vendor/                    # Librerie JS locali (fallback CDN)
│   │       ├── pdf.js/
│   │       ├── fabric.js/
│   │       ├── plotly.js/
│   │       ├── htmx.min.js
│   │       ├── alpine.min.js
│   │       └── html5-qrcode/
│   │
│   ├── translations/                  # Flask-Babel i18n
│   │   ├── babel.cfg                  # Config estrazione stringhe
│   │   ├── messages.pot               # Template stringhe estratte
│   │   ├── it/LC_MESSAGES/
│   │   │   ├── messages.po            # Traduzioni italiano
│   │   │   └── messages.mo            # Compilato
│   │   └── en/LC_MESSAGES/
│   │       ├── messages.po            # Traduzioni inglese
│   │       └── messages.mo            # Compilato
│   │
│   └── tests/
│       ├── test_auth_pages.py
│       ├── test_measure_flow.py
│       └── test_maker_flow.py
│
└── docs/                              # Documentazione
    ├── API.md                         # Documentazione API REST completa
    ├── DEPLOYMENT.md                  # Guida deployment (server + client + MySQL)
    ├── USER_GUIDE.md                  # Guida utente per tutti i ruoli
    └── COMPETITOR_ANALYSIS.md         # Analisi dettagliata concorrenza

5. Modello Dati MySQL

Diagramma ER

┌──────────────┐       ┌────────────────┐       ┌──────────────────┐
│    users      │       │    recipes      │       │ system_settings   │
│──────────────│       │────────────────│       │──────────────────│
│ id (PK)      │       │ id (PK)         │       │ key (PK)          │
│ username     │       │ code (UNIQUE)   │       │ value              │
│ password_hash│       │ name            │       │ type               │
│ email        │       │ description     │       │ description        │
│ display_name │       │ created_by (FK)─┼───┐   │ updated_at         │
│ roles (JSON) │   ┌───┤ created_at      │   │   │ updated_by (FK)    │
│ language_pref│   │   │ active          │   │   └──────────────────┘
│ theme_pref   │   │   └───────┬────────┘   │
│ is_admin     │   │           │ 1:N         │
│ active       │   │   ┌───────┴────────┐   │
│ api_key      │   │   │recipe_versions  │   │
│ created_at   │   │   │────────────────│   │
│ last_login   │   │   │ id (PK)         │   │
└──────┬───────┘   │   │ recipe_id (FK)  │   │
       │           │   │ version_number  │   │
       │           │   │ is_current      │   │
       │           └───┤ created_by (FK) │   │
       │               │ created_at      │   │
       │               │ change_notes    │   │
       │               └───────┬────────┘   │
       │                       │ 1:N         │
       │               ┌───────┴────────┐   │
       │               │  recipe_tasks   │   │
       │               │────────────────│   │
       │               │ id (PK)         │   │
       │               │ version_id (FK) │   │
       │               │ order_index     │   │
       │               │ title           │   │
       │               │ directive       │   │
       │               │ description     │   │
       │               │ file_path       │   │
       │               │ file_type       │   │
       │               │ annotations_json│   │
       │               └───────┬────────┘   │
       │                       │ 1:N         │
       │               ┌───────┴────────┐   │
       │               │recipe_subtasks  │   │
       │               │────────────────│   │
       │               │ id (PK)         │   │
       │               │ task_id (FK)    │   │
       │               │ marker_number   │   │
       │               │ description     │   │
       │               │ measurement_type│   │
       │               │ nominal         │   │
       │               │ utl, uwl        │   │
       │               │ lwl, ltl        │   │
       │               │ unit            │   │
       │               └───────┬────────┘   │
       │                       │ 1:N         │
       │               ┌───────┴──────────┐ │
       └───────────────┤  measurements     │ │
                       │──────────────────│ │
                       │ id (PK BIGINT)    │ │
                       │ subtask_id (FK)   │ │
                       │ version_id (FK)   │ │
                       │ measured_by (FK)──┘ │
                       │ value              │
                       │ pass_fail          │
                       │ deviation          │
                       │ lot_number         │
                       │ serial_number      │
                       │ input_method       │
                       │ measured_at        │
                       │ synced_to_csv      │
                       └───────────────────┘

┌──────────────────────┐    ┌──────────────────────────┐
│    access_logs        │    │  recipe_version_audit     │
│──────────────────────│    │──────────────────────────│
│ id (PK BIGINT)       │    │ id (PK BIGINT)            │
│ user_id (FK)         │    │ recipe_id (FK)             │
│ action               │    │ old_version_id (FK NULL)   │
│ details (JSON)       │    │ new_version_id (FK)        │
│ ip_address           │    │ changed_by (FK)            │
│ user_agent           │    │ change_type                │
│ created_at           │    │ change_reason              │
└──────────────────────┘    │ created_at                 │
                            └──────────────────────────┘

Schema SQL Dettagliato

-- =============================================
-- UTENTI
-- =============================================
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(100) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    email VARCHAR(255),
    display_name VARCHAR(255) NOT NULL,
    -- Ruoli: combinazione di "Maker", "MeasurementTec", "Metrologist"
    roles JSON NOT NULL DEFAULT '[]',
    -- Flag admin separato (almeno 1 utente deve essere admin)
    is_admin BOOLEAN NOT NULL DEFAULT FALSE,
    -- Preferenze personali configurabili dall'utente
    language_pref ENUM('it', 'en') NOT NULL DEFAULT 'it',
    theme_pref ENUM('light', 'dark') NOT NULL DEFAULT 'light',
    -- Stato
    active BOOLEAN NOT NULL DEFAULT TRUE,
    api_key VARCHAR(64) UNIQUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    last_login TIMESTAMP NULL,
    INDEX idx_username (username),
    INDEX idx_api_key (api_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- =============================================
-- RICETTE (Master - metadati condivisi tra versioni)
-- =============================================
CREATE TABLE recipes (
    id INT PRIMARY KEY AUTO_INCREMENT,
    code VARCHAR(100) NOT NULL UNIQUE,   -- Codice ricetta (per barcode)
    name VARCHAR(255) NOT NULL,
    description TEXT,
    created_by INT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    active BOOLEAN NOT NULL DEFAULT TRUE,
    FOREIGN KEY (created_by) REFERENCES users(id),
    INDEX idx_code (code),
    INDEX idx_active (active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- =============================================
-- VERSIONI RICETTA (Immutabili - copy-on-write)
-- Ogni modifica crea una nuova versione.
-- Le misure restano legate alla versione originale.
-- =============================================
CREATE TABLE recipe_versions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    recipe_id INT NOT NULL,
    version_number INT NOT NULL,          -- Auto-incrementale per ricetta
    is_current BOOLEAN NOT NULL DEFAULT FALSE,
    -- Audit
    created_by INT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    change_notes TEXT,                    -- Motivo modifica
    FOREIGN KEY (recipe_id) REFERENCES recipes(id),
    FOREIGN KEY (created_by) REFERENCES users(id),
    UNIQUE KEY uk_recipe_version (recipe_id, version_number),
    INDEX idx_current (recipe_id, is_current)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- =============================================
-- TASK (legati a una versione specifica della ricetta)
-- =============================================
CREATE TABLE recipe_tasks (
    id INT PRIMARY KEY AUTO_INCREMENT,
    version_id INT NOT NULL,
    order_index INT NOT NULL DEFAULT 0,   -- Ordine visualizzazione
    title VARCHAR(255) NOT NULL,
    directive TEXT,                        -- Direttiva breve (es: "Misurare diametro interno")
    description TEXT,                      -- Descrizione estesa
    file_path VARCHAR(500),               -- Path relativo file immagine/PDF
    file_type ENUM('image', 'pdf') NULL,
    annotations_json JSON,                -- Fabric.js canvas export (frecce, marker, aree)
    FOREIGN KEY (version_id) REFERENCES recipe_versions(id),
    INDEX idx_version_order (version_id, order_index)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- =============================================
-- SUBTASK (indicatori numerici posizionati su immagine)
-- Ogni marker numerico corrisponde a un punto di misura
-- =============================================
CREATE TABLE recipe_subtasks (
    id INT PRIMARY KEY AUTO_INCREMENT,
    task_id INT NOT NULL,
    marker_number INT NOT NULL,           -- Numero indicatore su immagine (1, 2, 3...)
    description VARCHAR(500) NOT NULL,    -- Es: "Diametro interno foro A"
    measurement_type VARCHAR(100),        -- Es: "diametro", "lunghezza", "profondita", "angolo"
    nominal DECIMAL(12,6),                -- Valore nominale target
    utl DECIMAL(12,6),                    -- Upper Tolerance Limit (limite superiore)
    uwl DECIMAL(12,6),                    -- Upper Warning Limit (warning superiore)
    lwl DECIMAL(12,6),                    -- Lower Warning Limit (warning inferiore)
    ltl DECIMAL(12,6),                    -- Lower Tolerance Limit (limite inferiore)
    unit VARCHAR(20) NOT NULL DEFAULT 'mm', -- Unita: mm, inch, deg, etc.
    FOREIGN KEY (task_id) REFERENCES recipe_tasks(id) ON DELETE CASCADE,
    UNIQUE KEY uk_task_marker (task_id, marker_number),
    INDEX idx_task (task_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- =============================================
-- MISURAZIONI
-- Ogni record = una singola misura effettuata
-- =============================================
CREATE TABLE measurements (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    subtask_id INT NOT NULL,              -- Quale subtask e stato misurato
    version_id INT NOT NULL,              -- Link DIRETTO alla versione ricetta (immutabile)
    measured_by INT NOT NULL,             -- Chi ha misurato (MeasurementTec)
    -- Dati misura
    value DECIMAL(12,6) NOT NULL,
    pass_fail ENUM('pass', 'warning', 'fail') NOT NULL,
    deviation DECIMAL(12,6),              -- value - nominal
    -- Tracciabilita
    lot_number VARCHAR(100),              -- Numero lotto produzione
    serial_number VARCHAR(100),           -- Numero seriale pezzo
    -- Metodo input
    input_method ENUM('usb_caliper', 'manual') NOT NULL DEFAULT 'manual',
    -- Timestamp
    measured_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    -- Sync flag per CSV
    synced_to_csv BOOLEAN DEFAULT FALSE,
    FOREIGN KEY (subtask_id) REFERENCES recipe_subtasks(id),
    FOREIGN KEY (version_id) REFERENCES recipe_versions(id),
    FOREIGN KEY (measured_by) REFERENCES users(id),
    INDEX idx_version (version_id),
    INDEX idx_subtask (subtask_id),
    INDEX idx_measured_at (measured_at),
    INDEX idx_lot (lot_number),
    INDEX idx_serial (serial_number),
    INDEX idx_operator (measured_by)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- =============================================
-- LOG ACCESSI
-- =============================================
CREATE TABLE access_logs (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,
    action VARCHAR(100) NOT NULL,         -- login, logout, recipe_create, recipe_update, etc.
    details JSON,                          -- Dettagli aggiuntivi (es: recipe_id, version_id)
    ip_address VARCHAR(45),               -- IPv4 o IPv6
    user_agent VARCHAR(500),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id),
    INDEX idx_user_time (user_id, created_at),
    INDEX idx_action (action)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- =============================================
-- IMPOSTAZIONI SISTEMA (key-value configurabile)
-- =============================================
CREATE TABLE system_settings (
    setting_key VARCHAR(100) PRIMARY KEY,
    setting_value TEXT NOT NULL,
    setting_type ENUM('string', 'number', 'boolean', 'json') DEFAULT 'string',
    description VARCHAR(500),
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    updated_by INT,
    FOREIGN KEY (updated_by) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Dati iniziali settings
INSERT INTO system_settings (setting_key, setting_value, setting_type, description) VALUES
('company_name', 'TieMeasureFlow', 'string', 'Nome azienda visualizzato in navbar e report'),
('company_logo_path', '', 'string', 'Path logo azienda (relativo a uploads/logos/)'),
('max_upload_size_mb', '50', 'number', 'Dimensione massima upload file in MB'),
('csv_export_delimiter', ';', 'string', 'Delimitatore CSV per export'),
('csv_export_decimal', ',', 'string', 'Separatore decimale CSV per export'),
('default_language', 'it', 'string', 'Lingua default per nuovi utenti'),
('default_theme', 'light', 'string', 'Tema default per nuovi utenti');

-- =============================================
-- AUDIT VERSIONI RICETTA
-- Traccia ogni modifica alle ricette
-- =============================================
CREATE TABLE recipe_version_audit (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    recipe_id INT NOT NULL,
    old_version_id INT,                   -- NULL se prima creazione
    new_version_id INT NOT NULL,
    changed_by INT NOT NULL,
    change_type ENUM('CREATE', 'UPDATE', 'ACTIVATE', 'RETIRE') NOT NULL,
    change_reason TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (recipe_id) REFERENCES recipes(id),
    FOREIGN KEY (changed_by) REFERENCES users(id),
    INDEX idx_recipe_time (recipe_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

6. API REST Endpoints

Autenticazione & Utenti

Metodo Endpoint Descrizione Ruolo
POST /api/auth/login Login utente (username + password) Tutti
POST /api/auth/logout Logout (invalida sessione) Tutti
GET /api/auth/me Profilo corrente con ruoli Tutti
PUT /api/auth/me Aggiorna profilo (display_name, lingua, tema) Tutti
GET /api/users Lista utenti con ruoli Admin
POST /api/users Crea utente con ruoli Admin
PUT /api/users/{id} Modifica utente (ruoli, stato, admin) Admin
DELETE /api/users/{id} Disattiva utente (soft delete) Admin
POST /api/users/{id}/regenerate-key Rigenera API key utente Admin

Ricette

Metodo Endpoint Descrizione Ruolo
GET /api/recipes Lista ricette attive (paginata) Tutti
GET /api/recipes/{id} Dettaglio ricetta con versione corrente + task Tutti
GET /api/recipes/code/{code} Ricetta per codice barcode MeasurementTec
POST /api/recipes Crea nuova ricetta (versione 1) Maker
PUT /api/recipes/{id} Aggiorna ricetta (crea nuova versione) Maker
DELETE /api/recipes/{id} Disattiva ricetta Maker
GET /api/recipes/{id}/versions Lista tutte le versioni Maker, Metrologist
GET /api/recipes/{id}/versions/{v} Dettaglio versione specifica Maker, Metrologist
GET /api/recipes/{id}/versions/{v}/measurement-count Conteggio misure per versione Maker

Task & Subtask

Metodo Endpoint Descrizione Ruolo
GET /api/recipes/{id}/tasks Lista task versione corrente (ordinati) Tutti
POST /api/recipes/{id}/tasks Aggiungi task (crea nuova versione) Maker
PUT /api/tasks/{id} Modifica task Maker
DELETE /api/tasks/{id} Elimina task Maker
PUT /api/tasks/reorder Riordina task (drag-and-drop) Maker
POST /api/tasks/{id}/subtasks Aggiungi subtask con tolleranze Maker
PUT /api/subtasks/{id} Modifica subtask Maker
DELETE /api/subtasks/{id} Elimina subtask Maker

Misurazioni

Metodo Endpoint Descrizione Ruolo
POST /api/measurements Salva singola misura MeasurementTec
POST /api/measurements/batch Salva batch di misure MeasurementTec
GET /api/measurements Query misure (con filtri paginati) Metrologist
GET /api/measurements/export/csv Export CSV server-side MeasurementTec, Metrologist

Statistiche SPC

Metodo Endpoint Descrizione Ruolo
GET /api/statistics/control-chart Dati carta di controllo X-bar/R Metrologist
GET /api/statistics/histogram Dati istogramma + distribuzione Metrologist
GET /api/statistics/capability Indici Cp/Cpk/Pp/Ppk Metrologist
GET /api/statistics/trend Trend temporali indici Metrologist
GET /api/statistics/summary Riepilogo pass/fail/warning count Metrologist
GET /api/statistics/compare-versions Confronto SPC tra versioni ricetta Metrologist
GET /api/statistics/alerts Western Electric rules violations Metrologist

Filtri comuni per tutti gli endpoint statistics (query params):

  • recipe_id - Ricetta specifica
  • version_id - Versione specifica (opzionale, default=tutte)
  • subtask_id - Subtask specifico
  • date_from, date_to - Intervallo date
  • operator_id - MeasurementTec specifico
  • lot_number - Numero lotto
  • serial_number - Numero seriale

File & Report

Metodo Endpoint Descrizione Ruolo
POST /api/files/upload Upload immagine/PDF per task Maker
GET /api/files/{path} Download/serve file Tutti
DELETE /api/files/{path} Elimina file Maker
GET /api/reports/spc Genera PDF report SPC (filtri come statistics) Metrologist
GET /api/reports/measurements Genera PDF report misure tabulare Metrologist

Settings

Metodo Endpoint Descrizione Ruolo
GET /api/settings Leggi tutte le impostazioni Tutti
PUT /api/settings Aggiorna impostazioni (batch) Admin
POST /api/settings/logo Upload logo azienda Admin

7. Ruoli e Autorizzazioni

Matrice Ruoli

Funzionalita MeasurementTec Maker Metrologist Admin
Login / Logout / Profilo personale X X X X
Modificare: nome display, lingua, tema X X X X
Seleziona ricetta (barcode/manual/URL) X
Visualizza task con immagine annotata X
Inserisce misure (numpad / calibro USB) X
Vede feedback colore (pass/warning/fail) X
Export CSV misure X
Crea nuove ricette X
Modifica ricette (crea nuova versione) X
Upload immagini / PDF X
Editor annotazioni Fabric.js X
Gestione task e subtask con tolleranze X
Anteprima ricetta come MeasurementTec X
Storico versioni ricetta X X
Dashboard SPC overview X
Carte di controllo X-bar / R X
Istogrammi e distribuzione X
Indici capability Cp/Cpk/Pp/Ppk X
Trend temporali e confronto periodi X
Alert Western Electric rules X
Download report PDF X
Confronto SPC tra versioni ricetta X
Gestione utenti (CRUD) X
Impostazioni sistema (logo, nome, config) X

Regole Combinazione Ruoli

  • Un utente puo avere 1, 2 o 3 ruoli contemporaneamente (JSON array)
  • is_admin e un flag separato (non un ruolo), combinabile con qualsiasi ruolo
  • La navbar mostra solo le voci accessibili ai ruoli dell'utente corrente
  • Esempio: utente con roles: ["Maker", "Metrologist"], is_admin: true vede tutto
  • Almeno 1 utente deve essere admin (vincolo applicativo)
  • Un utente senza ruoli puo solo fare login e modificare il proprio profilo

8. UX Design e Wireframe

Pagina Login

┌──────────────────────────────────────────────┐
│                                              │
│         [Logo Azienda Configurabile]         │
│         ──────────────────────────           │
│              TieMeasureFlow                   │
│              by Tielogic                      │
│                                              │
│    ┌──────────────────────────────┐          │
│    │  Username                    │          │
│    └──────────────────────────────┘          │
│    ┌──────────────────────────────┐          │
│    │  Password                    │          │
│    └──────────────────────────────┘          │
│                                              │
│    ┌──────────────────────────────┐          │
│    │         ACCEDI               │          │
│    └──────────────────────────────┘          │
│                                              │
│                         [IT] [EN]  [Dark]    │
└──────────────────────────────────────────────┘

Navbar (dinamica per ruoli)

┌──────────────────────────────────────────────────────────────┐
│ [Logo] TieMeasureFlow   | Misure | Ricette | Statistiche |  │
│                          └──MeT──┘ └─Maker─┘ └─Metrolog──┘  │
│                                          [IT/EN] [☀/🌙] [👤]│
└──────────────────────────────────────────────────────────────┘
  Voci visibili in base ai ruoli dell'utente loggato

MeasurementTec - Esecuzione Task

┌──────────────────────────────────────────────────────────────┐
│ [Navbar]                                    [Calibro: ●]     │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  Task 2 di 5: Controllo Diametri Foro                        │
│  Direttiva: Misurare i diametri indicati nel disegno         │
│                                                              │
│  ┌──────────────────────────────┐  ┌──────────────────────┐ │
│  │                              │  │                      │ │
│  │    [Immagine/PDF con         │  │  Marker #2           │ │
│  │     annotazioni overlay]     │  │  Diametro Int. (mm)  │ │
│  │                              │  │  Nom: 12.500         │ │
│  │      ①──→                    │  │  Tol: ±0.050         │ │
│  │           ②──→               │  │                      │ │
│  │                ③──→          │  │  ┌────────────────┐  │ │
│  │                              │  │  │    12.487      │  │ │
│  │    [Rettangolo area]         │  │  └────────────────┘  │ │
│  │                              │  │  ██████████████░░░░  │ │
│  │                              │  │  (barra verde OK)    │ │
│  └──────────────────────────────┘  │                      │ │
│                                    │  ┌───┬───┬───┬───┐  │ │
│                                    │  │ 7 │ 8 │ 9 │ ⌫ │  │ │
│                                    │  ├───┼───┼───┼───┤  │ │
│                                    │  │ 4 │ 5 │ 6 │ C │  │ │
│                                    │  ├───┼───┼───┼───┤  │ │
│                                    │  │ 1 │ 2 │ 3 │+/-│  │ │
│                                    │  ├───┼───┼───┼───┤  │ │
│                                    │  │ 0 │ . │   │ ✓ │  │ │
│                                    │  └───┴───┴───┴───┘  │ │
│                                    │                      │ │
│                                    │  → Prossima: #3 Lung.│ │
│                                    └──────────────────────┘ │
│                                                              │
│  [← Task precedente]                    [Task successivo →]  │
└──────────────────────────────────────────────────────────────┘

Maker - Editor Annotazioni

┌──────────────────────────────────────────────────────────────┐
│ [Navbar]                                                     │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  Ricetta: COUPLING-256 (v3)  [Salva] [Anteprima] [Annulla]  │
│                                                              │
│  ┌── Toolbar Fabric.js ──────────────────────────────────┐   │
│  │ [Freccia] [Marker#] [Rettangolo] [Testo] [Elimina]   │   │
│  └───────────────────────────────────────────────────────┘   │
│                                                              │
│  ┌──────────────────────────────┐  ┌──────────────────────┐ │
│  │                              │  │  Task 2: Diametri    │ │
│  │    [Canvas Fabric.js]        │  │                      │ │
│  │    Immagine/PDF con          │  │  Subtask (per marker):│ │
│  │    annotazioni editabili     │  │                      │ │
│  │                              │  │  #1 Diam. Esterno    │ │
│  │    Drag frecce, marker,      │  │     Nom: 25.000 mm   │ │
│  │    rettangoli area           │  │     Tol: ±0.100      │ │
│  │                              │  │     [Modifica] [X]   │ │
│  │                              │  │                      │ │
│  │                              │  │  #2 Diam. Interno    │ │
│  │                              │  │     Nom: 12.500 mm   │ │
│  │                              │  │     Tol: ±0.050      │ │
│  │                              │  │     [Modifica] [X]   │ │
│  │                              │  │                      │ │
│  └──────────────────────────────┘  │  [+ Aggiungi Subtask] │ │
│                                    └──────────────────────┘ │
│                                                              │
│  [Upload nuova immagine/PDF]                                 │
└──────────────────────────────────────────────────────────────┘

Metrologist - Dashboard SPC

┌──────────────────────────────────────────────────────────────┐
│ [Navbar]                                                     │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌── Filtri ───────────────────────────────────────────────┐ │
│  │ Ricetta: [COUPLING-256 ▼]  Versione: [Tutte ▼]         │ │
│  │ Dal: [2026-01-01] Al: [2026-02-06]                      │ │
│  │ Operatore: [Tutti ▼]  Lotto: [________]  Seriale: [__] │ │
│  │                                        [Applica filtri] │ │
│  └─────────────────────────────────────────────────────────┘ │
│                                                              │
│  ┌─────────────────────┐  ┌──────────────────────────────┐  │
│  │  Riepilogo           │  │  Capability                   │  │
│  │  Misure: 1.247       │  │                               │  │
│  │  Pass: 1.198 (96.1%) │  │  Cp:  1.45  Cpk: 1.32       │  │
│  │  Warn: 31 (2.5%)     │  │  Pp:  1.41  Ppk: 1.28       │  │
│  │  Fail: 18 (1.4%)     │  │                               │  │
│  └─────────────────────┘  │  [Gauge indicator ████████░░] │  │
│                            └──────────────────────────────┘  │
│                                                              │
│  ┌───────────────────────────────────────────────────────┐   │
│  │  Carta di Controllo X-bar / R              [Plotly.js] │   │
│  │  ═══════════════════ UTL ═════════════════             │   │
│  │  ─ ─ ─ ─ ─ ─ ─ ─ ─ UWL ─ ─ ─ ─ ─ ─ ─ ─             │   │
│  │       ·   ·  · ·  ·    ·  · ·  ·  Target             │   │
│  │  ─ ─ ─ ─ ─ ─ ─ ─ ─ LWL ─ ─ ─ ─ ─ ─ ─ ─             │   │
│  │  ═══════════════════ LTL ═════════════════             │   │
│  └───────────────────────────────────────────────────────┘   │
│                                                              │
│  ┌────────────────────┐  ┌────────────────────────────────┐  │
│  │  Istogramma         │  │  Trend Cpk ultimi 30 giorni    │  │
│  │  [Plotly.js]        │  │  [Plotly.js]                   │  │
│  │   ▄                 │  │       ·  · ·                   │  │
│  │  ▄█▄                │  │    ·       ·  · ·              │  │
│  │ ▄███▄               │  │  ·            ·  ·             │  │
│  │▄█████▄              │  │                                │  │
│  └────────────────────┘  └────────────────────────────────┘  │
│                                                              │
│  [Scarica Report PDF]  [Confronta Versioni]                  │
└──────────────────────────────────────────────────────────────┘

9. Fasi di Sviluppo

Fase Descrizione Dipendenze
FASE 0 Setup Progetto: repo, dipendenze, config, DB Nessuna
FASE 1 Backend Core: modelli, auth, API ricette/utenti/files Fase 0
FASE 2 Client Base: layout, login, navbar ruoli, tema, lingua Fase 0 (parallelo a Fase 1)
FASE 3 Flusso MeasurementTec: ricette, task, misure, numpad, CSV Fase 1 + 2
FASE 4 Editor Maker: Fabric.js, upload, task/subtask, versioning Fase 1 + 2
FASE 5 Calibro USB + Barcode: Web Serial, html5-qrcode Fase 3
FASE 6 Dashboard Metrologist: SPC, grafici Plotly, report PDF Fase 1 + 2
FASE 7 Polish & Testing: i18n, test E2E, security, docs Tutte

Note: Fase 3, 4 e 6 possono essere sviluppate in parallelo dopo che Fase 1 e 2 sono complete.


10. Dettaglio Task e Agenti

Legenda Agenti (prefisso oh-my-claudecode: quando usati via Task tool):

Agente Modello Specializzazione
executor-low Haiku Task semplici, file singolo
executor Sonnet Implementazione standard
executor-high Opus Logica complessa, multi-file
designer Sonnet UI/UX, template HTML, CSS
designer-high Opus Design system complesso
architect Opus Analisi, verifica architettura
researcher Sonnet Ricerca documentazione, API docs
tdd-guide Sonnet Test-driven development
build-fixer Sonnet Fix errori build/type
writer Haiku Documentazione, traduzioni
code-reviewer Opus Review qualita codice
security-reviewer Opus Review sicurezza

FASE 0 - Setup Progetto

# Task Subtask Agente Parallelo
0.1 Init repository
0.1.1 - Creare .gitignore (Python, Node, uploads) executor-low
0.1.2 - Creare .env.example (DB, API keys, paths) executor-low Con 0.1.1
0.1.3 - Creare CLAUDE.md progetto writer Con 0.1.1
0.2 Setup server
0.2.1 - Creare requirements.txt server executor-low
0.2.2 - Creare main.py FastAPI base con CORS executor Dopo 0.2.1
0.2.3 - Creare config.py (settings da .env) executor Con 0.2.2
0.2.4 - Creare database.py (async engine + session) executor Dopo 0.2.2
0.3 Setup client Parallelo con 0.2
0.3.1 - Creare requirements.txt client executor-low
0.3.2 - Creare app.py Flask base con blueprints executor Dopo 0.3.1
0.3.3 - Setup TailwindCSS (config + build) executor Con 0.3.2
0.3.4 - Creare struttura static/ + vendor/ executor-low Con 0.3.2
0.4 Database
0.4.1 - Setup Alembic migrations executor Dopo 0.2.4
0.4.2 - docker-compose.yml con MySQL 8.0 executor-low Con 0.4.1

FASE 1 - Backend Core

# Task Subtask Agente Parallelo
1.1 Modelli SQLAlchemy
1.1.1 - models/user.py (User + roles JSON + is_admin) executor
1.1.2 - models/recipe.py (Recipe + RecipeVersion) executor Con 1.1.1
1.1.3 - models/task.py (RecipeTask + RecipeSubtask) executor Con 1.1.1
1.1.4 - models/measurement.py (Measurement) executor Con 1.1.1
1.1.5 - models/access_log.py + setting.py executor-low Con 1.1.1
1.2 Schemas Pydantic Parallelo con 1.1
1.2.1 - schemas/user.py (Create, Update, Response) executor
1.2.2 - schemas/recipe.py (+ version schemas) executor Con 1.2.1
1.2.3 - schemas/task.py (+ subtask schemas) executor Con 1.2.1
1.2.4 - schemas/measurement.py (Create, Query, Response) executor Con 1.2.1
1.2.5 - schemas/statistics.py (SPC response schemas) executor Con 1.2.1
1.3 Middleware Parallelo con 1.1
1.3.1 - middleware/api_key.py (verifica header) executor
1.3.2 - middleware/logging.py (access log automatico) executor-low Con 1.3.1
1.4 Router Auth Dopo 1.1, 1.2
1.4.1 - routers/auth.py (login, logout, me) executor
1.4.2 - services/auth_service.py (hash, verify, API key) executor Con 1.4.1
1.5 Router Users Con 1.4
1.5.1 - routers/users.py (CRUD + admin check) executor
1.6 Router Recipes Dopo 1.4
1.6.1 - routers/recipes.py (CRUD + versioning endpoints) executor-high
1.6.2 - services/recipe_service.py (copy-on-write logic) executor-high Con 1.6.1
1.7 Router Tasks Con 1.6
1.7.1 - routers/tasks.py (CRUD task + subtask + reorder) executor
1.8 Router Files Con 1.6
1.8.1 - routers/files.py (upload + download + thumbnail) executor
1.8.2 - Configurazione storage disco (paths, limits) executor-low Con 1.8.1
1.9 Router Settings Con 1.4
1.9.1 - routers/settings.py (GET/PUT + logo upload) executor
1.10 Test Backend Dopo 1.4-1.9
1.10.1 - conftest.py + test_auth.py tdd-guide
1.10.2 - test_recipes.py (CRUD + versioning + measurement count) tdd-guide Con 1.10.1
1.10.3 - test_measurements.py (save + query + pass/fail) tdd-guide Con 1.10.1
1.11 Review Backend Dopo 1.10
1.11.1 - Code review completa code-reviewer
1.11.2 - Security review (API key, SQL injection, upload) security-reviewer Con 1.11.1

FASE 2 - Client Base

# Task Subtask Agente Parallelo
2.1 Layout e Tema
2.1.1 - base.html (layout, navbar, footer, logo, brand) designer
2.1.2 - themes.css (CSS variables: brand colors + dark/light) designer Con 2.1.1
2.1.3 - Alpine.js init + tema toggle + localStorage designer Con 2.1.1
2.2 Login e Profilo Dopo 2.1
2.2.1 - blueprints/auth.py (routes Flask) executor
2.2.2 - login.html (logo azienda, form, lingua/tema) designer Con 2.2.1
2.2.3 - profile.html (modifica: nome, lingua, tema) designer Con 2.2.1
2.3 API Client Parallelo con 2.1
2.3.1 - services/api_client.py (wrapper requests + API key) executor
2.4 Navbar dinamica Dopo 2.1, 2.2
2.4.1 - navbar.html (voci basate su ruoli utente) designer
2.4.2 - Logo + nome azienda caricati da settings API executor Con 2.4.1
2.5 i18n Setup Parallelo con 2.1
2.5.1 - Configurare Flask-Babel + babel.cfg executor
2.5.2 - Configurare alpinejs-i18n per switch dinamico executor Con 2.5.1
2.5.3 - Stringhe base IT/EN (login, navbar, common) writer Dopo 2.5.1

FASE 3 - Flusso MeasurementTec

# Task Subtask Agente Parallelo
3.1 Selezione Ricetta
3.1.1 - blueprints/measure.py (routes) executor
3.1.2 - select_recipe.html (lista + ricerca + lotto/seriale input) designer Con 3.1.1
3.1.3 - Supporto parametro URL (?recipe=CODE&lot=X&serial=Y) executor Dopo 3.1.2
3.2 Visualizzazione Task Dopo 3.1
3.2.1 - task_list.html (lista task con miniature + progress bar) designer
3.2.2 - PDF.js viewer integrato per file PDF executor Con 3.2.1
3.2.3 - Canvas overlay per annotazioni (display-only) executor Dopo 3.2.2
3.2.4 - annotation-viewer.js (render Fabric.js JSON su canvas) executor Con 3.2.3
3.3 Esecuzione Subtask Dopo 3.2
3.3.1 - task_execute.html (split: immagine sx, misure dx) designer
3.3.2 - measurement_feedback.html (barra colore pass/warn/fail) designer Con 3.3.1
3.3.3 - next_measurement.html (indicatore prossima misura) designer Con 3.3.1
3.3.4 - Salvataggio misure via API + calcolo pass/fail client executor Dopo 3.3.1
3.4 Tastierino Touch (Numpad) Parallelo con 3.3
3.4.1 - numpad.html (componente Alpine.js) designer
3.4.2 - numpad.js (cifre, punto, +/-, backspace, clear, conferma) designer Con 3.4.1
3.4.3 - numpad.css (bottoni 56x56px, touch-friendly) designer Con 3.4.1
3.4.4 - Integrazione numpad nel form task_execute executor Dopo 3.4.2
3.5 Export CSV Dopo 3.3
3.5.1 - csv-export.js (Blob API + config delimiter/decimal) executor
3.5.2 - Bottone download CSV in riepilogo designer Con 3.5.1
3.6 Completamento Task Dopo 3.3
3.6.1 - task_complete.html (riepilogo: tutte misure + pass/fail + CSV) designer
3.7 Router Measurements API Parallelo con 3.1
3.7.1 - routers/measurements.py (POST singola, POST batch, GET query) executor
3.7.2 - services/measurement_service.py (pass/fail calc, deviation) executor Con 3.7.1

FASE 4 - Editor Maker

# Task Subtask Agente Parallelo
4.1 Lista Ricette
4.1.1 - blueprints/maker.py (routes) executor
4.1.2 - recipe_list.html (CRUD, filtri, badge versione, stato) designer Con 4.1.1
4.2 Editor Ricetta Dopo 4.1
4.2.1 - recipe_editor.html (form metadati + upload area) designer
4.2.2 - Upload immagine/PDF con anteprima live executor Con 4.2.1
4.2.3 - Ricerca Context7 docs Fabric.js per annotazioni researcher Prima di 4.2.4
4.2.4 - annotation-editor.js (Fabric.js: canvas, oggetti, eventi) executor-high Dopo 4.2.3
4.2.5 - Toolbar: frecce, marker numerati, rettangoli area, elimina designer-high Con 4.2.4
4.2.6 - Export/import annotazioni JSON (save/load Fabric.js canvas) executor Dopo 4.2.4
4.3 Editor Task/Subtask Dopo 4.2
4.3.1 - task_editor.html (CRUD task inline, drag reorder) designer
4.3.2 - Form subtask: marker#, descrizione, tipo, nominale, UTL/UWL/LWL/LTL, unita designer Con 4.3.1
4.3.3 - Collegamento bidirezionale marker Fabric.js ↔ subtask list executor-high Dopo 4.3.2
4.4 Anteprima Ricetta Dopo 4.2, 4.3
4.4.1 - recipe_preview.html (esattamente come vista MeasurementTec) designer
4.5 Versioning UI Dopo 4.2
4.5.1 - Avviso "N misure esistenti" su modifica + conferma executor
4.5.2 - version_history.html (storico versioni + change notes) designer Con 4.5.1

FASE 5 - Calibro USB + Barcode

# Task Subtask Agente Parallelo
5.1 Web Serial API (Calibro USB)
5.1.1 - Ricerca Context7 docs Web Serial API researcher
5.1.2 - caliper.js (requestPort, open, read, parse protocollo) executor Dopo 5.1.1
5.1.3 - caliper_status.html (icona: disconnesso/connesso/errore) designer Con 5.1.2
5.1.4 - Integrazione: dato calibro → campo numpad automatico executor Dopo 5.1.2
5.2 Barcode Scanner Parallelo con 5.1
5.2.1 - barcode.js (html5-qrcode: init camera, decode callback) executor
5.2.2 - barcode_scanner.html (modal con preview camera) designer Con 5.2.1
5.2.3 - Integrazione: barcode decodificato → API /recipes/code/{code} executor Dopo 5.2.1

FASE 6 - Dashboard Metrologist

# Task Subtask Agente Parallelo
6.1 Backend SPC
6.1.1 - Ricerca librerie SPC Python (spc-plotly, scipy.stats) researcher
6.1.2 - services/spc_service.py (Cp, Cpk, Pp, Ppk, X-bar, R, sigma) executor-high Dopo 6.1.1
6.1.3 - routers/statistics.py (tutti gli endpoint con filtri) executor Con 6.1.2
6.1.4 - test_spc.py (test calcoli con dataset noti) tdd-guide Dopo 6.1.2
6.2 Frontend Dashboard Dopo 6.1
6.2.1 - blueprints/statistics.py (routes Flask) executor
6.2.2 - dashboard.html (overview: riepilogo + capability + alert) designer Con 6.2.1
6.2.3 - filters.html (componente filtri riusabile con htmx) designer Con 6.2.1
6.3 Grafici SPC Plotly.js Dopo 6.2
6.3.1 - spc-charts.js (configurazioni Plotly: layout, colori, zone) executor
6.3.2 - control_chart.html (X-bar / R con zone colorate) designer Con 6.3.1
6.3.3 - histogram.html (distribuzione + curva normale sovrapposta) designer Con 6.3.1
6.3.4 - capability.html (gauge Cp/Cpk/Pp/Ppk con indicatori) designer Con 6.3.1
6.3.5 - trend.html (trend temporali + confronto periodi + versioni) designer Con 6.3.1
6.4 Alert e Regole Dopo 6.3
6.4.1 - Western Electric rules detection in spc_service.py executor-high
6.4.2 - Visualizzazione alert su dashboard (badge + dettaglio) designer Dopo 6.4.1
6.5 Report PDF Dopo 6.3
6.5.1 - services/report_service.py (WeasyPrint + Kaleido) executor
6.5.2 - base_report.html (layout report con logo azienda + brand) designer Con 6.5.1
6.5.3 - spc_report.html (grafici SVG + tabelle statistiche) designer Con 6.5.1
6.5.4 - measurement_report.html (tabella misure dettagliata) designer Con 6.5.1
6.5.5 - routers/reports.py (genera + serve PDF download) executor Dopo 6.5.1

FASE 7 - Polish & Testing

# Task Subtask Agente Parallelo
7.1 i18n Completo
7.1.1 - Estrarre tutte le stringhe traducibili (pybabel extract) executor
7.1.2 - Traduzione IT completa (messages.po) writer Dopo 7.1.1
7.1.3 - Traduzione EN completa (messages.po) writer Con 7.1.2
7.1.4 - Stringhe client-side Alpine.js (JSON IT/EN) writer Con 7.1.2
7.2 Ottimizzazione Tablet Parallelo con 7.1
7.2.1 - Test responsive su risoluzioni tablet Windows designer
7.2.2 - Touch target minimi 44x44px su tutti i bottoni designer Con 7.2.1
7.2.3 - Performance: lazy load PDF.js, ottimizzare bundle JS executor Con 7.2.1
7.3 Testing End-to-End Dopo 7.1
7.3.1 - Test flusso MeasurementTec completo tdd-guide
7.3.2 - Test flusso Maker completo (incluso versioning) tdd-guide Con 7.3.1
7.3.3 - Test flusso Metrologist completo (SPC + PDF) tdd-guide Con 7.3.1
7.4 Security & Review finale Dopo 7.3
7.4.1 - Security review completa (OWASP top 10) security-reviewer
7.4.2 - Code review finale code-reviewer Con 7.4.1
7.4.3 - Verifica architettura con architect architect Con 7.4.1
7.5 Documentazione Parallelo con 7.3
7.5.1 - API.md (documentazione API REST con esempi) writer
7.5.2 - DEPLOYMENT.md (guida: server, client, MySQL, ZeroTier) writer Con 7.5.1
7.5.3 - USER_GUIDE.md (guida per MeasurementTec, Maker, Metrologist) writer Con 7.5.1

11. Versioning Ricette

Principio: Immutable Copy-on-Write

Regola fondamentale: le versioni delle ricette sono IMMUTABILI. Una volta creata, una versione non viene mai modificata. Ogni modifica crea una nuova versione.

Flusso di Modifica Ricetta

1. Maker apre ricetta "COUPLING-256" (versione corrente: v3)
2. Maker clicca "Modifica"
3. Sistema chiama GET /api/recipes/{id}/versions/3/measurement-count
4. Risultato:

   ├── SE measurement_count > 0:
   │   └── Mostra avviso:
   │       ╔══════════════════════════════════════════════════╗
   │       ║  Attenzione: Esistono 847 misure per la v3.     ║
   │       ║  La modifica creera la versione v4.              ║
   │       ║  Le misure esistenti resteranno legate a v3.     ║
   │       ║                                                  ║
   │       ║  Motivo modifica: [________________________]     ║
   │       ║                                                  ║
   │       ║        [Procedi]          [Annulla]              ║
   │       ╚══════════════════════════════════════════════════╝
   │
   └── SE measurement_count == 0:
       └── Procede alla modifica (crea comunque nuova versione per audit)

5. Maker effettua modifiche (task, subtask, annotazioni, tolleranze)
6. Maker salva → Server:
   a. Crea v4 copiando struttura da v3
   b. Applica le modifiche del Maker
   c. Copia file immagini/PDF nella cartella v4
   d. UPDATE recipe_versions SET is_current = FALSE WHERE version_number = 3
   e. INSERT recipe_versions (version_number = 4, is_current = TRUE)
   f. INSERT recipe_version_audit (change_type = 'UPDATE', change_reason = ...)
7. MeasurementTec successivi lavoreranno con v4
8. Misure storiche restano legate a v3 (immutabile, intoccabile)

Query Metrologist Cross-Versione

Il Metrologist puo:

  • Filtrare misure per versione specifica della ricetta
  • Vedere tutte le versioni aggregate (timeline completa)
  • Confrontare statistiche tra versioni (es: "la v4 ha migliorato il Cpk?")
  • Vedere quando una versione e stata attivata e perche (audit trail)

12. Gestione File Server

Struttura Storage

server/uploads/                        # Root (configurabile via UPLOAD_DIR env var)
├── images/                            # Immagini task
│   └── {recipe_id}/
│       └── {version_id}/
│           ├── task_1_drawing.jpg     # Originale
│           └── task_1_drawing_thumb.jpg # Miniatura 200px auto-generata
│
├── pdfs/                              # PDF task (single page consigliato)
│   └── {recipe_id}/
│       └── {version_id}/
│           └── task_2_technical.pdf
│
├── logos/                             # Logo azienda configurabile
│   └── company_logo.png              # Caricato da Admin
│
└── reports/                           # Report PDF generati (temporanei)
    └── spc_report_20260206_a1b2c3.pdf # Auto-pulizia dopo 24h

Regole Storage

Regola Dettaglio
Dimensione max upload Configurabile via system_settings (default 50MB)
Formati immagine JPG, JPEG, PNG, WebP, BMP
Formati PDF Solo PDF
Miniature Auto-generate a 200px con Pillow per lista task
Naming task_{order}_{original_name}.{ext} (sanitizzato)
Versioning file File copiati fisicamente quando si crea nuova versione ricetta
Pulizia report Cron/scheduled task elimina report > 24h
Backup Directory uploads/ inclusa nei backup (escluso reports/)
Spazio disco Monitorare con health check endpoint

Configurazione

# server/config.py
UPLOAD_DIR = os.environ.get("UPLOAD_DIR", "./uploads")
MAX_UPLOAD_SIZE_MB = int(os.environ.get("MAX_UPLOAD_SIZE_MB", "50"))
ALLOWED_IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp", ".bmp"}
ALLOWED_PDF_EXTENSIONS = {".pdf"}
THUMBNAIL_SIZE = (200, 200)
REPORT_RETENTION_HOURS = 24

13. Tastierino Touch (Numpad)

Design Visuale

┌───────────────────────────────────────────┐
│  Marker #2 - Diametro Interno (mm)        │
│  Nominale: 12.500   Tolleranza: ±0.050    │
│                                           │
│  ┌─────────────────────────────────┐      │
│  │            12.487               │      │
│  └─────────────────────────────────┘      │
│  ████████████████████████████░░░░░░ PASS  │
│                                           │
│  ┌──────┬──────┬──────┬──────┐           │
│  │      │      │      │      │           │
│  │  7   │  8   │  9   │  ⌫   │           │
│  │      │      │      │      │           │
│  ├──────┼──────┼──────┼──────┤           │
│  │      │      │      │      │           │
│  │  4   │  5   │  6   │  C   │           │
│  │      │      │      │      │           │
│  ├──────┼──────┼──────┼──────┤           │
│  │      │      │      │      │           │
│  │  1   │  2   │  3   │ +/-  │           │
│  │      │      │      │      │           │
│  ├──────┼──────┼──────┼──────┤           │
│  │      │      │      │      │           │
│  │  0   │  .   │      │  ✓   │           │
│  │      │      │      │ (OK) │           │
│  └──────┴──────┴──────┴──────┘           │
│                                           │
│  → Prossima: Marker #3 - Lunghezza totale │
└───────────────────────────────────────────┘

Specifiche

Caratteristica Dettaglio
Dimensione bottoni Minimo 56x56px per touch ottimale su tablet
Layout 4x4 grid: cifre 0-9, punto ., backspace , clear C, +/- , conferma
Font display JetBrains Mono, dimensione grande (24px+), ben leggibile
Feedback colore Bordo campo cambia in tempo reale: verde/giallo/rosso
Barra feedback Progress bar colorata sotto il display con stato PASS/WARNING/FAIL
Validazione Impedisce doppio punto, max 6 decimali, range ragionevole
Auto-focus Numpad si attiva sul subtask corrente automaticamente
Tasto Enter HW Tasto Enter da tastiera fisica = bottone conferma ✓
USB override Dato da calibro USB popola il campo e mostra feedback automaticamente
Navigazione Dopo conferma, avanza automaticamente al subtask successivo
Vibrazione navigator.vibrate(50) su pressione tasto (se supportato)

14. Internazionalizzazione e Temi

i18n: Italiano / Inglese

Approccio ibrido:

Layer Tecnologia Stringhe
Server (Jinja2) Flask-Babel Template HTML, messaggi errore, label form
Client (Alpine.js) alpinejs-i18n Stringhe dinamiche, numpad, feedback real-time
Report PDF Flask-Babel Contenuto report generato server-side

Workflow traduzione:

  1. Sviluppatore marca stringhe: {{ _('Dashboard') }} o {% trans %}Misure{% endtrans %}
  2. pybabel extract → genera messages.pot
  3. pybabel update → aggiorna it/messages.po e en/messages.po
  4. Traduttore compila → pybabel compile → file .mo

Preferenza utente: salvata in users.language_pref, applicata su ogni request.

Tema Dark / Light

Implementazione CSS Variables:

/* themes.css */
:root {
  /* Brand colors (sempre uguali) */
  --color-primary: #2563EB;
  --color-secondary: #64748B;
  --color-accent: #1E40AF;
  --color-pass: #059669;
  --color-warning: #D97706;
  --color-fail: #DC2626;

  /* Light theme (default) */
  --bg-primary: #F8FAFC;
  --bg-secondary: #F1F5F9;
  --bg-card: #FFFFFF;
  --text-primary: #0F172A;
  --text-secondary: #475569;
  --border-color: #E2E8F0;
}

.dark {
  /* Dark theme */
  --bg-primary: #0F172A;
  --bg-secondary: #1E293B;
  --bg-card: #334155;
  --text-primary: #F1F5F9;
  --text-secondary: #94A3B8;
  --border-color: #475569;
}

Preferenza utente: salvata in users.theme_pref + localStorage per applicazione immediata.


15. Sicurezza e Rete

Autenticazione API Key

Aspetto Dettaglio
Header X-API-Key: <chiave> su ogni request
Generazione 64 caratteri random (secrets.token_urlsafe)
Storage Hash nel DB, chiave in chiaro solo al momento della generazione
Rotazione Admin puo rigenerare API key per utente
Rate limiting Opzionale (future): limitare request per API key

HTTPS su ZeroTier

Ambiente Certificato Note
Sviluppo Self-signed Generato con openssl, accettare nel browser
Produzione Let's Encrypt + Caddy Caddy reverse proxy con auto-HTTPS

Best Practice Sicurezza

  • Password hashate con bcrypt (cost factor 12)
  • SQL injection: prevenuta da SQLAlchemy ORM (query parametrizzate)
  • XSS: Jinja2 auto-escaping attivo, CSP headers
  • Upload: validazione tipo file, dimensione max, sanitizzazione nome
  • CORS: configurato solo per dominio client Flask
  • API Key: mai loggata in chiaro, trasmessa solo via HTTPS
  • Session Flask: cookie HttpOnly, Secure, SameSite

16. Evoluzioni Future

v2.0 - Misura Digitale via Camera

Tablet camera → Frame capture → OpenCV/MediaPipe
→ Edge detection → Calibrazione (riferimento noto)
→ Misura calcolata → Validazione operatore (accetta/rifiuta/ripeti)
  • Tecnologie: OpenCV.js (browser) o Python+OpenCV (server)
  • Prerequisito gia previsto: campo input_method estendibile (aggiungere 'camera')
  • API modulare: aggiungere endpoint senza modifiche strutturali

v2.1 - Rete Neurale Analisi Buono/Scarto

Immagine pezzo → CNN classificazione (buono/scarto/dubbio)
→ Confidence score:
  > 95% → Auto-classificazione
  70-95% → Review operatore
  < 70% → Classificazione manuale
  • Tecnologie: PyTorch/TensorFlow (training), ONNX Runtime (inferenza server), TensorFlow.js (inferenza tablet)
  • Training: dataset da misure storiche, transfer learning (ResNet/EfficientNet)
  • Prerequisito gia previsto: sistema immagini, misure storiche nel DB
  • Nuovo: tabella ai_predictions per audit trail predizioni ML

v2.2 - Altre Evoluzioni

Feature Descrizione
Offline mode (PWA) Service worker, IndexedDB locale, sync alla riconnessione
Dashboard real-time WebSocket per aggiornamento live grafici SPC
Notifiche Alert email/push quando Cpk scende sotto soglia configurabile
Integrazione ERP API per scambio dati con SAP, Oracle, etc.
Multi-stabilimento Supporto multi-sede con dati centralizzati
Calibrazione strumenti Gestione scadenze calibrazione calibri, alert scadenza
Export AQDEF Formato standard automotive per scambio dati qualita

17. Decisioni Architetturali

# Decisione Motivazione
D1 Monorepo server + client Deploy semplificato, versioning unificato
D2 FastAPI async + asyncmy Performance per tablet multipli simultanei
D3 Versioning immutabile ricette (copy-on-write) Integrita dati storici, compliance QMS/ISO
D4 TailwindCSS + CSS Variables Personalizzazione tema dark/light, look moderno professionale
D5 Plotly.js (browser) + Kaleido + WeasyPrint (PDF) Grafici interattivi + report PDF professionali vettoriali
D6 Fabric.js per editor annotazioni Editor completo drag-and-drop, export JSON, MIT license
D7 Web Serial API + fallback input manuale Supporto calibri USB con fallback universale
D8 API Key authentication Semplice, adeguata per rete ZeroTier privata
D9 Ruoli combinabili JSON + flag admin separato Flessibilita massima senza tabelle join complesse
D10 File organizzati per recipe_id/version_id Isolamento versioni, backup granulare, pulizia facile
D11 Numpad touch custom (56x56px) UX ottimale su tablet, nessuna dipendenza tastiera fisica
D12 Branding configurabile (logo + nome da DB) Riusabilita del sistema per clienti/installazioni diverse
D13 i18n ibrido Flask-Babel + alpinejs-i18n Copertura completa IT/EN: server-side + client-side
D14 Font Inter + JetBrains Mono UI professionale + numeri allineati e leggibili
D15 Nome "TieMeasureFlow" by Tielogic Brand diretto: collega (Tie) misure (Measure) in un flusso (Flow)

Prossimo passo: Approvazione piano → Inizio implementazione FASE 0