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 · Eliminazione dell’account solo con permessi di eliminazione

  • Modificato: DELETE /v1/account risponde con 403 ai ruoli viewer e contributor e alle Publishable Key (qr3_pk_) e non elimina nulla. Prima, qualsiasi chiave valida poteva svuotare il workspace. POST /v1/account/privacy/consents richiede i permessi di scrittura. Le Secret Key con lo scope predefinito non sono interessate. Dettagli: GDPR e privacy.
  • Modificato: L’eliminazione archivia i QR Code, elimina definitivamente le scansioni dei QR Code e le richieste DPP e revoca le chiavi API, ma non più le chiavi gestite dal sistema con cui accede la dashboard. Finora revocava anche quelle, quindi dopo un’eliminazione da parte di un membro del team il proprietario restava escluso dalla dashboard.
  • Modificato: GET /v1/account/export risponde con 403 alle Publishable Key: il file contiene gli indirizzi di destinazione e le note di tutti i codici.

2026-10 · Richieste DPP nell’esportazione dei dati personali

  • Novità: GET /v1/account/export contiene dpp_scan_aggregates: per ogni passaporto del prodotto, il numero di richieste memorizzate, il numero di paesi e la prima e l’ultima richiesta. Come per le scansioni QR, gli pseudonimi IP non vengono mai esportati.
  • Novità: GET /v1/account/privacy conta in stored_data le scansioni memorizzate: scan_records per i QR Code, dpp_scan_records per i passaporti del prodotto. Finora le scansioni mancavano del tutto nella panoramica. Dettagli: GDPR e privacy.

2026-10 · TypeScript-SDK 1.3.0

  • Risolto in @qr3/sdk 1.3.0: client.account.export() restituisce il file di esportazione così come lo invia l’API (tipo AccountExport). Le voci di codes sono righe grezze del database: is_dynamic vale 0 o 1, tags è il testo JSON memorizzato. Prima il metodo era tipizzato come link di download (download_url, expires_at), che l’API non ha mai restituito, e restituiva sempre undefined.
  • Modificato: client.account.deleteAccount() restituisce la conferma dell’API (deleted, workspace_id, deleted_at, gdpr_note) invece di void.
  • Modificato (tipi): client.account.get() restituisce ciò che invia GET /v1/account/me: { acting_user_id, is_superadmin, role }. I campi id, email, plan, organization_id, workspace_id e created_at non sono mai stati valorizzati; plan è fornito da client.account.usage(). La compatibilità a livello di codice sorgente è limitata: il codice che legge i vecchi campi non compila più (TS2339) invece di ricevere silenziosamente undefined, e return client.account.deleteAccount() in una funzione dichiarata come Promise<void> fallisce con TS2322.
  • Aggiornamento: npm install @qr3/sdk@latest. Dettagli: GDPR e privacy.

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.