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/codeseGET /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/userse/v1/webhooks/:id/deliveries. Tutti eseguivano la paginazione unicamente tramitecreated_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 restituiscono400, mentre i vecchi cursori basati su timestamp continueranno a essere accettati temporaneamente. EccezioneGET /v1/webhooks/:id/deliveries: lìnext_cursorrimane l’ID dell’ultima consegna (ID sconosciuto → prima pagina). I client che restituiscononext_cursorinvariato — 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_atveniva restituito nel formato SQLite senza fuso orario (2026-08-17 09:00:00), sebbene la specifica OpenAPI prevedaformat: date-timee la creazione (POST) fornisca il timestamp ISO (2026-08-17T09:00:00.000Z). Lo stesso valeva perdeleted_at/updated_atdurante il soft-delete, nonché per i percorsi di modifica/eliminazione di chiavi API, organizzazioni, workspace, membri, commenti e webhook, e inoltre perlast_used_atdelle chiavi API elast_triggered_atdei webhook. Tutti i percorsi di scrittura ora registrano in formato ISO 8601 (UTC,TeZ). - Impatto: I client che analizzano
updated_atconnew 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 scriveYYYY-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/codeseGET /v1/dpppaginavano esclusivamente tramitecreated_at. Tuttavia, i codici provenienti daPOST /v1/codes/batch,POST /v1/dpp/batche dall’importazione CSV/XLSX condividono un unico timestamp — non appena un batch era più grande dilimit(default 20), la seconda pagina non restituiva più le righe rimanenti dello stesso timestamp. I codici esistevano ed erano accessibili tramiteGET /v1/codes/:id, ma non comparivano mai nell’elenco (Dashboard, CLIqr3 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 ora400invece 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_atcadeva 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 immediatamente401. - Contesto:
expires_atviene 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-keysrimane 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_hashnon è mai incluso nell’esportazione. - Comportamento in caso di errore: È stata documentata anche la risposta
400della validazione della richiesta: il corpo è l’errore Zod grezzo, non un documento di errore RFC-7807 — tuttavia, viene restituito con il Content-Typeapplication/problem+json.
2026-08 · Copia dei link pubblici dei file
- 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 anchepublic_url. Il campo è valorizzato solo per i file convisibility: 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.
2026-06 · Link esterni sulla landing page del codice
- 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/codesaccettano un arraylinks(0–20 voci,http(s), ≤ 2048 caratteri). Ogni URL viene verificato con Google Web Risk; un URL non sicuro restituisce422. 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 intestazionenoindex.
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/codescontinua 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.tspreviene regressioni suconfirm()nel flusso di eliminazione del codice QR.
2026-04 · Test dei link brevi nella dashboard per i codici QR dinamici
- 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
wu3qaaaprehttps://qr3.app/{shortCode}in una nuova scheda. - i18n: aggiunti i testi dei tooltip per tedesco e inglese.
- Test:
packages/dashboard/tests/dashboard.test.tsprotegge l’href del link, il comportamento della nuova scheda,noopener noreferrere 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 utilizzaqr3.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/pricingnon vengano bloccate dal Redirect Worker. - Test:
packages/redirect/tests/unit/redirect.test.tsverifica 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 ledpp_scansdel workspace dell’API key (active_dpps,scans_by_day,top_dppscon 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(migrazione0011) — separata dascans(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/:dppIdcon 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 contieneeu_compliance+preview.changed_fields. - Dashboard: scheda del simulatore nel dettaglio del DPP (
/dashboard/dpp/:dppId) — chip perDE/AT/FR/IT/ES/NL+ personalizzati, menu a discesa dello stato, Preview EU impact / Save changes / Reset. Non bloccante tramite RemixuseFetcher. - 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/validatefornisce in aggiuntaeu_compliance— lo stesso validatore diGET /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-complianceconcompliant/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
textilecon catena di obblighi AGEC (tessitura/maglieria → tintura/stampa → confezionamento), per fibraorigin_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/importaccetta CSV e XLSX (compatibile con i Worker tramite SheetJSxlsx, 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_csvdella risposta 201;GET /v1/dpp/import/templates/:category?format=csv|xlsxfornisce modelli pronti per batterie e prodotti tessili. - Dashboard: caricamento drag-and-drop all’indirizzo
/dashboard/dpp/importcon proxy del modello e download CSV in linea.
Estensioni LTS non-breaking
Tutte le modifiche sopra menzionate sono additive:
- I client
POST /v1/dpp/validateesistenti ignorano il nuovo campoeu_compliancesenza modifiche. - I flussi
batteryesistenti rimangono invariati. market_countriesè opzionale e ha come valore predefinito[].
Vedi Versione delle API per la policy sui breaking change.