Skip to content

История на промените

История на промените

Подбрани акценти от последните версии. За пълните версии на API и политиката за несъвместими промени (Breaking Changes) вижте Версиониране на API & LTS политика.

Подробни промени по отделните крайни точки: OpenAPI спецификация и интерактивна API справка.


2026-10 · Цветове в Dashboard

  • Ново: страницата с подробности за код има карта Цветове: преден план и фон като шестнадесетична стойност, прозрачен фон, преглед чрез реалния маршрут на изображението. Проверката е същата като при PATCH /v1/codes/{id}: критичните двойки изискват потвърждение, двойки под 1,5:1 не могат да се запазят.
  • Нулирането до черно на бяло отново връща и в четирите формата същите байтове като без цветове. Кодовете без цветове не се променят.
  • Прозрачните кодове се показват върху шахматна дъска във всички прегледи в Dashboard. Подробности: Цветове в Dashboard.

2026-10 · Цветове в PDF и EPS

  • Ново: qr.pdf и qr.eps изчертават fg и bg, като параметри и като запазени цветове. Черното и всяко сиво се записват като нива на сивото (само черна плака), всеки друг цвят като CMYK в цели проценти, например 1F4E79 като C74 M36 Y0 K53.
  • Фон като при SVG: Веднага след като бъде избран цвят, зад кода и неговата зона на безопасност се разполага плътен фон, бял или bg. bg=transparent не изчертава такъв. Заглавието остава черно, а подложката на логото – бяла.
  • Без промяна без цветове: Без fg/bg и без запазени цветове и двата формата предоставят същите байтове като преди. PDF файлът на продуктовия паспорт остава неоцветен.
  • Ограничения: без ICC профил, без PDF/X. Подробности: Цветове при печат.

2026-09 · Статични кодове без кеш за пренасочване, едновременно изтриване

  • Променено: Статичните кодове вече не се съхраняват в кеша за пренасочване. Извикването на тяхната кратка връзка (redirect_url) винаги чете текущото състояние. Поради това след DELETE /v1/account статичният код вече не пренасочва при следващото извикване (преди това до 24 часа). Промяната на тарифния план също влиза в сила незабавно за статичните кодове. Изтриването на акаунта изчиства динамичните кодове както досега. Отпечатаните статични кодове съдържат своята цел директно и не са засегнати.
  • Коригирано: Две едновременни заявки DELETE /v1/codes/:id към един и същ код връщат веднъж 200 и веднъж 404. Уебхукът qr.deleted се изпраща точно веднъж, преди това два пъти.
  • Ново: POST и DELETE /v1/codes/:id/logo отговарят с 409 (errors/conflict), ако друга заявка е променила логото на същия код едновременно, и тогава не променят нищо. Преди това качено лого можеше да остане записано, без да се използва. Две едновременни заявки DELETE /v1/codes/:id/logo връщат и двете 200. Подробности: Лого.

2026-09 · TypeScript-SDK 1.2.0

  • Ново в @qr3/sdk 1.2.0: client.codes.update() приема appearance и връща резултатите от проверката на контраста като issues в резултата; при липса на констатации полето липсва. client.codes.imageUrl() приема fg, bg и ecc. Всеки код, който API връща (get, list, create, update, batchCreate), съдържа title и appearance.
  • Обновяване: npm install @qr3/sdk@latest. Следват Python, Go и PHP. Подробности: SDK и CLI и Запазване на цветове към кода.

2026-09 · Промененото време на изтичане се прилага в рамките на около една минута

  • Коригирано: Изпращането на PATCH към expires_at вече изчиства кеша за пренасочване на кода. По този начин новото време на изтичане се прилага в рамките на около една минута, вместо до 24 часа по-късно. Преди това премахнато или отложено изтичане продължаваше да връща 410 до 24 часа, а изтичане, настроено за текущия момент, позволяваше на пренасочването да продължи да работи до 24 часа.
  • Коригирано: Код, създаден с expires_at, вече изтича навреме дори ако изтичането е в рамките на първите 24 часа.
  • Коригирано: Ако даден код бъде изтрит, докато логото му се качва или премахва, POST и DELETE /v1/codes/:id/logo отговарят с 404 и не променят изтрития код, точно както вече прави PATCH.
  • Коригирано: Статичен код, чийто кратък линк (redirect_url) е бил достъпен, също се съхранява в кеша за пренасочване. Промяната, поставянето на пауза и изтриването вече го изчистват и него, а не само при динамичните кодове.

2026-09 · Запазване на цветове в кода

  • Ново: PATCH /v1/codes/:id приема appearance с foreground_color и background_color (#RRGGBB, за фонов цвят също и transparent). qr.svg и qr.png изчертават запазените цветове без параметри; параметър на заявката като ?fg=000000 продължава да бъде с предимство. PDF и EPS ще изчертават цветове едва в по-късна версия.
  • Проверка на контраста: Двойка под 1,5:1 връща 422. По-слабите двойки се запазват и се съобщават в meta.issues като warning или critical; прозрачният фон винаги е critical, никога блокиран.
  • Обединяване: Пропуснатите полета запазват своята запазена стойност, null нулира. Едновременните промени по един и същ код вече не се препокриват взаимно.
  • Във всеки отговор за код: appearance присъства във всеки отговор за код и в уебхуковете qr.created и qr.updated. POST, пакетната обработка и импортирането го отхвърлят с 422.
  • Без промяна за съществуващите кодове: Без запазени цветове всеки код предоставя същите байтове като преди. Подробности: Запазване на цветове в кода.

2026-09 · Цветове и корекция на грешки като параметри на маршрутите за изображения

  • Ново: Всичките четири маршрута за изображения приемат fg (цвят на преден план), bg (цвят на заден план или transparent) и ecc (корекция на грешки L, M, Q, H). SVG и PNG изчертават цветовете; PDF и EPS ги приемат, но ще ги изчертават едва в по-късна версия. ecc действа във всичките четири формата, а лого продължава да изисква H.
  • Прозрачност: bg=transparent връща SVG без заден план и PNG с истински алфа канал. Основата трябва да бъде светла и да оставя свободна тихата зона.
  • Никога грешка: Невалидните стойности се игнорират; тогава изображението се връща точно както без параметри.
  • Кеш: Всеки ефективен параметър връща Cache-Control: public, max-age=300 вместо 24-те часа на стандартното изображение.
  • Без промяна в поведението без параметри: Всеки съществуващ код връща същите байтове във всичките четири формата, както преди.
  • Налично във всеки тарифен план. Подробности: Цветове и корекция на грешки.

2026-09 · PDF и EPS вече също вграждат логото

  • Разширение: qr.pdf и qr.eps вече вграждат зададеното лого по същия начин като qr.svg и qr.png (вижте по-долу) — като вградено изображение (PDF чрез Image XObject, EPS чрез речник за изображения в PostScript, там само с %%LanguageLevel: 3), центрирано върху същата площ, със същото повишаване на корекцията на грешки до H. Досега и двата формата не доставяха логото; това вече е коригирано.
  • Кеш: При зададено лого qr.pdf и qr.eps вече също връщат Cache-Control: public, max-age=300 вместо обичайните 24 часа — точно както SVG/PNG.
  • Резервен вариант: Ако самото изображение на логото не може да бъде обработено (например повреден съхранен обект), корекцията на грешки остава H, но запазената площ остава празна вместо изображение — никога не се стига до сървърна грешка.
  • Без промяна в поведението без лого: Кодовете без лого продължават да връщат qr.pdf/qr.eps байт за байт идентични, с непроменен 24-часов кеш.
  • Подробности и инструкции за печат: Лого в QR кода.

2026-09 · Лого в QR кода — Dashboard и API

  • Ново: Вече един код може да съдържа лого в средата. В Dashboard страницата с подробности за кода създава собствена карта за лого: Избор на лого, при първото добавяне или при премахване се потвърждава предупреждение със задължително квадратче за отметка (и двете променят точковия модел), след което Качване на лого/Премахване на лого. Една Замяна не изисква потвърждение — променя се само изображението, а не моделът. Ролята viewer вижда статуса и визуализацията, но никое от трите действия.
  • API: POST /v1/codes/{id}/logo (поле с множество части file; PNG, JPEG или WebP, най-много 1 MB, SVG се отхвърля) създава лого или го заменя; DELETE /v1/codes/{id}/logo го премахва отново и е идемпотентна. Твърде голямо изображение връща 413, неподдържан формат 422, а ролята viewer 403.
  • Рендериране: qr.svg и qr.png вграждат логото като действителни пиксели (512 × 512, нормализирано) и за целта повишават корекцията на грешки на H. По този начин добавянето и премахването променят точковия модел (M ↔ H), а замяната — не. qr.pdf и qr.eps не вграждат лого и остават непроменени. Вече отпечатан код продължава да работи във всеки случай, тъй като кодираната цел не зависи от логото — повторно отпечатване е необходимо само за тези, които искат да видят (новия) външен вид на логото и върху материала, като при това не трябва да смесват стари и нови файлове за печат.
  • Кеш: При зададено лого qr.svg и qr.png връщат Cache-Control: public, max-age=300 вместо обичайните 24 часа. Подробности, гранични стойности и инструкции за печат: Лого в QR кода.

2026-08 · operationId за всички 75 операции и ръководство „Кога“ за агенти

  • Допълнение: Всички 75 операции от OpenAPI спецификацията вече имат operationId — listCodes, createCode, getCodeStats, archiveWorkspace и така нататък. Досега това поле липсваше навсякъде, така че всеки генератор трябваше да извлича името на метода от HTTP метода и пътя (postV1Codes). Тези имена зависят от пътя и се променят при всяко преструктуриране на пътя. Форматът на имената е еднакъв на всички 75 места: list/get/create/update/replace/delete, в противен случай се използва глаголът на бизнес операцията (validateDpp, registerGs1Identifier, pingWebhook). Глаголът следва бизнес логиката, а не HTTP метода — archiveWorkspace е DELETE, а importDpps е POST.
  • Въздействие върху самостоятелно генерирани клиенти: Всеки, който генерира своето SDK от спецификацията, при следващото стартиране ще получи преименувани методи (postV1Codes → createCode). Това е целта на промяната, но тъй като представлява преименуване в чужд код, се споменава изрично тук. Пътищата, параметрите, форматите на отговорите и кодовете за състояние са непроменени; официалните SDK, CLI и MCP сървъри не са засегнати.
  • Въведение за агенти: https://qr3.app/llms.txt съдържа раздел ## When to use qr3.app — шест задачи вместо шест функции, плюс изречението за какво qr3.app не е подходящият инструмент. Същата информация предоставя вече и MCP сървърът при първоначалното установяване на връзка (handshake): initialize към https://mcp.qr3.app/mcp отговаря с поле instructions (преди: единадесет инструмента без никакво класифициране). Включено е също кои повиквания изискват API ключ — initialize и tools/list не изискват, но всяко tools/call изисква.
  • Корекции в llms.txt: Четири твърдения бяха тествани спрямо реалната среда (продукция) и се оказаха неточни: (1) Python SDK qr3app не е публикувано в PyPI — редът pip install е премахнат без замяна; (2) Accept: text/markdown важи за началната страница и блога, а не за всяка рендирана от страна на сървъра страница; (3) адресът за контакт е [email protected], включително в JSON-LD на началната страница; (4) /de/security/ е пренасочване към котва, а не самостоятелна страница. Нов линк: docs.qr3.app/de/skills/.
  • Подсигуряване: Три дефинирани правила (assertions) в openapi-spec.test.ts — пълнота, уникалност, lowerCamelCase —, всяко от които е проверено чрез мутация. Още девет теста фиксират четирите коригирани данни, за да се предотврати повторната им поява.
  • Известно ограничение: Две от 75-те операции са описани в спецификацията, но връщат 404 (GET /v1/codes/{id}/stats и GET /v1/account). Те получиха име тук и ще го загубят отново, веднага щом бъде взето решение дали ще бъдат разработени или премахнати.

2026-08 · Даунгрейдовете на плановете и прекратяванията вече влияят и върху лимитите

  • Корекция: При смяна на плана и прекратяване Stripe webhook-ът записваше само името на плана, но не и четирите колони за лимити на организацията (max_workspaces, max_members, max_dynamic_codes, max_scans_per_month). Тъй като прилагането на лимитите взема максимума от записаната стойност и базовата линия на плана, организация с намален план или прекратен абонамент запазваше старите си, по-високи лимити — даунгрейдът нямаше ефект. Сега webhook-ът задава стойностите в колоните при всяка действителна смяна на плана към базовата линия на новия план, а при прекратяване — към Free базовата линия — точно както вече прави администраторското управление.
  • Поведение: Рутинните актуализации на абонамента (подновяване, платежно средство, пропорционално преизчисляване) продължават да не засягат лимитите; индивидуално предоставените по-високи лимити се запазват непроменени. Само действителна смяна на плана ги променя до базовата линия на новия план.
  • Въздействие: Без промени в API или във формата на отговора. Организациите, чийто даунгрейд е извършен преди тази корекция, запазват старите стойности, докато не влезе в сила следващата смяна на плана или докато поддръжката не ги коригира.

2026-08 · Keyset-курсор вече на всички списъчни крайни точки

  • Корекция: Корекцията на курсора за GET /v1/codes и GET /v1/dpp (вижте по-долу) вече е внедрена за всички останали списъци с пагинация чрез курсор: GET /v1/qr-codes/:id/comments, /v1/workspaces, /v1/gs1/identifiers, /v1/members, /v1/audit-logs, /v1/admin/orgs, /v1/admin/users и /v1/webhooks/:id/deliveries. Всички те се прелистваха само по created_at; редове с идентично времево клеймо (одит записи от групова операция, повторни опити за webhook, импортиране на членове) можеха да бъдат изгубени на следващата страница. Ключът за сортиране навсякъде вече е кортежът (created_at, id).
  • Промяна в API: В тези списъци meta.pagination.next_cursor отсега нататък също е непрозрачна стойност (base64url) вместо чисто времево клеймо; нечетливите курсори връщат 400, а старите курсори с времево клеймо ще продължат да се приемат преходно. Изключение прави GET /v1/webhooks/:id/deliveries: там next_cursor остава идентификаторът на последната доставка (неизвестен ID → първа страница). Клиентите, които връщат next_cursor непроменен — Табло, CLI, SDKs, MCP —, не трябва да променят нищо.
  • Въздействие: Не е необходима миграция. Ако са ви липсвали записи при прелистване в някой от тези списъци (напр. одит лог или лог на доставките в Таблото): те никога не са изчезвали — списъците вече ги показват изцяло.

2026-08 · Времевите клейма след редактиране и изтриване отново съответстват на OpenAPI

  • Корекция: След PATCH /v1/codes/{id} updated_at се връщаше във формат на SQLite без часова зона (2026-08-17 09:00:00), въпреки че OpenAPI спецификацията обещава format: date-time и създаването (POST) предоставя ISO времево клеймо (2026-08-17T09:00:00.000Z). Същото важеше за deleted_at/updated_at при меко изтриване (soft-delete), както и за пътищата за редактиране/изтриване на API-Keys, организации, Workspaces, членове, коментари и webhooks, освен това и за last_used_at на API-Keys и last_triggered_at на webhooks. Всички пътища за запис сега записват времето по ISO 8601 (UTC, T и Z).
  • Въздействие: Клиентите, които анализират updated_at с new Date(...) (SDKs, CLI, Табло), разчитаха формата с интервал като местно време — CLI показваше времето, изместено с локалното отместване при веднъж редактирани кодове (Виена: −2 h). Това е коригирано. Освен това миграцията на данни нормализира вече записаните стойности в стария формат към ISO, за да бъдат правилни сортирането и сравненията в смесени масиви. Без промени в имената на полетата или структурата на отговора.
  • Контекст: Същият клас грешка като двете корекции по-долу (изтичане на API-Key, времеви лимит за повторно сканиране): datetime('now') на SQLite записва YYYY-MM-DD HH:MM:SS, докато всички останали записващи механизми използват ISO 8601. Тест за защита на изходния код ще предотвратява нови случаи в бъдеще.

2026-08 · Пагинацията на списъци вече не губи партидни кодове

  • Корекция: GET /v1/codes и GET /v1/dpp извършваха пагинация само по created_at. Кодовете от POST /v1/codes/batch, POST /v1/dpp/batch и CSV/XLSX импорта обаче споделят едно и също времево клеймо — веднага щом дадена партида беше по-голяма от limit (по подразбиране 20), втората страница вече не връщаше останалите редове със същото времево клеймо. Кодовете съществуваха и бяха достъпни чрез GET /v1/codes/:id, но никога не се появяваха в списъка (Табло, CLI qr3 list, SDKs, MCP). Курсорът вече е набор от ключове (keyset) върху (created_at, id).
  • Промяна в API: meta.pagination.next_cursor отсега нататък е непрозрачна стойност (base64url) вместо чисто времево клеймо. Всеки, който връща курсора непроменен като ?cursor= — както правят Таблото, CLI, всички SDKs и MCP сървърът — не трябва да променя нищо. Старите курсори с времеви клейма ще продължат да се приемат временно; нечетливите курсори вече връщат 400 вместо мълчаливо да зареждат първата страница.
  • Въздействие: За тези, които след партидно импортиране са виждали по-малко кодове в списъка, отколкото са били създадени: Кодовете никога не са изчезвали — отсега нататък списъкът ги показва изцяло. Не е необходима миграция.

2026-08 · Повторните сканирания за сигурност отново се изпълняват на всеки 24 часа

  • Корекция: Периодичното повторно сканиране на целевите URL адреси и на връзките на лендинг страницата (Google Web Risk) пропускаше кодове, чието последно сканиране е било в същия календарен ден като 24-часовия времеви лимит — в зависимост от часа, повторното сканиране се забавяше с до още един ден. Времевият лимит сега се изчислява в същия ISO формат, в който се съхраняват времевите клейма за сканиране.
  • Въздействие: Целеви URL адрес, който бъде класифициран като опасен след последното сканиране, отново води до автоматично спиране на кода на пауза в рамките на документирания 24-часов прозорец. Без промени в API или формата на отговора.

2026-08 · API-Keys изтичат точно в момента на изтичане

  • Корекция: API-Key, чийто expires_at беше на същия ден, се приемаше до полунощ UTC. Изтичането вече се сравнява като времево клеймо вместо като низ — изтекъл ключ незабавно връща 401.
  • Контекст: expires_at се съхранява като ISO времево клеймо (2026-08-14T09:00:00Z), а сравняваната страна предоставяше формат с интервал (2026-08-14 09:00:00). Поради това директното сравнение на низове беше коректно само когато датите вече се различаваха.
  • Въздействие: Не е необходима миграция, форматът на отговора на GET /v1/api-keys остава непроменен. Нечетливите стойности за изтичане вече се считат за изтекли вместо за валидни.

2026-08 · Справка за API: Документирано управление на Tenant

  • OpenAPI: Спецификацията — а с това и интерактивната справка — вече документира организации (вкл. GET /v1/organizations/usage), Workspaces, членове и роли и Audit-Logs.
  • Billing: Прегледът на плановете (GET /v1/billing/plans) е публичен; Checkout (POST /v1/billing/checkout) и клиентският портал на Stripe (GET /v1/billing/portal) са посочени като крайни точки за администратори на организации.
  • Експорт на сканирания: Статистиките за сканиранията (GET /v1/codes/{id}/scans) и експортът на сурови данни (…/scans.csv, …/scans.xlsx) са напълно документирани — включително бележка за GDPR: ip_hash никога не се съдържа в експорта.
  • Поведение при грешки: Новодокументиран е и отговорът 400 при валидиране на заявка: тялото е суровата грешка от Zod, а не RFC-7807 документ за проблем — въпреки това той се доставя с Content-Type application/problem+json.

2026-08 · Копиране на публични връзки към файлове

  • Dashboard: Публичните файлове на страницата с детайли на кода вече имат бутон, който копира публичната им връзка в клипборда – готова за директно използване като целеви URL на QR код, когато сканирането трябва веднага да отвори конкретен документ вместо лендинг страницата със списъка с файлове.
  • API: Крайните точки за файлове (/v1/files) връщат допълнително public_url. Полето е зададено само при файлове с visibility: public – частните файлове не получават публичен адрес.
  • Поведение: Връзката не изисква влизане в акаунт и отваря файла директно в браузъра. Действието Замени не променя връзката, така че отпечатаният с нея код остава валиден. Подробности: Файлове и информационни листове.

2026-07 · Екипни роли: Сътрудник без изтриване и администраторско таксуване

  • Ново: Роля за членове Сътрудник (без изтриване) — създава и редактира QR кодове, файлове и Digital Product Passports, но не може да изтрива съдържание и да генерира API ключове. Всички деструктивни API endpoints проверяват ролята на сървърно ниво (403).
  • Таксуване: Надграждането на планове и достъпът до клиентския портал на Stripe (POST /v1/billing/checkout, GET /v1/billing/portal) вече са разрешени само за Администратори на организацията — всички останали роли виждат преглед на абонамента само за четене.
  • Dashboard: Действията, които не са разрешени за съответната роля, се скриват автоматично: потребител с роля Наблюдател например не вижда бутони за създаване, редактиране или изтриване, докато списъците, изтеглянията и статистиките остават достъпни. Подробности: Екип и роли.

2026-06 · Външни връзки на лендинг страницата на кода

  • Лендинг страница: Хостваната от qr3 лендинг страница на код вече може да изброява външни, самостоятелно хоствани връзки ({ label, url }) в допълнение към или вместо качените файлове – например за технически данни на собствения ви сайт.
  • API: POST/PATCH /v1/codes приемат масив links (0–20 записа, http(s), ≤ 2048 знака). Всеки URL се проверява с Google Web Risk; незащитен URL връща 422. Празен масив изтрива всички връзки.
  • Dashboard: Добавяне, пренареждане и премахване на връзки на страницата с детайли на кода.
  • Сигурност: Рендираните връзки остават XSS-защитени (екранирани, само http(s)) и страницата запазва своя noindex хедър.

2026-04 · Анализи в таблото за управление (Dashboard) за всеки QR код

  • Dashboard: Бутонът за анализи в списъка с QR кодове вече отваря страницата със статистика за съответния QR код на адрес /dashboard/codes/{id}.
  • Routing: Псевдонимът (alias) /dashboard/codes продължава да пренасочва към /dashboard, но вече не прихваща детайлни маршрути като /dashboard/codes/{id}.
  • API: Страницата с детайли зарежда QR кода директно чрез GET /v1/codes/:id; по този начин тя вече не зависи от ограниченията за пагинация на списъка.
  • Tests: Регресионните тестове покриват пренасочването на псевдонима и директното зареждане на кода.

2026-04 · Диалогов прозорец за изтриване на QR кодове в таблото (Dashboard)

  • Dashboard: Иконата с кошче в списъка с QR кодове вече отваря собствен React диалогов прозорец вместо системно изскачащо съобщение на браузъра.
  • Feedback: След изтриване се появява изскачащо известие (toast) за успех или грешка.
  • Tests: packages/dashboard/tests/dashboard.test.ts предотвратява регресии при confirm() в процеса на изтриване на QR кодове.

2026-04 · Тест на кратки връзки в таблото (Dashboard) за динамични QR кодове

  • Dashboard: Кратките кодове (shortcodes) в списъка с QR кодове вече могат да се кликват директно като външни връзки за пренасочване. Иконата за външна връзка до напр. wu3qaa отваря https://qr3.app/{shortCode} в нов раздел.
  • i18n: Добавени са текстове за подсказки (tooltips) на немски и английски език.
  • Tests: packages/dashboard/tests/dashboard.test.ts защитава href на връзката, поведението за нов раздел, noopener noreferrer и иконата срещу регресии.

2026-04 · Маршрут на Redirect-Worker за динамични QR кодове

  • Корекция: Динамичните QR кодове на адрес https://qr3.app/{shortCode} отново се обработват от Redirect-Worker. Производственият маршрут (production route) вече използва qr3.app/*, тъй като маршрутите на Cloudflare Workers не поддържат параметри на пътя от типа :code.
  • Укрепване: Несъвпадащите пътища се препращат към оригиналния хост (landing origin), за да не се блокират нормални страници като /de/pricing от Redirect-Worker.
  • Tests: packages/redirect/tests/unit/redirect.test.ts проверява маршрута с маска (wildcard route), обработката на кратки кодове и преминаването към оригиналния хост (origin pass-through).

2026-04 · Общ преглед на сканиранията на DPP в работното пространство (Q3.4.2)

  • Ново: GET /v1/workspace/stats/dpp?days=30 — агрегира всички dpp_scans на работното пространство на API ключа (active_dpps, scans_by_day, top_dpps с име на продукт/категория).
  • Dashboard: Карта на началната страница (/dashboard) с 30-дневна хистограма + списъци с най-популярните — успоредно с картите за QR кодове.
  • Public: Маркетингова кратка връзка GET /dpp/dpp_<id> (един сегмент) за демонстрации на живо, успоредно с /dpp/{gtin}/{serial}.

2026-04 · Анализи на сканиранията на DPP (Q3.4.1)

  • Ново: GET /v1/dpp/:id/stats?days=30 — агрегирани сканирания от публичния GS1-Resolver за всяко DPP. Полета: total_scans, period_scans, scans_by_day, top_countries, top_devices, top_representations.
  • Ново: Таблица dpp_scans (миграция 0011) — отделно от scans (Redirect-Worker). IP адресите се хешират с ежедневно ротираща сол (salt), суровите IP адреси никога не достигат до D1.
  • Dashboard: Мини диаграма (SVG, без външна библиотека за графики) на страница /dashboard/dpp/:dppId с 30-дневни стълбове + разбивка на топ 3. Празно състояние (empty state), веднага щом даден DPP е активен, но все още няма сканирания.

2026-04 · Симулатор за съответствие с изискванията на ЕС в реално време (Q3.3.7)

  • Ново: POST /v1/dpp/:id/validate-update — симулира частични актуализации без състояние (stateless) (статус, списък с пазари, …) без персистентност. Отговорът съдържа eu_compliance + preview.changed_fields.
  • Dashboard: Карта на симулатора в детайлите на DPP (/dashboard/dpp/:dppId) — чипове за DE/AT/FR/IT/ES/NL + персонализирани, падащо меню за статус, Preview EU impact / Save changes / Reset. Неблокиращо чрез Remix useFetcher.
  • Укрепване: Изнесени помощни функции за симулатора (readUpdatePatchFromForm, marketCountriesKey) + 18 нови единични теста (unit tests); отстранена грешка: въвеждането на единичен не-ISO код вече не изтрива списъка с пазари.

2026-04 · Преглед на съответствието с изискванията на ЕС в реално време във формата за създаване (Q3.3.6)

  • Променено: POST /v1/dpp/validate допълнително връща eu_compliance — същият валидатор като GET /v1/dpp/:id/eu-compliance, без състояние (stateless) преди записване.
  • Dashboard: Преглед под съществуващия панел за валидация + нов банер за защита при запис (Save-Guard) преди бутоните за изпращане, ако има нерешени грешки/предупреждения (i18n плурализация за DE/EN).

2026-04 · Валидатор за ЕС + Текстилен потребителски интерфейс (Q3.3.4 + Q3.3.5)

  • Ново: Валидатор за съответствие с изискванията на ЕС с 5 текстилни правила (TEXTILE_AGEC_REQUIRED, TEXTILE_MICROPLASTICS_CONSISTENCY, TEXTILE_SVHC_THRESHOLD, TEXTILE_GREENWASHING, TEXTILE_ESPR_READY).
  • Ново: GET /v1/dpp/:id/eu-compliance с compliant / espr_ready / issues[] / summary.
  • Dashboard: Секция за съответствие с изискванията на ЕС в детайлите на DPP (обобщаващи плочки, групирани карти с проблеми, бадж ESPR-Ready в заглавната част).

2026-04 · Схема за текстилен DPP (Q3.3.1–Q3.3.3)

  • Ново: Категория textile със задължителна верига по AGEC (тъкане/плетене → боядисване/печат → конфекциониране), за всяко влакно origin_country + recycled_pct, svhc_substances[], ESPR-Opt-in (PEF, експлоатационен живот, Recyclability).
  • Ново: Основно поле market_countries: string[] (ISO 3166-1 alpha-2) за всички категории DPP — управлява специфичните за Франция правила по AGEC и френската задължителна бележка за потребителите.
  • Ново: Потребителски HTML шаблон с предупредително поле за микропластмаса по AGEC, 3-степенна верига на произход (хапчета с флагове), списък със SVHC, секция за Durability и Recyclability.
  • Migration: 0010_dpp_market_countries (D1).

2026-04 · Масов импорт на DPP (Q3.2.1–Q3.2.5)

  • Ново: POST /v1/dpp/import приема CSV и XLSX (съвместим с Workers чрез SheetJS xlsx, ~283 KB gzip пакет).
  • Мащабирано: лимит на базата на абонаментния план (Free 100 → Enterprise 10k) + разделяне на части (chunked) db.batch() по 100 + 5 MB лимит на тялото (body limit).
  • Ново: Отчет за грешки като CSV в полето errors_csv на отговор 201; GET /v1/dpp/import/templates/:category?format=csv|xlsx предоставя готови шаблони за батерии и текстил.
  • Dashboard: Качване чрез влачене и пускане (drag-and-drop) на адрес /dashboard/dpp/import с прокси за шаблони и директно изтегляне на CSV.

Съвместими промени (Non-Breaking) — разширения на LTS

Всички горепосочени промени са адитивни (добавъчни):

  • Съществуващите клиенти на POST /v1/dpp/validate игнорират новото поле eu_compliance без промяна.
  • Съществуващите процеси за battery остават непроменени.
  • Полето market_countries е незадължително и по подразбиране е [].

Вижте Версиониране на API за политиката относно несъвместимите промени (Breaking-Change-Policy).