# Princípios

### Há 3 caminhos para o fracasso

1. Não ensinar o que se sabe.
2. Não praticar o que se ensina.
3. Não perguntar o que se ignora.

### Há 3 caminhos para o sucesso

1. Generosidade mental, ensine o que sabe.
2. Coerência ética, pratique o que ensina.
3. Humildade intelectual, não ignore, pergunte.


# Arquitetura Front-end

— Guilherme Siquinelli  🗓️  17/09/2022

Atualmente, com necessidades mais complexas e equipes numerosas, problemas e erros difíceis de resolver aparecem. É uma tendência natural que projetos se tornem obsoletos com o passar do tempo e, a dificuldade de mantê-los atualizados aumenta quando temos um número alto de dependências, fazendo com que a entropia do projeto cresça. A pessoa responsável pela arquitetura entra em cena, pois ela vê o software como ponto principal para que o produto consiga gerar o valor esperado, planejando um design de alto nível que será o alicerce, a estrutura sobre a qual o software será desenvolvido.

Fazendo uma analogia entre o desenvolvimento de software e a construção de um prédio, o arquiteto faz o desenho considerando suas necessidades estruturais e o uso que é previsto para ele, tanto em casos de uso como em intensidade. Então entrega aos engenheiros e técnicos que irão trabalhar na construção. Isso é muito importante na engenharia de software, porque diferente de um prédio, o software segue sendo construído e modificado, e não é concluído em 1 ou alguns poucos anos. É muito comum que novos planos apareçam com mudanças no escopo, este mercado é muito mais rápido, não só pelas variações de oferta e demandas no mercado, mas também por evoluções de tecnologias usadas. A arquitetura de software facilita o desenvolvimento de produtos mais robustos e sofisticados, criando diretrizes claras que permitem aos engenheiros saber a todo momento que tipo de código precisam construir para obter os resultados esperados.

Tendo uma visão ampla sobre a vida útil de um software, os arquitetos podem incluir já nos estágios iniciais estruturas chaves que se feitas quando o produto estiver em produção, demandam alto custo de implementação. É muito comum que empresas de tecnologia se concentrem mais na funcionalidade e na entrega de resultados imediatos do que na arquitetura e no ciclo de vida de seus produtos. Isso faz com que elas comecem a usar técnicas que não escalam bem e frameworks fáceis de usar ou que dependem muito de serviços de terceiros, porém quando aparecem milhares ou milhões de usuários e os investidores exigem escalabilidade com estabilidade, as coisas se complicam.

Alterar a estrutura de uma aplicação que ninguém usa e uma mudança global que afeta milhões de usuários ao mesmo tempo são coisas completamente diferentes, assim como não é a mesma coisa alterar a Stack ou framework usado quando apenas algumas pessoas trabalham no projeto, que realizar isso com centenas de colaboradores envolvidos.

A arquitetura de software ajuda na tomada de decisões a tempo de escolher quais riscos desejam ser assumidos ou evitados e, que poderiam afetar para sempre o rumo do projeto.


# Arquitetura em camadas

Uma abordagem sobre responsabilidades e relacionamentos

## Estrutura de fundação

Existem dois estilos de monorepos: repositórios integrados e repositórios baseados em pacotes. A diferença é mais sobre a mentalidade do que os recursos usados e a escolha do estilo é um espectro — não um booleano.

### Os baseados em pacotes

Os baseados em pacotes concentram-se na flexibilidade e na facilidade de adoção.

São uma coleção de pacotes que dependem uns dos outros por meio de arquivos package.json. Com essa configuração, você normalmente tem diferentes dependências para cada projeto. Ferramentas como Jest ou Webpack funcionam normalmente, já que tudo é resolvido como se cada pacote estivesse em um repositório separado e todas as suas dependências fossem publicadas no npm. Mover um pacote existente para um repositório baseado em pacotes é bem fácil, pois geralmente deixamos intocadas as ferramentas e configurações de build existentes. Já não podemos dizer o mesmo para a\
criação de novos pacotes usando este estilo de monorepo. Criar pacotes é tão difícil quanto criar um novo repositório, pois precisamos configurar tudo do zero.

#### Exemplo de estrutura

```
package-based/
├── packages/
├── nx.json
└── package.json
```

Lerna, Yarn, Lage, Turborepo e Nx (sem plugins) suportam esse estilo.

### Integrados

Concentram-se na eficiência e na facilidade de manutenção.

Eles contém projetos que dependem uns dos outros por importação padrão.\
Normalmente, há uma única versão de cada dependência definida na raiz. É mais difícil adicionar um pacote existente a esse estilo de repositório porque as ferramentas de build deste pacote podem recisar ser modificadas. É fácil adicionar um novo projeto ao repositório porque todas as decisões de ferramentas já foram tomadas.

#### Exemplo de estrutura

```
integrated/
├── apps/
├── libs/
├── nx.json
└── package.json
```

Bazel e Nx (com plugins) suportam este estilo.

## Tipos de bibliotecas

De uns anos para frente (6 \~ 7) até o momento, vi vários tipos de bibliotecas em monorepos, testando a aplicação de todos conforme os descobria. Estes tipos de bibliotecas são a forma com que separamos o código em camadas em um repositório com vários projetos. Com o tempo aprendi que muitos tipos de bibliotecas e também um número alto de aninhamento no repositório causa dificuldade não apenas de navegação mas também de entendimento…

Para manter um senso de organização em repositórios de médio e grande porte, recomenda-se a divisão entre 4 a 6 tipos de bibliotecas, sendo elas camadas com responsabilidades bem definidas e relacionamentos controlados. Trata-se de uma estrutura de diretórios com no máximo 2 níveis de aninhamento ou 3 em caso de agrupamento por escopos, contando a partir de apps, libs ou packages.

Para a maior parte dos casos, recomenda-se o uso de 4 tipos de bibliotecas, sendo suficiente para manter o código organizado em uma arquitetura de baixa complexidade.

1. Bibliotecas **feature**, para componentes com regras de negócio e aplicação (smart), geralmente são específicas de algum aplicativo, como páginas ou funcionalidades.
2. Bibliotecas **data-access**, para classes e funções relacionadas a acesso a dados e gerenciamento de estado, como código para acessar uma API back-end.
3. Bibliotecas **util**, para código sem regras e compartilhado por muitas bibliotecas.
4. Bibliotecas **ui**, para componentes sem regras (dumb) e compartilhados por algum escopo ou diversas bibliotecas no repositório.

Além destes 4, quando entendido em consenso, temos recomendações para outros 2.

1. Bibliotecas **domain**, para casos de uso com regras de negócios puras, dependentes apenas de entidades e abstrações para acesso a dados.
2. Bibliotecas **api** servem como porta de acesso para permitir que bibliotecas de diferentes escopos se comuniquem entre si.

### Escopos de bibliotecas

Escopo é um diretório agrupador, eles podem representar diferentes conjuntos de funcionalidades ou APIs disponíveis. Cada biblioteca ou um grupo de bibliotecas pode ter seu próprio escopo, que define quais recursos são públicos, privados ou internos. Isso permite que os usuários da biblioteca acessem apenas as partes relevantes e evita a exposição de implementações internas. Isso é feito através do tipo API.

As principais diferenças a serem consideradas ao decidir entre abordagens de 4 ou 6 tipos pode variar dependendo das necessidades e características específicas do projeto, como:

1. Complexidade e tamanho do projeto: O uso de 4 tipos de bibliotecas pode ser mais adequado para projetos menores e menos complexos, nos quais a modularidade é alcançada com uma estrutura mais simples. Isso evita uma segmentação excessiva e reduz a sobrecarga de gerenciamento de várias bibliotecas. Por outro lado, projetos maiores e mais complexos podem se beneficiar do uso de 6 tipos de bibliotecas, pois isso permite uma maior granularidade e organização do código.
2. Reutilização de código: O uso de 6 tipos de bibliotecas, incluindo Bibliotecas Domain e Bibliotecas API, promove uma maior reutilização de código em diferentes partes do projeto. Isso é especialmente benéfico quando há casos de uso com regras de negócio puras que podem ser compartilhadas entre aplicativos ou quando diferentes bibliotecas precisam se comunicar entre si. Se a reutilização de código é uma prioridade, a abordagem com 6 tipos de bibliotecas pode ser mais\
   apropriada.
3. Flexibilidade e extensibilidade: A inclusão de Bibliotecas Domain permite que a lógica de negócio seja encapsulada e independente de frameworks externos, facilitando a modificação e a expansão do projeto no futuro. Isso permite que diferentes aplicativos ou partes do código utilizem a mesma lógica de domínio, proporcionando uma maior flexibilidade e extensibilidade. Se o projeto requer\
   uma estrutura que possa se adaptar a mudanças futuras com facilidade, o uso de 6 tipos de bibliotecas pode ser vantajoso.
4. Manutenção: O uso de uma maior quantidade de tipos de bibliotecas pode tornar a manutenção do código mais organizada e compreensível. Cada tipo de biblioteca tem sua responsabilidade bem definida, o que facilita a localização e a modificação de partes específicas do código. Isso torna o processo de depuração e correção de problemas mais eficiente. Se a manutenção do código é uma preocupação importante, a abordagem com 6 tipos de bibliotecas pode ser preferível.

Veremos cada um dos tipos de bibliotecas para esclarecer cada um deles.

#### Principais diferenças para adoção de 4 ou 6 tipos

Também preciso esclarecer sobre escopos, que são nada mais que diretórios agrupadores.

Antes disso, quero adiantar que abordarei sobre restrições de dependências entre elas e que as restrições podem variar dependendo da quantidade de tipos de bibliotecas adotados no repositório, darei minha perspectiva sobre 2 casos, 4 tipos e 6 tipos, como vimos acima.

### Bibliotecas feature

Conhecida como biblioteca de recursos ou funcionalidades, devemos considerar implementações da interface do usuário inteligentes (smart components), que tenham acesso às fontes de dados e gerenciamento de estado da camada de acesso a dados.

#### Convenção de nomenclatura

**feature** (caso aninhado) ou **feature-\***

exemplo: **feature-auth**

As bibliotecas do tipo Feature são componentes que possuem regras de negócio e aplicação específicas de um determinado aplicativo. Elas são desenvolvidas para abordar funcionalidades ou partes específicas de um sistema. Essas bibliotecas são projetadas para serem reutilizáveis em diferentes partes do aplicativo, como páginas, módulos ou funcionalidades.

A principal característica das bibliotecas do tipo Feature é encapsular as regras de negócio específicas de uma determinada funcionalidade. Elas contêm a lógica necessária para implementar e manipular as características relacionadas.

Ao criar uma biblioteca do tipo Feature, é importante considerar sua coesão, ou seja, o quanto ela está focada em uma única funcionalidade ou conceito. Isso garante que a biblioteca seja clara e específica em seu propósito, facilitando sua utilização e entendimento pelos desenvolvedores. Elas podem incluir, lógica de negócio, interfaces de usuário personalizadas, validações de formulários, entre outros elementos necessários para implementar a funcionalidade em questão. Essas bibliotecas são desenvolvidas com o objetivo de serem páginas da aplicação carregadas lentamente (lazy-loading) ou uma parte de uma aplicação maior, utilizada em diferentes partes, o que leva a uma maior eficiência no desenvolvimento.

#### Restrições de dependência

Para 4 principais tipos

Bibliotecas feature podem depender de qualquer tipo de biblioteca.

Para 6 tipos utilizados

Não é recomendado que uma biblioteca feature dependa diretamente de bibliotecas domain, mas que seja criado por exemplo um facade na camada de acesso a dados ou dependa de uma biblioteca do tipo API que exponha publicamente apenas o necessário para que os casos de uso sejam utilizados sem que haja dependência direta, pois quando permitimos importações diretas, qualquer coisa que está disponível pode ser utilizada, causando possíveis transtornos em quaisquer alterações, pois podem estar dependendo do recurso que está sendo alterado e manter retrocompatibilidade não é algo que queremos quando há alternativas sem danos ao negócio.

### Bibliotecas data-access

Este tipo de biblioteca serve como uma camada de delegação no lado do cliente, contendo código de acesso a dados em APIs REST e todo tipo de arquivo relacionado ao gerenciamento de estado e estes, por convenção, residem no diretório src/lib/+state.

#### Convenção de nomenclatura

**data-access** (caso aninhado) ou **data-access-\***

exemplo: **data-access-auth**

As bibliotecas do tipo Data Access são projetadas para facilitar o acesso a dados e o gerenciamento de estado em um aplicativo. Elas fornecem um conjunto de classes, métodos e utilitários que permitem recuperar, armazenar, atualizar e excluir informações de uma fonte de dados, como um banco de dados ou uma API back-end.

O objetivo principal das bibliotecas do tipo Data Access é abstrair as complexidades e detalhes técnicos envolvidos no acesso a dados. Elas oferecem uma camada de abstração que permite que os desenvolvedores interajam com os dados de maneira simplificada e consistente, independentemente da origem dos dados.

Essas bibliotecas geralmente fornecem abstrações e classes concretas para realizar operações comuns de acesso a dados, como consultas, inserções, atualizações e exclusões. Elas também podem oferecer recursos adicionais, como mapeamento objeto-relacional (ORM), gerenciamento de transações, cache de dados e tratamento de erros.

Ao utilizar uma biblioteca do tipo Data Access, os desenvolvedores podem se concentrar na lógica de negócio do aplicativo, em vez de se preocupar com os detalhes de como se conectar e interagir com a fonte de dados. Isso aumenta a produtividade e a eficiência do desenvolvimento, permitindo que eles se concentrem nas funcionalidades principais do aplicativo.

Outra vantagem das bibliotecas do tipo Data Access é a padronização do acesso a dados. Elas estabelecem convenções e melhores práticas para a interação com a fonte de dados, o que ajuda a garantir a consistência e a integridade dos dados manipulados pelo aplicativo. Além disso, a abstração fornecida por essas bibliotecas permite que seja mais fácil alterar a fonte de dados no futuro, caso seja necessário migrar para um banco de dados diferente ou uma API atualizada.

#### Restrições de dependências

Para 4 principais tipos

Camadas de acesso a dados podem depender de outras camadas de acesso a dados ou camadas utilitárias.

Para 6 tipos utilizados

Neste caso, acesso a dados também pode depender do tipo domain no mesmo escopo e da camada API para acesso a domínios em outros escopos.

### Bibliotecas ui

Abriga uma coleção de componentes de apresentação relacionados. Geralmente não dependem de serviços por injeção de dependências, todos os dados necessários devem vir de entradas (valores de atributos / props) e eventos para emissão de dados.

#### Convenção de nomenclatura

**ui** (caso aninhado) ou **ui-\***

exemplo: **ui-dialogs**

As bibliotecas do tipo UI são projetadas para fornecer componentes de interface do usuário que podem ser compartilhados entre diferentes partes de um aplicativo ou até mesmo entre aplicativos distintos. Essas bibliotecas são frequentemente chamadas de "UI shared" ou "UI kits".

O objetivo principal das bibliotecas do tipo UI é promover a consistência e a eficiência no desenvolvimento da interface do usuário. Elas encapsulam componentes reutilizáveis, como botões, caixas de texto, menus, barras de navegação e outros elementos de interface comuns. Esses componentes são projetados para serem flexíveis, personalizáveis e facilmente integrados em  diferentes partes do aplicativo.

Ao utilizar uma biblioteca do tipo UI, os desenvolvedores podem economizar tempo e esforço, pois não precisam criar cada componente de interface do zero. Eles podem simplesmente importar os componentes fornecidos pela biblioteca e utilizá-los em suas implementações. Isso resulta em uma padronização visual e de comportamento em todo o aplicativo, oferecendo uma experiência de usuário consistente.

As bibliotecas do tipo UI também podem incluir estilos de CSS, temas e padrões de design para garantir a coerência estética do aplicativo. Isso facilita a manutenção do visual do aplicativo e a aplicação de alterações de estilo de forma consistente em todo o sistema.

Além disso, essas bibliotecas geralmente fornecem uma abstração do código complexo e detalhado necessário para criar interações de interface do usuário. Os componentes encapsulam a lógica necessária para responder a eventos, interagir com o usuário e atualizar a interface conforme necessário. Isso ajuda a simplificar o desenvolvimento e a garantir uma base sólida para a construção de uma interface do usuário interativa e responsiva.

Uma das principais vantagens das bibliotecas do tipo UI é a reutilização de código. Ao usar os componentes fornecidos pela biblioteca em todo o aplicativo, as atualizações e correções em um único lugar se refletirão automaticamente em todos os locais onde esses componentes são utilizados. Isso reduz a duplicação de código, facilita a manutenção e melhora a consistência.

No entanto, é importante notar que as bibliotecas do tipo UI podem não ser adequadas para todas as situações. Em alguns casos, pode ser necessário criar componentes personalizados para atender às necessidades específicas do aplicativo. Além disso, a escolha de uma biblioteca do tipo UI deve levar em consideração a compatibilidade com as tecnologias e frameworks utilizados no projeto.

#### Restrições de dependência

Para 4 e 6 principais tipos

Bibliotecas UI podem depender de outras UIs ou utilitárias.

### Bibliotecas util

Uma biblioteca de utilitários contém código de baixo nível usado por muitas bibliotecas. Frequentemente, não há código específico do framework e a biblioteca é simplesmente uma coleção de utilitários ou funções puras.

#### Convenção de nomenclatura

**util** (caso aninhado) ou **util-\***

exemplo: **util-testing**

Elas oferecem funcionalidades genéricas e comuns que podem ser usadas em diferentes partes de um aplicativo ou até mesmo em vários aplicativos. Elas são projetadas para fornecer um conjunto de ferramentas e utilidades que facilitam tarefas comuns de programação, independentemente do domínio específico do aplicativo.

O objetivo principal das bibliotecas do tipo Útil é promover a reutilização de código e simplificar o desenvolvimento, fornecendo funcionalidades comuns que podem ser usadas em várias partes do aplicativo. Essas bibliotecas abrangem uma ampla gama de recursos e utilidades, como manipulação de strings, formatação de datas, cálculos matemáticos, conversões de dados, operações de arquivo, gerenciamento de configurações e muito mais.

Ao usar bibliotecas do tipo Útil, os desenvolvedores podem economizar tempo e esforço ao evitar a necessidade de implementar essas funcionalidades comuns repetidamente em diferentes partes do código. Isso resulta em um código mais limpo, mais conciso e mais legível, além de melhorar a manutenibilidade e a consistência do aplicativo.

Elas são projetadas para serem independentes do domínio do aplicativo, o que significa que podem ser utilizadas em diferentes projetos, independentemente do seu escopo ou propósito.

Essas bibliotecas normalmente são compostas por uma coleção de classes, funções e utilitários que são organizados de forma coesa e bem documentada. Também podem ser distribuídas como pacotes ou módulos separados, permitindo que os desenvolvedores escolham e utilizem apenas as funcionalidades que são relevantes para suas necessidades.

Além de fornecer funcionalidades genéricas, as bibliotecas do tipo Util também podem incluir recursos adicionais, como tratamento de erros, logging, serialização/deserialização de objetos, geração de código, criptografia e muito mais. Esses recursos adicionais ajudam a melhorar a qualidade, a segurança e o desempenho do aplicativo.

### Bibliotecas domain

As bibliotecas do tipo domain são projetadas para encapsular as regras de negócio e a lógica pura de um domínio específico. Elas são focadas em representar conceitos, entidades e operações relacionadas ao núcleo da aplicação, independentemente da implementação técnica ou do ambiente em que o sistema está sendo executado.

#### Convenção de nomenclatura

**domain** (caso aninhado) ou **domain-\***

exemplo: **domain-accounts**

O objetivo principal destas bibliotecas é separar e isolar a lógica de negócio do restante do código da aplicação. Elas encapsulam as regras de negócio complexas e fornecem uma interface clara e coesa para que as outras partes do sistema possam interagir com o domínio de negócio específico.

Ao utilizar bibliotecas do tipo domain, os desenvolvedores podem se concentrar no entendimento e na modelagem do domínio em que estão trabalhando. Isso permite uma melhor expressão da lógica de negócio e facilita a manutenção e a evolução do sistema ao longo do tempo.

As bibliotecas do tipo domain são tipicamente compostas por classes, interfaces e estruturas que representam as entidades e os conceitos do domínio. Elas encapsulam as operações e as interações entre essas entidades, bem como as regras e as restrições que governam o comportamento do domínio.

Essas bibliotecas podem conter métodos e algoritmos específicos do domínio, validações de dados, cálculos complexos, fluxos de negócio e outras operações relacionadas às regras e ao comportamento específico do domínio.

Uma vantagem significativa das bibliotecas do tipo domain é a reutilização de lógica de negócio entre diferentes partes do aplicativo ou até mesmo entre projetos diferentes. Ao separar as regras de negócio em uma biblioteca de domínio, é possível compartilhar e reutilizar a lógica em várias camadas da aplicação, como a camada de interface do usuário, a camada de acesso a dados e a camada de serviços.

Essas bibliotecas também podem ser testadas de forma independente, facilitando a realização de testes unitários e de integração para validar a lógica de negócio do domínio. Isso permite a detecção precoce de erros e garante que a lógica de negócio esteja funcionando corretamente.

### Bibliotecas API

Essas bibliotecas atuam como pontos de entrada para acessar recursos e funcionalidades específicas do monorepo. Elas podem fornecer métodos e classes que expõem serviços, endpoints de API ou outros mecanismos de comunicação.

#### Convenção de nomenclatura

**api** (caso aninhado) ou **api-\***

exemplo: **api-products**

Ao utilizar bibliotecas do tipo API em monorepos, é possível promover a reutilização de código e a consistência na comunicação entre os diferentes componentes do sistema. Elas permitem que os módulos do monorepo interajam uns com os outros de maneira padronizada, evitando duplicação de código e facilitando a manutenção e a evolução do sistema.

Quando diferentes partes do monorepo importam diretamente umas às outras, isso cria uma dependência rígida entre essas partes. Isso significa que qualquer mudança em uma parte pode afetar diretamente as outras partes que dependem dela. Essa dependência direta pode resultar em acoplamento excessivo, dificultando a manutenção e a evolução do código.

Ao usar bibliotecas do tipo API, cria-se uma camada de abstração entre os módulos. Cada módulo acessa a funcionalidade e os recursos de outros módulos por meio de uma interface definida pela biblioteca API. Isso permite que os módulos dependam apenas da interface da biblioteca, em vez de depender diretamente uns dos outros.


# Navigation

The Navigation API

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/API/Navigation_API>" %}

Pois é, tem um bom tempo que trabalhamos com gerenciamento de navegação em aplicações SPA e, conseguirmos fazer isso nativamente é um baita ganho pois muitos apps simples são criados utilizando frameworks apenas pra ter um controle de rotas facilitado.

Eu diria que essa é a funcionalidade de maior importância na web e vejo a **Navigation API** como um inicio de solução que ainda tem um caminho de evolução que merece ser bem projetada e não pode de maneira alguma cair no mesmo limbo que a [Web Components API](https://www.notion.so/Lista-das-APIs-da-Web-mais-teis-ou-pontualmente-interessantes-5799bdd79b1e4b178f4065d8c2ad8849?pvs=21) está atualmente.

[Link da documentação oficial](https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-api) - **whatwg**


# Barcode Detection API

Detectar códigos de barras lineares e bidimensionais em imagens nunca foi tão simples.

Esta é uma especificação escrita por um grupo da comunidade W3C, nomeado como Accelerated Shape Detection in Images ([shape detection api](https://wicg.github.io/shape-detection-api)).

### Introdução

Fotos e imagens constituem a maior parte da Web e muitas incluem informações detectáveis por métodos computacionais, que por sua vez são um tanto caros de processar, no entanto levaria a casos de uso interessantes como marcação de pessoas ou objetos em fotos e encaminhamento para páginas com facilidade. Você pode estar pensando "mas clicar em um link não é mais simples que ler um QRCode?" e a resposta é sim!

Porém, existem outros casos de uso onde estamos no mundo real e desejamos acessar um recurso do mundo virtual, um exemplo bem útil e comum de encontrar é quando chegamos a um restaurante e o acesso ao cardápio é feito através de um QRCode impresso, sem isso precisamos descobrir a URL e digita-la letra por letra. Pode não parecer, mas em algumas ocasiões isso pode ser frustrante ou desafiador, caso o domínio não seja amigável ou até mesmo em casos de acessibilidade para um surdo-mudo ou alguém com dificuldades especiais.

### Compatibilidade

<table data-header-hidden><thead><tr><th width="259">Navegador</th><th width="153.33333333333331" data-type="checkbox">Suporte</th><th>Versão</th></tr></thead><tbody><tr><td><strong>Chrome</strong></td><td>true</td><td>83+</td></tr><tr><td><strong>Edge</strong></td><td>true</td><td>83+</td></tr><tr><td><strong>Opera</strong></td><td>true</td><td>69+</td></tr><tr><td><strong>Android Browser</strong></td><td>true</td><td>126</td></tr><tr><td><strong>Chrome for Android</strong></td><td>true</td><td>126</td></tr><tr><td><strong>Opera Mobile</strong></td><td>true</td><td>80+</td></tr><tr><td><strong>Samsung Internet</strong></td><td>true</td><td>13+</td></tr><tr><td><strong>Safari on iOS</strong></td><td>false</td><td></td></tr><tr><td><strong>Firefox</strong></td><td>false</td><td></td></tr><tr><td><strong>Safari</strong></td><td>false</td><td></td></tr></tbody></table>

### Conceitos e uso

Alguns casos de uso por meio de formatos de código de barras suportados. Os códigos QR podem ser usados ​​para pagamentos on-line, navegação na web ou estabelecimento de conexões de mídia social, os códigos Aztec podem ser usados ​​para escanear cartões de embarque e os aplicativos de compras podem usar códigos de barras EAN para comparar preços de itens físicos.

### Exemplos de tipos de código

| Format       | Description                                                                                                                                                                                                                                      | Image                                                               |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
| aztec        | Uma matriz quadrada bidimensional seguindo iso24778 e com um padrão quadrado de alvo no centro, lembrando assim uma pirâmide asteca. Não requer uma zona vazia circundante.                                                                      | <img src="/files/5Y4n5DVJ3d81xiIDYYDL" alt="" data-size="original"> |
| code\_128    | Um código de barras linear (unidimensional), decodificáveis bidirecionalmente e autoverificável seguindo iso15417 e capaz de codificar todos os 128 caracteres do [ASCII](https://developer.mozilla.org/en-US/docs/Glossary/ASCII) (daí o nome). | <img src="/files/pYxrbrqXNO2gVR3WHevr" alt="" data-size="original"> |
| code\_39     | Um código de barras linear (unidimensional) de autoverificação seguindo iso16388. É um tipo de código de barras discreto e de comprimento variável.                                                                                              | <img src="/files/7PvaYR3UsVnwRMyz2oM5" alt="" data-size="original"> |
| data\_matrix | Um código de barras bidimensional independente de orientação composto por módulos preto e branco dispostos em um padrão quadrado ou retangular seguindo a iso16022.                                                                              | <img src="/files/lQJWYQd8D1otU4I4RlwA" alt="" data-size="original"> |
| ean\_13      | Um código de barras linear baseado no padrão UPC-A e definido em iso15420.                                                                                                                                                                       | <img src="/files/LcnNyBXG4pVeNrHnwjEH" alt="" data-size="original"> |
| ean\_8       | Um código de barras linear definido em iso15420 e derivado de EAN-13.                                                                                                                                                                            | <img src="/files/pFmb3WT8pnUedk9dCc4W" alt="" data-size="original"> |
| qr\_code     | Um código de barras bidimensional que utiliza o padrão iso18004. As informações codificadas podem ser texto, URL ou outros dados.                                                                                                                | <img src="/files/z6dHudil7bhNMxGVsJvx" alt="" data-size="original"> |
| unknown      | Este valor é usado pela plataforma para indicar que ela não sabe ou especifica qual formato de código de barras está sendo detectado ou suportado.                                                                                               |                                                                     |

### Conceitos técnicos

Entrando nos conceitos técnicos, a detecção é obtida por meio do método `detect()`, que recebe um objeto, podendo ser um dos a seguir, `HTMLImageElement`, `SVGImageElement`, `HTMLVideoElement`, `HTMLCanvasElement`, `ImageBitmap`, `OffscreenCanvas`, `VideoFrame`, `Blob`, ou `ImageData`. Além de parâmetros opcionais que podem fornecer dicas sobre quais formatos de código detectar.

### Implementação

Bem, agora podemos começar a explorar as APIs disponíveis no objeto `window`

Verifique se está utilizando algum dos navegadores que tenham suporte, conforme a tabela acima e usando o console JavaScript, execute:

`BarcodeDetector.getSupportedFormats().then(console.log)`

```javascript
["aztec", "code_128", "code_39", "code_93", "data_matrix", "ean_13", "ean_8", "itf", "pdf417", "qr_code", "upc_e"]
```

O retorno é um array contendo os formatos de códigos que podem ser lidos.

#### Recursos

Faça o download do pacote de imagens em SVG que preparei para nossos testes.

{% file src="/files/a1YyU5it3xnMqKkUwFSH" %}

#### Exemplo

Para testar essa API da Web apenas um arquivo HTML simples será suficiente, vamos lá.

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
  </head>
  <body>
    <img src="aztec.svg" alt="aztec" />
    <img src="data-matrix.svg" alt="data-matrix" />
    <img src="code_128.svg" alt="code_128" />
    <img src="code_39.svg" alt="code_39" />
    <img src="ean13.svg" alt="ean13" />
    <img src="ean8.svg" alt="ean8" />
    <img src="qr-code.svg" alt="qr-code" />

    <script>
      setTimeout(() => {
        const detector = new BarcodeDetector();

        const log = (id) => {
          return (...data) => {
            console.log(id, ...data);
          };
        };

        for (const image of document.images) {
          detector.detect(image).then(log(image.alt));
        }
      }, 1000);
    </script>
  </body>
</html>
```

Hoje paramos por aqui mas em breve escrevo uma implementação mais avançada usando esta API.

Valeu, abraço.

\[]s


# Barcode Detection API - Parte 2

Usando a câmera para detectar código

Desta vez usaremos **TypeScript** e para que isso seja feito sem alertas de erro no código, precisaremos que a API esteja devidamente tipada, porém, não temos disponível no arquivo `lib.dom.ts` do **TypeScript**. Eu mesmo escrevi um seguindo a especificação, vai servir por enquanto.

## barcode.d.ts

Crie um arquivo barcode.d.ts com o conteúdo a seguir.

```typescript
interface BarcodeDetector {
  new (barcodeDetectorOptions?: BarcodeDetectorOptions): BarcodeDetector;

  static getSupportedFormats(): Promise<BarcodeFormat[]>;

  detect(image: ImageBitmapSource): Promise<DetectedBarcode[]>;
}

declare var BarcodeDetector: {
  prototype: BarcodeDetector;
  new (barcodeDetectorOptions?: BarcodeDetectorOptions): BarcodeDetector;
};

interface BarcodeDetectorOptions {
  formats: BarcodeFormat;
}

interface Point2D {
  x: number
  y: number
}

interface DetectedBarcode {
  boundingBox: DOMRectReadOnly;
  rawValue: string;
  format: BarcodeFormat;
  cornerPoints: Point2D[];
}

type BarcodeFormat =
  | "aztec"
  | "code_128"
  | "code_39"
  | "code_93"
  | "codabar"
  | "data_matrix"
  | "ean_13"
  | "ean_8"
  | "itf"
  | "pdf417"
  | "qr_code"
  | "unknown"
  | "upc_a"
  | "upc_e";

```

Agora sim, partimos para implementação.

Basicamente o que precisamos fazer é:

1. Capturar o `stream` de vídeo do dispositivo
2. Desenhar o `video` em um elemento `canvas`
3. Executar o método de detecção no `canvas`
4. Se houver resultados, desenhar no `canvas`

Vamos lá!

## main.ts

```typescript
const stream$ = navigator.mediaDevices.getUserMedia({
  video: {facingMode: 'environment'},
})

const detector = new BarcodeDetector()

const value = new Text()
const h1 = document.createElement('h1')
h1.append(value)

const video = document.createElement('video')
video.autoplay = true

const canvas = document.createElement('canvas')
canvas.width = 640
canvas.height = 480

document.body.append(canvas, h1)

const context = canvas.getContext('2d')
if (!context) throw `context error`
```

Vamos separar a função `draw`

## draw\.ts

```typescript
export function draw(
  context: CanvasRenderingContext2D,
  paths: Point2D[],
  color = 'lime',
  width = 3
) {
  const [topLeft, topRight, bottomRight, bottomLeft] = paths
  context.strokeStyle = color
  context.lineWidth = width

  context.beginPath()
  context.moveTo(topLeft.x, topLeft.y)
  context.lineTo(topRight.x, topRight.y)
  context.lineTo(bottomRight.x, bottomRight.y)
  context.lineTo(bottomLeft.x, bottomLeft.y)
  context.closePath()
  context.stroke()
}

```

De volta ao `main.ts`, vamos finalizar!

```typescript
// ...

stream$.then((stream) => {
  video.srcObject = stream
  video.ontimeupdate = async () => {
    context.drawImage(video, 0, 0, 640, 480)

    const result = await detector.detect(canvas)

    if (result.length > 0) {
      for (const detected of result) {
        draw(context, detected.cornerPoints)
        value.textContent = detected.rawValue
      }
    }
  }
})

```

E então, o que achou? Espero que tenha gostado!

Abraço


# Atribuibilidade entre tipos

Tabela de atribuibilidade entre tipos TypeScript

As linhas indicam a que cada um é atribuível, as colunas indicam o que é atribuível a eles.

<table><thead><tr><th align="center"></th><th data-type="checkbox">any</th><th data-type="checkbox">unknown</th><th data-type="checkbox">object</th><th data-type="checkbox">void</th><th data-type="checkbox">undefined</th><th data-type="checkbox">null</th><th data-type="checkbox">never</th></tr></thead><tbody><tr><td align="center"><strong>any</strong></td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td align="center"><strong>unknown</strong></td><td>true</td><td>true</td><td>false</td><td>false</td><td>false</td><td>false</td><td>false</td></tr><tr><td align="center"><strong>object</strong></td><td>true</td><td>true</td><td>true</td><td>false</td><td>false</td><td>false</td><td>false</td></tr><tr><td align="center"><strong>void</strong></td><td>true</td><td>true</td><td>false</td><td>true</td><td>false</td><td>false</td><td>false</td></tr><tr><td align="center"><strong>undefined</strong></td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td align="center"><strong>null</strong></td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td align="center"><strong>never</strong></td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr></tbody></table>


# Pipe

Concatenando funções

Quem programa está acostumado com o conceito de pipe, pois utilizamos pipes em diversos lugares, certo? Por exemplo, quando pegamos a saída de um comando e usamos como entrada para outro comando em no terminal.

```bash
history | grep x
```

Usamos o caractere pipe `|` para concatenar 2 comandos.

Quando trabalhamos com streaming de dados também vemos o uso de pipes, seja com a biblioteca [rxjs](https://rxjs.dev) ou nativamente com a api da web [streams](https://streams.spec.whatwg.org), ou ainda com a api [web streams](https://nodejs.org/api/webstreams.html) do nodejs.

Mas como eu posso concatenar funções, para que uma função receba como argumento o retorno da função anterior? E eu lhe digo, isso pode ser feito usando [reduce](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)!

Vamos primeiro implementar usando apenas JavaScript, para entender de forma simples o que é estritamente necessário para essa implementação.

```javascript
function pipe(...[fn, ...fns]) {
  return (value) => fns.reduce((prev, curr) => curr(prev), fn(value))
}
```

Então podemos criar como exemplo uma função que calcula um valor ao quadrado.

```javascript
const square = (value) => value * 2
```

Perceba que ela só precisa do valor que será trafegado entre as funções e nada mais, agora vamos criar outra função que calcula a porcentagem e desta vez precisamos informar quantos % queremos.

```javascript
const percent = (n) => (value) => (n / 100) * value
```

Vamos concatenar os 2 exemplos.

```javascript
const calculate = pipe(square, percent(10))
```

Agora temos uma função nomeada `calculate`, que recebe um parâmetro e processa o fluxo com ele, retornando o resultado final.

```javascript
calculate(100) // 20
```

O que achou?

No próximo vou mostrar como escrever em TypeScript, facilitando a experiência de uso com tipagem estática.

Valeu, abraço

\[]s


# Event Emitter

Como criar um gerenciador de eventos

## Introdução

Se você trabalhou com JavaScript, sabe o quanto da interação do usuário é tratada por meio de eventos: cliques do mouse, cliques de botões, entradas do teclado, reações aos movimentos do mouse e assim por diante.

Além disso, também usamos este conceito em vários outros lugares, como WebSocket e até arquiteturas que se baseiam em eventos. Vamos criar nosso próprio gerenciador de eventos e assim integrar onde fizer sentido em nossos projetos.

Para evitar confusão com eventos do DOM, usaremos nomenclaturas utilizadas no EventEmitter do NodeJS.

## Requisitos

Basicamente, nosso EventEmitter será composto por 4 métodos em sua API pública, são eles:

1. `on`: espera o nome do evento e uma função callback, que será executada toda vez que houver uma emissão para o evento.
2. `once`: espera o nome do evento e uma função callback, que será executada apenas uma vez para o evento.
3. `off`: espera o nome do evento e a função callback que não será mais executada para o evento.
4. `emit`: espera o nome do evento e o valor que será emitido para as funções callback ouvindo o evento.

## Implementação

Certo, vamos começar definindo nossa interface `Callback`.

```typescript
export interface Callback<T> {
  (value: T): void
  once?: boolean
}
```

Definimos que `Callback` é uma função e possui uma flag `once` que usaremos para identificar se devemos remover essa função da lista de execuções depois da primeira execução.

Na classe `EventEmitter`, vamos começar definindo nossas propriedades e métodos privados, eles serão utilizados nos métodos da API pública.

<pre class="language-typescript"><code class="lang-typescript"><strong>export class EventEmitter&#x3C;T> {
</strong>  #listeners = new Map()
  
  #getListeners&#x3C;K extends keyof T>(type: K): Set&#x3C;Callback&#x3C;T[K]>> {
    return this.#listeners.get(type) ?? new Set()
  }
}
</code></pre>

Perceba que `#listeners` é um `Map` que registra um `Set` de `Callback` para cada evento.

### `off`

O método `off` será utilizado por quase todos os demais.

```typescript
export class EventEmitter<T> {
  
  off<K extends keyof T>(type: K, callback: Callback<T[K]>) {
    const listeners = this.#getListeners(type)
    listeners.delete(callback)
    this.#listeners.set(type, listeners)
  }
  
}
```

Veja, nós atribuímos o `Set` de um determinado evento em `listeners`, removemos a função solicitada e então sobrescrevemos o evento com o novo `Set`, sem a função.

### `on`

Geralmente este é o método mais utilizado.

```typescript
export class EventEmitter<T> {
  
  on<K extends keyof T>(type: K, callback: Callback<T[K]>) {
    const listeners = this.#getListeners(type)
    this.#listeners.set(type, listeners.add(callback))
    return {off: () => this.off(type, callback)}
  }
  
}
```

Atribuímos o `Set` de um determinado evento em `listeners` e sobrescrevemos o evento com o novo `Set`, com a função adicionada.

### `once`

Aqui precisamos definir a flag que determina quantas vezes a função será executada.

```typescript
export class EventEmitter<T> {
  
  once<K extends keyof T>(type: K, callback: Callback<T[K]>) {
    callback.once = true
    this.on(type, callback)
  }
  
}
```

Repare que apenas adicionamos a flag `once`, e aproveitamos a implementação do método `on`.

### `emit`

Vamos para nosso último e 2º principal método.

```typescript
export class EventEmitter<T> {

  emit<K extends keyof T>(type: K, value: T[K]) {
    const listeners = this.#getListeners(type)
    for (const fn of listeners) {
      if (fn.once) this.off(type, fn)
      fn(value)
    }
  }

}
```

Atribuímos o `Set` de um determinado evento em `listeners` e percorremos para a execução de cada um passando o valor a ser emitido, também removemos a função caso possua a flag `once`.<br>

### Código completo

```typescript
export interface Callback<T> {
  (value: T): void
  once?: boolean
}

export class EventEmitter<T> {
  #listeners = new Map()
  
  on<K extends keyof T>(type: K, callback: Callback<T[K]>) {
    const listeners = this.#getListeners(type)
    this.#listeners.set(type, listeners.add(callback))
    return {off: () => this.off(type, callback)}
  }
  
  once<K extends keyof T>(type: K, callback: Callback<T[K]>) {
    callback.once = true
    this.on(type, callback)
  }
  
  emit<K extends keyof T>(type: K, value: T[K]) {
    const listeners = this.#getListeners(type)
    for (const fn of listeners) {
      if (fn.once) this.off(type, fn)
      fn(value)
    }
  }
  
  off<K extends keyof T>(type: K, callback: Callback<T[K]>) {
    const listeners = this.#getListeners(type)
    listeners.delete(callback)
    this.#listeners.set(type, listeners)
  }
  
  #getListeners<K extends keyof T>(type: K): Set<Callback<T[K]>> {
    return this.#listeners.get(type) ?? new Set()
  }
}
```

## Demo

```typescript
import {EventEmitter} from './event-emitter'

interface EmitterMap {
  update: number
}

const emitter = new EventEmitter<EmitterMap>()

emitter.on('update', (value) => {
  // Usa o value pra algo útil
})

emitter.emit('update', 10)
```

A interface `EmitterMap` pode conter vários eventos, definindo seus respectivos tipos de valores emitidos.

Espero que este conhecimento seja útil pra você, abraço.


# Criando uma biblioteca TypeScript

Como criar uma biblioteca TypeScript  publicável no npm do zero? É isso que faremos a seguir.

Começaremos criando o diretório do projeto e alguns arquivos como package.json e tsconfig.json. Usarei como exemplo uma biblioteca para requisições HTTP, mas você pode escolher qualquer coisa.

Use seu terminal para executar os comandos a seguir.

```bash
mkdir http

cd http

npm init -y

npm install --save-dev typescript

npx tsc --init
```

Pausado, logo continuo...


# Etiqueta para e-mails

Dicas sobre como escrever ou responder mensagens de e-mail, principalmente os profissionais.

1. Se você espera que ações sejam tomadas, não as espalhe pelo corpo do e-mail. Isso dificulta o entendimento do destinatário, podendo fazer com que seja necessária mais de uma leitura para compreender o que precisa ser feito. Ao invés disso, economize tempo do leitor trazendo a tona informações relevantes para ele. Escreva exatamente o que precisa que o destinatário faça diretamente no assunto do e-mail e caso seja conveniente, o tempo estimado que ele levaria na execução da ação solicitada.<br>

   Por exemplo, ao invés de "Feedback para o projeto X", pode ser "Escreva um feedback de 5 minutos sobre a pesquisa X". Caso uma estimativa de tempo não seja apropriada, seja específico na ação solicitada, outro exemplo é, ao invés de "Estimativa de gastos para o quarto trimestre", escreva "Aprove a estimativa de gastos para o quarto trimestre"<br>

   Estas sutis diferenças podem influenciar a tomada de decisão sobre executar a ação antes mesmo da abertura do e-mail ou aguardar um tempo livre para saber o que precisa ser feito sobre o assunto. Sabendo o que deve ser feito previamente, torna a decisão prática e rápida de ser tomada, já que seria factível a execução entre esta reunião e a próxima.\ <br>
2. Caso seu e-mail seja sobre um assunto que já foi iniciado, continue utilizando a mesma thread ao invés de enviar um novo e-mail sobre o mesmo assunto. Isso mantém o contexto claro para todos envolvidos nesta thread.\ <br>
3. Sempre que necessário adicionar ou remover novos destinatários a uma thread, explique o motivo antes da sua mensagem no e-mail, ou seja, no topo do e-mail seguido de quebra de linha, para que os leitores saibam imediatamente quem são os novos destinatários.\ <br>
4. Evite escrever muita informação no inicio do e-mail e deixar sua mensagem relevante, solicitando ou oferecendo algo para o final do e-mail. Sempre inclua primeiro o seu ponto principal, seguido do contexto. Veja um exemplo simples.\
   \
   ...\
   \
   — Olá Lucia, meu nome é Guilherme e faço parte da equipe de arquitetura Front-end. Estamos preparando uma apresentação das decisões tomadas e novidades que vem pela frente, para a comunidade, que está carente em saber o que andamos fazendo por aqui e por isso estamos tendo pouca adoção no uso de nossas ferramentas atuais e não queremos que isso ocorra para o que estamos planejando para o próximo ano. Posso pedir que nos ajude preparando uma arte gráfica que enviaremos na próxima semana a todas as pessoas envolvidas na comunidade?\
   \
   ...\
   \
   Agora compare com a mensagem abaixo.\
   \
   ...\
   \
   — Olá Lucia, posso incomodá-la pedindo que prepare uma arte gráfica que enviaremos na próxima semana a todas as pessoas envolvidas na comunidade?\
   \
   Contexto: Nossa comunidade está carente sobre o que andamos fazendo por aqui e por isso estamos tendo pouca adoção no uso de nossas ferramentas atuais e não queremos que isso ocorra para o que estamos planejando para o próximo ano.\
   \
   ...\
   \
   Percebeu a diferença? Escrevendo desta forma estamos dando a oportunidade do leitor escolher ler ou não a parte menos importante do e-mail.\ <br>
5. Quando receber um e-mail com muito conteúdo desorganizado, resuma os principais pontos do remetente para ele em sua resposta. Isso não somente ajuda confirmar seu entendimento do e-mail, como também fará a outra parte se sentir agradecida pela sua ajuda na organização dos pensamentos.

\
Espero que estas dicas sejam úteis em seu dia-a-dia, grande abraço!\
\
\---\
Guilherme Siquinelli, dia 6 de abril de 2024.


# Introdução

A senha tão difamada e frequentemente hackeada, roubada ou comprometida não é mais um limite de segurança na Web de hoje. Seu substituto é a especificação emergente de Autenticação da Web (WebAuthn), uma API de gerenciamento de credenciais desenvolvida pelo World Wide Web Consortium (W3C) e padronizada para atender às necessidades de computação online segura e moderna.

Aqui obteremos um breve histórico de por que as senhas falharam e, em seguida, começaremos quebrar a definição de WebAuthn para aprendermos por partes.

Eventualmente usaremos essas partes para construir um ambiente de servidor WebAuthn que incorpora os recursos do lado do cliente, do servidor e do autenticador, que são a base da WebAuthn.

O trabalho para criar a API de autenticação da Web começou em fevereiro de 2016 dentro do W3C, e está gerando muito interesse para inovação em torno da autenticação e segurança.

Agora, Yubico e o W3C se uniram para criar um curso introdutório que descreve a próxima descoberta em autenticação segura e reúne a comunidade de desenvolvedores para dar-lhe vida. Este curso e seu trabalho árduo foram elaborados para atingir esse objetivo.

A autenticação da Web (WebAuthn), foi desenvolvida para atender às necessidades de segurança da autenticação online moderna. Ele combina segurança apoiada por hardware com uma experiência de usuário simples e fácil. O resultado é a redefinição do acesso seguro, incluindo a primeira inovação legítima em autenticação sem senha.

Esses avanços e o trabalho que define a API estão contidos neste curso, incluindo conceitos básicos como registro, autenticação e infraestrutura de servidor, juntamente com outros blocos de construção para a criação de um ambiente Web Authn.

O W3C, os voluntários de suas empresas-membro e os especialistas convidados são os administradores da comunidade internacional do W3C dedicada a construir padrões abertos para a World Wide Web.

Mais de 450 membros contribuem ativamente para construir e manter uma série de especificações e diretrizes. Os padrões W3C definem uma plataforma Web aberta para desenvolvimento de aplicativos que inclui HTML5, CSS e a API de gerenciamento de credenciais, que é o coração da autenticação da Web.

O WebAuthn representa a primeira tecnologia de credencial de chave pública baseada na Web a oferecer uma alternativa segura aos logins de senha sub-padrão atuais e à tecnologia obsoleta de vários fatores. O WebAuthn não depende de um repositório centralizado de segredos compartilhados. A API é compatível [com navegadores da Web comumente usados](https://caniuse.com/webauthn) , como Google Chrome, Microsoft Edge, Mozilla Firefox e Apple Safari - todos os quais servem como clientes da Web front-end.

Em abril de 2021, o W3C [WebAuthn Working Group](https://www.w3.org/blog/webauthn/) concluiu a segunda versão de sua API - conhecida como WebAuthn Nível 2 - para coincidir com uma onda crescente de interesse nos recursos de segurança da tecnologia, incluindo setores de mercado como bancos e pagamentos eletrônicos e avanços técnicos, nomeadamente resistência ao phishing.

A especificação é regida pela política de patentes livre de royalties do W3C, que a torna disponível gratuitamente para qualquer pessoa. A versão mais recente das especificações WebAuthn estão disponíveis [aqui](https://www.w3.org/TR/webauthn-2/) e é uma tarefa de leitura para este curso.

O conceito de um padrão WebAuthn foi originalmente criado pela [FIDO Alliance](https://fidoalliance.org), uma associação aberta da indústria com uma missão focada em padrões de autenticação que ajudam a reduzir a dependência mundial excessiva de senhas.

A Alliance desenvolveu duas especificações - o Universal Authentication Framework (UAF) e o protocolo Universal Second Factor (U2F), que introduziu autenticadores apoiados por hardware baseados em criptografia de chave pública assimétrica - hoje geralmente conhecidos como Chaves de Segurança.

Por insistência da Microsoft e de outros, o U2F se tornou a base do WebAuthn, com o objetivo de oferecer suporte à autenticação segura da web para consumidores individuais, bem como para empresas e governos. Hoje, a FIDO adicionou o protocolo cliente para autenticador (CTAP), que junto com o WebAuthn define o FIDO2.

As senhas são um único ponto de falha. Hoje, a ameaça número um à segurança cibernética são as senhas fracas e reutilizadas.

Por exemplo, os ataques geralmente começam com o aproveitamento de senhas comprometidas de outros serviços para obter acesso a outras contas de destino que uma vítima possa estar usando. As senhas são o elo mais fraco nesses cenários, pois são segredos compartilhados, fáceis de quebrar e muitas vezes fáceis de adivinhar e, uma vez conhecidas, podem ser usadas em qualquer lugar.

Por exemplo, em 2020, a [PC Magazine relatou](https://www.pcmag.com/news/2020s-most-common-passwords-are-laughably-insecure)  que "123456" era a senha mais popular e reutilizada, tendo sido violada mais de 23 milhões de vezes. O roubo de credenciais também é uma ameaça, pois os invasores usam a engenharia social, na qual usam informações postadas publicamente nas redes sociais ou em outras fontes para apresentar uma máscara de aparência legítima, para enganar vítimas bem-intencionadas para que exponham suas senhas. Esses ataques podem variar de se passar por um colega pedindo informações a e-mails que parecem oficiais de entidades governamentais ameaçando agir, todos com o objetivo de manipular a vítima para fornecer ao invasor sua senha.


# 1º Módulo

### Soluções multifatoriais

Soluções multifatoriais, em que a credencial que protege a conta de um usuário não é apenas uma senha, tornaram-se a resposta a ataques destinados a comprometer senhas. Ao combinar uma senha com outro fator, como soluções de autenticação suportadas por hardware, os invasores não conseguem extrair tudo o que é necessário para comprometer uma conta.

### Nem toda autenticação multifator é igual

Ter um usuário utilizando qualquer forma de autenticação multifator é melhor do que usar uma senha de fator único, mas a tecnologia multifator de primeira geração que usa segredos compartilhados, como um código de uso único enviado para um telefone celular ou um aplicativo push um telefone celular que exige que o usuário confirme o acesso também é vulnerável a ataques de engenharia social. Com o tempo, os invasores infelizmente desenvolveram métodos fáceis de criar para explorar essas fraquezas, enganando as vítimas e não apenas entregando suas senhas, mas também evitando essas proteções adicionais. É aqui que os desenvolvedores e usuários veem o valor da WebAuthn.

A WebAuthn representa a próxima etapa na evolução constante da autenticação forte, com foco em fornecer segurança superior às soluções de autenticação existentes, enquanto permanece fácil para os serviços se levantarem e os usuários aproveitarem. O design do WebAuthn é baseado na segurança comprovada oferecida por uma estrutura de credenciais de infraestrutura de chave pública (PKI). A PKI é comumente usada para proteger uma série de casos de uso em que a segurança é essencial, incluindo autenticação máquina a máquina e cartões inteligentes emitidos pelo governo.

### Atende ao mesmo nível de segurança

Uma das dificuldades significativas no uso de uma estrutura de credenciais PKI é configurar a infraestrutura para emitir credenciais e autenticar com elas. Em uma implantação de PKI tradicional, cada emissão de credencial ou autenticação requer uma cadeia de autenticação de volta para uma autoridade central que atesta a autenticidade de cada etapa envolvida. Esses requisitos tornam a implantação de PKI tradicional inadequada para soluções voltadas ao público e desajeitada para serviços da web. WebAuthn resolve esses problemas descentralizando a estrutura tradicional de PKI.

Com WebAuthn, um serviço da web, conhecido como  Relying Party (Parte confiante), se comunica com o Authenticator (Autenticador) de um usuário por meio de um navegador da web, que atua como o Client (Cliente) WebAuthn . Esses termos e interações serão discutidos com mais detalhes nas próximas seções. Nesse caso, o navegador, como o cliente WebAuthn, fornece a infraestrutura que conecta o autenticador do usuário à parte confiável e facilita a comunicação confiável entre eles. A maioria dos navegadores da web populares oferece suporte ao WebAuthn, removendo a responsabilidade do usuário e de qualquer serviço de manter esse recurso. Tudo o que o usuário precisa é um dispositivo autenticador WebAuthn, enquanto o serviço só precisa se preocupar em ter um serviço WebAuthn ou serviço para oferecer suporte.

As credenciais WebAuthn, ao contrário de senhas, códigos de uso único ou outras soluções mais antigas, são construídas em torno de chaves criptográficas assimétricas, onde um par de chaves públicas e privadas matematicamente associadas constituem a base para a verificação do usuário. Essas credenciais são criadas no autenticador do usuário e a chave privada nunca é exportada; apenas a chave pública deixa o dispositivo. As chaves públicas são inúteis para um invasor que deseja roubar uma credencial, protegendo contra ataques que visam serviços e também tentando enganar o usuário para que exponha sua credencial.

Além disso, o cliente WebAuthn garante que a comunicação entre o autenticador e a parte confiável permaneça segura, verificando se a comunicação não é interceptada ou redirecionada em trânsito, evitando a captura de uma interação válida da WebAuthn para uso em um ataque. Os serviços também podem exigir que os usuários verifiquem sua propriedade de um autenticador para interações WebAuthn, exigindo que o usuário forneça algo conhecido, como um PIN, ou algo intrínseco a eles, como uma impressão digital biométrica, para seu autenticador antes de prosseguir. A WebAuthn evita que as credenciais sejam fracas e reutilizáveis, resolvendo os problemas subjacentes às senhas, bem como à geração anterior de autenticação multifator.

A WebAuthn possui vários recursos exclusivos que atendem aos desafios atuais de autenticação. Exploraremos alguns desses desafios com mais detalhes posteriormente no curso. Mas primeiro vamos fazer um inventário rápido.

1. **WebAuthn makes use of asymmetric cryptography** (WebAuthn usa criptografia assimétrica), que permite o uso de chaves criptográficas separadas para assinar e verificar informações.
2. **WebAuthn is scoped** (WebAuthn tem escopo definido),  cada serviço ou site usando WebAuthn é registrado diretamente no autenticador de um usuário, sem informações sobre outros serviços registrados compartilhados entre eles.
3. **WebAuthn is user privacy focused** (WebAuthn tem como foco a privacidade do usuário), que é um dos principais benefícios de um protocolo de autenticação com escopo definido. As informações sobre os serviços nos quais um usuário se registrou não são compartilhadas com terceiros não relacionados.
4. **WebAuthn is attested** (WebAuthn é atestado). O atestado permite que o provedor do autenticador verifique se seus usuários têm autenticadores WebAuthn seguros e processos de registro adequados.
5. **WebAuthn allows services to require user consent** (WebAuthn permite que os serviços exijam o consentimento do usuário). O protocolo pode permitir interações que exijam que o usuário execute uma ação física para permitir o registro ou autenticação usando um dispositivo WebAuthn, evitando ataques remotos que contornem um usuário.
6. **WebAuthn flips the authentication paradigm** (WebAuthn inverte o paradigma de autenticação). Ao contrário da autenticação baseada em senha, os usuários autenticam localmente e as **partes confiáveis** validam localmente. Nenhuma infraestrutura de chave pública é necessária, e o protocolo lida com muito do trabalho manual que um desenvolvedor poderia ter.

Até agora, aprendemos que a WebAuthn é um método inovador e seguro para autenticação forte com resistência a phishing e outros recursos integrados ao protocolo.

Mas o que o torna único em comparação com seus pares de autenticação multifator e como ele difere de sua autenticação de senha padrão?

### Fluxo bidirecional exclusivo

O processo geral de autenticação da WebAuthn usa um fluxo bidirecional exclusivo que é completamente diferente dos modos de autenticação anteriores.

Seu fluxo de autenticação baseado em senha típico é assim:

<figure><img src="/files/vIedkwjjJJeqQ6zWjCzs" alt=""><figcaption><p>Fluxo tradicional</p></figcaption></figure>

Se o usuário deseja efetuar login, ele fornece sua senha, e talvez sua senha de uso único, para a página da web em que está atualmente. Essas credenciais acabam indo... para *algum lugar.* Para o bem do usuário, a preferência é que ele tenha inserido essas credenciais no site real que o usuário estava tentando acessar, mas se ele estiver sendo fisicamente ativo, esse pode não ser o caso. É aí que reside o problema da autenticação tradicional baseada em senha.

Agora, vamos dar uma olhada em um fluxo de autenticação WebAuthn:

<figure><img src="/files/oZjxyaPlaca6EqEizoQ1" alt=""><figcaption><p>Fluxo de autenticação</p></figcaption></figure>

Ao contrário do fluxo de senha anterior, a interação da WebAuthn é um ciclo bidirecional entre a **parte confiável** WebAuthn do serviço da Web através do cliente WebAuthn do navegador para os usuários WebAuthn Authenticator e vice-versa.

Vamos fazer uma pausa aqui para um pouco de vocabulário. WebAuthn é composto por esses  **três componentes fundamentais**.

1. **WebAuthn Authenticator** (Autenticador WebAuthn) é o dispositivo do usuário que contém as chaves privadas registradas pelo usuário, usadas para autenticação. O Autenticador WebAuthn pode ser integrado à plataforma de um usuário ou dispositivo móvel, como Windows Hello ou TouchID e FaceID, ou pode ser um autenticador "móvel", como uma chave de segurança. Autenticadores de roaming são dispositivos externos que podem ser conectados ou se comunicar sem fio com um dispositivo host.
2. **O WebAuthn Client** (Cliente WebAuthn) é a "máquina no meio" que atua como uma ponte entre a Parte Confiante e o autenticador WebAuthn do usuário. Pode ser um navegador da web, um cliente embutido em um aplicativo ou até mesmo um sistema operacional como Windows, Android ou iOS.
3. **A Relying Party** (Parte Confiável) é outro nome para o serviço ou site que hospeda seu próprio servidor WebAuthn. O usuário se registra e autentica com a parte confiável e é a parte confiável que realiza várias verificações para garantir que o registro ou autenticação é válido de acordo com as regras que definiu.

Embora pareça complicado, a experiência do usuário é tranquila, sem comprometer a segurança. Veremos a interação entre esses três componentes principais posteriormente neste módulo.

Por enquanto, vamos continuar e explorar os  fluxos de **Registro** e **Autenticação** com mais detalhes.

### Fluxo de registro do WebAuthn

Lembre-se de que isso é principalmente para sua compreensão do que está acontecendo entre os três componentes fundamentais. Muito disso já será feito para você como um desenvolvedor da Web se você usar uma biblioteca ou framework WebAuthn.

Um fluxo de registro WebAuthn é a interação para criar e associar uma nova credencial WebAuthn a uma parte confiável; em essência, registrar um autenticador WebAuthn com uma conta em um serviço de suporte WebAuthn.

Da perspectiva da experiência do usuário, neste ponto, o usuário pode ter clicado em um link para iniciar o processo de registro. Por exemplo, o link pode dizer “Adicionar chave de segurança”. Esse link aciona nosso Javascript WebAuthn do lado do cliente para iniciar seu processo e acionar uma série de outros eventos. Voltemos ao nosso diagrama da seção anterior. Aqui, mais uma vez temos nossos três componentes fundamentais esperando algo para fazer.

Primeiro no fluxo de registro, nossa **Relying Party** (Parte Confiável) criará um identificador exclusivo para si mesma e um sobre o usuário e o passará para a **WebAuthn Client** (Cliente WebAuthn).

<figure><img src="/files/C9slvWz2fqqNx8QWyiRn" alt=""><figcaption><p>Fluxo de registro</p></figcaption></figure>

Agora, estamos na **WebAuthn Client**. O cliente anotará o nome de domínio que fez a solicitação de registro e o comparará com as informações que a **Relying Party** enviou para sua segurança.

Se tudo correr bem, a **WebAuthn Client** pedirá ao usuário que prove que deseja registrar um dispositivo. Isso é conhecido como  **Proof of Presence** (Prova de Presença) e é outra verificação de segurança que ajuda garantir que haja um ser humano nos bastidores fazendo essa tentativa. Normalmente, provar que você deseja registrar um dispositivo envolve nada mais do que tocar em um botão, inserir um PIN ou verificar um atributo biométrico no Autenticador WebAuthn.

<figure><img src="/files/iohEzGgFBhzUGooybyNj" alt=""><figcaption><p>Prova de presença</p></figcaption></figure>

Agora, aqui estamos no Autenticador WebAuthn, onde um par de chaves exclusivo será feito para esta parte / sessão confiável, e uma chave pública será enviada ao **WebAuthn Client** (Cliente WebAuthn), que a encaminhará para a **Relying Party** (Parte Confiável) para proteção.

<figure><img src="/files/Vdl1di4mcaUsDYOUF8um" alt=""><figcaption></figcaption></figure>

Agora que temos um dispositivo WebAuthn registrado, vamos revisar o fluxo de autenticação.

Autenticar um dispositivo WebAuthn não é muito diferente do fluxo de registro. Vamos trazer nossos diagramas mais uma vez, mas desta vez para  **autenticação.**

Uma interação de autenticação WebAuthn ocorre quando um autenticador WebAuthn registrado é verificado; essencialmente, quando um autenticador WebAuthn é usado para autenticar uma conta na qual ele foi registrado anteriormente.

A **Relying Party** (Parte Confiável) dá o pontapé inicial. Ele gera alguns dados aleatórios e os combina com algumas informações sobre si mesmo. Chamamos isso de **Challenge** (Desafio)

A Parte Confiável encaminhará isso ao Cliente WebAuthn.

<figure><img src="/files/G5Goy5dkqH55wjDc0bWI" alt=""><figcaption></figcaption></figure>

Agora, aqui no cliente WebAuthn, o desafio é verificado para ver se a URL que alega ter se originado (chamado de origem) corresponde ao URL do site ao qual o usuário está conectado no momento, evitando ataques que tentem enganar os usuários para que usem páginas fraudulentas . Se tudo estiver alinhado, o desafio é enviado ao Autenticador WebAuthn.

<figure><img src="/files/ZaBCWP0uet3iAZx4o7J6" alt=""><figcaption></figcaption></figure>

O Autenticador WebAuthn precisa que o usuário prove que há um humano do outro lado, da mesma forma que fez quando o usuário registrou o dispositivo. Feito isso, o desafio é assinado e enviado de volta na cadeia até a Parte Confiante.

<figure><img src="/files/nlVTtsSychrZJ1NTkYlb" alt=""><figcaption></figcaption></figure>

Assim que a Parte Confiável receber de volta o material assinado, ela terá tudo de que precisa para confirmar se o usuário está sendo phishing ou não.

<figure><img src="/files/cwkf8zdrowLJZWof1S1l" alt=""><figcaption></figcaption></figure>

A confirmação depende de informações como "qual site solicitou a autenticação?" e "este é o autenticador WebAuthn certo para este usuário?". Os dados de origem fornecidos pelo Cliente WebAuthn são uma parte crucial do motivo pelo qual o protocolo é tão poderoso.

Por design, a WebAuthn evita uma série de ataques que prejudicam os esforços para proteger senhas e outros esquemas de credenciais obsoletos. Essas proteções são exclusivas da WebAuthn e representam um salto em frente para a autenticação. As características de prevenção de ataques da WebAuthn incluem a gravação da URL de um serviço ou site da Web - e a captura dos dados de "origem" dentro do autenticador, um processo que revisamos na última seção, conforme vimos como o protocolo funciona. Nesta seção, exploraremos como esses recursos garantem segurança e privacidade.

### Ataques comuns

Vamos abordar alguns dos ataques mais comuns contra a autenticação tradicional:

1. **Man-in-the-Middle:** ele se concentra em capturar a comunicação entre um usuário e o serviço para o qual ele está tentando se autenticar, capturando as credenciais passadas do usuário e permitindo que o invasor use disse credenciais diretamente. Esses tipos de ataque podem comprometer as senhas de uso único (OTPs) de uso único, bem como as senhas.
2. **Phishing:** um ataque de phishing ocorre quando um invasor direciona um usuário a uma página que parece uma página de login legítima, mas na verdade direciona as credenciais do usuário para o invasor. As páginas de phishing usam vários truques para fazer com que o conteúdo da página e o endereço pareçam corretos, geralmente enganando os usuários.
3. **Engenharia social:** os ataques de engenharia social se concentram no uso de informações públicas sobre um usuário para induzi-lo a permitir que um invasor acesse suas credenciais. Esses ataques incluem um amplo espectro, variando de e-mails solicitando informações de senha a ataques mais complexos que tentam convencer os usuários a usar soluções de autenticação como um aplicativo push, que é então usado para aprovar as tentativas de login do invasor.

<figure><img src="/files/ZkOaWXHQubUYV7OGK3Xi" alt=""><figcaption></figcaption></figure>


