Pular para o conteúdo

Changelog

Changelog

Destaques selecionados dos lançamentos mais recentes. Para versões completas da API e política de alterações incompatíveis (breaking changes), consulte a Versão da API e Política LTS.

Alterações detalhadas em endpoints individuais: Especificação OpenAPI e referência interativa da API.


2026-10 · Cores no Dashboard

  • Novo: a página de detalhes de um código tem o cartão Cores: primeiro plano e fundo como valor hexadecimal, fundo transparente, pré-visualização pela rota de imagem real. A verificação é a de PATCH /v1/codes/{id}: pares críticos precisam de confirmação, pares abaixo de 1,5:1 não podem ser salvos.
  • Redefinir para preto sobre branco volta a entregar nos quatro formatos os mesmos bytes que sem cores. Códigos sem cores não mudam.
  • Códigos transparentes aparecem sobre um quadriculado em todas as pré-visualizações do Dashboard. Detalhes: Cores no Dashboard.

2026-10 · Cores em PDF e EPS

  • Novo: qr.pdf e qr.eps desenham fg e bg, como parâmetros e como cores salvas. O preto e qualquer cinza são gravados como escala de cinza (apenas placa preta), qualquer outra cor como CMYK em porcentagens inteiras, por exemplo 1F4E79 como C74 M36 Y0 K53.
  • Fundo como no SVG: Assim que uma cor é selecionada, existe uma área opaca por trás do código e da sua zona de silêncio, branca ou bg. bg=transparent não desenha nenhuma. O título permanece preto, a placa do logotipo branca.
  • Sem alterações sem cores: Sem fg/bg e sem cores salvas, ambos os formatos fornecem os mesmos bytes que antes. O PDF de um passaporte de produto permanece sem cor.
  • Limites: sem perfil ICC, sem PDF/X. Detalhes: Cores na impressão.

2026-09 · Códigos estáticos sem cache de redirecionamento, exclusão simultânea

  • Alterado: Os códigos estáticos não ficam mais no cache de redirecionamento. Uma chamada ao seu link curto (redirect_url) sempre lê o estado atual. Por isso, após DELETE /v1/account, um código estático deixa de redirecionar já na chamada seguinte; antes, isso podia continuar por até 24 horas. Uma mudança de plano também tem efeito imediato nos códigos estáticos. A exclusão da conta limpa os códigos dinâmicos como antes. Códigos estáticos impressos contêm o destino diretamente e não são afetados.
  • Corrigido: Duas requisições DELETE /v1/codes/:id simultâneas para o mesmo código retornam uma vez 200 e uma vez 404. O webhook qr.deleted é enviado exatamente uma vez, e não mais duas.
  • Novo: POST e DELETE /v1/codes/:id/logo respondem com 409 (errors/conflict) se outra requisição tiver alterado o logotipo do mesmo código ao mesmo tempo e, nesse caso, não alteram nada. Antes, um logotipo enviado podia ficar armazenado sem uso. Duas requisições DELETE /v1/codes/:id/logo simultâneas retornam ambas 200. Detalhes: Logotipo.

2026-09 · TypeScript-SDK 1.2.0

  • Novo no @qr3/sdk 1.2.0: O client.codes.update() aceita appearance e fornece os resultados da verificação de contraste como issues no resultado; sem resultados, o campo fica ausente. O client.codes.imageUrl() aceita fg, bg e ecc. Cada código retornado pela API (get, list, create, update, batchCreate) contém title e appearance.
  • Atualizar: npm install @qr3/sdk@latest. Python, Go e PHP seguem-se. Detalhes: SDKs & CLI e Salvar cores no código.

2026-09 · Tempo de expiração alterado aplica-se dentro de cerca de um minuto

  • Corrigido: Um PATCH em expires_at agora limpa o cache de redirecionamento do código. O novo tempo de expiração aplica-se, assim, dentro de cerca de um minuto, em vez de apenas até 24 horas mais tarde. Anteriormente, uma expiração removida ou adiada continuava a retornar 410 por até 24 horas, e uma expiração definida para agora permitia que o redirecionamento continuasse a funcionar por até 24 horas.
  • Corrigido: Um código criado com expires_at expira agora pontualmente, mesmo que a expiração ocorra dentro das primeiras 24 horas.
  • Corrigido: Se um código for excluído enquanto o seu logotipo está sendo enviado ou removido, o POST e o DELETE /v1/codes/:id/logo respondem com 404 e não alteram o código excluído, assim como já ocorre com o PATCH.
  • Corrigido: Mesmo um código estático cujo link curto (redirect_url) foi acessado fica armazenado no cache de redirecionamento. Alterar, pausar e excluir agora também limpam esse cache, e não apenas no caso de códigos dinâmicos.

2026-09 · Salvar cores no código

  • Novo: PATCH /v1/codes/:id aceita appearance com foreground_color e background_color (#RRGGBB, o fundo também transparent). qr.svg e qr.png desenham as cores armazenadas sem qualquer parâmetro; um parâmetro de consulta como ?fg=000000 continua a ter precedência. O PDF e o EPS apenas desenharão as cores numa versão posterior.
  • Verificação de contraste: Um par abaixo de 1,5:1 resulta em 422. Pares mais fracos são salvos e reportados em meta.issues como warning ou critical; um fundo transparente é sempre critical, nunca bloqueado.
  • Mesclagem: Os campos omitidos mantêm o seu valor salvo, null redefine. Alterações simultâneas no mesmo código já não se sobrescrevem mutuamente.
  • Em cada resposta de código: appearance está presente em cada resposta de código e nos webhooks qr.created e qr.updated. O POST, o lote e a importação rejeitam com 422.
  • Sem alterações para códigos existentes: Sem cores salvas, cada código fornece os mesmos bytes que antes. Detalhes: Salvar cores no código.

2026-09 · Cores e correção de erros como parâmetros das rotas de imagem

  • Novo: Todas as quatro rotas de imagem aceitam fg (cor do primeiro plano), bg (cor de fundo ou transparent) e ecc (correção de erros L, M, Q, H). SVG e PNG desenham as cores; PDF e EPS aceitam-nas, mas só as desenham numa versão posterior. ecc funciona em todos os quatro formatos, um logotipo continua a forçar H.
  • Transparente: bg=transparent fornece um SVG sem fundo e um PNG com canal alfa real. O fundo deve ser claro e deixar a zona de silêncio livre.
  • Nunca é um erro: Valores inválidos são ignorados; a imagem é então fornecida exatamente como sem parâmetros.
  • Cache: Cada parâmetro eficaz fornece Cache-Control: public, max-age=300 em vez das 24 horas da imagem padrão.
  • Sem alteração de comportamento sem parâmetros: Qualquer código existente fornece os mesmos bytes que antes em todos os quatro formatos.
  • Disponível em qualquer plano. Detalhes: Cores e correção de erros.
  • Extensão: qr.pdf e qr.eps agora incorporam um logo definido exatamente da mesma forma que qr.svg e qr.png (ver abaixo) — como uma imagem incorporada (PDF através de um Image XObject, EPS através de um dicionário de imagem em PostScript, lá apenas com %%LanguageLevel: 3), centrado na mesma área, com o mesmo aumento da correção de erros para H. Ambos os formatos anteriormente não forneciam o logo; isto está agora corrigido.
  • Cache: Com um logo definido, qr.pdf e qr.eps agora também fornecem Cache-Control: public, max-age=300 em vez das habituais 24 horas — exatamente como SVG/PNG.
  • Fallback: Se a própria imagem do logo não puder ser processada (por exemplo, um objeto armazenado corrompido), a correção de erros permanece em H, mas a área reservada permanece vazia em vez de uma imagem — nunca um erro do servidor.
  • Sem alteração de comportamento sem logo: Códigos sem logo continuam a fornecer qr.pdf/qr.eps de forma idêntica em termos de bytes, com o cache de 24 horas inalterado.
  • Detalhes e instruções de impressão: Logo no código QR.

2026-09 · Logo no QR Code — Dashboard e API

  • Novo: Um código agora pode ter um logo no centro. No Dashboard, a página de detalhes de um código cria um cartão de logo próprio: Selecionar logo, ao adicionar pela primeira vez ou ao remover, confirmar um aviso com uma caixa de seleção obrigatória (ambos alteram o padrão de pontos), depois Carregar logo/Remover logo. Uma substituição não precisa de confirmação — apenas a imagem muda, não o padrão. A função viewer vê o estado e a pré-visualização, mas nenhuma das três ações.
  • API: POST /v1/codes/{id}/logo (campo multipart file; PNG, JPEG ou WebP, no máximo 1 MB, SVG é rejeitado) cria ou substitui um logo; DELETE /v1/codes/{id}/logo remove-o novamente e é idempotente. Uma imagem grande demais retorna 413, um formato não suportado 422, a função viewer 403.
  • Apresentação: qr.svg e qr.png incorporam o logo como pixels reais (512 × 512, normalizado) e, para isso, aumentam a correção de erros para H. A adição e a remoção alteram, assim, o padrão de pontos (M ↔ H), mas a substituição não. qr.pdf e qr.eps não incorporam nenhum logo e permanecem inalterados. Um código já impresso continua a funcionar em qualquer caso, porque o destino codificado não depende do logo — só precisa de reimprimir quem quiser ver o (novo) visual do logo também no material físico, e, ao fazê-lo, não misturar arquivos de impressão antigos e novos.
  • Cache: Com o logo definido, qr.svg e qr.png fornecem Cache-Control: public, max-age=300 em vez das habituais 24 horas. Detalhes, limites e instruções de impressão: Logo no QR Code.

2026-08 · operationId para todas as 75 operações, e um guia de quando usar para agentes

  • Adição: Todas as 75 operações da especificação OpenAPI agora possuem uma operationId — listCodes, createCode, getCodeStats, archiveWorkspace e assim por diante. Anteriormente, este campo estava totalmente ausente, fazendo com que cada gerador tivesse que derivar o nome do método a partir do método HTTP e do caminho (postV1Codes). Esses nomes dependem do caminho e mudam a cada reestruturação de caminho. O formato do nome é o mesmo em todos os 75 locais: list/get/create/update/replace/delete, caso contrário, o verbo da ação de negócio (validateDpp, registerGs1Identifier, pingWebhook). O verbo segue a lógica de negócio, não o método HTTP — archiveWorkspace é um DELETE, importDpps é um POST.
  • Impacto em clientes gerados automaticamente: Quem gera o seu SDK a partir da especificação obterá métodos renomeados na próxima execução (postV1Codes → createCode). Este é o objetivo da alteração, mas trata-se de uma renomeação em código de terceiros — por isso é explicitamente mencionada aqui. Caminhos, parâmetros, formatos de resposta e códigos de status permanecem inalterados; os SDKs oficiais, CLI e servidores MCP não são afetados.
  • Introdução para agentes: https://qr3.app/llms.txt tem uma seção ## When to use qr3.app — seis tarefas em vez de seis funções, além da frase que explica para o que a qr3.app não é a ferramenta certa. A mesma informação é agora fornecida pelo servidor MCP no handshake: initialize contra https://mcp.qr3.app/mcp responde com um campo instructions (anteriormente: onze ferramentas sem qualquer classificação). Também está incluído quais chamadas precisam de uma chave de API — initialize e tools/list não precisam, mas cada tools/call sim.
  • Correções em llms.txt: Quatro informações foram testadas em produção e não se confirmaram: (1) o SDK Python qr3app não está publicado no PyPI — a linha pip install foi removida sem substituição; (2) Accept: text/markdown aplica-se à página inicial e ao blog, não a todas as páginas renderizadas no servidor; (3) o endereço de contato é [email protected], inclusive no JSON-LD da página inicial; (4) /de/security/ é um redirecionamento para uma âncora, não uma página própria. Novo link: docs.qr3.app/de/skills/.
  • Garantia de qualidade: Três asserções em openapi-spec.test.ts — integridade, unicidade, lowerCamelCase —, cada uma verificada com uma mutação. Mais nove testes fixam as quatro informações corrigidas para garantir que não voltem a ocorrer.
  • Limitação conhecida: Duas das 75 operações estão descritas na especificação, mas respondem com 404 (GET /v1/codes/{id}/stats e GET /v1/account). Elas receberam um nome aqui e irão perdê-lo assim que for decidido se serão implementadas ou removidas.

2026-08 · Downgrades de plano e cancelamentos agora também afetam os limites

  • Fix: O webhook do Stripe, ao alterar ou cancelar o plano, apenas escrevia o nome do plano e não as quatro colunas de limite da organização (max_workspaces, max_members, max_dynamic_codes, max_scans_per_month). Como a aplicação dos limites utiliza o valor máximo entre o valor salvo e a baseline do plano, uma organização que sofria downgrade ou cancelamento mantinha os seus limites antigos e mais elevados — o downgrade não tinha efeito. O webhook agora define as colunas para a baseline do novo plano em cada alteração real de plano e para a baseline do plano Free em caso de cancelamento — exatamente como a administração de admin já faz.
  • Comportamento: As atualizações de rotina da assinatura (renovação, meio de pagamento, proration) continuam a não alterar os limites; os limites mais elevados concedidos individualmente permanecem inalterados. Apenas uma alteração real de plano os redefine para a baseline do novo plano.
  • Impacto: Sem alterações na API ou no formato de resposta. As organizações cujo downgrade ocorreu antes desta correção mantêm os valores antigos até que a próxima alteração de plano entre em vigor ou o suporte os ajuste.

2026-08 · Cursor keyset agora em todos os endpoints de lista

  • Fix: A correção do cursor para GET /v1/codes e GET /v1/dpp (veja abaixo) foi agora implementada em todas as demais listas paginadas por cursor: GET /v1/qr-codes/:id/comments, /v1/workspaces, /v1/gs1/identifiers, /v1/members, /v1/audit-logs, /v1/admin/orgs, /v1/admin/users e /v1/webhooks/:id/deliveries. Todas paginavam apenas por created_at; linhas com carimbo de data/hora idêntico (entradas de auditoria de uma operação em lote, novas tentativas de webhook, importações de membros) podiam se perder na página seguinte. A chave de ordenação agora é, em todas elas, a tupla (created_at, id).
  • Alteração na API: Nestas listas, meta.pagination.next_cursor passa a ser também um valor opaco (base64url) em vez de um carimbo de data/hora simples; cursores ilegíveis retornam 400, cursores antigos de carimbo de data/hora continuarão sendo aceitos temporariamente. Exceção GET /v1/webhooks/:id/deliveries: ali, next_cursor continua sendo o ID da última entrega (ID desconhecido → primeira página). Os clientes que retornam next_cursor sem alterações — Painel, CLI, SDKs, MCP — não precisam alterar nada.
  • Impacto: Nenhuma migração é necessária. Se sentiu falta de entradas ao paginar numa destas listas (por exemplo, log de auditoria ou log de entregas no Painel): elas nunca desapareceram — as listas passam a mostrá-las na totalidade a partir de agora.

2026-08 · Timestamps novamente em conformidade com a OpenAPI após edição e exclusão

  • Fix: Após PATCH /v1/codes/{id}, o updated_at retornava no formato SQLite sem fuso horário (2026-08-17 09:00:00), embora a especificação OpenAPI especifique format: date-time e a criação (POST) forneça o timestamp ISO (2026-08-17T09:00:00.000Z). O mesmo se aplicava a deleted_at/updated_at na exclusão lógica (soft-delete), bem como aos caminhos de edição e exclusão de API-Keys, organizações, workspaces, membros, comentários e webhooks, além de last_used_at de API-Keys e last_triggered_at de webhooks. Todos os caminhos de gravação agora registram em ISO 8601 (UTC, T e Z).
  • Impacto: Clientes que analisam updated_at com new Date(...) (SDKs, CLI, Painel) liam o formato com espaço como hora local — a CLI mostrava, para códigos que já haviam sido editados, a hora deslocada pelo offset local (Viena: −2 h). Isso foi corrigido. Além disso, uma migração de dados normaliza os valores já salvos no formato antigo para ISO, para que a ordenação e as comparações em registros mistos funcionem corretamente. Nenhuma alteração nos nomes dos campos ou na estrutura de resposta. Isso foi corrigido. Além disso, uma migração de dados normaliza os valores já salvos no formato antigo para ISO, para que a ordenação e as comparações em registros mistos funcionem corretamente. Nenhuma alteração nos nomes dos campos ou na estrutura de resposta.
  • Contexto: Mesma classe de erro que as duas correções abaixo (expiração de API-Key, limite de re-scan): o datetime('now') do SQLite grava YYYY-MM-DD HH:MM:SS, enquanto todos os outros gravadores usam ISO 8601. Um teste de proteção no código-fonte evitará novas ocorrências no futuro.

2026-08 · Paginação de listas não perde mais códigos em lote

  • Fix: GET /v1/codes e GET /v1/dpp paginavam apenas por created_at. No entanto, os códigos de POST /v1/codes/batch, POST /v1/dpp/batch e da importação de CSV/XLSX compartilham um único carimbo de data/hora — assim que um lote era maior que limit (padrão 20), a segunda página não retornava mais as linhas restantes do mesmo carimbo de data/hora. Os códigos existiam e estavam acessíveis via GET /v1/codes/:id, mas nunca apareciam na lista (Painel, CLI qr3 list, SDKs, MCP). O cursor agora é um keyset sobre (created_at, id).
  • Alteração na API: meta.pagination.next_cursor agora é um valor opaco (base64url) em vez de um carimbo de data/hora simples. Quem retorna o cursor inalterado como ?cursor= — como o Painel, CLI, todos os SDKs e o servidor MCP fazem — não precisa alterar nada. Cursores antigos de carimbo de data/hora continuarão sendo aceitos temporariamente; cursores ilegíveis agora retornam 400 em vez de entregar silenciosamente a primeira página.
  • Impacto: Se você viu menos códigos na lista após uma importação em lote do que os que foram criados: os códigos nunca sumiram — a lista agora os exibe por completo. Nenhuma migração é necessária.

2026-08 · Re-scans de segurança voltam a ser executados a cada 24 horas

  • Fix: O re-escaneamento periódico de URLs de destino e links de landing pages (Google Web Risk) ignorava códigos cujo último escaneamento ocorria no mesmo dia civil que o cutoff de 24 horas — dependendo do horário, o re-escaneamento era atrasado em até mais um dia. O cutoff agora é calculado no mesmo formato ISO em que os timestamps de escaneamento são armazenados.
  • Impacto: Uma URL de destino classificada como insegura após o último escaneamento resultará novamente na pausa automática do código dentro da janela documentada de 24 horas. Sem alterações na API ou no formato de resposta.

2026-08 · Chaves de API expiram no momento exato de expiração

  • Fix: Uma chave de API cujo expires_at ocorria no mesmo dia continuava sendo aceita até a meia-noite UTC. A expiração agora é comparada como um timestamp em vez de uma string — uma chave expirada retorna imediatamente 401.
  • Contexto: O expires_at é armazenado como um timestamp ISO (2026-08-14T09:00:00Z), mas o lado da comparação fornecia o formato com espaço (2026-08-14 09:00:00). Por isso, a comparação direta de strings só funcionava corretamente quando a data em si já era diferente.
  • Impacto: Nenhuma migração é necessária, o formato de resposta de GET /v1/api-keys permanece inalterado. Valores de expiração ilegíveis agora são considerados expirados em vez de válidos.

2026-08 · Referência da API: Gestão de Tenants documentada

  • OpenAPI: A especificação — e, portanto, a referência interativa — agora documenta Organizações (incl. GET /v1/organizations/usage), Workspaces, Membros e Funções e Logs de Auditoria.
  • Faturamento: A visão geral dos planos (GET /v1/billing/plans) é pública; o checkout (POST /v1/billing/checkout) e o portal do cliente Stripe (GET /v1/billing/portal) estão identificados como endpoints para administradores da organização.
  • Exportação de Scans: As estatísticas de scan (GET /v1/codes/{id}/scans) e a exportação de dados brutos (…/scans.csv, …/scans.xlsx) estão totalmente documentadas — incluindo o aviso de RGPD: o ip_hash nunca está incluído na exportação.
  • Comportamento de erro: Também está documentada a resposta 400 da validação de requisições: o corpo é o erro Zod bruto, não um documento de problema RFC-7807 — no entanto, é fornecido sob o Content-Type application/problem+json.
  • Dashboard: Os arquivos públicos na página de detalhes do código agora têm um botão que copia o seu link público para a área de transferência – utilizável diretamente como URL de destino de um QR Code, caso um escaneamento precise abrir imediatamente um documento específico em vez da landing page com la lista de arquivos.
  • API: Os endpoints de arquivos (/v1/files) agora também retornam public_url. Este campo é definido apenas para arquivos com visibility: public – arquivos privados não recebem um endereço público.
  • Comportamento: O link não requer login e abre o arquivo diretamente no navegador. A substituição do arquivo mantém o link inalterado, portanto, um código impresso com ele continua válido. Detalhes: Arquivos e Fichas Técnicas.

2026-07 · Funções de Equipe: Editor sem exclusão e Faturamento de Administrador

  • Novo: Nova função de membro Editor (sem exclusão) — cria e edita QR Codes, arquivos e Digital Product Passports, mas não pode excluir nada nem criar API-Keys. Todos os endpoints destrutivos verificam a função no lado do servidor (403).
  • Faturamento: Upgrades de plano e o portal do cliente Stripe (POST /v1/billing/checkout, GET /v1/billing/portal) agora são reservados para administradores da organização — todas as outras funções visualizam uma visão geral do plano em modo somente leitura.
  • Dashboard: As ações não permitidas pela função do usuário são ocultadas: um Visualizador, por exemplo, não vê botões para criar, editar ou excluir; listas, downloads e estatísticas continuam visíveis. Detalhes: Equipe e Funções.
  • Landing page: A landing page de um código hospedada pela qr3 agora pode listar links externos hospedados pelo próprio usuário ({ label, url }) – além de ou em vez de arquivos enviados, por exemplo, para fichas técnicas em seu próprio site.
  • API: POST/PATCH /v1/codes aceitam um array links (0–20 itens, http(s), ≤ 2048 caracteres). Cada URL é verificada com o Google Web Risk; uma URL insegura retorna 422. Um array vazio remove todos os links.
  • Dashboard: Adicionar, ordenar e remover links na página de detalhes do código.
  • Segurança: Os links renderizados permanecem protegidos contra XSS (escapados, apenas http(s)) e a página mantém seu cabeçalho noindex.

2026-04 · Análise do Dashboard por QR Code

  • Dashboard: O botão de análise na lista de QR Codes agora abre a página de estatísticas do respectivo QR Code em /dashboard/codes/{id}.
  • Roteamento: O alias /dashboard/codes continua redirecionando para /dashboard, mas não intercepta mais rotas de detalhes como /dashboard/codes/{id}.
  • API: A página de detalhes carrega o QR Code diretamente via GET /v1/codes/:id; com isso, ela não depende mais dos limites de paginação da lista.
  • Testes: Testes de regressão cobrem o redirecionamento do alias e o carregamento direto do código.

2026-04 · Diálogo de exclusão do Dashboard para QR Codes

  • Dashboard: O ícone de lixeira na lista de QR Codes agora abre um diálogo React próprio em vez de um pop-up nativo do navegador.
  • Feedback: Após a exclusão, uma notificação toast é exibida para indicar sucesso ou erro.
  • Testes: packages/dashboard/tests/dashboard.test.ts evita regressões no confirm() no fluxo de exclusão de QR Codes.
  • Dashboard: Os shortcodes na lista de QR Codes agora são clicáveis diretamente como links de redirecionamento externos. O ícone de link externo ao lado de, por exemplo, wu3qaa abre https://qr3.app/{shortCode} em uma nova aba.
  • i18n: Textos de dica de ferramenta (tooltips) adicionados para alemão e inglês.
  • Testes: packages/dashboard/tests/dashboard.test.ts protege o href do link, o comportamento de nova aba, noopener noreferrer e o ícone contra regressões.

2026-04 · Rota do Redirect-Worker para QR Codes dinâmicos

  • Fix: Correção: QR Codes dinâmicos em https://qr3.app/{shortCode} voltam a ser processados pelo Redirect-Worker. A rota de produção agora usa qr3.app/*, pois as rotas do Cloudflare Workers não suportam parâmetros de caminho :code.
  • Robustez: Caminhos que não correspondem são repassados para a origem da landing page, para que páginas normais como /de/pricing não sejam bloqueadas pelo Redirect-Worker.
  • Testes: packages/redirect/tests/unit/redirect.test.ts verifica a rota curinga (wildcard), o processamento de shortcodes e o redirecionamento para a origem (pass-through).

2026-04 · Visão geral de escaneamentos de DPP do Workspace (Q3.4.2)

  • Novo: GET /v1/workspace/stats/dpp?days=30 — agrega todos os dpp_scans do workspace da API-Key (active_dpps, scans_by_day, top_dpps com nome do produto/categoria).
  • Dashboard: Card na página inicial (/dashboard) com gráfico de barras de 30 dias + listas dos mais acessados — em paralelo com os cards de QR Codes.
  • Público: Link curto de marketing GET /dpp/dpp_<id> (um segmento) para demonstrações ao vivo, em paralelo com /dpp/{gtin}/{serial}.

2026-04 · Análise de escaneamentos de DPP (Q3.4.1)

  • Novo: GET /v1/dpp/:id/stats?days=30 — escaneamentos agregados do resolvedor GS1 público por DPP. Campos: total_scans, period_scans, scans_by_day, top_countries, top_devices, top_representations.
  • Novo: Tabela dpp_scans (migração 0011) — separada de scans (Redirect-Worker). Os endereços IP são hasheados com um salt rotativo diário, IPs brutos nunca chegam ao D1.
  • Dashboard: Card de mini-gráfico (SVG, sem biblioteca de gráficos) em /dashboard/dpp/:dppId com barras de 30 dias + detalhamento dos top 3. Estado vazio (empty state) assim que um DPP estiver ativo, mas ainda não tiver escaneamentos.

2026-04 · Simulador de conformidade da UE ao vivo (Q3.3.7)

  • Novo: POST /v1/dpp/:id/validate-update — simula atualizações parciais stateless (status, lista de mercados, …) sem persistência. A resposta contém eu_compliance + preview.changed_fields.
  • Dashboard: Card do simulador nos detalhes do DPP (/dashboard/dpp/:dppId) — chips para DE/AT/FR/IT/ES/NL + personalizado, menu suspenso de status, Preview EU impact / Save changes / Reset. Não bloqueante via Remix useFetcher.
  • Robustez: Helpers do simulador extraídos (readUpdatePatchFromForm, marketCountriesKey) + 18 novos testes unitários; correção de bug: entrada única não ISO não limpa mais a lista de mercados.

2026-04 · Visualização de conformidade da UE ao vivo no formulário de criação (Q3.3.6)

  • Alterado: POST /v1/dpp/validate agora também retorna eu_compliance — o mesmo validador de GET /v1/dpp/:id/eu-compliance, stateless antes de salvar.
  • Dashboard: Visualização abaixo do painel de validação existente + novo banner de proteção ao salvar (Save-Guard-Banner) antes dos botões de envio quando houver erros/avisos pendentes (pluralização i18n DE/EN).

2026-04 · Validador da UE + UI de Têxteis (Q3.3.4 + Q3.3.5)

  • Novo: Validador de conformidade da UE com 5 regras de têxteis (TEXTILE_AGEC_REQUIRED, TEXTILE_MICROPLASTICS_CONSISTENCY, TEXTILE_SVHC_THRESHOLD, TEXTILE_GREENWASHING, TEXTILE_ESPR_READY).
  • Novo: GET /v1/dpp/:id/eu-compliance com compliant / espr_ready / issues[] / summary.
  • Dashboard: Seção de conformidade da UE nos detalhes do DPP (blocos de resumo, cards de problemas agrupados, selo ESPR-Ready no cabeçalho).

2026-04 · Esquema de DPP para Têxteis (Q3.3.1–Q3.3.3)

  • Novo: Categoria textile com cadeia obrigatória AGEC (tecelagem/tricô → tingimento/impressão → confecção), por fibra origin_country + recycled_pct, svhc_substances[], opt-in ESPR (PEF, vida útil, reciclabilidade).
  • Novo: Campo básico market_countries: string[] (ISO 3166-1 alpha-2) em todas as categorias de DPP — controla as regras AGEC específicas da França e a nota obrigatória do consumidor francês.
  • Novo: Modelo HTML do consumidor com caixa de aviso de microplásticos AGEC, cadeia de origem de 3 etapas (pílulas com bandeiras), lista SVHC, seção de durabilidade e reciclabilidade.
  • Migração: 0010_dpp_market_countries (D1).

2026-04 · Importação em lote de DPP (Q3.2.1–Q3.2.5)

  • Novo: POST /v1/dpp/import aceita CSV e XLSX (compatível com Workers via SheetJS xlsx, pacote gzip de ~283 KB).
  • Escalável: limite baseado no plano (Free 100 → Enterprise 10k) + db.batch() em blocos (chunked) de 100 + limite de corpo de 5 MB.
  • Novo: Relatório de erros como CSV no campo errors_csv da resposta 201; GET /v1/dpp/import/templates/:category?format=csv|xlsx fornece modelos prontos para baterias e têxteis.
  • Dashboard: Upload por arrastar e soltar em /dashboard/dpp/import com proxy de modelo e download de CSV inline.

Extensões LTS sem alterações incompatíveis (Non-Breaking)

Todas as alterações mencionadas acima são aditivas:

  • Clientes existentes de POST /v1/dpp/validate ignoram o novo campo eu_compliance sem alterações.
  • Fluxos existentes de battery permanecem inalterados.
  • market_countries é opcional e tem como padrão [].

Consulte Versão da API para obter a política de alterações incompatíveis (breaking changes).