Hoppa till innehåll

Changelog

Changelog

Kurerade höjdpunkter från de senaste versionerna. För fullständiga API-versioner och policy för brytande ändringar, se API-versionering & LTS-policy.

Detaljerade ändringar för enskilda slutpunkter: OpenAPI-specifikation och interaktiv API-referens.


2026-10 · Färger i Dashboard

  • Nytt: Detaljsidan för en kod har kortet Färger: förgrund och bakgrund som hexvärde, transparent bakgrund, förhandsvisning via den riktiga bildrutten. Kontrollen är densamma som för PATCH /v1/codes/{id}: Kritiska par kräver en bekräftelse, par under 1,5:1 kan inte sparas.
  • Återställning till svart på vitt levererar återigen samma byte i alla fyra format som utan färger. Koder utan färger ändras inte.
  • Transparenta koder visas på ett schackrutigt mönster i alla förhandsvisningar i Dashboard. Detaljer: Färger i Dashboard.

2026-10 · Färger i PDF och EPS

  • Nytt: qr.pdf och qr.eps ritar fg och bg, som parametrar och som sparade färger. Svart och varje gråton skrivs som gråskala (endast svartplatta), alla andra färger som CMYK i hela procent, till exempel 1F4E79 som C74 M36 Y0 K53.
  • Bakgrund som för SVG: Så snart en färg har valts ligger en täckande yta bakom koden och dess tysta zon, vit eller bg. bg=transparent ritar ingen. Rubriken förblir svart, logotypplattan vit.
  • Ingen ändring utan färger: Utan fg/bg och utan sparade färger levererar båda formaten samma byte som tidigare. PDF-filen för ett produktpass förblir ofärgad.
  • Begränsningar: ingen ICC-profil, ingen PDF/X. Detaljer: Färger vid tryck.

2026-09 · Statiska koder utan omdirigeringscache, samtidig radering

  • Ändrat: Statiska koder ligger inte längre i omdirigeringscachen. Ett anrop till deras kortlänk (redirect_url) läser alltid det aktuella tillståndet. Efter DELETE /v1/account omdirigerar en statisk kod därför inte längre vid nästa anrop, vilket tidigare kunde ta upp till 24 timmar. Även ett abonnemangsbyte har omedelbar effekt för statiska koder. Dynamiska koder rensas bort vid kontoradering som tidigare. Tryckta statiska koder innehåller sitt mål direkt och påverkas inte.
  • Åtgärdat: Två samtidiga DELETE /v1/codes/:id mot samma kod returnerar en 200 och en 404. Webhooken qr.deleted skickas exakt en gång, tidigare två gånger.
  • Nytt: POST och DELETE /v1/codes/:id/logo svarar med 409 (errors/conflict) om en annan förfrågan har ändrat logotypen för samma kod samtidigt, och ändrar då ingenting. Tidigare kunde en uppladdad logotyp förbli sparad utan att användas. Två samtidiga DELETE /v1/codes/:id/logo returnerar båda 200. Detaljer: Logotyp.

2026-09 · TypeScript-SDK 1.2.0

  • Nytt i @qr3/sdk 1.2.0: client.codes.update() tar emot appearance och returnerar resultatet av kontrastkontrollen som issues i resultatet; om inga problem identifieras saknas fältet. client.codes.imageUrl() tar emot fg, bg och ecc. Varje kod som API:et returnerar (get, list, create, update, batchCreate) innehåller title och appearance.
  • Uppdatera: npm install @qr3/sdk@latest. Python, Go och PHP följer. Detaljer: SDK:er & CLI och Spara färger på koden.

2026-09 · Ändrad utgångstid gäller inom cirka en minut

  • Åtgärdat: En PATCH på expires_at rensar nu kodens omdirigeringscache. Den nya utgångstiden gäller därmed inom cirka en minut istället för först upp till 24 timmar senare. Tidigare fortsatte en borttagen eller framflyttad utgångstid att returnera 410 i upp till 24 timmar, och en utgångstid inställd på nu lät omdirigeringen fortsätta i upp till 24 timmar.
  • Åtgärdat: En kod som skapats med expires_at löper ut i tid även om utgångstiden ligger inom de första 24 timmarna.
  • Åtgärdat: Om en kod raderas samtidigt som dess logotyp laddas upp eller tas bort, svarar POST och DELETE /v1/codes/:id/logo med 404 och ändrar inte den raderade koden, precis som PATCH.
  • Åtgärdat: Även en statisk kod vars kortlänk (redirect_url) har anropats ligger i omdirigeringscachen. Att ändra, pausa och radera rensar den nu också, inte bara för dynamiska koder.

2026-09 · Spara färger på koden

  • Nytt: PATCH /v1/codes/:id tar emot appearance med foreground_color och background_color (#RRGGBB, bakgrunden även transparent). qr.svg och qr.png ritar de sparade färgerna utan parametrar; en parameter som ?fg=000000 har fortfarande företräde. PDF och EPS ritar färger först i en senare version.
  • Kontrastkontroll: Ett par under 1,5:1 ger 422. Svagare par sparas och rapporteras i meta.issues som warning eller critical; en transparent bakgrund är alltid critical, aldrig spärrad.
  • Sammanslagning: Utelämnade fält behåller sitt sparade värde, null återställer. Samtidiga ändringar på samma kod skriver inte längre över varandra.
  • I varje kodsvar: appearance finns i varje kodsvar och i webhookarna qr.created och qr.updated. POST, batchen och importen avvisar det med 422.
  • Ingen ändring för befintliga koder: Utan sparade färger levererar varje kod samma bytes som tidigare. Detaljer: Spara färger på koden.

2026-09 · Färger och felkorrigering som parametrar för bildrutterna

  • Nytt: Alla fyra bildrutter accepterar fg (förgrundsfärg), bg (bakgrundsfärg eller transparent) och ecc (felkorrigering L, M, Q, H). SVG och PNG ritar färgerna; PDF och EPS accepterar dem, men ritar dem först i en senare version. ecc fungerar i alla fyra format, en logotyp tvingar fortfarande fram H.
  • Genomskinlig: bg=transparent ger en SVG utan bakgrund och en PNG med äkta alfakanal. Underlaget måste vara ljust och lämna den tysta zonen fri.
  • Aldrig ett fel: Ogiltiga värden ignoreras; bilden levereras då exakt som utan parametrar.
  • Cachning: Varje effektiv parameter ger Cache-Control: public, max-age=300 istället för standardbildens 24 timmar.
  • Ingen beteendeförändring utan parametrar: Varje befintlig kod levererar samma byte som tidigare i alla fyra format.
  • Tillgängligt i alla abonnemang. Detaljer: Färger och felkorrigering.

2026-09 · PDF och EPS bäddar nu också in logotypen

  • Utökning: qr.pdf och qr.eps bäddar nu in en angiven logotyp på exakt samma sätt som qr.svg och qr.png (se nedan) — som en inbäddad bild (PDF via ett Image XObject, EPS via ett bildlexikon i PostScript, där endast med %%LanguageLevel: 3), centrerad på samma yta, med samma höjning av felkorrigeringen till H. Båda formaten levererade tidigare inte logotypen; detta är nu åtgärdat.
  • Cachning: Med en angiven logotyp levererar nu även qr.pdf och qr.eps Cache-Control: public, max-age=300 istället för de annars vanliga 24 timmarna — precis som SVG/PNG.
  • Fallback: Om själva logotypbilden inte kan bearbetas (till exempel ett skadat sparat objekt), förblir felkorrigeringen H, men den reserverade ytan förblir tom istället för en bild — aldrig ett serverfel.
  • Ingen beteendeförändring utan logotyp: Koder utan logotyp levererar fortfarande qr.pdf/qr.eps byte-identiskt, med oförändrad 24-timmars cache.
  • Detaljer och tryckanvisningar: Logotyp i QR-koden.

2026-09 · Logo i QR-kod — Dashboard och API

  • Nytt: En kod kan nu ha en logotyp i mitten. I Dashboard skapar detaljsidan för en kod ett eget logotyp-kort: Välj logotyp, vid första tillägget eller vid borttagning bekräftas en varning med en obligatorisk kryssruta (båda ändrar punktmönstret), sedan Ladda upp logotyp/Ta bort logotyp. En ersättning kräver ingen bekräftelse — endast bilden ändras, inte mönstret. Rollen viewer ser status och förhandsgranskning, men ingen av de tre åtgärderna.
  • API: POST /v1/codes/{id}/logo (multipart-fält file; PNG, JPEG eller WebP, max 1 MB, SVG avvisas) skapar eller ersätter en logotyp; DELETE /v1/codes/{id}/logo tar bort den igen och är idempotent. En för stor bild returnerar 413, ett format som inte stöds returnerar 422, rollen viewer returnerar 403.
  • Visning: qr.svg och qr.png bäddar in logotypen som faktiska pixlar (512 × 512, normaliserad) och höjer för detta ändamål felkorrigeringen till H. Att lägga till och ta bort ändrar därmed punktmönstret (M ↔ H), men inte en ersättning. qr.pdf och qr.eps bäddar inte in någon logotyp och förblir oförändrade. En redan tryckt kod fungerar i alla lägen eftersom det kodade målet inte beror på logotypen — endast den som vill se det (nya) logotyp-utseendet på materialet behöver trycka på nytt, och bör då inte blanda gamla och nya tryckfiler.
  • Cachning: Med en logotyp inställd returnerar qr.svg och qr.png Cache-Control: public, max-age=300 istället för de annars vanliga 24 timmarna. Detaljer, gränsvärden och tryckanvisningar: Logo i QR-kod.

2026-08 · operationId för alla 75 operationer, och en vägledning för agenter om när qr3.app passar

  • Tillägg: Alla 75 operationer i OpenAPI-specifikationen har nu en operationId — listCodes, createCode, getCodeStats, archiveWorkspace och så vidare. Tidigare saknades fältet helt, vilket gjorde att varje generator var tvungen att härleda metodnamnet från HTTP-metod och sökväg (postV1Codes). Sådana namn är beroende av sökvägen och ändras vid varje omstrukturering av sökvägen. Namnformen är densamma på alla 75 ställen: list/get/create/update/replace/delete, annars verbet för domänåtgärden (validateDpp, registerGs1Identifier, pingWebhook). Verbet följer domänen, inte HTTP-metoden — archiveWorkspace är en DELETE, importDpps en POST.
  • Inverkan på självgenererade klienter: De som genererar sitt SDK från specifikationen kommer vid nästa körning att få omdöpta metoder (postV1Codes → createCode). Detta är syftet med ändringen, men det innebär en namnändring i extern kod — därför nämns det uttryckligen här. Sökvägar, parametrar, svarsformat och statuskoder är oförändrade; de officiella SDK:erna, CLI och MCP-servern påverkas inte.
  • Startpunkt för agenter: https://qr3.app/llms.txt har ett avsnitt ## When to use qr3.app — sex uppgifter istället för sex funktioner, plus meningen om vad qr3.app inte är rätt verktyg för. Samma information levererar MCP-servern nu i handskakningen: initialize mot https://mcp.qr3.app/mcp svarar med ett fält instructions (tidigare: elva verktyg helt utan sammanhang). Det framgår också vilka anrop som kräver en API-nyckel — initialize och tools/list gör det inte, men varje tools/call gör det.
  • Rättelser i llms.txt: Fyra uppgifter stämde inte överens med produktionen: (1) Python-SDK:et qr3app är inte publicerat på PyPI — raden med pip install har tagits bort helt; (2) Accept: text/markdown gäller för startsidan och bloggen, inte för varje serversidigt renderad sida; (3) kontaktadressen är [email protected], även i JSON-LD på startsidan; (4) /de/security/ är en omdirigering till ett ankare, inte en egen sida. Ny länk: docs.qr3.app/de/skills/.
  • Säkring: Tre assertioner i openapi-spec.test.ts — fullständighet, unikhet, lowerCamelCase —, var och en verifierad med en mutation. Ytterligare nio tester säkerställer de fyra korrigerade uppgifterna så att de inte återkommer.
  • Känd begränsning: Två av de 75 operationerna beskrivs i specifikationen men svarar med 404 (GET /v1/codes/{id}/stats och GET /v1/account). De har fått ett namn här och kommer att förlora det igen så snart det har beslutats om de ska byggas eller tas bort.

2026-08 · Nedgraderingar av abonnemang och uppsägningar påverkar nu även gränserna

  • Fix: Stripe-webhooken skrev vid planbyte och uppsägning endast plannamnet, inte organisationens fyra gränskolumner (max_workspaces, max_members, max_dynamic_codes, max_scans_per_month). Eftersom tillämpningen tar det maximala värdet av det sparade värdet och planens baslinje, behöll en nedgraderad eller uppsagd organisation sina gamla, högre gränser — nedgraderingen var verkningslös. Webhooken sätter nu kolumnerna vid varje faktiskt planbyte till den nya planens baslinje och vid uppsägning till Free-baslinjen — precis som administratörsverktyget redan gör.
  • Beteende: Rutinuppdateringar av prenumerationen (förnyelse, betalningsmetod, proration) rör fortfarande inte gränserna; individuellt beviljade högre gränser förblir oförändrade. Först vid ett faktiskt planbyte återställs de till den nya planens baslinje.
  • Konsekvens: Ingen ändring av API eller svarsformat. Organisationer vars nedgradering skedde före denna fix behåller de gamla värdena tills nästa planbyte träder i kraft eller supporten justerar dem.

2026-08 · Keyset-cursor nu på alla list-slutpunkter

  • Fix: Cursor-fixen för GET /v1/codes och GET /v1/dpp (se nedan) har nu rullats ut till alla övriga cursor-paginerade listor: GET /v1/qr-codes/:id/comments, /v1/workspaces, /v1/gs1/identifiers, /v1/members, /v1/audit-logs, /v1/admin/orgs, /v1/admin/users och /v1/webhooks/:id/deliveries. Alla bläddrade tidigare enbart via created_at; rader med identisk tidsstämpel (audit-loggposter från en batch-operation, webhook-retries, medlemsimporter) kunde gå förlorade på nästa sida. Sorteringsnyckeln är nu överallt tupeln (created_at, id).
  • API-ändring: I dessa listor är meta.pagination.next_cursor från och med nu också ett opakt värde (base64url) istället för en ren tidsstämpel; oläsbara cursors returnerar 400, gamla tidsstämpel-cursors accepteras fortfarande under en övergångsperiod. Undantag GET /v1/webhooks/:id/deliveries: där förblir next_cursor ID:t för den senaste leveransen (okänt ID → första sidan). Klienter som returnerar next_cursor oförändrat — Dashboard, CLI, SDKs, MCP — behöver inte ändra någonting.
  • Konsekvens: Ingen migrering krävs. Om du har saknat poster när du bläddrat i någon av dessa listor (t.ex. audit-loggen eller leveransloggen i Dashboard): De var aldrig borta — listorna visar dem fullständigt från och med nu.

2026-08 · Tidsstämplar efter redigering och radering åter OpenAPI-kompatibla

  • Fix: Efter PATCH /v1/codes/{id} returnerades updated_at i SQLite-format utan tidszon (2026-08-17 09:00:00), trots att OpenAPI-specifikationen utlovar format: date-time och skapande (POST) returnerar ISO-tidsstämpeln (2026-08-17T09:00:00.000Z). Detsamma gällde för deleted_at/updated_at vid soft-delete samt för redigerings-/raderingssökvägarna för API-nycklar, organisationer, workspaces, medlemmar, kommentarer och webhooks, och dessutom för last_used_at för API-nycklar och last_triggered_at för webhooks. Alla skrivsökvägar stämplar nu ISO 8601 (UTC, T och Z).
  • Konsekvens: Klienter som parsar updated_at med new Date(...) (SDKs, CLI, Dashboard) läste formatet med mellanslag som lokal tid — CLI visade tiden för koder som redigerats en gång förskjuten med den lokala tidsförskjutningen (Wien: −2 h). Detta är åtgärdat. Dessutom normaliserar en datamigrering redan sparade värden i det gamla formatet till ISO, så att sortering och jämförelser i blandade data blir korrekta. Inga ändringar av fältnamn eller svarsstruktur.
  • Bakgrund: Samma felklass som de två korrigeringarna nedan (utgångstid för API-nycklar, re-scan-cutoff): SQLites datetime('now') skriver YYYY-MM-DD HH:MM:SS, alla andra skrivare ISO 8601. Ett källkodstest (guard test) förhindrar framtida förekomster.

2026-08 · Listpaginering tappar inte längre batchkoder

  • Fix: GET /v1/codes och GET /v1/dpp paginerade enbart via created_at. Koder från POST /v1/codes/batch, POST /v1/dpp/batch och CSV/XLSX-importen delar dock på en tidsstämpel — så fort en batch var större än limit (standardvärde 20), returnerade den andra sidan inte längre de återstående raderna för samma tidsstämpel. Koderna existerade och var tillgängliga via GET /v1/codes/:id, men dök aldrig upp i listan (Dashboard, CLI qr3 list, SDKs, MCP). Cursorn är nu ett keyset över (created_at, id).
  • API-ändring: meta.pagination.next_cursor är från och med nu ett opakt värde (base64url) istället för en ren tidsstämpel. De som returnerar cursorn oförändrad som ?cursor= — precis som Dashboard, CLI, alla SDKs och MCP-servern gör — behöver inte ändra någonting. Gamla tidsstämpel-cursors accepteras fortfarande under en övergångsperiod; oläsbara cursors returnerar nu 400 istället för att tyst leverera den första sidan.
  • Konsekvens: För de som såg färre koder i listan efter en batchimport än vad som skapades: Koderna var aldrig borta — listan visar dem fullständigt från och med nu. Ingen migrering krävs.

2026-08 · Säkerhets-re-scans körs återigen i 24-timmarstakt

  • Fix: Den periodiska re-scanningen av mål-URL:er och länkar på landningssidor (Google Web Risk) hoppade över koder vars senaste skanning inföll på samma kalenderdag som 24-timmars-cutoffen — beroende på klockslag fördröjdes re-scannen med upp till ytterligare en dag. Cutoffen beräknas nu i samma ISO-format som skanningstidsstämplarna är sparade i.
  • Konsekvens: En mål-URL som klassificeras som osäker efter den senaste skanningen leder återigen till att koden pausas automatiskt inom det dokumenterade 24-timmarsfönstret. Inga ändringar i API eller svarsformat.

2026-08 · API-nycklar löper ut vid utgångstidpunkten

  • Fix: En API-nyckel vars expires_at inföll samma dag fortsatte att accepteras fram till midnatt UTC. Utgångstiden jämförs nu som en tidsstämpel istället för som en sträng — en utgången nyckel returnerar omedelbart 401.
  • Bakgrund: expires_at sparas som en ISO-tidsstämpel (2026-08-14T09:00:00Z), medan jämförelsesidan returnerade formatet med mellanslag (2026-08-14 09:00:00). Den råa strängjämförelsen stämde därför endast så länge som själva datumet skilde sig åt.
  • Konsekvens: Ingen migrering krävs, svarsformatet för GET /v1/api-keys förblir oförändrat. Oläsbara utgångsvärden betraktas nu som utgångna istället för giltiga.

2026-08 · API-referens: Tenant-hantering dokumenterad

  • OpenAPI: Specifikationen — och därmed den interaktiva referensen — dokumenterar nu organisationer (inkl. GET /v1/organizations/usage), workspaces, medlemmar & roller och audit-loggar.
  • Billing: Abonnemangsöversikten (GET /v1/billing/plans) är offentlig; checkout (POST /v1/billing/checkout) och Stripe-kundportalen (GET /v1/billing/portal) är angivna som slutpunkter för organisationsadministratörer.
  • Skanningsexport: Skanningsstatistik (GET /v1/codes/{id}/scans) och rådataexporten (…/scans.csv, …/scans.xlsx) är fullständigt dokumenterade — inklusive GDPR-information: ip_hash är aldrig inkluderad i exporten.
  • Felbeteende: Även 400-svaret från request-valideringen är nu dokumenterat: Bodyn är det råa Zod-felet, inte ett RFC-7807-problemdokument — det levereras ändå med Content-Type application/problem+json.

2026-08 · Kopiera offentliga fillänkar

  • Dashboard: Offentliga filer på koddetaljsidan har nu en knapp som kopierar deras offentliga länk till urklipp – direkt användbar som måladress för en QR-kod om en skanning omedelbart ska öppna ett specifikt dokument istället för landningssidan med fillistan.
  • API: Fil-slutpunkterna (/v1/files) returnerar nu även public_url. Fältet är endast satt för filer med visibility: public – privata filer får ingen offentlig adress.
  • Beteende: Länken kräver ingen inloggning och öppnar filen direkt i webbläsaren. Att ersätta filen lämnar länken oförändrad, så en tryckt kod förblir giltig. Detaljer: Filer & datablad.

2026-07 · Teamroller: Redaktör utan borttagning & administratörsfakturering

  • Nytt: Medlemsrollen Redaktör (utan borttagning) — skapar och redigerar QR-koder, filer och Digital Product Passports, men kan inte ta bort något eller skapa API-nycklar. Alla destruktiva slutpunkter kontrollerar rollen på serversidan (403).
  • Fakturering: Abonnemangsuppgraderingar och Stripe-kundportalen (POST /v1/billing/checkout, GET /v1/billing/portal) är nu reserverade för organisationsadministratörer — alla andra roller ser en skrivskyddad abonnemangsöversikt.
  • Dashboard: Åtgärder som den egna rollen inte tillåter döljs: En Läsare ser till exempel inga knappar för att skapa, redigera eller ta bort; listor, nedladdningar och statistik förblir synliga. Detaljer: Team & roller.

2026-06 · Externa länkar på kodens landningssida

  • Landningssida: Landningssidan för en kod som är värd på qr3 kan nu lista externa, självhostade länkar ({ label, url }) – utöver eller istället för uppladdade filer, till exempel för datablad på den egna webbplatsen.
  • API: POST/PATCH /v1/codes accepterar en links-array (0–20 poster, http(s), ≤ 2048 tecken). Varje URL kontrolleras med Google Web Risk; en osäker URL returnerar 422. En tom array tar bort alla länkar.
  • Dashboard: Lägg till, sortera och ta bort länkar på koddetaljsidan.
  • Säkerhet: Renderade länkar förblir XSS-säkra (escaped, endast http(s)) och sidan behåller sin noindex-header.

2026-04 · Dashboard-analys per QR-kod

  • Dashboard: Analysknappen i QR-kodlistan öppnar nu statistik-sidan för respektive QR-kod under /dashboard/codes/{id}.
  • Routing: Aliaset /dashboard/codes omdirigerar fortfarande till /dashboard, men fångar inte längre upp detaljerade rutter som /dashboard/codes/{id}.
  • API: Detaljsidan läser in QR-koden direkt via GET /v1/codes/:id; därmed är den inte längre beroende av pagineringsgränser för listor.
  • Tester: Regressionstester täcker alias-omdirigeringen och den direkta inläsningen av koden.

2026-04 · Dashboard-borttagningsdialog för QR-koder

  • Dashboard: Papperskorgen i QR-kodlistan öppnar nu en egen React-dialogruta istället för en inbyggd popup i webbläsaren.
  • Feedback: Efter borttagning visas ett toast-meddelande för framgång eller fel.
  • Tester: packages/dashboard/tests/dashboard.test.ts förhindrar regressioner för confirm() i QR-kodens borttagningsflöde.

2026-04 · Dashboard-kortlänkstest för dynamiska QR-koder

  • Dashboard: Shortcodes in QR-kodlistan är nu direkt klickbara som externa omdirigeringslänkar. Ikonen för extern länk bredvid t.ex. wu3qaa öppnar https://qr3.app/{shortCode} i en ny flik.
  • i18n: Tooltip-texter för tyska och engelska har lagts till.
  • Tester: packages/dashboard/tests/dashboard.test.ts skyddar länk-href, beteende för ny flik, noopener noreferrer och ikon mot regressioner.

2026-04 · Redirect-Worker-rutt för dynamiska QR-koder

  • Fix: Dynamiska QR-koder under https://qr3.app/{shortCode} hanteras återigen av omdirigerings-workern. Produktionsrutten använder nu qr3.app/* eftersom Cloudflare Workers rutter inte stöder :code-sökvägsparametrar.
  • Härdning: Sökvägar som inte matchar skickas vidare till landnings-origin, så att vanliga sidor som /de/pricing inte blockeras av omdirigerings-workern.
  • Tester: packages/redirect/tests/unit/redirect.test.ts testar wildcard-rutten, shortcode-bearbetningen och origin-pass-through.

2026-04 · Workspace-DPP-skanningsöversikt (Q3.4.2)

  • Nytt: GET /v1/workspace/stats/dpp?days=30 — aggregerar alla dpp_scans för API-nyckelns workspace (active_dpps, scans_by_day, top_dpps med produktnamn/kategori).
  • Dashboard: Kort på startsidan (/dashboard) med 30-dagars stapeldiagram + topplistor — parallellt med QR-kodkorten.
  • Public: Marknadsföringskortlänk GET /dpp/dpp_<id> (ett segment) för livedemos, parallellt med /dpp/{gtin}/{serial}.

2026-04 · DPP-skanningsanalys (Q3.4.1)

  • Nytt: GET /v1/dpp/:id/stats?days=30 — aggregerade skanningar från den offentliga GS1-resolveraren per DPP. Fält: total_scans, period_scans, scans_by_day, top_countries, top_devices, top_representations.
  • Nytt: Tabellen dpp_scans (migrering 0011) — separerad från scans (omdirigerings-worker). IP-adresser hashas med ett dagligen roterande salt, råa IP-adresser når aldrig D1.
  • Dashboard: Mini-diagramkort (SVG, inget diagrambibliotek) på /dashboard/dpp/:dppId med 30-dagarsstaplar + topp 3-uppdelningar. Empty-state så snart en DPP är live men ännu inte har haft några skanningar.

2026-04 · Live-EU-efterlevnadssimulator (Q3.3.7)

  • Nytt: POST /v1/dpp/:id/validate-update — simulerar delvisa uppdateringar stateless (status, marknadslista, …) utan persistens. Svaret innehåller eu_compliance + preview.changed_fields.
  • Dashboard: Simulatorkort i DPP-detaljvyn (/dashboard/dpp/:dppId) — chips för DE/AT/FR/IT/ES/NL + anpassad, status-rullgardinsmeny, Preview EU impact / Save changes / Reset. Icke-blockerande via Remix useFetcher.
  • Härdning: Utbrutna simulatorhjälpare (readUpdatePatchFromForm, marketCountriesKey) + 18 nya enhetstester; buggfix: Enstaka icke-ISO-indata tömmer inte längre marknadslistan.

2026-04 · Live-EU-efterlevnadsförhandsvisning i skapa-formuläret (Q3.3.6)

  • Ändrat: POST /v1/dpp/validate returnerar nu även eu_compliance — samma validerare som GET /v1/dpp/:id/eu-compliance, stateless före sparning.
  • Dashboard: Förhandsvisning under den befintliga valideringspanelen + ny Save-Guard-banner före skicka-knapparna om det finns öppna fel/varningar (i18n-pluralisering DE/EN).

2026-04 · EU-validerare + textil-UI (Q3.3.4 + Q3.3.5)

  • Nytt: EU-efterlevnadsvaliderare med 5 textilregler (TEXTILE_AGEC_REQUIRED, TEXTILE_MICROPLASTICS_CONSISTENCY, TEXTILE_SVHC_THRESHOLD, TEXTILE_GREENWASHING, TEXTILE_ESPR_READY).
  • Nytt: GET /v1/dpp/:id/eu-compliance med compliant / espr_ready / issues[] / summary.
  • Dashboard: EU-efterlevnadssektion i DPP-detaljvyn (sammanfattningskort, grupperade problemkort, ESPR-Ready-badge i headern).

2026-04 · Textil-DPP-schema (Q3.3.1–Q3.3.3)

  • Nytt: Kategorin textile med obligatorisk AGEC-kedja (vävning/stickning → färgning/tryckning → konfektion), per fiber origin_country + recycled_pct, svhc_substances[], ESPR-opt-in (PEF, livslängd, återvinningsbarhet).
  • Nytt: Basfältet market_countries: string[] (ISO 3166-1 alpha-2) på alla DPP-kategorier — styr FR-specifika AGEC-regler och det franska obligatoriska konsumentmeddelandet.
  • Nytt: Konsument-HTML-mall med AGEC-mikroplastvarning, ursprungskedja i 3 steg (flaggpiller), SVHC-lista samt sektioner för hållbarhet och återvinningsbarhet.
  • Migrering: 0010_dpp_market_countries (D1).

2026-04 · DPP-massimport (Q3.2.1–Q3.2.5)

  • Nytt: POST /v1/dpp/import accepterar CSV och XLSX (Worker-kompatibel via SheetJS xlsx, ~283 KB gzip-bundle).
  • Skalat: abonnemangsbaserad gräns (Free 100 → Enterprise 10k) + uppdelad db.batch() à 100 + 5 MB body-gräns.
  • Nytt: Felrapport som CSV i fältet errors_csv i 201-svaret; GET /v1/dpp/import/templates/:category?format=csv|xlsx levererar färdiga mallar för batteri och textil.
  • Dashboard: Dra-och-släpp-uppladdning under /dashboard/dpp/import med mall-proxy och inline-CSV-nedladdning.

Icke-brytande — LTS-utökningar

Alla ovan nämnda ändringar är additiva:

  • Befintliga POST /v1/dpp/validate-klienter ignorerar det nya eu_compliance-fältet utan ändringar.
  • Befintliga battery-flöden är oförändrade.
  • market_countries är valfritt och har standardvärdet [].

Se API-versionering för policyn gällande brytande ändringar.