Salta ai contenuti

Changelog

Changelog

Highlight curati degli ultimi rilasci. Per le versioni complete delle API e la policy sui breaking change, consulta la Versione delle API e policy LTS.

Modifiche dettagliate ai singoli endpoint: Specifica OpenAPI e Riferimento API interattivo.


2026-08 · Cursore keyset ora su tutti gli endpoint di elenco

  • Fix: La correzione del cursore per GET /v1/codes e GET /v1/dpp (vedi sotto) è ora estesa a tutti gli altri elenchi paginati tramite cursore: GET /v1/qr-codes/:id/comments, /v1/workspaces, /v1/gs1/identifiers, /v1/members, /v1/audit-logs, /v1/admin/orgs, /v1/admin/users e /v1/webhooks/:id/deliveries. Tutti eseguivano la paginazione unicamente tramite created_at; le righe con timestamp identici (voci di audit di un’operazione batch, tentativi di webhook, importazioni di membri) potevano andare perse nella pagina successiva. La chiave di ordinamento è ora ovunque la tupla (created_at, id).
  • Modifica API: Su questi elenchi, meta.pagination.next_cursor è da ora in poi anch’esso un valore opaco (base64url) invece di un semplice timestamp; i cursori non leggibili restituiscono 400, mentre i vecchi cursori basati su timestamp continueranno a essere accettati temporaneamente. Eccezione GET /v1/webhooks/:id/deliveries: lì next_cursor rimane l’ID dell’ultima consegna (ID sconosciuto → prima pagina). I client che restituiscono next_cursor invariato — Dashboard, CLI, SDK, MCP — non devono apportare alcuna modifica.
  • Impatto: Nessuna migrazione richiesta. Se hai notato la mancanza di voci durante la navigazione in uno di questi elenchi (ad es. il registro di audit o il registro delle consegne nella dashboard): non sono mai andate perdute — gli elenchi ora le mostrano completamente.

2026-08 · Timestamp di nuovo conformi a OpenAPI dopo la modifica e l’eliminazione

  • Fix: Dopo PATCH /v1/codes/{id}, updated_at veniva restituito nel formato SQLite senza fuso orario (2026-08-17 09:00:00), sebbene la specifica OpenAPI preveda format: date-time e la creazione (POST) fornisca il timestamp ISO (2026-08-17T09:00:00.000Z). Lo stesso valeva per deleted_at/updated_at durante il soft-delete, nonché per i percorsi di modifica/eliminazione di chiavi API, organizzazioni, workspace, membri, commenti e webhook, e inoltre per last_used_at delle chiavi API e last_triggered_at dei webhook. Tutti i percorsi di scrittura ora registrano in formato ISO 8601 (UTC, T e Z).
  • Impatto: I client che analizzano updated_at con new Date(...) (SDK, CLI, Dashboard) leggevano il formato con lo spazio come ora locale — la CLI mostrava l’ora sfalsata dell’offset locale per i codici modificati una volta (Vienna: −2 h). Questo problema è stato risolto. Inoltre, una migrazione dei dati normalizza i valori già memorizzati nel vecchio formato in ISO, in modo che l’ordinamento e i confronti nei set di dati misti siano corretti. Nessuna modifica ai nomi dei campi o alla struttura della risposta.
  • Contesto: Stessa classe di errore delle due correzioni riportate di seguito (scadenza delle chiavi API, cutoff del re-scan): la funzione datetime('now') di SQLite scrive YYYY-MM-DD HH:MM:SS, mentre tutti gli altri percorsi di scrittura usano ISO 8601. Un test di controllo del codice sorgente preverrà futuri casi simili.

2026-08 · La paginazione dell’elenco non perde più i codici batch

  • Fix: GET /v1/codes e GET /v1/dpp paginavano esclusivamente tramite created_at. Tuttavia, i codici provenienti da POST /v1/codes/batch, POST /v1/dpp/batch e dall’importazione CSV/XLSX condividono un unico timestamp — non appena un batch era più grande di limit (default 20), la seconda pagina non restituiva più le righe rimanenti dello stesso timestamp. I codici esistevano ed erano accessibili tramite GET /v1/codes/:id, ma non comparivano mai nell’elenco (Dashboard, CLI qr3 list, SDK, MCP). Il cursore è ora un keyset su (created_at, id).
  • Modifica API: meta.pagination.next_cursor è da ora un valore opaco (base64url) invece di un semplice timestamp. Chi restituisce il cursore invariato come ?cursor= — come fanno la Dashboard, la CLI, tutti gli SDK e il server MCP — non deve modificare nulla. I vecchi cursori timestamp continueranno a essere accettati durante un periodo di transizione; i cursori non leggibili restituiscono ora 400 invece di mostrare silenziosamente la prima pagina.
  • Impatto: Per chi ha visualizzato meno codici nell’elenco rispetto a quelli creati dopo un’importazione batch: i codici non sono mai andati perduti — l’elenco ora li mostra completamente. Nessuna migrazione necessaria.

2026-08 · I re-scan di sicurezza tornano a essere eseguiti ogni 24 ore

  • Fix: La nuova scansione periodica degli URL di destinazione e dei link delle landing page (Google Web Risk) saltava i codici il cui ultimo scan risaliva allo stesso giorno di calendario del cutoff di 24 ore — a seconda dell’ora, il re-scan veniva ritardato fino a un giorno in più. Il cutoff viene ora calcolato nello stesso formato ISO in cui sono memorizzati i timestamp di scansione.
  • Impatto: Un URL di destinazione classificato come non sicuro dopo l’ultima scansione comporta di nuovo la messa in pausa automatica del codice entro la finestra documentata di 24 ore. Nessuna modifica all’API o al formato di risposta.

2026-08 · Le chiavi API scadono al momento esatto della scadenza

  • Fix: Una chiave API il cui expires_at cadeva nello stesso giorno continuava a essere accettata fino a mezzanotte UTC. La scadenza viene ora confrontata come timestamp anziché come stringa — una chiave scaduta restituisce immediatamente 401.
  • Contesto: expires_at viene memorizzato come timestamp ISO (2026-08-14T09:00:00Z), mentre il lato di confronto forniva il formato con lo spazio (2026-08-14 09:00:00). Il confronto grezzo tra stringhe era quindi corretto solo finché la data stessa differiva.
  • Impatto: Nessuna migrazione richiesta, il formato di risposta di GET /v1/api-keys rimane invariato. I valori di scadenza non leggibili sono ora considerati scaduti anziché validi.

2026-08 · Riferimento API: Gestione tenant documentata

  • OpenAPI: La specifica — e quindi il riferimento interattivo — ora documenta le organizzazioni (incluso GET /v1/organizations/usage), i workspace, i membri e ruoli e gli audit log.
  • Billing: La panoramica dei piani (GET /v1/billing/plans) è pubblica; il checkout (POST /v1/billing/checkout) e il portale clienti Stripe (GET /v1/billing/portal) sono indicati come endpoint per gli amministratori dell’organizzazione.
  • Esportazione scansioni: Le statistiche di scansione (GET /v1/codes/{id}/scans) e l’esportazione dei dati grezzi (…/scans.csv, …/scans.xlsx) sono completamente documentate — inclusa l’informativa GDPR: l’ip_hash non è mai incluso nell’esportazione.
  • Comportamento in caso di errore: È stata documentata anche la risposta 400 della validazione della richiesta: il corpo è l’errore Zod grezzo, non un documento di errore RFC-7807 — tuttavia, viene restituito con il Content-Type application/problem+json.
  • Dashboard: i file pubblici nella pagina di dettaglio del codice hanno ora un pulsante che ne copia il link pubblico negli appunti — utilizzabile direttamente come URL di destinazione di un codice QR quando una scansione deve aprire subito un documento specifico anziché la landing page con l’elenco dei file.
  • API: gli endpoint dei file (/v1/files) restituiscono anche public_url. Il campo è valorizzato solo per i file con visibility: public — i file privati non ricevono un indirizzo pubblico.
  • Comportamento: il link non richiede alcuna autenticazione e apre il file direttamente nel browser. La funzione Sostituisci lo lascia invariato, quindi un codice stampato con quel link resta valido. Dettagli: File e schede tecniche.

2026-07 · Ruoli del team: Collaboratore senza eliminazione e fatturazione per Amministratori

  • Novità: ruolo membro Collaboratore (senza eliminazione) — crea e modifica codici QR, file e Digital Product Passports, ma non può eliminare nulla né creare chiavi API. Tutti gli endpoint distruttivi verificano il ruolo lato server (403).
  • Fatturazione: gli upgrade di piano e il portale clienti Stripe (POST /v1/billing/checkout, GET /v1/billing/portal) sono ora riservati agli Amministratori dell’organizzazione — tutti gli altri ruoli visualizzano una panoramica del piano in sola lettura.
  • Dashboard: le azioni non consentite dal proprio ruolo vengono nascoste: un Visualizzatore, ad esempio, non vede i pulsanti per creare, modificare o eliminare; elenchi, download e statistiche restano visibili. Dettagli: Team e ruoli.
  • Landing page: La landing page di un codice ospitata da qr3 può ora elencare link esterni self-hosted ({ label, url }) oltre o al posto dei file caricati, ad esempio per schede tecniche che risiedono sul tuo sito.
  • API: POST/PATCH /v1/codes accettano un array links (0–20 voci, http(s), ≤ 2048 caratteri). Ogni URL viene verificato con Google Web Risk; un URL non sicuro restituisce 422. Un array vuoto rimuove tutti i link.
  • Dashboard: Aggiungi, riordina e rimuovi i link nella pagina di dettaglio del codice.
  • Sicurezza: I link renderizzati restano protetti da XSS (con escape, solo http(s)) e la pagina mantiene la sua intestazione noindex.

2026-04 · Analytics della dashboard per codice QR

  • Dashboard: il pulsante Analytics nell’elenco dei codici QR ora apre la pagina delle statistiche del rispettivo codice QR all’indirizzo /dashboard/codes/{id}.
  • Routing: l’alias /dashboard/codes continua a reindirizzare a /dashboard, ma non intercetta più le rotte di dettaglio come /dashboard/codes/{id}.
  • API: la pagina di dettaglio carica il codice QR direttamente tramite GET /v1/codes/:id; in questo modo non dipende più dai limiti di paginazione dell’elenco.
  • Test: i test di regressione coprono il reindirizzamento dell’alias e il caricamento diretto del codice.

2026-04 · Dialogo di eliminazione della dashboard per i codici QR

  • Dashboard: l’icona del cestino nell’elenco dei codici QR ora apre un dialogo React dedicato invece di un popup nativo del browser.
  • Feedback: dopo l’eliminazione, viene visualizzata una notifica toast di successo o di errore.
  • Test: packages/dashboard/tests/dashboard.test.ts previene regressioni su confirm() nel flusso di eliminazione del codice QR.
  • Dashboard: gli shortcode nell’elenco dei codici QR sono ora cliccabili direttamente come link di reindirizzamento esterni. L’icona del link esterno accanto, ad esempio, a wu3qaa apre https://qr3.app/{shortCode} in una nuova scheda.
  • i18n: aggiunti i testi dei tooltip per tedesco e inglese.
  • Test: packages/dashboard/tests/dashboard.test.ts protegge l’href del link, il comportamento della nuova scheda, noopener noreferrer e l’icona da regressioni.

2026-04 · Rotta del Redirect Worker per i codici QR dinamici

  • Fix: i codici QR dinamici all’indirizzo https://qr3.app/{shortCode} vengono nuovamente elaborati dal Redirect Worker. La rotta di produzione ora utilizza qr3.app/* perché le rotte dei Cloudflare Workers non supportano i parametri di percorso :code.
  • Consolidamento: i percorsi non corrispondenti vengono passati all’origine della landing page, in modo che le pagine normali come /de/pricing non vengano bloccate dal Redirect Worker.
  • Test: packages/redirect/tests/unit/redirect.test.ts verifica la rotta wildcard, l’elaborazione dello shortcode e il pass-through dell’origine.

2026-04 · Panoramica delle scansioni DPP del workspace (Q3.4.2)

  • Nuovo: GET /v1/workspace/stats/dpp?days=30 — aggrega tutte le dpp_scans del workspace dell’API key (active_dpps, scans_by_day, top_dpps con nome prodotto/categoria).
  • Dashboard: scheda nella pagina iniziale (/dashboard) con grafico a barre a 30 giorni + elenchi dei migliori — in parallelo alle schede dei codici QR.
  • Pubblico: shortlink di marketing GET /dpp/dpp_<id> (un segmento) per demo live, in parallelo a /dpp/{gtin}/{serial}.

2026-04 · Analytics delle scansioni DPP (Q3.4.1)

  • Nuovo: GET /v1/dpp/:id/stats?days=30 — scansioni aggregate del resolver GS1 pubblico per DPP. Campi: total_scans, period_scans, scans_by_day, top_countries, top_devices, top_representations.
  • Nuovo: tabella dpp_scans (migrazione 0011) — separata da scans (Redirect Worker). Gli indirizzi IP vengono crittografati con un salt a rotazione giornaliera, gli IP grezzi non raggiungono mai D1.
  • Dashboard: mini-scheda con grafico (SVG, nessuna libreria di grafici) su /dashboard/dpp/:dppId con barre a 30 giorni + suddivisione dei primi 3. Stato vuoto (empty state) non appena un DPP è attivo ma non ha ancora registrato scansioni.

2026-04 · Simulatore di conformità UE live (Q3.3.7)

  • Nuovo: POST /v1/dpp/:id/validate-update — simula aggiornamenti parziali stateless (stato, elenco mercati, …) senza persistenza. La risposta contiene eu_compliance + preview.changed_fields.
  • Dashboard: scheda del simulatore nel dettaglio del DPP (/dashboard/dpp/:dppId) — chip per DE/AT/FR/IT/ES/NL + personalizzati, menu a discesa dello stato, Preview EU impact / Save changes / Reset. Non bloccante tramite Remix useFetcher.
  • Consolidamento: helper del simulatore esternalizzati (readUpdatePatchFromForm, marketCountriesKey) + 18 nuovi unit test; correzione di bug: l’input non ISO singolo non cancella più l’elenco dei mercati.

2026-04 · Anteprima di conformità UE live nel modulo di creazione (Q3.3.6)

  • Modificato: POST /v1/dpp/validate fornisce in aggiunta eu_compliance — lo stesso validatore di GET /v1/dpp/:id/eu-compliance, stateless prima del salvataggio.
  • Dashboard: anteprima sotto il pannello di validazione esistente + nuovo banner di protezione salvataggio prima dei pulsanti di invio se ci sono errori/avvisi aperti (pluralizzazione i18n DE/EN).

2026-04 · Validatore UE + UI tessile (Q3.3.4 + Q3.3.5)

  • Nuovo: validatore di conformità UE con 5 regole per il settore tessile (TEXTILE_AGEC_REQUIRED, TEXTILE_MICROPLASTICS_CONSISTENCY, TEXTILE_SVHC_THRESHOLD, TEXTILE_GREENWASHING, TEXTILE_ESPR_READY).
  • Nuovo: GET /v1/dpp/:id/eu-compliance con compliant / espr_ready / issues[] / summary.
  • Dashboard: sezione di conformità UE nel dettaglio del DPP (schede di riepilogo, schede dei problemi raggruppate, badge ESPR-Ready nell’intestazione).

2026-04 · Schema DPP tessile (Q3.3.1–Q3.3.3)

  • Nuovo: categoria textile con catena di obblighi AGEC (tessitura/maglieria → tintura/stampa → confezionamento), per fibra origin_country + recycled_pct, svhc_substances[], opt-in ESPR (PEF, durata di vita, Recyclability).
  • Nuovo: campo di base market_countries: string[] (ISO 3166-1 alpha-2) su tutte le categorie DPP — controlla le regole AGEC specifiche per la Francia e la nota informativa obbligatoria per i consumatori francesi.
  • Nuovo: template HTML per i consumatori con box di avviso microplastiche AGEC, catena di origine a 3 fasi (pillole con bandiere), elenco SVHC, sezione Durability e Recyclability.
  • Migrazione: 0010_dpp_market_countries (D1).

2026-04 · Importazione in blocco DPP (Q3.2.1–Q3.2.5)

  • Nuovo: POST /v1/dpp/import accetta CSV e XLSX (compatibile con i Worker tramite SheetJS xlsx, bundle gzip di circa 283 KB).
  • Scalato: limite basato sul piano (Free 100 → Enterprise 10k) + db.batch() suddiviso in blocchi (chunked) da 100 + limite del corpo di 5 MB.
  • Nuovo: report degli errori in formato CSV nel campo errors_csv della risposta 201; GET /v1/dpp/import/templates/:category?format=csv|xlsx fornisce modelli pronti per batterie e prodotti tessili.
  • Dashboard: caricamento drag-and-drop all’indirizzo /dashboard/dpp/import con proxy del modello e download CSV in linea.

Estensioni LTS non-breaking

Tutte le modifiche sopra menzionate sono additive:

  • I client POST /v1/dpp/validate esistenti ignorano il nuovo campo eu_compliance senza modifiche.
  • I flussi battery esistenti rimangono invariati.
  • market_countries è opzionale e ha come valore predefinito [].

Vedi Versione delle API per la policy sui breaking change.