- Nuovo servizio ai_service.py: estrae testo da PDF (pdfplumber) + analisi AI (OpenRouter)
- Endpoint POST /api/recipes/{id}/parse-technical-sheet con validazione file
- UI: bottone "Importa da PDF" nel task editor con modale upload + preview editabile
- Task suggeriti modificabili/rimovibili prima della creazione bulk
- Config: OPENROUTER_API_KEY e OPENROUTER_MODEL in .env
- Dipendenze: pdfplumber + httpx aggiunti a server deps
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Recipe: nuovo campo measurement_interval_minutes (migration 003) con UI nel recipe editor
- Auto-logout: impostazione di sistema configurabile da admin/settings, timer inattività JS
con warning modale 60s prima del logout, tracking eventi utente throttled
- Navbar: aggiunto link "Impostazioni" per admin (desktop + mobile)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- setup: corregge path templates (sibling di api/, non figlio) e firma TemplateResponse
- setup: invalida sessione client dopo operazioni che ruotano l'API key (init DB, creazione admin, cambio password, attivazione utente)
- api_client: include il nome del campo nei messaggi di errore 422 (FastAPI validation)
- ui: nuovo componente _app_logo.html (SVG inline theme-aware) usato su login e navbar
- /measure/select: aggiunta miniatura 64×64 accanto al nome ricetta
(object-contain per mantenere l'immagine intera, non croppata).
Lo schema backend RecipeSummary esponeva solo id/code/name/active:
aggiunti image_path e description così la card può rendere thumb
e sottotitolo.
- /maker/recipes: la miniatura passa da object-cover (crop) a
object-contain (fit), per visualizzare l'intera immagine della
ricetta senza tagli.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- test_recipes: split update test into in-place vs copy-on-write paths
(PUT now updates in-place when current version has no measurements).
Added _seed_measurement() helper to force copy-on-write where needed.
- test_tasks::reorder: expunge_all() between POST and GET so the shared
test session re-fetches RecipeVersion.tasks instead of returning the
cached collection. Prod uses one session per request, so identity-map
staleness only affects tests.
- test_measure::save_measurement_proxy: payload aligned to current API
(version_id is required; pass_fail/deviation are computed server-side).
All 179 tests green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GET /api/measurements required Metrologist, but the operator workflow
calls it from task_complete.html to render the post-recipe riepilogo —
silently empty for every non-Metrologist user. Open to any authenticated
user; payload carries no PII beyond numeric values + recipe ref.
Regression test added.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both came from the src/ restructure and only show up at runtime, so
the test suite had not caught them.
- src/backend/config.py: env_file was "../../.env", which pydantic-
settings resolves against the *cwd*, not the file. Running uvicorn
or alembic from the project root therefore looked for
../../.env one level above the repo and silently fell back to the
default DB_PASSWORD ("change_me_in_production"), hiding the real
password. Now resolved as Path(__file__).resolve().parents[2] /
".env" so the lookup is always against the project root regardless
of cwd.
- src/backend/models/orm/__init__.py: Station and
StationRecipeAssignment were never imported here, so anything that
triggers Base.metadata.create_all without first importing the
setup router (which has its own Station import) ended up with no
stations / station_recipe_assignments tables. Verified locally:
/api/setup/seed used to fail with "Table tiemeasureflow.stations
doesn't exist" before this fix.
- .gitignore: ignore src/frontend/flask_app/package.json and
package-lock.json (local npm-install artifacts; the Dockerfile
installs tailwindcss directly).
Smoke verified end-to-end: uvicorn + gunicorn + MySQL, login + admin
stations + select_recipe + admin users all 200 OK.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cleanup
- Remove src/backend/Dockerfile.legacy and
src/frontend/flask_app/Dockerfile.legacy (history is in git, build
uses the new uv-based root Dockerfile / Dockerfile.frontend).
- Remove src/frontend/flask_app/verify_i18n.py (had hardcoded paths
pointing at the old client/ tree).
Group docs/
- New docs/README.md indexes everything in one place.
- New docs/architecture/STATO_PROGETTO.md: snapshot of what works in
V2.0.0 (inherited V1.0.7 features, rev04 Phase 1 stations,
worker scaling, src/ restructure, test status, stack, decisions).
- New docs/architecture/ROADMAP.md: what's next — Phases 2-7 of the
rev04 migration with status, open client decisions (D-0.1 through
D-0.10), tech debt and time estimates for M1 / M2.
- Move PIANO_IMPLEMENTAZIONE.md (90KB V1.0.0 plan) to
docs/archive/2026-02-06-piano-implementazione-v1.md (historical).
- Move Schema sviluppo SW TieFlow_rev04-2026.docx to docs/specs/
with ISO date filename so the customer spec is now tracked.
- Move src/frontend/flask_app/I18N_SETUP.md to docs/I18N_SETUP.md
and rewrite paths to the new src/frontend/flask_app/ tree.
.dockerignore: simplified now that legacy Dockerfiles are gone;
docs/ stays excluded from the build context.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Aligns the repo with the python-project-spec-design.md template chosen
for V2.0.0. Big move, no logic changes. The 3 pre-existing test
failures (test_recipes::test_update_recipe, test_recipes::
test_recipe_versioning, test_tasks::test_reorder_tasks, plus the
client test_save_measurement_proxy) survive unchanged.
Layout changes
- server/ -> src/backend/
- server/middleware/ -> src/backend/api/middleware/
- server/routers/ -> src/backend/api/routers/
- server/models/ -> src/backend/models/orm/
- server/schemas/ -> src/backend/models/api/
- server/uploads/ -> uploads/ (project root, mounted volume)
- server/tests/ -> src/backend/tests/
- client/ -> src/frontend/flask_app/ (Flask kept; React
deroga is documented in CLAUDE.md, justified by tablet UX, USB
caliper/barcode workflow and Fabric.js integration)
Tooling
- pyproject.toml: monorepo with [project] core deps and
optional-dependencies server / client / dev. Replaces both
server/requirements.txt and client/requirements.txt.
- uv.lock + .python-version (3.11) committed for reproducible builds.
- Dockerfile (root, backend) and Dockerfile.frontend rewritten to use
uv sync --frozen --no-dev --extra server|client; legacy Dockerfiles
preserved as Dockerfile.legacy for reference but excluded from build
context via .dockerignore.
- docker-compose.dev.yml + docker-compose.yml: build context now ".",
dockerfile pointing to the root files.
Code adjustments forced by the move
- Every "from config|database|models|schemas|services|routers|middleware
import ..." rewritten to its src.backend.* equivalent (50+ files
including indented inline imports inside test bodies).
- src/backend/migrations/env.py: insert project root into sys.path so
alembic can resolve src.backend.* imports regardless of cwd.
- src/backend/config.py: env_file ../../.env (was ../.env), upload_path
resolves project root via parents[2].
- src/backend/tests/conftest.py + tests: import ... from src.backend.*
instead of bare names; old per-directory pytest.ini files removed in
favor of root pyproject.toml [tool.pytest.ini_options].
- .gitignore: uploads/ at root, src/frontend/flask_app/static/css/
tailwind.css path; .dockerignore tightened.
- CLAUDE.md: rewrote sections "Layout del repository", "Comandi di
Sviluppo", "Database & Migrations", "Test", "i18n", and all path
references throughout the architecture sections.
Verified
- uv lock resolves 77 packages; uv sync --extra server --extra client
--extra dev installs cleanly.
- uv run pytest: 171 passed, 4 pre-existing failures.
- uv run alembic -c src/backend/migrations/alembic.ini check loads
config and metadata (errors only on the absent local MySQL).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>