Changelog
Changelog
Wybrane najważniejsze zmiany z ostatnich wydań. Pełne wersje API i zasady wprowadzania zmian niekompatybilnych wstecz (Breaking-Change-Policy) znajdują się w sekcji Wersjonowanie API i polityka LTS.
Szczegółowe zmiany w poszczególnych punktach końcowych: Specyfikacja OpenAPI oraz interaktywna referencja API.
2026-10 · Kolory w Dashboardzie
- Nowość: strona szczegółów kodu ma kartę Kolory: pierwszy plan i tło jako wartość szesnastkowa, przezroczyste tło, podgląd przez rzeczywistą ścieżkę obrazu. Kontrola jest taka sama jak w
PATCH /v1/codes/{id}: pary krytyczne wymagają potwierdzenia, pary poniżej 1,5:1 nie dają się zapisać. - Przywrócenie czarnego na białym dostarcza we wszystkich czterech formatach znów te same bajty co bez kolorów. Kody bez kolorów się nie zmieniają.
- Przezroczyste kody pojawiają się na szachownicy we wszystkich podglądach Dashboardu. Szczegóły: Kolory w Dashboardzie.
2026-10 · Kolory w PDF i EPS
- Nowość:
qr.pdfiqr.epsrenderująfgibg, jako parametry oraz jako zapisane kolory. Czerń i każda szarość są zapisywane jako skala szarości (tylko czarna płyta), a każdy inny kolor jako CMYK w pełnych procentach, na przykład1F4E79jako C74 M36 Y0 K53. - Tło jak w SVG: Gdy tylko zostanie wybrany kolor, za kodem i jego strefą ochronną znajduje się kryjący obszar, biały lub
bg.bg=transparentnie renderuje tła. Tytuł pozostaje czarny, a płyta logo biała. - Brak zmian bez kolorów: Bez
fg/bgi bez zapisanych kolorów oba formaty dostarczają te same bajty co wcześniej. Plik PDF paszportu produktu pozostaje bezbarwny. - Ograniczenia: brak profilu ICC, brak PDF/X. Szczegóły: Kolory w druku.
2026-09 · Statyczne kody bez pamięci podręcznej przekierowań, jednoczesne usuwanie
- Zmieniono: Statyczne kody nie znajdują się już w pamięci podręcznej przekierowań. Wywołanie ich krótkiego linku (
redirect_url) zawsze odczytuje aktualny stan. Dlatego poDELETE /v1/accountstatyczny kod nie przekierowuje już przy następnym wywołaniu (wcześniej trwało to do 24 godzin). Również zmiana taryfy działa natychmiast w przypadku statycznych kodów. Usuwanie konta czyści kody dynamiczne tak jak dotychczas. Wydrukowane kody statyczne zawierają swój cel bezpośrednio i ta zmiana ich nie dotyczy. - Naprawiono: Dwa jednoczesne żądania
DELETE /v1/codes/:iddo tego samego kodu zwracają raz200, a raz404. Webhookqr.deletedjest wysyłany dokładnie raz, wcześniej dwukrotnie. - Nowość:
POSTiDELETE /v1/codes/:id/logoodpowiadają kodem409(errors/conflict), jeśli inne żądanie jednocześnie zmieniło logo tego samego kodu, i wtedy nic nie zmieniają. Wcześniej przesłane logo mogło pozostać zapisane i nieużywane. Dwa jednoczesne żądaniaDELETE /v1/codes/:id/logozwracają w obu przypadkach200. Szczegóły: Logo.
2026-09 · TypeScript-SDK 1.2.0
- Nowość w
@qr3/sdk1.2.0:client.codes.update()przyjmujeappearancei zwraca wyniki testu kontrastu jakoissuesw wyniku; przy braku uwag pole to nie występuje.client.codes.imageUrl()przyjmujefg,bgiecc. Każdy kod zwracany przez API (get,list,create,update,batchCreate) zawieratitleiappearance. - Aktualizacja:
npm install @qr3/sdk@latest. Python, Go i PHP wkrótce. Szczegóły: SDKs & CLI oraz Zapisywanie kolorów w kodzie.
2026-09 · Zmieniony czas wygaśnięcia obowiązuje w ciągu około minuty
- Naprawiono: Żądanie
PATCHnaexpires_atczyści teraz pamięć podręczną przekierowań kodu. Nowy czas wygaśnięcia obowiązuje dzięki temu w ciągu około minuty, zamiast dopiero do 24 godzin później. Poprzednio usunięty lub przesunięty czas wygaśnięcia nadal zwracał410przez maksymalnie 24 godziny, a czas wygaśnięcia ustawiony na “teraz” pozwalał na dalsze działanie przekierowania przez maksymalnie 24 godziny. - Naprawiono: Kod utworzony z
expires_atwygasa terminowo również wtedy, gdy wygaśnięcie następuje w ciągu pierwszych 24 godzin. - Naprawiono: Jeśli kod zostanie usunięty podczas przesyłania lub usuwania jego logo,
POSTorazDELETE /v1/codes/:id/logoodpowiadają statusem404i nie modyfikują usuniętego kodu, podobnie jak miało to już miejsce w przypadkuPATCH. - Naprawiono: Również kod statyczny, którego krótki link (
redirect_url) został wywołany, znajduje się w pamięci podręcznej przekierowań. Modyfikacja, wstrzymanie i usunięcie również go teraz czyszczą, a nie tylko w przypadku kodów dynamicznych.
2026-09 · Zapisywanie kolorów dla kodu
- Nowość:
PATCH /v1/codes/:idakceptujeappearancezforeground_coloribackground_color(#RRGGBB, tło równieżtransparent).qr.svgiqr.pngrysują zapisane kolory bez żadnych parametrów; parametr zapytania, taki jak?fg=000000, nadal ma pierwszeństwo. PDF i EPS będą rysować kolory dopiero w późniejszej wersji. - Kontrola kontrastu: Para poniżej 1,5:1 zwraca
422. Słabsze pary są zapisywane i zgłaszane wmeta.issuesjakowarninglubcritical; przezroczyste tło jest zawsze traktowane jakocritical, nigdy blokowane. - Scalanie: Pominięte pola zachowują swoją zapisaną wartość,
nullresetuje ustawienia. Jednoczesne zmiany w tym samym kodzie nie nadpisują się już wzajemnie. - W każdej odpowiedzi kodu:
appearanceznajduje się w każdej odpowiedzi kodu oraz w webhookachqr.creatediqr.updated.POST, proces wsadowy (batch) oraz import odrzucają je z błędem422. - Brak zmian dla istniejących kodów: Bez zapisanych kolorów każdy kod dostarcza te same bajty co wcześniej. Szczegóły: Zapisywanie kolorów dla kodu.
2026-09 · Kolory i korekcja błędów jako parametry ścieżek obrazu
- Nowość: Wszystkie cztery ścieżki obrazu akceptują
fg(kolor pierwszego planu),bg(kolor tła lubtransparent) orazecc(korekcja błędówL,M,Q,H). SVG i PNG renderują kolory; PDF i EPS akceptują je, ale będą je renderować dopiero w późniejszym wydaniu.eccdziała we wszystkich czterech formatach, a logo nadal wymuszaH. - Przezroczystość:
bg=transparentzwraca SVG bez tła oraz PNG z prawdziwym kanałem alfa. Podłoże musi być jasne i pozostawiać wolną strefę ciszy. - Nigdy nie powoduje błędu: Nieprawidłowe wartości są ignorowane; obraz jest wtedy zwracany dokładnie tak samo, jak bez parametrów.
- Pamięć podręczna: Każdy skuteczny parametr zwraca
Cache-Control: public, max-age=300zamiast 24 godzin dla obrazu standardowego. - Brak zmian w zachowaniu bez parametrów: Każdy istniejący kod zwraca we wszystkich czterech formatach te same bajty co wcześniej.
- Dostępne w każdym planie. Szczegóły: Kolory i korekcja błędów.
2026-09 · PDF i EPS teraz również osadzają logo
- Rozszerzenie:
qr.pdfiqr.epsosadzają teraz ustawione logo dokładnie tak samo jakqr.svgiqr.png(patrz poniżej) — jako osadzony obraz (PDF poprzezImage XObject, EPS poprzez słownik obrazu w PostScript, tam tylko z%%LanguageLevel: 3), wyśrodkowany na tym samym obszarze, z tym samym podniesieniem korekcji błędów doH. Oba formaty do tej pory nie dostarczały logo; zostało to teraz naprawione. - Pamięć podręczna: Przy ustawionym logo również
qr.pdfiqr.epszwracają terazCache-Control: public, max-age=300zamiast zwykłych 24 godzin — dokładnie tak samo jak SVG/PNG. - Wariant awaryjny: Jeśli sam obraz logo nie może zostać przetworzony (na przykład uszkodzony zapisany obiekt), korekcja błędów pozostaje na poziomie
H, ale zarezerwowany obszar pozostaje pusty zamiast obrazu — nigdy nie powoduje to błędu serwera. - Brak zmian w zachowaniu bez logo: Kody bez logo nadal dostarczają
qr.pdf/qr.epsw identycznej postaci bajtowej, z niezmienioną 24-godzinną pamięcią podręczną. - Szczegóły i wskazówki dotyczące druku: Logo w kodzie QR.
2026-09 · Logo w kodzie QR — Dashboard i API
- Nowość: Kod może teraz zawierać logo na środku. W Dashboardzie strona szczegółów kodu tworzy dedykowaną kartę logo: Wybierz logo, przy pierwszym dodaniu lub przy usuwaniu potwierdź ostrzeżenie z wymaganym polem wyboru (obie czynności zmieniają wzór punktowy), a następnie Prześlij logo/Usuń logo. Zastąpienie nie wymaga potwierdzenia — zmienia się tylko obraz, a nie wzór. Rola
viewerwidzi status i podgląd, ale nie ma dostępu do żadnej z trzech akcji. - API:
POST /v1/codes/{id}/logo(pole typu multipartfile; PNG, JPEG lub WebP, maksymalnie 1 MB, SVG jest odrzucane) tworzy lub zastępuje logo;DELETE /v1/codes/{id}/logousuwa je i jest idempotentne. Zbyt duży obraz zwraca413, nieobsługiwany format422, a rolaviewerzwraca403. - Renderowanie:
qr.svgiqr.pngosadzają logo jako rzeczywiste piksele (512 × 512, znormalizowane) i w tym celu podnoszą poziom korekcji błędów doH. Dodanie i usunięcie zmieniają tym samym wzór punktowy (M↔H), natomiast zastąpienie go nie zmienia.qr.pdfiqr.epsnie osadzają logo i pozostają bez zmian. Wydrukowany już kod działa w każdym przypadku dalej, ponieważ zakodowany cel nie zależy od logo — ponowny wydruk jest konieczny tylko wtedy, gdy chce się zobaczyć (nowy) wygląd logo również na materiale, i nie należy przy tym mieszać starych i nowych plików do druku. - Pamięć podręczna: Przy ustawionym logo
qr.svgiqr.pngzwracająCache-Control: public, max-age=300zamiast zazwyczaj stosowanych 24 godzin. Szczegóły, limity i wskazówki dotyczące drukowania: Logo w kodzie QR.
2026-08 · operationId dla wszystkich 75 operacji oraz instrukcja „kiedy używać” dla agentów
- Uzupełnienie: Wszystkie 75 operacji w specyfikacji OpenAPI posiada teraz
operationId—listCodes,createCode,getCodeStats,archiveWorkspacei tak dalej. Do tej pory tego pola brakowało we wszystkich miejscach, przez co każdy generator musiał wyprowadzać nazwę metody z metody HTTP i ścieżki (postV1Codes). Takie nazwy są powiązane ze ścieżką i zmieniają się przy każdej modyfikacji ścieżki. Format nazw jest taki sam we wszystkich 75 miejscach:list/get/create/update/replace/delete, w innych przypadkach czasownik określający operację biznesową (validateDpp,registerGs1Identifier,pingWebhook). Czasownik wynika z logiki biznesowej, a nie z metody HTTP —archiveWorkspacetoDELETE, aimportDppstoPOST. - Wpływ na samodzielnie generowane klienty: Każdy, kto generuje swoje SDK ze specyfikacji, przy kolejnym uruchomieniu otrzyma zmienione nazwy metod (
postV1Codes→createCode). Taki jest cel tej zmiany, ale wiąże się to ze zmianą nazw w zewnętrznym kodzie — stąd ta wyraźna wzmianka. Ścieżki, parametry, formaty odpowiedzi i kody statusu pozostają bez zmian; oficjalne SDK, CLI i serwery MCP nie są objęte tą zmianą. - Wprowadzenie dla agentów:
https://qr3.app/llms.txtzawiera sekcję## When to use qr3.app— sześć zadań zamiast sześciu funkcji, plus zdanie określające, do czego qr3.app nie jest odpowiednim narzędziem. Te same informacje serwer MCP przekazuje teraz podczas nawiązywania połączenia (handshake):initializewysłane dohttps://mcp.qr3.app/mcpodpowiada poleminstructions(wcześniej: jedenaście narzędzi bez żadnego przyporządkowania). Zawiera również informację, które wywołania wymagają klucza API —initializeoraztools/listnie, natomiast każdetools/calltak. - Poprawki w
llms.txt: Cztery informacje zostały zweryfikowane z produkcją i okazały się niepoprawne: (1) SDK dla języka Pythonqr3appnie jest opublikowane w PyPI — linijka zpip installzostała usunięta bez zamiennika; (2) nagłówekAccept: text/markdowndotyczy strony głównej i bloga, a nie każdej strony renderowanej po stronie serwera; (3) adres kontaktowy to[email protected], również w JSON-LD strony głównej; (4)/de/security/to przekierowanie do kotwicy, a nie osobna strona. Nowy link:docs.qr3.app/de/skills/. - Zabezpieczenie: Trzy asercje w
openapi-spec.test.ts— kompletność, unikalność,lowerCamelCase— każda zweryfikowana za pomocą mutacji. Dziewięć kolejnych testów utrwala te cztery poprawione informacje, aby zapobiec ich ponownemu pojawieniu się. - Znane ograniczenie: Dwie z 75 operacji są opisane w specyfikacji, ale zwracają kod
404(GET /v1/codes/{id}/statsorazGET /v1/account). Otrzymały one tutaj nazwę i utracą ją ponownie, gdy tylko zapadnie decyzja, czy zostaną zaimplementowane, czy usunięte.
2026-08 · Downgrade’y planów i anulowania subskrypcji wpływają teraz również na limity
- Poprawka: Webhook Stripe przy zmianie planu i anulowaniu subskrypcji zapisywał tylko nazwę planu, a nie cztery kolumny limitów organizacji (
max_workspaces,max_members,max_dynamic_codes,max_scans_per_month). Ponieważ egzekwowanie limitów przyjmuje wartość maksymalną z zapisanej wartości oraz poziomu bazowego planu (baseline), zredukowana lub anulowana organizacja zachowywała swoje stare, wyższe limity — downgrade był bezskuteczny. Webhook ustawia teraz te kolumny przy każdej rzeczywistej zmianie planu na poziom bazowy nowego planu, a przy anulowaniu na poziom bazowy planu Free — dokładnie tak, jak robi to już panel administracyjny. - Zachowanie: Rutynowe aktualizacje subskrypcji (przedłużenie, metoda płatności, proporcjonalne rozliczenie) nadal nie wpływają na limity; indywidualnie przyznane wyższe limity pozostają bez zmian. Dopiero rzeczywista zmiana planu resetuje je do poziomu bazowego nowego planu.
- Wpływ: Brak zmian w API lub formacie odpowiedzi. Organizacje, których downgrade nastąpił przed tą poprawką, zachowują stare wartości, dopóki nie wejdzie w życie kolejna zmiana planu lub wsparcie techniczne ich nie dostosuje.
2026-08 · Kursor typu keyset teraz na wszystkich endpointach list
- Poprawka: Poprawka kursora dla
GET /v1/codesiGET /v1/dpp(patrz poniżej) została teraz wdrożona dla wszystkich pozostałych list z paginacją opartą na kursorze:GET /v1/qr-codes/:id/comments,/v1/workspaces,/v1/gs1/identifiers,/v1/members,/v1/audit-logs,/v1/admin/orgs,/v1/admin/usersoraz/v1/webhooks/:id/deliveries. Wszystkie one stronicowały wyłącznie pocreated_at; wiersze o identycznym znaczniku czasu (wpisy audytowe operacji wsadowej, ponowne próby webhooków, importy członków) mogły zostać pominięte na kolejnej stronie. Kluczem sortowania jest teraz wszędzie krotka(created_at, id). - Zmiana w API: Na tych listach
meta.pagination.next_cursorjest od teraz również wartością nieprzezroczystą (base64url) zamiast zwykłego znacznika czasu; nieczytelne kursory zwracają400, a stare kursory oparte na znacznikach czasu będą tymczasowo nadal akceptowane. Wyjątek stanowiGET /v1/webhooks/:id/deliveries: tamnext_cursorpozostaje identyfikatorem ostatniego doręczenia (nieznany identyfikator → pierwsza strona). Klienci, którzy zwracająnext_cursorbez zmian — Dashboard, CLI, SDKs, MCP — nie muszą nic zmieniać. - Wpływ: Brak konieczności migracji. Jeśli na którejś z tych list (np. dzienniku audytu lub dzienniku doręczeń w Dashboardzie) brakowało Ci wpisów podczas stronicowania: nigdy nie zniknęły — od teraz listy wyświetlają je w całości.
2026-08 · Znaczniki czasu po edycji i usunięciu ponownie zgodne z OpenAPI
- Poprawka: Po wykonaniu
PATCH /v1/codes/{id}poleupdated_atbyło zwracane w formacie SQLite bez strefy czasowej (2026-08-17 09:00:00), mimo że specyfikacja OpenAPI deklarujeformat: date-time, a tworzenie (POST) zwraca znacznik czasu ISO (2026-08-17T09:00:00.000Z). To samo dotyczyłodeleted_at/updated_atprzy soft-delete, a także ścieżek edycji i usuwania kluczy API, organizacji, obszarów roboczych, członków, komentarzy i webhooków, jak równieżlast_used_atdla kluczy API ilast_triggered_atdla webhooków. Wszystkie ścieżki zapisu generują teraz znaczniki czasu w formacie ISO 8601 (UTC,TiZ). - Wpływ: Klienty, które parsują
updated_atza pomocąnew Date(...)(SDKs, CLI, Dashboard), odczytywały format ze spacją jako czas lokalny — CLI wyświetlało dla kodów, które były już edytowane, godzinę przesuniętą o lokalny offset (Wiedeń: −2 h). Zostało to naprawione. Dodatkowo migracja danych normalizuje już zapisane wartości w starym formacie do standardu ISO, aby sortowanie i porównania w mieszanych zbiorach danych działały poprawnie. Brak zmian w nazwach pól czy strukturze odpowiedzi. - Tło: Ta sama klasa błędu, co w przypadku dwóch poniższych poprawek (wygaśnięcie klucza API, punkt odcięcia ponownego skanowania): funkcja
datetime('now')w SQLite zapisujeYYYY-MM-DD HH:MM:SS, podczas gdy wszystkie inne procesy zapisu używają ISO 8601. Test zabezpieczający w kodzie źródłowym zapobiegnie ponownemu wystąpieniu tego problemu w przyszłości.
2026-08 · Paginacja list nie gubi już kodów tworzonych wsadowo
- Poprawka: Metody
GET /v1/codesiGET /v1/dpprealizowały paginację wyłącznie na podstawiecreated_at. Jednak kody zPOST /v1/codes/batch,POST /v1/dpp/batchoraz importu CSV/XLSX współdzielą jeden znacznik czasu — gdy tylko partia była większa niżlimit(domyślnie 20), druga strona nie zwracała już pozostałych wierszy z tym samym znacznikiem czasu. Kody istniały i były dostępne przezGET /v1/codes/:id, ale nigdy nie pojawiały się na liście (Dashboard, CLIqr3 list, SDKs, MCP). Kursor jest teraz zestawem kluczy (keyset) opartym na(created_at, id). - Zmiana w API:
meta.pagination.next_cursorjest od teraz wartością nieprzezroczystą (base64url) zamiast zwykłego znacznika czasu. Każdy, kto przekazuje kursor w niezmienionej formie jako?cursor=— tak jak robią to Dashboard, CLI, wszystkie SDKs i serwer MCP — nie musi nic zmieniać. Stare kursory oparte na znacznikach czasu będą tymczasowo nadal akceptowane; nieczytelne kursory zwracają teraz błąd400zamiast po cichu zwracać pierwszą stronę. - Wpływ: Jeśli po imporcie wsadowym na liście widocznych było mniej kodów niż utworzono: kody te nigdy nie zniknęły — od teraz lista wyświetla je w całości. Brak konieczności migracji.
2026-08 · Ponowne skanowanie bezpieczeństwa znów działa w cyklu 24-godzinnym
- Poprawka: Okresowe ponowne skanowanie docelowych adresów URL i linków stron docelowych (Google Web Risk) pomijało kody, których ostatnie skanowanie przypadało na ten sam dzień kalendarzowy, co 24-godzinny punkt odcięcia — w zależności od godziny ponowne skanowanie opóźniało się o maksymalnie kolejny dzień. Punkt odcięcia jest teraz obliczany w tym samym formacie ISO, w którym zapisywane są znaczniki czasu skanowania.
- Wpływ: Docelowy adres URL, który po ostatnim skanowaniu zostanie sklasyfikowany jako niebezpieczny, ponownie powoduje automatyczne wstrzymanie kodu w udokumentowanym 24-godzinnym oknie. Brak zmian w API lub formacie odpowiedzi.
2026-08 · Klucze API wygasają w momencie wygaśnięcia
- Poprawka: Klucz API, którego
expires_atprzypadał na ten sam dzień, był akceptowany do północy UTC. Wygaśnięcie jest teraz porównywane jako znacznik czasu, a nie jako ciąg znaków — wygasły klucz natychmiast zwraca401. - Tło:
expires_atjest zapisywany jako znacznik czasu ISO (2026-08-14T09:00:00Z), natomiast strona porównująca dostarczała format ze spacją (2026-08-14 09:00:00). Surowe porównanie ciągów znaków działało poprawnie tylko wtedy, gdy różniła się już sama data. - Wpływ: Brak konieczności migracji, format odpowiedzi
GET /v1/api-keyspozostaje bez zmian. Nieczytelne wartości wygaśnięcia są teraz traktowane jako wygasłe, a nie jako ważne.
2026-08 · Referencja API: Zarządzanie tenantami udokumentowane
- OpenAPI: Specyfikacja — a tym samym interaktywna referencja — dokumentuje teraz organizacje (w tym
GET /v1/organizations/usage), workspaces, członków i role oraz dzienniki audytu. - Billing: Przegląd planów taryfowych (
GET /v1/billing/plans) jest publiczny; proces płatności (POST /v1/billing/checkout) oraz portal klienta Stripe (GET /v1/billing/portal) są oznaczone jako punkty końcowe dla administratorów organizacji. - Eksport skanów: Statystyki skanowania (
GET /v1/codes/{id}/scans) oraz eksport surowych danych (…/scans.csv,…/scans.xlsx) są w pełni udokumentowane — w tym uwaga dotycząca RODO:ip_hashnigdy nie jest zawarty w eksporcie. - Obsługa błędów: Nowo udokumentowana jest również odpowiedź
400walidacji żądania: treść (body) to surowy błąd Zod, a nie dokument błędu RFC-7807 — niemniej jednak jest on dostarczany z nagłówkiem Content-Typeapplication/problem+json.
2026-08 · Kopiowanie publicznych linków do plików
- Dashboard: Pliki publiczne na stronie szczegółów kodu mają teraz przycisk, który kopiuje ich link publiczny do schowka – wystarczy wkleić go jako docelowy adres URL kodu QR, gdy zeskanowanie ma od razu otwierać konkretny dokument zamiast strony docelowej z listą plików.
- API: Endpointy plików (
/v1/files) zwracają dodatkowopublic_url. Pole jest ustawiane tylko przy plikach zvisibility: public– pliki prywatne nie mają publicznego adresu. - Zachowanie: Link nie wymaga logowania i otwiera plik bezpośrednio w przeglądarce. Opcja Zamień nie zmienia tego adresu, więc wydrukowany kod QR pozostaje ważny. Szczegóły: Pliki i karty danych.
2026-07 · Role zespołowe: Współtwórca bez usuwania i rozliczenia dla Administratorów
- Nowość: Rola członka Współtwórca (bez usuwania) — tworzy i edytuje kody QR, pliki oraz Digital Product Passports, ale nie może niczego usuwać ani tworzyć kluczy API. Wszystkie destrukcyjne endpointy sprawdzają rolę po stronie serwera (
403). - Rozliczenia: Ulepszenia planów i portal klienta Stripe (
POST /v1/billing/checkout,GET /v1/billing/portal) są teraz zarezerwowane dla Administratorów organizacji — wszystkie pozostałe role widzą podgląd planu tylko do odczytu. - Dashboard: Akcje, na które nie pozwala własna rola, są ukrywane: Widz nie widzi na przykład przycisków do tworzenia, edycji ani usuwania; listy, pobieranie plików i statystyki pozostają widoczne. Szczegóły: Zespół i role.
2026-06 · Linki zewnętrzne na stronie docelowej kodu
- Strona docelowa: Hostowana przez qr3 strona docelowa kodu może teraz wyświetlać zewnętrzne, samodzielnie hostowane linki (
{ label, url }) obok przesłanych plików lub zamiast nich – na przykład dla kart katalogowych na Twojej własnej stronie. - API:
POST/PATCH /v1/codesprzyjmują tablicęlinks(0–20 wpisów,http(s), ≤ 2048 znaków). Każdy adres URL jest sprawdzany za pomocą Google Web Risk; niebezpieczny URL zwraca422. Pusta tablica usuwa wszystkie linki. - Dashboard: Dodawanie, zmiana kolejności i usuwanie linków na stronie szczegółów kodu.
- Bezpieczeństwo: Wyrenderowane linki pozostają bezpieczne pod kątem XSS (z zastosowaniem znaków ucieczki, tylko
http(s)), a strona zachowuje swój nagłóweknoindex.
2026-04 · Analityka dla pojedynczego kodu QR w Dashboardzie
- Dashboard: Przycisk analityki na liście kodów QR otwiera teraz stronę statystyk danego kodu QR pod adresem
/dashboard/codes/{id}. - Routing: Alias
/dashboard/codesnadal przekierowuje na/dashboard, ale nie przechwytuje już tras szczegółowych, takich jak/dashboard/codes/{id}. - API: Strona szczegółów ładuje kod QR bezpośrednio przez
GET /v1/codes/:id; dzięki temu nie zależy już od limitów stronicowania listy. - Testy: Testy regresyjne obejmują przekierowanie aliasu oraz bezpośrednie ładowanie kodu.
2026-04 · Okno dialogowe usuwania kodu QR w Dashboardzie
- Dashboard: Ikona kosza na liście kodów QR otwiera teraz dedykowane okno dialogowe React zamiast natywnego wyskakującego okienka przeglądarki.
- Informacja zwrotna: Po usunięciu pojawia się powiadomienie typu toast informujące o sukcesie lub błędzie.
- Testy: Plik
packages/dashboard/tests/dashboard.test.tszapobiega regresjom związanym zconfirm()w procesie usuwania kodu QR.
2026-04 · Test krótkiego linku dla dynamicznych kodów QR w Dashboardzie
- Dashboard: Krótkie kody (shortcodes) na liście kodów QR można teraz klikać bezpośrednio jako zewnętrzne linki przekierowujące. Ikona linku zewnętrznego obok np.
wu3qaaotwierahttps://qr3.app/{shortCode}w nowej karcie. - i18n: Dodano teksty podpowiedzi (tooltips) dla języka niemieckiego i angielskiego.
- Testy: Plik
packages/dashboard/tests/dashboard.test.tschroni przed regresjami atrybut linku href, zachowanie otwierania w nowej karcie,noopener noreferreroraz ikonę.
2026-04 · Trasa Redirect-Worker dla dynamicznych kodów QR
- Poprawka: Dynamiczne kody QR pod adresem
https://qr3.app/{shortCode}są ponownie przetwarzane przez Redirect-Worker. Trasa produkcyjna używa terazqr3.app/*, ponieważ trasy Cloudflare Workers nie obsługują parametrów ścieżki:code. - Zabezpieczenie: Niedopasowane ścieżki są przekazywane do landing origin, aby standardowe strony, takie jak
/de/pricing, nie były blokowane przez Redirect-Worker. - Testy: Plik
packages/redirect/tests/unit/redirect.test.tsweryfikuje trasę wieloznaczną (wildcard), przetwarzanie krótkich kodów oraz przekazywanie do origin.
2026-04 · Przegląd skanowań DPP w przestrzeni roboczej (Q3.4.2)
- Nowość:
GET /v1/workspace/stats/dpp?days=30— agreguje wszystkiedpp_scansdla przestrzeni roboczej klucza API (active_dpps,scans_by_day,top_dppsz nazwą produktu/kategorią). - Dashboard: Karta na stronie głównej (
/dashboard) z 30-dniowym wykresem słupkowym + listami najpopularniejszych — równolegle do kart kodów QR. - Publiczne: Krótki link marketingowy
GET /dpp/dpp_<id>(jeden segment) do prezentacji na żywo, równolegle do/dpp/{gtin}/{serial}.
2026-04 · Analityka skanowań DPP (Q3.4.1)
- Nowość:
GET /v1/dpp/:id/stats?days=30— zagregowane skanowania publicznego resolvera GS1 dla każdego DPP. Pola:total_scans,period_scans,scans_by_day,top_countries,top_devices,top_representations. - Nowość: Tabela
dpp_scans(migracja0011) — oddzielona odscans(Redirect-Worker). Adresy IP są haszowane przy użyciu codziennie rotowanej soli (salt), surowe adresy IP nigdy nie trafiają do D1. - Dashboard: Karta z miniwykresem (SVG, bez zewnętrznej biblioteki wykresów) pod adresem
/dashboard/dpp/:dppIdz 30-dniowymi słupkami + zestawieniem top 3. Stan pusty (empty state), gdy DPP jest aktywny, ale nie ma jeszcze skanowań.
2026-04 · Symulator zgodności z przepisami UE na żywo (Q3.3.7)
- Nowość:
POST /v1/dpp/:id/validate-update— symuluje częściowe aktualizacje w sposób bezstanowy (stateless) (status, lista rynków itp.) bez zapisywania danych. Odpowiedź zawieraeu_compliance+preview.changed_fields. - Dashboard: Karta symulatora w szczegółach DPP (
/dashboard/dpp/:dppId) — znaczniki (chips) dlaDE/AT/FR/IT/ES/NL+ niestandardowe, lista rozwijana statusu, Preview EU impact / Save changes / Reset. Bez blokowania interfejsu dzięki RemixuseFetcher. - Zabezpieczenie: Wydzielone funkcje pomocnicze symulatora (
readUpdatePatchFromForm,marketCountriesKey) + 18 nowych testów jednostkowych; poprawka błędu: pojedyncza wartość wejściowa spoza standardu ISO nie powoduje już wyczyszczenia listy rynków.
2026-04 · Podgląd zgodności z przepisami UE na żywo w formularzu tworzenia (Q3.3.6)
- Zmieniono:
POST /v1/dpp/validatezwraca dodatkowoeu_compliance— ten sam walidator coGET /v1/dpp/:id/eu-compliance, działający bezstanowo przed zapisaniem. - Dashboard: Podgląd pod istniejącym panelem walidacji + nowy baner ostrzegawczy (Save-Guard-Banner) przed przyciskami zapisu, jeśli występują błędy/ostrzeżenia (pluralizacja i18n DE/EN).
2026-04 · EU-Validator + Textil-UI (Q3.3.4 + Q3.3.5)
- Nowość: Walidator zgodności z przepisami UE z 5 regułami dla tekstyliów (
TEXTILE_AGEC_REQUIRED,TEXTILE_MICROPLASTICS_CONSISTENCY,TEXTILE_SVHC_THRESHOLD,TEXTILE_GREENWASHING,TEXTILE_ESPR_READY). - Nowość:
GET /v1/dpp/:id/eu-compliancez polamicompliant/espr_ready/issues[]/summary. - Dashboard: Sekcja zgodności z przepisami UE w szczegółach DPP (kafelki podsumowania, pogrupowane karty problemów, plakietka ESPR-Ready w nagłówku).
2026-04 · Textil-DPP-Schema (Q3.3.1–Q3.3.3)
- Nowość: Kategoria
textilez obowiązkowym łańcuchem AGEC (tkanie/dzianie → barwienie/drukowanie → konfekcjonowanie), dla każdego włóknaorigin_country+recycled_pct,svhc_substances[], ESPR-Opt-in (PEF, żywotność, Recyclability). - Nowość: Podstawowe pole
market_countries: string[](ISO 3166-1 alpha-2) we wszystkich kategoriach DPP — steruje specyficznymi dla Francji regułami AGEC oraz francuską obowiązkową notą dla konsumentów. - Nowość: Szablon HTML dla konsumenta z ostrzeżeniem AGEC o mikroplastiku, 3-stopniowym łańcuchem pochodzenia (pigułki z flagami), listą SVHC oraz sekcjami Durability i Recyclability.
- Migracja:
0010_dpp_market_countries(D1).
2026-04 · DPP-Bulk-Import (Q3.2.1–Q3.2.5)
- Nowość:
POST /v1/dpp/importakceptuje pliki CSV i XLSX (kompatybilne z Workers dzięki SheetJSxlsx, paczka gzip o rozmiarze ok. 283 KB). - Skalowanie: limit zależny od planu (Free 100 → Enterprise 10k) + wsadowe
db.batch()po 100 + limit rozmiaru żądania (body) 5 MB. - Nowość: Raport o błędach jako CSV w polu
errors_csvodpowiedzi 201;GET /v1/dpp/import/templates/:category?format=csv|xlsxdostarcza gotowe szablony dla baterii i tekstyliów. - Dashboard: Przesyłanie metodą przeciągnij i upuść (drag-and-drop) pod adresem
/dashboard/dpp/importz proxy szablonów i pobieraniem CSV inline.
Zmiany nie-breaking — rozszerzenia LTS
Wszystkie wyżej wymienione zmiany mają charakter addytywny:
- Istniejący klienci
POST /v1/dpp/validateignorują nowe poleeu_compliancebez konieczności wprowadzania zmian. - Istniejące procesy (
battery-Flows) pozostają bez zmian. - Pole
market_countriesjest opcjonalne i domyślnie przyjmuje wartość[].
Zasady wprowadzania zmian niekompatybilnych wstecz (Breaking-Change-Policy) opisano w sekcji Wersjonowanie API.