Gå til indhold

Changelog

Changelog

Kuraterede højdepunkter fra de seneste udgivelser. For fuldstændige API-versioner og breaking change-politik, se API-versionering & LTS-politik.

Detaljerede ændringer for de enkelte endepunkter: OpenAPI-specifikation og interaktiv API-reference.


2026-10 · Farver i Dashboard

  • Nyt: Detaljesiden for en kode har kortet Farver: forgrund og baggrund som hex-værdi, transparent baggrund, forhåndsvisning via den rigtige billedrute. Kontrollen er den samme som ved PATCH /v1/codes/{id}: Kritiske par kræver en bekræftelse, par under 1,5:1 kan ikke gemmes.
  • Nulstilling til sort på hvid leverer igen de samme bytes i alle fire formater som uden farver. Koder uden farver ændres ikke.
  • Transparente koder vises på et skakbrætmønster i alle forhåndsvisninger i Dashboard. Detaljer: Farver i Dashboard.

2026-10 · Farver i PDF og EPS

  • Nyhed: qr.pdf og qr.eps tegner fg og bg, som parametre og som gemte farver. Sort og enhver gråtone skrives som gråskala (kun sort plade), enhver anden farve som CMYK i hele procenter, f.eks. 1F4E79 som C74 M36 Y0 K53.
  • Baggrund som ved SVG: Så snart en farve er valgt, ligger der en dækkende flade bag koden og dens frizone, hvid eller bg. bg=transparent tegner ingen. Titel forbliver sort, logoplade hvid.
  • Ingen ændring uden farver: Uden fg/bg og uden gemte farver leverer begge formater de samme bytes som før. PDF’en af et produktpas forbliver ufarvet.
  • Begrænsninger: intet ICC-profil, intet PDF/X. Detaljer: Farver i tryk.

2026-09 · Statiske koder uden viderestillingscache, samtidig sletning

  • Ændret: Statiske koder ligger ikke længere i viderestillingscachen. Et kald af deres korte link (redirect_url) læser altid den aktuelle status. Efter DELETE /v1/account viderestiller en statisk kode derfor ikke længere ved næste kald, hvor det før kunne tage op til 24 timer. En abonnementsændring har også øjeblikkelig virkning for statiske koder. Sletning af kontoen rydder op i dynamiske koder som hidtil. Printede statiske koder indeholder deres destination direkte og er ikke berørt.
  • Rettet: To samtidige DELETE /v1/codes/:id mod den samme kode returnerer én gang 200 og én gang 404. Webhooket qr.deleted sendes nøjagtig én gang, tidligere to gange.
  • Nyt: POST og DELETE /v1/codes/:id/logo svarer med 409 (errors/conflict), hvis en anden anmodning har ændret logoet for den samme kode samtidigt, og ændrer i så fald ingenting. Tidligere kunne et uploadet logo forblive gemt uden at blive brugt. To samtidige DELETE /v1/codes/:id/logo returnerer begge 200. Detaljer: Logo.

2026-09 · TypeScript-SDK 1.2.0

  • Nyt i @qr3/sdk 1.2.0: client.codes.update() accepterer appearance og returnerer resultaterne af kontrastkontrollen som issues i resultatet; uden fund mangler feltet. client.codes.imageUrl() accepterer fg, bg og ecc. Enhver kode, som API’en returnerer (get, list, create, update, batchCreate), indeholder title og appearance.
  • Opdatering: npm install @qr3/sdk@latest. Python, Go og PHP følger. Detaljer: SDK’er & CLI og Gem farver på koden.

2026-09 · Ændret udløbstid gælder inden for cirka et minut

  • Rettet: En PATCH på expires_at rydder nu kodens viderestillings-cache. Den nye udløbstid gælder dermed inden for cirka et minut i stedet for først op til 24 timer senere. Tidligere leverede et fjernet eller udskudt udløb fortsat 410 i op til 24 timer, og et udløb sat til nu lod viderestillingen fortsætte i op til 24 timer.
  • Rettet: En kode oprettet med expires_at udløber også til tiden, hvis udløbet ligger inden for de første 24 timer.
  • Rettet: Hvis en kode slettes, mens dens logo uploades eller fjernes, svarer POST og DELETE /v1/codes/:id/logo med 404 og ændrer ikke den slettede kode, ligesom PATCH allerede gør.
  • Rettet: En statisk kode, hvis korte link (redirect_url) er blevet kaldt, ligger også i viderestillings-cachen. Ændring, pausering og sletning rydder den nu også, ikke kun for dynamiske koder.

2026-09 · Gem farver på koden

  • Nyhed: PATCH /v1/codes/:id accepterer appearance med foreground_color og background_color (#RRGGBB, baggrunden også transparent). qr.svg og qr.png tegner de gemte farver uden parametre; en parameter som ?fg=000000 har fortsat forrang. PDF og EPS tegner først farver i en senere version.
  • Kontrastkontrol: Et par under 1,5:1 resulterer i 422. Svagere par gemmes og rapporteres i meta.issues som warning eller critical; en gennemsigtig baggrund er altid critical, aldrig blokeret.
  • Sammenfletning: Udeladte felter beholder deres gemte værdi, null nulstiller. Samtidige ændringer på den samme kode overskriver ikke længere hinanden.
  • I hvert kodesvar: appearance er inkluderet i hvert kodesvar og i webhooks qr.created og qr.updated. POST, batchen og importen afviser det med 422.
  • Ingen ændring for eksisterende koder: Uden gemte farver leverer hver kode de samme bytes som før. Detaljer: Gem farver på koden.

2026-09 · Farver og fejlkorrektion som parametre til billedruterne

  • Ny: Alle fire billedruter accepterer fg (forgrundsfarve), bg (baggrundsfarve eller transparent) og ecc (fejlkorrektion L, M, Q, H). SVG og PNG tegner farverne; PDF og EPS accepterer dem, men tegner dem først med en senere udgivelse. ecc virker i alle fire formater, og et logo gennemtvinger fortsat H.
  • Gennemsigtighed: bg=transparent returnerer en SVG uden baggrund og en PNG med ægte alfakanal. Underlaget skal være lyst og holde frizonen fri.
  • Aldrig en fejl: Ugyldige værdier ignoreres; billedet leveres så præcis som uden parameteren.
  • Caching: Enhver gældende parameter leverer Cache-Control: public, max-age=300 i stedet for standardbilledets 24 timer.
  • Ingen ændring uden parametre: Enhver eksisterende kode leverer de samme bytes som før i alle fire formater.
  • Tilgængelig i alle abonnementer. Detaljer: Farver og fejlkorrektion.

2026-09 · PDF og EPS indlejrer nu også logoet

  • Udvidelse: qr.pdf og qr.eps indlejrer nu et defineret logo på nøjagtig samme måde som qr.svg og qr.png (se nedenfor) — som et indlejret billede (PDF via et Image XObject, EPS via en billed-dictionary i PostScript, der kun med %%LanguageLevel: 3), centreret på det samme område, med den samme forøgelse af fejlkorrektionen til H. Begge formater leverede tidligere ikke logoet; dette er nu rettet.
  • Caching: Med et defineret logo leverer qr.pdf og qr.eps nu også Cache-Control: public, max-age=300 i stedet for de sædvanlige 24 timer — præcis som SVG/PNG.
  • Fallback: Hvis selve logobilledet ikke kan behandles (f.eks. et beskadiget gemt objekt), forbliver fejlkorrektionen H, men det reserverede område forbliver tomt i stedet for et billede — aldrig en serverfejl.
  • Ingen ændring i adfærd uden logo: Koder uden logo leverer fortsat qr.pdf/qr.eps byte-identisk, med uændret 24-timers cache.
  • Detaljer og trykvejledning: Logo i QR-koden.

2026-09 · Logo i QR-kode — Dashboard og API

  • Ny: En kode kan nu have et logo i midten. I Dashboard opretter detaljesiden for en kode sit eget logo-kort: Vælg logo, ved første tilføjelse eller ved fjernelse skal en advarsel bekræftes med et obligatorisk afkrydsningsfelt (begge ændrer punktmønsteret), derefter Upload logo/Fjern logo. En erstatning kræver ikke bekræftelse — kun billedet skifter, ikke mønsteret. Rollen viewer ser status og forhåndsvisning, men ingen af de tre handlinger.
  • API: POST /v1/codes/{id}/logo (multipart-felt file; PNG, JPEG eller WebP, højst 1 MB, SVG afvises) opretter et logo eller erstatter det; DELETE /v1/codes/{id}/logo fjerner det igen og er idempotent. Et for stort billede returnerer 413, et ikke-understøttet format 422, rollen viewer 403.
  • Visning: qr.svg og qr.png indlejrer logoet som faktiske pixels (512 × 512, normaliseret) og hæver derved fejlkorrektionen til H. Tilføjelse og fjernelse ændrer dermed punktmønsteret (M ↔ H), men en erstatning gør ikke. qr.pdf og qr.eps indlejrer ikke noget logo og forbliver uændrede. En allerede trykt kode fungerer under alle omstændigheder fortsat, da den kodede destination ikke afhænger af logoet — kun de, der også ønsker at se det (nye) logo-udseende på materialet, behøver at genoptrykke, og de bør undgå at blande gamle og nye trykfiler.
  • Caching: Med et indstillet logo returnerer qr.svg og qr.png Cache-Control: public, max-age=300 i stedet for de sædvanlige 24 timer. Detaljer, grænseværdier og trykvejledning: Logo i QR-koden.

2026-08 · operationId for alle 75 operationer, og en vejledning til agenter om, hvornår qr3.app skal bruges

  • Tilføjelse: Alle 75 operationer i OpenAPI-specifikationen har nu en operationId — listCodes, createCode, getCodeStats, archiveWorkspace og så videre. Tidligere manglede feltet overalt, så enhver generator var nødt til at udlede metodenavnet fra HTTP-metode og sti (postV1Codes). Sådanne navne afhænger af stien og ændrer sig ved enhver omstrukturering af stien. Navneformatet er ens på alle 75 steder: list/get/create/update/replace/delete, ellers verbet for den forretningsmæssige handling (validateDpp, registerGs1Identifier, pingWebhook). Verbet følger forretningslogikken, ikke HTTP-metoden — archiveWorkspace er en DELETE, importDpps er en POST.
  • Konsekvens for selvgenererede klienter: Hvis du genererer dit SDK ud fra specifikationen, vil du ved næste kørsel få omdøbte metoder (postV1Codes → createCode). Dette er formålet med ændringen, men det er en omdøbning i ekstern kode — derfor nævnes det udtrykkeligt her. Stier, parametre, svarformater og statuskoder er uændrede; de officielle SDKs, CLI og MCP-serveren er ikke berørt.
  • Startpunkt for agenter: https://qr3.app/llms.txt har et afsnit ## When to use qr3.app — seks opgaver i stedet for seks funktioner, plus sætningen om, hvad qr3.app ikke er det rigtige værktøj til. Den samme information leverer MCP-serveren nu i sit håndtryk: initialize mod https://mcp.qr3.app/mcp svarer med et felt instructions (tidligere: elleve værktøjer uden nogen form for kontekst). Det er også angivet, hvilke kald der kræver en API-nøgle — initialize og tools/list gør ikke, men ethvert tools/call gør.
  • Rettelser i llms.txt: Fire oplysninger blev testet mod produktion og holdt ikke stik: (1) Python-SDK’et qr3app er ikke udgivet på PyPI — pip install-linjen er fjernet uden erstatning; (2) Accept: text/markdown gælder for startside og blog, ikke for enhver server-side renderet side; (3) kontaktadressen er [email protected], også i startsidens JSON-LD; (4) /de/security/ er en videresendelse til et anker, ikke en selvstændig side. Nyt link: docs.qr3.app/de/skills/.
  • Sikring: Tre assertioner i openapi-spec.test.ts — fuldstændighed, entydighed, lowerCamelCase —, hver især krydstjekket med en mutation. Ni yderligere test fastholder de fire rettede oplysninger, så de ikke vender tilbage.
  • Kendt begrænsning: To af de 75 operationer er beskrevet i specifikationen, men svarer med 404 (GET /v1/codes/{id}/stats og GET /v1/account). De har fået et navn her og mister det igen, så snart det er besluttet, om de skal bygges eller slettes.

2026-08 · Nedgraderinger af abonnementer og opsigelser påvirker nu også grænserne

  • Fix: Stripe-webhooken skrev kun abonnementsnavnet ved abonnementsskift og opsigelse, ikke organisationens fire grænsespalter (max_workspaces, max_members, max_dynamic_codes, max_scans_per_month). Da håndhævelsen tager maksimummet af den gemte værdi og abonnements-baselinen, beholdt en nedgraderet eller opsagt organisation sine gamle, højere grænser — nedgraderingen var uden virkning. Webhooken sætter nu spalterne til baselinen for det nye abonnement ved ethvert reelt abonnementsskift, og til Free-baselinen ved opsigelse — nøjagtig som admin-administrationen allerede gør.
  • Adfærd: Rutinemæssige opdateringer af abonnementet (fornyelse, betalingsmiddel, prorering) rører fortsat ikke ved grænserne; individuelt tildelte højere grænser forbliver uændrede. Først et reelt abonnementsskift nulstiller dem til baselinen for det nye abonnement.
  • Konsekvens: Ingen ændringer i API eller svarformat. Organisationer, hvis nedgradering fandt sted før dette fix, beholder de gamle værdier, indtil det næste abonnementsskift træder i kraft, eller supporten tilpasser dem.

2026-08 · Keyset-cursor nu på alle liste-endpoints

  • Fix: Cursor-rettelsen til GET /v1/codes og GET /v1/dpp (se nedenfor) er nu rullet ud til alle øvrige cursor-paginerede lister: GET /v1/qr-codes/:id/comments, /v1/workspaces, /v1/gs1/identifiers, /v1/members, /v1/audit-logs, /v1/admin/orgs, /v1/admin/users og /v1/webhooks/:id/deliveries. Alle paginerede udelukkende via created_at; rækker med identisk tidsstempel (audit-log-poster fra en batch-handling, webhook-retries, medlemsimporter) kunne gå tabt på den efterfølgende side. Sorteringsnøglen er nu overalt tuplen (created_at, id).
  • API-ændring: På disse lister er meta.pagination.next_cursor fra nu af også en opak værdi (base64url) i stedet for et råt tidsstempel; ulæselige cursorer returnerer 400, og gamle tidsstempel-cursorer accepteres fortsat i en overgangsperiode. Undtagelse GET /v1/webhooks/:id/deliveries: her forbliver next_cursor id’et på den sidste levering (ukendt id → første side). Klienter, der returnerer next_cursor uændret — Dashboard, CLI, SDKs, MCP —, skal ikke ændre noget.
  • Konsekvens: Ingen migrering nødvendig. Hvis du har manglet poster, når du bladrede i en af disse lister (f.eks. audit-log eller leveringslog i Dashboard): De var aldrig væk — listerne viser dem fuldstændigt fra nu af.

2026-08 · Tidsstempler efter redigering og sletning er igen OpenAPI-kompatible

  • Fix: Efter PATCH /v1/codes/{id} returnerede updated_at i SQLite-format uden tidszone (2026-08-17 09:00:00), selvom OpenAPI-specifikationen angiver format: date-time og oprettelse (POST) leverer ISO-tidsstemplet (2026-08-17T09:00:00.000Z). Det samme gjaldt for deleted_at/updated_at ved soft-delete samt for redigerings-/sletningsstierne for API-Keys, organisationer, workspaces, medlemmer, kommentarer og webhooks, derudover for last_used_at for API-Keys og last_triggered_at for webhooks. Alle skrivestier stempler nu ISO 8601 (UTC, T og Z).
  • Konsekvens: Klienter, der parser updated_at med new Date(...) (SDKs, CLI, Dashboard), læste mellemrumsformatet som lokaltid — CLI’en viste for koder, der var blevet redigeret, klokkeslættet forskudt med det lokale offset (Wien: −2 t). Dette er rettet. Derudover normaliserer en datamigrering allerede gemte værdier i det gamle format til ISO, så sortering og sammenligninger i blandede datasæt stemmer. Ingen ændring af feltnavne eller svarstruktur.
  • Baggrund: Samme fejlklasse som de to rettelser nedenfor (API-Key-udløb, re-scan-cutoff): SQLites datetime('now') skriver YYYY-MM-DD HH:MM:SS, alle andre skrivere skriver ISO 8601. En kildekods-guard-test forhindrer fremtidige forekomster.

2026-08 · Listepaginering mister ikke længere batch-koder

  • Fix: GET /v1/codes og GET /v1/dpp paginerede udelukkende via created_at. Koder fra POST /v1/codes/batch, POST /v1/dpp/batch og CSV/XLSX-importen deler dog ét tidsstempel — så snart et batch var større end limit (standard 20), leverede den anden side ikke længere de resterende rækker med det samme tidsstempel. Koderne eksisterede og var tilgængelige via GET /v1/codes/:id, men dukkede aldrig op i listen (Dashboard, CLI qr3 list, SDKs, MCP). Cursoren er nu et keyset over (created_at, id).
  • API-ændring: meta.pagination.next_cursor er fra nu af en opak værdi (base64url) i stedet for et råt tidsstempel. Hvis man returnerer cursoren uændret som ?cursor= — ligesom Dashboard, CLI, alle SDKs og MCP-serveren gør — behøver man ikke at ændre noget. Gamle tidsstempel-cursorer accepteres fortsat i en overgangsperiode; ulæselige cursorer returnerer nu 400 i stedet for stiltiende at levere den første side.
  • Konsekvens: Hvis du efter en batch-import så færre koder i listen, end der blev oprettet: Koderne var aldrig væk — listen viser dem fuldstændigt fra nu af. Ingen migrering nødvendig.

2026-08 · Sikkerheds-re-scanninger kører igen i 24-timers intervaller

  • Fix: Den periodiske re-scanning af destinations-URL’er og landingsside-links (Google Web Risk) sprang koder over, hvis seneste scanning lå på samme kalenderdag som 24-timers-cutoff’en — afhængigt af tidspunktet blev re-scanningen forsinket med op til en ekstra dag. Cutoff’en beregnes nu i samme ISO-format, som scannings-tidsstemplerne er gemt i.
  • Konsekvens: En destinations-URL, der efter den seneste scanning klassificeres som usikker, fører igen til automatisk pausering af koden inden for det dokumenterede 24-timers vindue. Ingen ændringer i API eller svarformat.

2026-08 · API-nøgler udløber på udløbstidspunktet

  • Fix: En API-nøgle, hvis expires_at var på samme dag, blev fortsat accepteret indtil midnat UTC. Udløbet sammenlignes nu som et tidsstempel i stedet for som en streng — en udløbet nøgle returnerer med det samme 401.
  • Baggrund: expires_at gemmes som et ISO-tidsstempel (2026-08-14T09:00:00Z), mens sammenligningssiden leverede formatet med mellemrum (2026-08-14 09:00:00). Den rå strengsammenligning stemte derfor kun, så længe selve datoen var forskellig.
  • Konsekvens: Ingen migrering nødvendig, svarformatet for GET /v1/api-keys forbliver uændret. Ulæselige udløbsværdier betragtes nu som udløbne i stedet for som gyldige.

2026-08 · API-reference: Tenant-administration dokumenteret

  • OpenAPI: Specifikationen — og dermed den interaktive reference — dokumenterer nu organisationer (inkl. GET /v1/organizations/usage), workspaces, medlemmer & roller og audit-logs.
  • Billing: Abonnementsoversigten (GET /v1/billing/plans) er offentlig; checkout (POST /v1/billing/checkout) og Stripe-kundeportal (GET /v1/billing/portal) er angivet som endpoints for organisationsadministratorer.
  • Scan-eksport: Scan-statistikker (GET /v1/codes/{id}/scans) og rådata-eksport (…/scans.csv, …/scans.xlsx) er fuldt dokumenteret — inklusive GDPR-bemærkning: ip_hash er aldrig inkluderet i eksporten.
  • Fejladfærd: Også 400-svaret for forespørgselsvalidering er nu dokumenteret: Bodyen er den rå Zod-fejl, ikke et RFC-7807-problemdokument — den leveres dog stadig under Content-Type application/problem+json.
  • Dashboard: Offentlige filer på en kodes detaljeside har nu en knap, der kopierer filens offentlige link til udklipsholderen. Linket kan bruges direkte som destinations-URL for en QR-kode, når en scanning straks skal åbne et bestemt dokument i stedet for landingssiden med fillisten.
  • API: Fil-endpoints (/v1/files) leverer desuden public_url. Feltet udfyldes kun for filer med visibility: public – private filer får ingen offentlig adresse.
  • Adfærd: Linket kræver ikke login og åbner filen direkte i browseren. Hvis du bruger Erstat på filen, ændres linket ikke, og en allerede trykt QR-kode forbliver gyldig. Detaljer: Filer & datablade.

2026-07 · Teamroller: Bidragyder uden sletning & administratorfakturering

  • Nyt: Medlemsrollen Bidragyder (uden sletning) — opretter og redigerer QR-koder, filer og Digital Product Passports, men kan ikke slette noget og ikke oprette API-Keys. Alle destruktive endpoints kontrollerer rollen på serversiden (403).
  • Fakturering: Abonnementopgraderinger og Stripe-kundeportalen (POST /v1/billing/checkout, GET /v1/billing/portal) er nu forbeholdt organisationsadministratorer — alle andre roller ser en skrivebeskyttet abonnementsoversigt.
  • Dashboard: Handlinger, som ens egen rolle ikke tillader, skjules: En Læser ser f.eks. ingen knapper til at oprette, redigere eller slette; lister, downloads og statistikker forbliver synlige. Detaljer: Team & roller.
  • Landingsside: En kodes qr3-hostede landingsside kan nu vise eksterne, selv-hostede links ({ label, url }) ud over eller i stedet for uploadede filer – f.eks. til datablade på dit eget websted.
  • API: POST/PATCH /v1/codes accepterer et links-array (0–20 poster, http(s), ≤ 2048 tegn). Hver URL kontrolleres med Google Web Risk; en usikker URL returnerer 422. Et tomt array rydder alle links.
  • Dashboard: Tilføj, omarranger og fjern links på kodens detaljeside.
  • Sikkerhed: Gengivne links forbliver XSS-sikre (escaped, kun http(s)), og siden bevarer sin noindex-header.

2026-04 · Dashboard-analyse pr. QR-kode

  • Dashboard: Analyse-knappen i QR-kodelisten åbner nu statistikside for den pågældende QR-kode under /dashboard/codes/{id}.
  • Routing: Aliasset /dashboard/codes viderestiller stadig til /dashboard, men fanger ikke længere detaljerede ruter som /dashboard/codes/{id}.
  • API: Detaljesiden indlæser QR-koden direkte via GET /v1/codes/:id; derved er den ikke længere afhængig af grænser for listepaginering.
  • Tests: Regressionstest dækker alias-viderestillingen og den direkte indlæsning af koden.

2026-04 · Dashboard-slettedialog for QR-koder

  • Dashboard: Skraldespandsikonet i QR-kodelisten åbner nu en dedikeret React-dialog i stedet for en nativ browser-popup.
  • Feedback: Efter sletning vises en toast-besked for succes eller fejl.
  • Tests: packages/dashboard/tests/dashboard.test.ts forhindrer regressioner på confirm() i QR-kode-sletteflowet.
  • Dashboard: Shortcodes i QR-kodelisten er nu direkte klikbare som eksterne viderestillingslinks. Det eksterne link-ikon ved siden af f.eks. wu3qaa åbner https://qr3.app/{shortCode} i en ny fane.
  • i18n: Tooltip-tekster tilføjet for tysk og engelsk.
  • Tests: packages/dashboard/tests/dashboard.test.ts beskytter link-href, ny fane-adfærd, noopener noreferrer og ikon mod regressioner.

2026-04 · Redirect-Worker-rute for dynamiske QR-koder

  • Fix: Dynamiske QR-koder under https://qr3.app/{shortCode} behandles igen af Redirect-Worker. Produktionsruten bruger nu qr3.app/*, fordi Cloudflare Worker-ruter ikke understøtter :code-stiparametre.
  • Hærdning: Ikke-matchende stier sendes videre til landing-origin, så normale sider som /de/pricing ikke blokeres af Redirect-Worker.
  • Tests: packages/redirect/tests/unit/redirect.test.ts tester wildcard-ruten, shortcode-behandling og origin-pass-through.

2026-04 · Workspace-DPP-scannings-oversigt (Q3.4.2)

  • Ny: GET /v1/workspace/stats/dpp?days=30 — aggregerer alle dpp_scans for API-nøgle-workspacet (active_dpps, scans_by_day, top_dpps med produktnavn/kategori).
  • Dashboard: Kort på startside (/dashboard) med 30-dages søjlediagram + toplister — parallelt med QR-kode-kortene.
  • Public: Marketing-kortlink GET /dpp/dpp_<id> (ét segment) til live-demoer, parallelt med /dpp/{gtin}/{serial}.

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

  • Ny: GET /v1/dpp/:id/stats?days=30 — aggregerede scanninger fra den offentlige GS1-resolver pr. DPP. Felter: total_scans, period_scans, scans_by_day, top_countries, top_devices, top_representations.
  • Ny: Tabel dpp_scans (migration 0011) — adskilt fra scans (Redirect-Worker). IP-adresser hashes med en dagligt roterende salt, rå IP’er når aldrig D1.
  • Dashboard: Mini-diagramkort (SVG, intet diagrambibliotek) på /dashboard/dpp/:dppId med 30-dages søjler + top 3-opdelinger. Empty-state så snart et DPP er live, men endnu ikke har haft nogen scanninger.

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

  • Ny: POST /v1/dpp/:id/validate-update — simulerer delvise opdateringer stateless (status, markedsliste, …) uden persistens. Svaret indeholder eu_compliance + preview.changed_fields.
  • Dashboard: Simulatorkort i DPP-detaljer (/dashboard/dpp/:dppId) — chips til DE/AT/FR/IT/ES/NL + Custom, status-dropdown, Forhåndsvis EU-indvirkning / Gem ændringer / Nulstil. Non-blocking via Remix useFetcher.
  • Hærdning: Udflyttede simulator-hjælpere (readUpdatePatchFromForm, marketCountriesKey) + 18 nye enhedstest; fejlretning: Enlig ikke-ISO-input sletter ikke længere markedslisten.

2026-04 · Live EU-overensstemmelsesforhåndsvisning i oprettelsesformularen (Q3.3.6)

  • Ændret: POST /v1/dpp/validate leverer yderligere eu_compliance — samme validator som GET /v1/dpp/:id/eu-compliance, stateless før lagring.
  • Dashboard: Forhåndsvisning under det eksisterende valideringspanel + nyt Save-Guard-banner før submit-knapperne, hvis der er udestående fejl/advarsler (i18n-pluralisering DE/EN).

2026-04 · EU-validator + tekstil-UI (Q3.3.4 + Q3.3.5)

  • Ny: EU-overensstemmelsesvalidator med 5 tekstilregler (TEXTILE_AGEC_REQUIRED, TEXTILE_MICROPLASTICS_CONSISTENCY, TEXTILE_SVHC_THRESHOLD, TEXTILE_GREENWASHING, TEXTILE_ESPR_READY).
  • Ny: GET /v1/dpp/:id/eu-compliance med compliant / espr_ready / issues[] / summary.
  • Dashboard: EU-overensstemmelsessektion i DPP-detaljer (oversigtsfliser, grupperede problemkort, ESPR-Ready-badge i headeren).

2026-04 · Tekstil-DPP-skema (Q3.3.1–Q3.3.3)

  • Ny: Kategori textile med obligatorisk AGEC-kæde (vævning/strikning → farvning/trykning → konfektionering), pr. fiber origin_country + recycled_pct, svhc_substances[], ESPR-tilvalg (PEF, levetid, genanvendelighed).
  • Ny: Basisfelt market_countries: string[] (ISO 3166-1 alpha-2) på alle DPP-kategorier — styrer FR-specifikke AGEC-regler og den franske obligatoriske forbrugeroplysning.
  • Ny: Forbruger-HTML-skabelon med AGEC-mikroplastadvarselsboks, 3-trins oprindelseskæde (flag-piller), SVHC-liste, holdbarheds- og genanvendelighedssektion.
  • Migration: 0010_dpp_market_countries (D1).

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

  • Ny: POST /v1/dpp/import accepterer CSV og XLSX (Worker-kompatibel via SheetJS xlsx, ~283 KB gzip bundle).
  • Skaleret: abonnementsbaseret grænse (Free 100 → Enterprise 10k) + chunked db.batch() à 100 + 5 MB body-grænse.
  • Ny: Fejlrapport som CSV i feltet errors_csv i 201-svaret; GET /v1/dpp/import/templates/:category?format=csv|xlsx leverer færdige skabeloner til batteri og tekstil.
  • Dashboard: Drag-and-drop-upload under /dashboard/dpp/import med skabelon-proxy og inline CSV-download.

Ikke-breaking — LTS-udvidelser

Alle ovennævnte ændringer er additive:

  • Eksisterende POST /v1/dpp/validate-klienter ignorerer det nye eu_compliance-felt uden ændringer.
  • Eksisterende battery-flows er uændrede.
  • market_countries er valgfri og har standardværdien [].

Se API-versionering for breaking change-politikken.