Files
dyncoll-dev/CLAUDE.md
Giuseppe Naponiello 36bcc9a842 first commit
2026-06-14 19:01:02 +02:00

8.5 KiB
Raw Permalink Blame History

CLAUDE.md — dyncoll.v2

Istruzioni per agenti AI (e umani) che lavorano su questo repository.

1. Cos'è

dyncoll.v2 è la riscrittura della piattaforma Dynamic Collections Plus: catalogo e curatela di collezioni digitali di reperti archeologici. Obiettivo trasversale della v2: esporre i dati secondo lo standard di harvesting KSamsök 2 Linked Art del Riksantikvarieämbetet (RAÄ) / SweDigArch, così da essere raccoglibili dall'aggregatore nazionale svedese.

  • v1 (legacy, in produzione): ../dyncoll.v1 — PHP MPA procedurale, MySQL.
  • Documentazione di mapping (sorgente di verità): ../workfile/K2_tech_doc260430/shm-2b/.
  • Contesto e decisioni storiche: file di memoria in ../ (memory/MEMORY.md e collegati).

2. Stack

Layer Tecnologia
Backend Laravel (PHP 8.3+/8.4), API-only
Auth Sanctum + Fortify (2FA TOTP via pragmarx/google2fa)
Code/cache Redis + Horizon
DB MySQL 8.4 (schema definito da migration Laravel)
OpenAPI scegliere UNO tra darkaonline/l5-swagger o dedoc/scramble (ora ci sono entrambi)
Linked Art ml/json-ld (serializzazione) + opis/json-schema (validazione contro gli schema RAÄ)
Frontend Vite + TypeScript, MPA con isole, Tailwind v4 + daisyUI, Leaflet
Docs MkDocs Material (documentation/)
Qualità SonarQube locale (http://sonar.local)

3. Architettura dati (decisione chiave)

  • v2 ha il proprio DB, schema da migration Laravel — NON si appoggia in read-only al DB di v1.
  • I dati arrivano da v1 tramite un comando ETL idempotente (php artisan v1:import), non via dump/restore manuale (gli schemi divergono volutamente).
  • Due connessioni in config/database.php: mysql (v2, scrivibile) e legacy (v1, sola lettura, variabili DB_LEGACY_*). Lo stesso ETL serve sia per i refresh di sviluppo sia per il cutover.
  • Progettare lo schema v2 già orientato al Linked Art: identificatori canonical/uuid stabili, vocabolari come tabelle con colonna URI, audit created/modified puliti.

4. Mapping Linked Art — vincoli da rispettare

Quando si genera JSON-LD (vedi mapping-protocol-key-facts in memoria):

  • Reperto → HumanMadeObject (E22). Documento annidato, non CRM piatto.
  • Ogni record porta RecordProvenance (license, dateCreated/Modified, ingestedAt+provider autogenerati).
  • Distinzione id (URI di retrieval dereferenziabile) vs canonical (id stabile kulturarvsdata.se/...).
  • Classi CRM astratte vietate come tipo concreto: E1,E2,E3,E14E19,E24,E28,E31,E32,E41,E63,E64,E70,E71,E72,E77,E83,E90,E92,E93,E96,E99.
  • Ogni record generato DEVE validare contro LinkedArtRecord-1.0.0.schema.json (test obbligatorio).
  • Endpoint Provider da implementare (path sotto /linkedart/v1): Tier 1 /batch (MUST), Tier 2 /changes + /objects/{id} (SHOULD), Tier 3 Search (MAY). Gli endpoint devono essere conformi a protokoll-openapi/raa-linkedart-service-1.0.0.yaml.

5. Regole di commit e qualità

Esiste un pre-commit hook (.git/hooks/pre-commit) che blocca il commit se:

  1. REUSE / licenze: ogni file deve avere copyright + licenza SPDX (header o REUSE.toml). Licenza codice prevista: EUPL-1.2; docs/dati: CC-BY-4.0.
  2. Test + coverage (PHP via PHPUnit, frontend via Vitest) sui file staged.
  3. SonarQube: quality gate (sonar.qualitygate.wait=true) deve passare. Token letto da $SONAR_TOKEN o da .git/sonar.token (mai in chiaro nel repo).

Conseguenze pratiche:

  • Aggiungere header SPDX a ogni nuovo file, altrimenti il commit fallisce.
  • Mantenere/aggiornare i test: nuovo codice senza test fa fallire la quality gate.
  • Backend e frontend devono essere up (docker compose up) perché l'hook gira i test nei container.

6. Segreti e ambiente

  • .env e .git/sonar.token non si versionano mai (vedi .gitignore).
  • Le variabili sono documentate in .env.example: aggiornarlo quando se ne aggiungono.
  • Nomi DB canonici (Laravel): DB_DATABASE, DB_USERNAME, DB_PASSWORD, DB_ROOT_PASSWORD. I compose devono mappare le MYSQL_* da questi (non introdurre DB_NAME/DB_USER paralleli).

6bis. Workflow host/container (IMPORTANTE — leggere prima di lanciare comandi)

Regola d'oro: chi scrive file lo fa come utente host (beppe, UID 1000); mai mischiare node_modules musl (container Alpine) e glibc (host). Usare i target del Makefile.

Operazione Dove Comando
Editare composer.json / package.json / codice HOST editor / tool agente (sempre beppe-owned)
Avviare lo stack di sviluppo (Vite HMR + backend + …) CONTAINER make up
composer install/update/require HOST make be-install / make be-update / make composer c="…"
Aggiornare deps frontend: edita package.json (host) → HOST + rebuild img make fe-install poi make fe-rebuild
artisan con servizi (migrate, db:*, queue, tinker, v1:import) CONTAINER come UID host make migrate / make import / make artisan c="…"
Permessi storage per php-fpm (www-data) HOST, una tantum make permissions

Motivi e asimmetria backend/frontend:

  • Backend: host PHP 8.4 == container; vendor/ è codice PHP portabile ed è bind-montato (./backend:/var/www/html), quindi composer gira sull'host e il container lo vede subito. config.platform in composer.json copre le estensioni mancanti sull'host (redis, gd, bcmath).
  • Frontend: il dev server di Vite gira nel container (make up, stage development). Il sorgente è bind-montato (./frontend:/app) → HMR; i node_modules non sono bind-montati ma vivono in un volume anonimo (/app/node_modules), così quelli musl dell'immagine schermano quelli glibc dell'host (mai mischiati). Si installano nella build dell'immagine, mai in un container in esecuzione. npm install su host serve solo a package-lock + type-check IDE; dopo modifiche a package.json rigenerare l'immagine con make fe-rebuild.
  • I comandi artisan con servizi girano nel container (dove db, redis, mailpit risolvono) ma con -u $(id -u):$(id -g) per non creare file root-owned.

Regole per l'agente AI:

  • Editare composer.json/package.json/codice coi propri tool (host, beppe-owned): OK.
  • NON lanciare composer install/update o npm install di propria iniziativa (l'ambiente host dell'utente è autoritativo). Se serve, usare i target make qui sopra.
  • Per artisan che tocca i servizi usare sempre make artisan c="…" (container come UID host).
  • Non bind-montare mai node_modules in un container Alpine.

Nota drift: l'IDE/type-check usa il Node dell'host (20.19/npm 9); il dev server di Vite usa il Node 24 dell'immagine. Conviene comunque allineare l'host a Node 22/24 LTS (Vite 8 richiede ≥ 20.19/22.12).

7. Comandi utili

Usare i target del Makefile (incapsulano la strategia host/container del §6bis):

make up                       # avvia l'intero stack dev (Vite HMR + backend + db + redis + docs + mailpit)
make migrate                  # artisan migrate (container come UID host)
make import                   # ETL da v1 (quando implementato)
make artisan c="test --coverage-clover=coverage.xml"   # test backend
make be-update                # composer update (host)
make fe-install               # npm install host (package-lock + type-check IDE)
make fe-rebuild               # ricostruisce l'immagine frontend dopo modifiche a package.json
make permissions              # fix permessi storage (una tantum, sudo)
make help                     # elenco completo

Frontend in dev: make up → Vite con HMR su https://dyncoll-dev.local (Traefik) o http://localhost:${APP_FRONTEND_DEVPORT}. Le modifiche al sorgente si ricaricano da sole; per nuove dipendenze npm: edita package.jsonmake fe-installmake fe-rebuild.

8. Convenzioni di codice

  • PHP: PSR-12, formattato con Laravel Pint (./vendor/bin/pint).
  • TypeScript: strict attivo (vedi frontend/tsconfig.json); evitare any.
  • Commenti in italiano ammessi (coerenti col resto del repo).
  • Non reintrodurre pattern v1 non sicuri: query parametrizzate sempre, mai interpolazione in SQL.

9. Stato dello scaffolding

Lo scaffolding iniziale è stato adattato da un altro progetto ("Valdarno Trails"/RMV) e contiene residui da ripulire (riferimenti RMV in frontend/vite.config.ts, frontend/frontend.Dockerfile, frontend/nginx.conf) e alcuni bug nei compose/Dockerfile. Verificare sempre lo stato reale dei file prima di darli per buoni; vedere le note di review.