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/accountrisponde con403ai ruoliviewerecontributore alle Publishable Key (qr3_pk_) e non elimina nulla. Prima, qualsiasi chiave valida poteva svuotare il workspace.POST /v1/account/privacy/consentsrichiede 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/exportrisponde con403alle 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/exportcontienedpp_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/privacyconta instored_datale scansioni memorizzate:scan_recordsper i QR Code,dpp_scan_recordsper 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/sdk1.3.0:client.account.export()restituisce il file di esportazione così come lo invia l’API (tipoAccountExport). Le voci dicodessono righe grezze del database:is_dynamicvale0o1,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 sempreundefined. - Modificato:
client.account.deleteAccount()restituisce la conferma dell’API (deleted,workspace_id,deleted_at,gdpr_note) invece divoid. - Modificato (tipi):
client.account.get()restituisce ciò che inviaGET /v1/account/me:{ acting_user_id, is_superadmin, role }. I campiid,email,plan,organization_id,workspace_idecreated_atnon sono mai stati valorizzati;planè fornito daclient.account.usage(). La compatibilità a livello di codice sorgente è limitata: il codice che legge i vecchi campi non compila più (TS2339) invece di ricevere silenziosamenteundefined, ereturn client.account.deleteAccount()in una funzione dichiarata comePromise<void>fallisce conTS2322. - 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.pdfeqr.epsdisegnanofgebg, 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 esempio1F4E79come 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=transparentnon ne disegna alcuna. Il titolo rimane nero, la piastra del logo bianca. - Nessuna modifica senza colori: Senza
fg/bge 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, dopoDELETE /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/:idsimultanee sullo stesso codice restituiscono una volta200e una volta404. Il webhookqr.deletedviene inviato esattamente una volta, mentre prima veniva inviato due volte. - Nuovo: Le richieste
POSTeDELETE /v1/codes/:id/logorispondono con409(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 richiesteDELETE /v1/codes/:id/logosimultanee restituiscono entrambe200. Dettagli: Logo.
2026-09 · TypeScript-SDK 1.2.0
- Novità in
@qr3/sdk1.2.0:client.codes.update()accettaappearancee restituisce i risultati del controllo del contrasto comeissuesnel risultato; in assenza di problemi, il campo è assente.client.codes.imageUrl()accettafg,bgeecc. Ogni codice restituito dall’API (get,list,create,update,batchCreate) contienetitleeappearance. - 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
PATCHsuexpires_atora 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 restituire410fino 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_atscade 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
POSTeDELETE /v1/codes/:id/logorispondono con404e non modificano il codice eliminato, proprio come già avviene perPATCH. - 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/:idaccettaappearanceconforeground_colorebackground_color(#RRGGBB, per lo sfondo anchetransparent).qr.svgeqr.pngdisegnano i colori memorizzati senza parametri; un parametro come?fg=000000ha 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 inmeta.issuescomewarningocritical; uno sfondo trasparente è semprecritical, mai bloccato. - Unione: I campi omessi mantengono il loro valore salvato,
nulleffettua 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 webhookqr.createdeqr.updated.POST, il batch e l’importazione lo rifiutano con422. - 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 otransparent) eecc(correzione degli erroriL,M,Q,H). SVG e PNG disegnano i colori; PDF ed EPS li accettano, ma li disegneranno solo con una release successiva.eccha effetto in tutti e quattro i formati, un logo continua a forzareH. - Trasparente:
bg=transparentrestituisce 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=300invece 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.
2026-09 · Anche PDF ed EPS ora incorporano il logo
- Estensione:
qr.pdfeqr.epsora incorporano un logo impostato esattamente comeqr.svgeqr.png(vedi sotto) — come immagine incorporata (PDF tramite unImage 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 aH. Finora entrambi i formati non includevano il logo; questo problema è stato ora risolto. - Caching: Con un logo impostato, anche
qr.pdfeqr.epsora restituisconoCache-Control: public, max-age=300invece 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.epsin 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
viewervede lo stato e l’anteprima, ma nessuna delle tre azioni. - API:
POST /v1/codes/{id}/logo(campo multipartfile; PNG, JPEG o WebP, massimo 1 MB, SVG viene rifiutato) crea o sostituisce un logo;DELETE /v1/codes/{id}/logolo rimuove ed è idempotente. Un’immagine troppo grande restituisce413, un formato non supportato422, il ruoloviewer403. - Rappresentazione:
qr.svgeqr.pngincorporano il logo come pixel effettivi (512 × 512, normalizzato) e aumentano per questo la correzione d’errore aH. L’aggiunta e la rimozione modificano quindi il motivo dei punti (M↔H), mentre la sostituzione no.qr.pdfeqr.epsnon 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.svgeqr.pngrestituisconoCache-Control: public, max-age=300invece 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,archiveWorkspacee 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è unDELETE,importDppsunPOST. - 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.txtha 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:initializeversohttps://mcp.qr3.app/mcprisponde con un campoinstructions(in precedenza: undici strumenti senza alcuna classificazione). È inoltre indicato quali chiamate richiedono una chiave API —initializeetools/listno, ognitools/callsì. - Correzioni in
llms.txt: Quattro informazioni sono state verificate rispetto alla produzione e non erano corrette: (1) l’SDK Pythonqr3appnon è pubblicato su PyPI — la rigapip installè stata rimossa senza sostituzione; (2)Accept: text/markdownsi 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}/statseGET /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/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.