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-10 · Colori nel Dashboard

  • Novità: la pagina dei dettagli di un codice ha la scheda Colori: primo piano e sfondo come valore esadecimale, sfondo trasparente, anteprima tramite la vera route dell’immagine. La verifica è quella di PATCH /v1/codes/{id}: le coppie critiche richiedono una conferma, quelle sotto 1,5:1 non si possono salvare.
  • Il ripristino a nero su bianco restituisce in tutti e quattro i formati gli stessi byte di un codice senza colori. I codici senza colori non cambiano.
  • I codici trasparenti compaiono su una scacchiera in tutte le anteprime del Dashboard. Dettagli: Colori nel Dashboard.

2026-10 · Colori in PDF ed EPS

  • Nuovo: qr.pdf e qr.eps disegnano fg e bg, come parametri e come colori salvati. Il nero e qualsiasi grigio vengono scritti come scala di grigi (solo lastra del nero), qualsiasi altro colore come CMYK in percentuali intere, ad esempio 1F4E79 come C74 M36 Y0 K53.
  • Sfondo come per l’SVG: Non appena viene scelto un colore, un’area coprente si trova dietro il codice e la sua zona di silenzio, bianca o bg. bg=transparent non ne disegna alcuna. Il titolo rimane nero, la piastra del logo bianca.
  • Nessuna modifica senza colori: Senza fg/bg e senza colori salvati, entrambi i formati forniscono gli stessi byte di prima. Il PDF di un passaporto del prodotto rimane non colorato.
  • Limiti: nessun profilo ICC, nessun PDF/X. Dettagli: Colori nella stampa.

2026-09 · Codici statici senza cache di reindirizzamento, eliminazione simultanea

  • Modificato: I codici statici non sono più memorizzati nella cache di reindirizzamento. Una chiamata al loro link breve (redirect_url) legge sempre lo stato corrente. Di conseguenza, dopo DELETE /v1/account, un codice statico non reindirizza più alla chiamata successiva, mentre in precedenza poteva continuare a farlo fino a 24 ore. Anche un cambio di piano ha effetto immediato sui codici statici. L’eliminazione dell’account rimuove i codici dinamici come in precedenza. I codici statici stampati contengono direttamente la loro destinazione e non sono interessati.
  • Risolto: Due richieste DELETE /v1/codes/:id simultanee sullo stesso codice restituiscono una volta 200 e una volta 404. Il webhook qr.deleted viene inviato esattamente una volta, mentre prima veniva inviato due volte.
  • Nuovo: Le richieste POST e DELETE /v1/codes/:id/logo rispondono con 409 (errors/conflict) se un’altra richiesta ha modificato contemporaneamente il logo dello stesso codice, e in tal caso non apportano modifiche. In precedenza, un logo caricato poteva rimanere memorizzato senza essere utilizzato. Due richieste DELETE /v1/codes/:id/logo simultanee restituiscono entrambe 200. Dettagli: Logo.

2026-09 · TypeScript-SDK 1.2.0

  • Novità in @qr3/sdk 1.2.0: client.codes.update() accetta appearance e restituisce i risultati del controllo del contrasto come issues nel risultato; in assenza di problemi, il campo è assente. client.codes.imageUrl() accetta fg, bg e ecc. Ogni codice restituito dall’API (get, list, create, update, batchCreate) contiene title e appearance.
  • Aggiornamento: npm install @qr3/sdk@latest. Seguiranno Python, Go e PHP. Dettagli: SDK e CLI e Salvare i colori nel codice.

2026-09 · Il tempo di scadenza modificato si applica entro circa un minuto

  • Risolto: Una richiesta PATCH su expires_at ora svuota la cache di reindirizzamento del codice. La nuova data di scadenza diventa quindi effettiva entro circa un minuto, anziché fino a 24 ore dopo. In precedenza, una scadenza rimossa o posticipata continuava a restituire 410 fino a 24 ore, e una scadenza impostata sul momento presente consentiva al reindirizzamento di continuare a funzionare fino a 24 ore.
  • Risolto: Un codice creato con expires_at scade puntualmente anche se la scadenza rientra nelle prime 24 ore.
  • Risolto: Se un codice viene eliminato mentre il suo logo viene caricato o rimosso, le richieste POST e DELETE /v1/codes/:id/logo rispondono con 404 e non modificano il codice eliminato, proprio come già avviene per PATCH.
  • Risolto: Anche un codice statico il cui link breve (redirect_url) è stato visitato viene memorizzato nella cache di reindirizzamento. La modifica, la sospensione e l’eliminazione ora svuotano la cache anche per questo, non solo per i codici dinamici.

2026-09 · Salvare i colori nel codice

  • Nuovo: PATCH /v1/codes/:id accetta appearance con foreground_color e background_color (#RRGGBB, per lo sfondo anche transparent). qr.svg e qr.png disegnano i colori memorizzati senza parametri; un parametro come ?fg=000000 ha comunque la precedenza. PDF ed EPS disegneranno i colori solo con una versione successiva.
  • Verifica del contrasto: Una coppia inferiore a 1,5:1 restituisce 422. Le coppie con contrasto inferiore vengono salvate e segnalate in meta.issues come warning o critical; uno sfondo trasparente è sempre critical, mai bloccato.
  • Unione: I campi omessi mantengono il loro valore salvato, null effettua il ripristino. Le modifiche simultanee allo stesso codice non si sovrascrivono più a vicenda.
  • In ogni risposta del codice: appearance è presente in ogni risposta del codice e nei webhook qr.created e qr.updated. POST, il batch e l’importazione lo rifiutano con 422.
  • Nessuna modifica per i codici esistenti: Senza colori salvati, ogni codice restituisce gli stessi byte di prima. Dettagli: Salvare i colori nel codice.

2026-09 · Colori e correzione degli errori come parametri delle rotte delle immagini

  • Novità: Tutte e quattro le rotte delle immagini accettano fg (colore di primo piano), bg (colore di sfondo o transparent) e ecc (correzione degli errori L, M, Q, H). SVG e PNG disegnano i colori; PDF ed EPS li accettano, ma li disegneranno solo con una release successiva. ecc ha effetto in tutti e quattro i formati, un logo continua a forzare H.
  • Trasparente: bg=transparent restituisce un SVG senza sfondo e un PNG con un canale alfa reale. La superficie sottostante deve essere chiara e lasciare libera la zona di rispetto.
  • Mai un errore: I valori non validi vengono ignorati; l’immagine viene quindi fornita esattamente come senza parametri.
  • Caching: Qualsiasi parametro efficace restituisce Cache-Control: public, max-age=300 invece delle 24 ore dell’immagine standard.
  • Nessuna modifica del comportamento senza parametri: Qualsiasi codice esistente restituisce gli stessi byte di prima in tutti e quattro i formati.
  • Disponibile in qualsiasi piano. Dettagli: Colori e correzione degli errori.
  • Estensione: qr.pdf e qr.eps ora incorporano un logo impostato esattamente come qr.svg e qr.png (vedi sotto) — come immagine incorporata (PDF tramite un Image XObject, EPS tramite un dizionario di immagini in PostScript, lì solo con %%LanguageLevel: 3), centrato sulla stessa area, con lo stesso aumento della correzione d’errore a H. Finora entrambi i formati non includevano il logo; questo problema è stato ora risolto.
  • Caching: Con un logo impostato, anche qr.pdf e qr.eps ora restituiscono Cache-Control: public, max-age=300 invece delle solite 24 ore — esattamente come SVG/PNG.
  • Fallback: Se l’immagine del logo stessa non può essere elaborata (ad esempio, un oggetto memorizzato danneggiato), la correzione d’errore rimane H, ma l’area riservata rimane vuota invece di mostrare un’immagine — senza mai generare un errore del server.
  • Nessuna modifica del comportamento senza logo: I codici senza logo continuano a fornire qr.pdf/qr.eps in modo byte-identico, con la cache di 24 ore invariata.
  • Dettagli e istruzioni di stampa: Logo nel codice QR.

2026-09 · Logo nel codice QR — Dashboard e API

  • Novità: Un codice può ora contenere un logo al centro. Nel Dashboard, la pagina di dettaglio di un codice presenta una scheda dedicata al logo: Seleziona logo, alla prima aggiunta o alla rimozione conferma un avviso con una spunta obbligatoria (entrambe le azioni modificano il motivo dei punti), quindi Carica logo/Rimuovi logo. Una Sostituzione non richiede conferma — cambia solo l’immagine, non il motivo. Il ruolo viewer vede lo stato e l’anteprima, ma nessuna delle tre azioni.
  • API: POST /v1/codes/{id}/logo (campo multipart file; PNG, JPEG o WebP, massimo 1 MB, SVG viene rifiutato) crea o sostituisce un logo; DELETE /v1/codes/{id}/logo lo rimuove ed è idempotente. Un’immagine troppo grande restituisce 413, un formato non supportato 422, il ruolo viewer 403.
  • Rappresentazione: qr.svg e qr.png incorporano il logo come pixel effettivi (512 × 512, normalizzato) e aumentano per questo la correzione d’errore a H. L’aggiunta e la rimozione modificano quindi il motivo dei punti (M ↔ H), mentre la sostituzione no. qr.pdf e qr.eps non incorporano alcun logo e rimangono invariati. Un codice già stampato continua a funzionare in ogni caso, poiché la destinazione codificata non dipende dal logo — deve ristampare solo chi desidera vedere il (nuovo) aspetto del logo anche sul materiale fisico, evitando di mescolare vecchi e nuovi file di stampa.
  • Caching: Con il logo impostato, qr.svg e qr.png restituiscono Cache-Control: public, max-age=300 invece delle solite 24 ore. Dettagli, limiti e istruzioni di stampa: Logo nel codice QR.

2026-08 · operationId per tutte le 75 operazioni, e una guida su “quando usare” per gli agenti

  • Integrazione: Tutte le 75 operazioni della specifica OpenAPI ora includono una operationId — listCodes, createCode, getCodeStats, archiveWorkspace e così via. In precedenza, questo campo mancava del tutto, costringendo ogni generatore a derivare il nome del metodo dal metodo HTTP e dal percorso (postV1Codes). Tali nomi dipendono dal percorso e cambiano a ogni modifica del percorso stesso. Il formato del nome è lo stesso in tutti i 75 punti: list/get/create/update/replace/delete, altrimenti il verbo dell’azione di business (validateDpp, registerGs1Identifier, pingWebhook). Il verbo segue la logica di business, non il metodo HTTP — archiveWorkspace è un DELETE, importDpps un POST.
  • Impatto sui client autogenerati: Chi genera il proprio SDK dalla specifica otterrà metodi rinominati (postV1Codes → createCode) alla prossima esecuzione. Questo è lo scopo della modifica, ma trattandosi di una ridenominazione in codice esterno, viene qui espressamente menzionata. Percorsi, parametri, formati di risposta e codici di stato rimangono invariati; gli SDK ufficiali, la CLI e il server MCP non sono interessati.
  • Introduzione per gli agenti: https://qr3.app/llms.txt ha una sezione ## When to use qr3.app — sei compiti invece di sei funzioni, più la frase che spiega per cosa qr3.app non è lo strumento adatto. Il server MCP fornisce ora la stessa informazione durante l’handshake: initialize verso https://mcp.qr3.app/mcp risponde con un campo instructions (in precedenza: undici strumenti senza alcuna classificazione). È inoltre indicato quali chiamate richiedono una chiave API — initialize e tools/list no, ogni tools/call sì.
  • Correzioni in llms.txt: Quattro informazioni sono state verificate rispetto alla produzione e non erano corrette: (1) l’SDK Python qr3app non è pubblicato su PyPI — la riga pip install è stata rimossa senza sostituzione; (2) Accept: text/markdown si applica alla home page e al blog, non a ogni pagina renderizzata lato server; (3) l’indirizzo di contatto è [email protected], anche nel JSON-LD della home page; (4) /de/security/ è un reindirizzamento a un’ancora, non una pagina a sé stante. Nuovo link: docs.qr3.app/de/skills/.
  • Salvaguardia: Tre asserzioni in openapi-spec.test.ts — completezza, univocità, lowerCamelCase —, ciascuna verificata con una mutazione. Altri nove test consolidano le quattro informazioni corrette, affinché non si ripresentino.
  • Limitazione nota: Due delle 75 operazioni sono descritte nella specifica, ma rispondono con 404 (GET /v1/codes/{id}/stats e GET /v1/account). In questa fase hanno ricevuto un nome, che perderanno nuovamente non appena sarà deciso se verranno implementate o rimosse.

2026-08 · I downgrade e le disdette dei piani ora influiscono anche sui limiti

  • Fix: Il webhook di Stripe, in caso di cambio di piano e disdetta, scriveva solo il nome del piano e non le quattro colonne dei limiti dell’organizzazione (max_workspaces, max_members, max_dynamic_codes, max_scans_per_month). Poiché l’applicazione dei limiti prende il valore massimo tra il valore memorizzato e la baseline del piano, un’organizzazione che aveva effettuato un downgrade o una disdetta manteneva i suoi vecchi limiti più elevati — rendendo il downgrade inefficace. Ora il webhook imposta le colonne sulla baseline del nuovo piano a ogni effettivo cambio di piano, e sulla baseline del piano Free in caso di disdetta — esattamente come fa già la gestione amministratore.
  • Comportamento: Gli aggiornamenti di routine dell’abbonamento (rinnovo, metodo di pagamento, proration) continuano a non toccare i limiti; i limiti più elevati concessi individualmente rimangono invariati. Solo un effettivo cambio di piano li reimposta sulla baseline del nuovo piano.
  • Impatto: Nessuna modifica all’API o al formato di risposta. Le organizzazioni il cui downgrade è avvenuto prima di questo fix manterranno i vecchi valori fino al successivo cambio di piano o fino a quando il supporto non li adatterà.

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.