---
title: "Segurança"
description: "Segurança do TrustBridge: o que protege o quê, onde fica cada segredo, como o PIN é comprovado em vez de enviado, o que o operador precisa guardar e o Cofre de Certificados como exceção às chaves locais."
canonical: "https://docs.lacunasoftware.com/articles/trustbridge/security"
locale: "pt-BR"
product: "TrustBridge"
last_updated: "2026-10-13"
---

# Segurança

O que protege o quê na plataforma, onde fica cada segredo e o que o operador precisa guardar.

## A premissa fundamental e sua única exceção

**A chave privada de um Certificado de Estação de Trabalho nunca sai da estação de trabalho.** O
Workstation Service é o único caminho até os certificados de uma máquina, a chave só vê um hash, e a
assinatura com um certificado A3 acontece no hardware que o guarda. Nada no Servidor consegue assinar
com um Certificado de Estação de Trabalho, e nada no produto exporta um.

O **Cofre de Certificados** é a exceção deliberada, desligada por padrão. Com `Vault:Enabled=true`,
um Administrador pode importar um certificado A1, com chave e tudo, e o Servidor assina com ele. Isso
troca custódia por conveniência: uma chave armazenada no próprio repositório da plataforma, em vez de
em um cartão que não consegue entregá-la. Qual custódia um certificado usa é assunto do operador e do
auditor; a aplicação cliente nunca é informada.

## Tratamento do PIN

O PIN é o que autentica o titular perante o token dele, para que uma assinatura possa ser feita. Desde
o Servidor 1.13.0 e o Workstation 1.5.0 (protocolo 5 das estações de trabalho), **o PIN que uma
aplicação cliente envia não passa do Servidor.** Quatro regras o regem:

- **O PIN é digitado localmente.** O titular o digita no Tray App da máquina em que o token está
  conectado, somente na sessão de console. O Workstation Service o guarda, criptografado, no Cache de
  PIN, indexado por certificado, com um TTL de inatividade deslizante (8 h por padrão). Para um
  Certificado A1, a máquina guarda em vez disso um verificador de um PIN do Certificado A1
  ([abaixo](https://docs.lacunasoftware.com/articles/trustbridge/security#o-pin-do-certificado-a1)).
- **Uma correspondência é uma prova que o Servidor confere.** Em `POST /v1/sessions`, o Servidor
  desafia todas as máquinas candidatas ao mesmo tempo com um nonce aleatório novo. Cada uma responde
  com uma **Prova de PIN**, um HMAC sobre o nonce cuja chave é o PIN que ela tem em cache (ou o
  verificador do PIN do Certificado A1), ou informa que não tem com o que provar. O Servidor calcula a
  prova esperada a partir do PIN que o cliente enviou e decide. A máquina a que a sessão se vincula é
  avisada disso, e uma máquina cujo pedido no Tray App foi respondido recebe o veredito sobre essa
  entrada; é tudo o que uma máquina fica sabendo. Uma máquina nunca recebe o PIN, e um valor errado
  vindo da rede nunca chega ao token nem consome o contador de tentativas dele. Só PINs digitados pelo
  titular chegam ao hardware. Uma máquina abaixo do protocolo 5 não recebe desafio nem pedido de PIN
  algum, então, para a criação de sessões, ela conta como desconectada.
- **Três limites restringem tentativas de adivinhação.**
  - **O bloqueio por CPF.** O Servidor bloqueia a criação de sessões para um CPF após
    `Sessions:MaxPinFailures` (5) falhas dentro de `Sessions:PinFailureWindow` (15 min), contadas em
    todas as chaves de API e respondidas com `429 TOO_MANY_PIN_ATTEMPTS`. Uma requisição conta no
    máximo uma falha. **Uma criação bem-sucedida não as zera**: elas saem da janela com o tempo.
  - **Os limites de provas com falha.** Toda Prova de PIN que uma estação de trabalho dá para um CPF e
    que não confere conta contra essa máquina e esse CPF, mesmo que outra candidata tenha
    correspondido, com os mesmos dois valores. Quando uma máquina esgota o seu limite, ela não recebe
    desafio nem pedido de PIN para esse CPF até as falhas saírem da janela; o Servidor registra um
    `Warning` e grava `pin.proof-budget-spent`. O Cofre de Certificados tem um limite por CPF nas mesmas
    condições: cada senha que ele tenta e que não abre nada conta uma vez por requisição. Assim, quem
    tem uma chave de API e uma máquina admitida só consegue testar um punhado de palpites por titular
    por janela, seja pela máquina, seja pelo cofre. O limite é cobrado da máquina que deu a prova e de
    nenhuma outra, mas a própria máquina do titular, se guarda vários certificados dele, gasta uma
    prova com falha por certificado a cada PIN errado, então pode ser deixada de lado antes de o
    bloqueio disparar. Uma linha `pin.proof-budget-spent`, portanto, não prova que houve adivinhação:
    leia-a junto com as linhas `pin.compared` do CPF.
    [Configuração](https://docs.lacunasoftware.com/articles/trustbridge/configuration#os-limites-de-pin-com-falha) mostra os três limites lado a lado.
  - **O limite da própria estação de trabalho.** Ela recusa entradas para um certificado após
    `Tray:MaxConsecutivePinFailures` (3) rejeições seguidas do token (ou PINs do Certificado A1
    errados), durante `Tray:PinFailureCooldown` (5 min).

  Nenhum deles torna impossível o bloqueio do hardware: o titular ainda pode bloquear o próprio token
  digitando errado.
- **PINs e Provas de PIN nunca aparecem na Trilha de Auditoria, no log do Servidor nem no log do
  Workstation Service.** Quem tem o nonce consegue quebrar uma prova por força bruta offline, então ela
  fica fora de todos os logs, como o PIN. O Cache de PIN fica só em memória por padrão;
  `PinCache:SurviveRestart` o persiste com DPAPI no escopo da máquina, em um arquivo acessível apenas a
  SYSTEM e aos Administradores, um desvio documentado que o administrador escolhe ativar.

O bloqueio e os limites são indexados pelo CPF do titular, qualquer que seja a Empresa que a sessão
indique: o e-CPF e os e-CNPJs de um titular costumam compartilhar um PIN, então um palpite para um é um
palpite para os outros.

Para um Certificado do Cofre, o `pin` que o cliente envia é a senha que abre o arquivo do
certificado. O Servidor a usa para abrir a chave na criação da sessão, a mantém em memória somente
para aquela sessão e nunca a grava. Desativar a sessão, ou reiniciar o Servidor, a descarta.

### O PIN do Certificado A1

Um Certificado A1 no repositório de certificados da máquina não tem token nem PIN próprio. Ele só
assina pelo TrustBridge depois que o titular define um **PIN do Certificado A1** para ele no Tray App,
na sessão de console, naquela máquina. O Workstation Service guarda um verificador PBKDF2 com salt,
nunca o PIN, em um arquivo em `C:\ProgramData\TrustBridge\` protegido como o do Cache de PIN. Trocá-lo
exige o atual, e um PIN esquecido é recuperado removendo o certificado do repositório e instalando-o de
novo. O verificador é a chave da Prova de PIN da máquina, então conferi-lo custa ao Servidor uma
derivação de chave por máquina por requisição. Ele é apagado quando o certificado sai da máquina e por
uma desinstalação completa, e uma atualização o mantém.

Quem consegue administrar o repositório de certificados de uma máquina, ou está no console dela antes
de um PIN do Certificado A1 ser definido, controla quem pode assinar com aquele A1. O PIN do
Certificado A1 decide quem pode assinar pelo TrustBridge; ele não protege a chave, que continua tão
utilizável no repositório quanto antes.

## O Protetor do Chaveiro

Os dois chaveiros (key rings) do Servidor são linhas no banco de dados dele:

| Chaveiro | Protege | Se não puder ser lido |
|---|---|---|
| `web-sessions` | Cookies do console administrativo, tokens antifalsificação (antiforgery), circuitos do Blazor | Todos os administradores entram de novo, e nada mais |
| `certificate-vault` | A chave privada de cada Certificado do Cofre | **O host para.** Gerar uma chave nova deixaria órfão, silenciosamente, todo certificado já armazenado |

Os dois são selados sob um único certificado X.509 com uma chave RSA que a plataforma **não** guarda:
o **Protetor do Chaveiro** (Key Ring Protector), fornecido como `KeyRingProtector:Certificate`
(PKCS#12 em base64). Todo Servidor precisa de um, com ou sem cofre, porque o chaveiro das sessões web
também precisa dele. Quem consegue ler o protetor e o banco de dados consegue ler todos os
Certificados do Cofre; portanto, o protetor é um segredo por si só, e o `.env` ou o app setting que o
contém merece o mesmo cuidado que uma chave privada.

**Faça backup do PKCS#12 permanentemente, em algum lugar que a plataforma não consiga acessar.**
Perdê-lo torna todos os Certificados do Cofre impossíveis de abrir por qualquer pessoa, inclusive por
esta plataforma. Não há custódia de recuperação (escrow), de propósito. Uma referência ao Key Vault no
Azure é um lugar conveniente para o Servidor em execução, e não um backup.

**A rotação é aditiva.** Um protetor novo sela chaves novas; ele nunca recriptografa o que já está
armazenado. O protetor que sai passa para `KeyRingProtector:RetiredCertificates:{n}:Certificate`, e o
PKCS#12 dele é guardado **para sempre**. Exclua um protetor aposentado e você terá destruído tudo o que
foi selado sob ele, com todos os sintomas apontando para o banco de dados. O Servidor informa essa
situação a cada inicialização: a impressão digital (thumbprint) atual e a quantidade de protetores
aposentados.

## O Cofre de Certificados

Ligar esse recurso traz três coisas:

- **A licença do Lacuna PKI SDK ganha uma segunda função.** Toda implantação já tem uma, porque ela é
  a licença com que a frota inteira funciona ([abaixo](https://docs.lacunasoftware.com/articles/trustbridge/security#a-licença-da-pki)). Com o cofre ligado, o
  Servidor também valida o que guarda por meio do SDK, que não lê nada sem licença. Com a licença
  recusada ou vencida, todo Certificado do Cofre aparece como `UNTRUSTED` e toda importação é recusada,
  o que é informado uma vez na inicialização, numa linha `Critical`, e num banner em todas as páginas
  administrativas.
- **Um PKCS#12 precisa estar no formato PFX legado.** A biblioteca com que a plataforma assina não lê
  uma chave protegida com `pkcs5PBES2`, que é o que `openssl pkcs12 -export` grava se não receber
  `-legacy`, e o que caminhos de exportação recentes do Windows também gravam. Um arquivo assim é
  recusado na importação, com a indicação de exportá-lo de novo:
  ```bash
  openssl pkcs12 -export -legacy -in holder.pem -inkey holder.key -out holder.pfx
  ```
- **O cofre pode ficar travado fechado** quando o Servidor inicia antes de o banco de dados responder.
  Veja [Operações](https://docs.lacunasoftware.com/articles/trustbridge/operations#a-trava-do-cofre).

A senha de importação é usada para provar que o arquivo abre e **nunca é armazenada**: nada consegue
abrir um arquivo armazenado sem alguém presente, e é também por isso que nenhum processo automático
consegue verificar se arquivos antigos estão no formato legado. Senhas erradas enviadas na criação de
sessões gastam o limite de provas com falha do cofre para aquele CPF
([Tratamento do PIN](https://docs.lacunasoftware.com/articles/trustbridge/security#tratamento-do-pin)). Não há caminho de exportação nem de download. Um certificado
sai do cofre ao ser **excluído**, o que destrói a chave e não pode ser desfeito, e a confirmação pede
que o CPF seja digitado. **Fora de uso** impede que um certificado abra sessões e assine, mas o mantém.

Uma Sessão de Assinatura vinculada ao cofre não sobrevive a um reinício do Servidor, porque o segredo
que abre o certificado fica só na memória. Isso é uma propriedade da custódia, não um defeito.

## Chaves de API

Uma **chave de API** autentica uma Aplicação Cliente em toda a superfície do contrato. Ela é emitida
na tela **Aplicações Cliente** com um nome e uma validade opcional, **exibida uma única vez** e
armazenada apenas como o SHA-256 dela. Todas as chaves aceitas de uma aplicação são equivalentes; a
chave não restringe nada.

- **Revogue** uma chave e a próxima requisição que a apresentar será recusada, permanentemente.
- **Desative** uma aplicação e todas as chaves dela passam a ser recusadas imediatamente; ativá-la de
  novo as restaura.
- **Faça uma chave expirar** no fim de um dia em UTC, ou apague a data para que ela volte a não ter
  validade.
- Para fazer a rotação, emita uma chave nova ao lado da antiga, implante-a e então revogue a antiga.

Chaves ausentes, desconhecidas, revogadas, expiradas e de aplicações desativadas são todas recusadas
da mesma forma, com `401 UNAUTHORIZED`, então quem chama não descobre qual era o caso. Cada chave tem
o próprio rastro na Trilha de Auditoria, inclusive as chamadas recusadas.

Um `sessionId` e um `signatureId` são tokens de portador daquilo que identificam: qualquer chave aceita
pode usar uma sessão ou buscar um documento cujo id ela tenha. Não entregue nenhum dos dois a quem não
deveria tê-los.

## Contas administrativas e o segundo fator

As Contas Administrativas são locais. Toda conta tem um **Segundo Fator** (TOTP de um aplicativo
autenticador) nos dois papéis, cadastrado pelo próprio dono e conhecido por mais ninguém. Os **Códigos
de Recuperação** são substitutos de uso único, emitidos em conjunto no cadastro e exibidos uma única
vez. Um Administrador pode limpar o segundo fator de outra pessoa, o que invalida os Códigos de
Recuperação dela e força um novo cadastro, mas nunca pode lê-lo nem defini-lo.

**O que o banco de dados guarda.** Senhas, chaves de API e Códigos de Recuperação são armazenados
apenas como hash; um Código de Recuperação recebe o mesmo hash de uma senha (PBKDF2 com salt), e os
códigos gravados por um Servidor anterior à 1.10.0 recebem hash na primeira inicialização depois da
atualização, sem desconectar ninguém. **O segredo do autenticador é armazenado em texto claro**,
porque o Servidor precisa calcular códigos a partir dele a cada trinta segundos. Quem tiver uma cópia
do banco de dados, como um backup roubado, consegue calcular os códigos do autenticador de qualquer
administrador; a senha continua valendo, mas, para essa pessoa, a conta tem um fator, e não dois.
Proteja os backups do banco de dados de acordo.

`Admin:SecondFactor:Required` (padrão `true`) é configuração da implantação e fica de fora, de
propósito, da tela **Configurações e usuários**: um interruptor que desativa o segundo fator,
acessível de dentro do próprio console que ele protege, é um interruptor que um invasor aciona no
caminho. Uma linha salva no banco de dados com essa chave é ignorada. A mesma proteção vale para as
chaves `Admin:CertificateSignIn:*` e para `Vault:Enabled`.

As senhas têm pelo menos doze caracteres. Não há e-mail de redefinição; um Administrador define uma
senha nova na tela **Configurações e usuários** e a entrega pessoalmente, e as sessões existentes da
conta terminam em até cinco minutos. Desativar uma conta a mantém, porque a Trilha de Auditoria
atribui a ela as ações passadas.

### Acesso com Certificado

Onde a implantação ativa `Admin:CertificateSignIn:Enabled`, uma conta também pode ser aberta por um
**e-CPF** ICP-Brasil lido pelo Lacuna Web PKI, sem senha e sem a etapa do Segundo Fator
([Console administrativo](https://docs.lacunasoftware.com/articles/trustbridge/admin-console#acesso-com-certificado)). Isso se apoia em:

- **A posse é comprovada assinando um desafio** gerado pelo Servidor: de uso único, de curta duração,
  vinculado ao nome de host e ao cookie de pré-autenticação do navegador, e assinado como bytes brutos,
  e não como um digest escolhido pelo Servidor. Isso impede a reutilização (replay), mas não o repasse
  em tempo real por uma página de outro domínio, que é o mesmo limite de um código de Segundo Fator
  repassado.
- **O certificado é validado como qualquer outro certificado da plataforma**, contra as raízes da
  ICP-Brasil e as Autoridades Certificadoras Confiáveis do Servidor, com a revogação verificada a cada
  entrada. Só `ACTIVE` passa. Um e-CNPJ nunca abre a conta de ninguém.
- **O vínculo é um CPF, nunca uma impressão digital ou um emissor.** Qualquer certificado em que o
  Servidor confia e que traga o **CPF vinculado** de uma conta abre essa conta; assim, uma renovação
  continua funcionando, e também um certificado de qualquer autoridade em que o Servidor confia. Daí
  vêm duas consequências, ambas aceitas:
  - **Um Administrador define todo CPF vinculado, e nunca o próprio.** Ninguém comprova que um CPF é
    seu; ele é digitado na tela de contas, então um vínculo é exatamente tão confiável quanto o
    Administrador que o digitou. Um Administrador poderia digitar o próprio CPF na conta de um colega e
    entrar como ele; a linha `admin.account-bound-cpf-set` mostra quem fez isso, e a página da conta do
    colega mostra quem definiu o vínculo dele e quando.
  - **Uma Autoridade Certificadora Confiável é uma emissora de credenciais para o console.** Quem
    controla uma autoridade adicionada na tela **Autoridades Certificadoras Confiáveis** pode emitir um
    certificado com qualquer CPF vinculado e entrar como aquela conta. A linha `admin.trusted-ca-added`
    mostra quem a adicionou, e cada linha `admin.certificate-sign-in` registra a impressão digital e o
    emissor do certificado apresentado. Recuperar-se de uma sessão de Administrador comprometida inclui
    revisar as Autoridades Certificadoras Confiáveis que ela adicionou. Numa implantação com
    `Certificates:Validation:UseLacunaTestPki` ligada, uma conta vinculada ao CPF de um certificado de
    exemplo fica aberta a qualquer um que tenha baixado esse exemplo.
- **Há limite de requisições, e não bloqueio.** O desafio é limitado a dez por minuto por endereço (um
  endereço IPv6 conta pelo /64), e no máximo oito verificações de certificado rodam ao mesmo tempo. Uma
  entrada por certificado que falha nunca afeta o bloqueio por senha, e uma conta bloqueada por senhas
  erradas ainda entra com o certificado. Atrás de um proxy reverso, o limite por endereço só conta
  navegadores onde o proxy está indicado em `ForwardedHeaders:TrustedProxies`
  ([Postura de rede](https://docs.lacunasoftware.com/articles/trustbridge/security#postura-de-rede)).
- **Substituir ou limpar um CPF vinculado encerra as sessões da pessoa em até cinco minutos**, como
  definir uma senha. Para tomar de volta uma conta de alguém, limpe também o CPF vinculado dela, ou
  desative a conta.

**As senhas podem ser desligadas** com `Admin:CertificateSignIn:Required=true`. Antes disso, confira
que todas as pessoas que precisam do console têm um CPF vinculado, que existem pelo menos dois
Administradores (um Administrador sozinho não tem quem defina o dele) e que o proxy reverso, se houver,
está indicado. Ligar a opção não encerra as sessões já abertas com senha. A cada inicialização com ela
ligada, o Servidor registra um aviso contando as contas ativas sem CPF vinculado, quantas delas são de
Administradores e quantos Administradores ativos existem: **quando o segundo número chega ao terceiro,
ninguém consegue administrar a plataforma.** O Servidor se recusa a iniciar com ela ligada enquanto
`Admin:CertificateSignIn:Enabled` estiver desligada.

### Acesso de emergência (break-glass): autenticador perdido

Um Administrador que perdeu o dispositivo pode ficar sem acesso mesmo enquanto a plataforma acredita
que outro Administrador consegue entrar. O caminho de volta é pela implantação, não pelas telas:

1. Defina `Admin:SecondFactor:Required=false` e reinicie o Servidor.
2. Deixe que ele entre com a senha e cadastre um autenticador novo.
3. Volte a configuração para `true` e reinicie.

O Servidor anuncia a postura enfraquecida em **toda** inicialização enquanto ela estiver desligada,
não só na primeira, porque um acesso de emergência que ninguém fechou de novo é justamente a falha
sobre a qual vale avisar.

### Acesso de emergência (break-glass): nenhum certificado consegue entrar

Com as senhas desligadas, várias coisas encerram todo Acesso com Certificado de uma vez: remover a
Autoridade Certificadora Confiável pela qual os certificados dos administradores encadeiam, uma
licença da PKI vencida, uma licença do Web PKI que não cobre mais o nome de host que as pessoas
digitam, uma atualização do navegador que quebre a extensão, ou o CPF vinculado do último
Administrador limpo. O Servidor nunca se recusa a iniciar por causa disso, então:

1. Defina `Admin:CertificateSignIn:Required=false` e reinicie. A entrada por senha volta, com a senha e
   o Segundo Fator de cada conta onde estavam.
2. Entre com uma senha e corrija o que impediu os certificados.
3. Volte a configuração para `true` e reinicie. Nada vai lembrar você de fazer isso.

## Admissão de estações de trabalho

Uma máquina **não tem segredo compartilhado** com que entrar na plataforma, e procurar um é procurar
algo que o produto deliberadamente não tem. Ela gera uma **Chave da Estação de Trabalho** no TPM,
quando há um utilizável (senão, em software), se anuncia e aguarda que um Administrador a admita.
Depois de admitida, ela se prova a cada conexão com uma **Workstation Assertion** assinada e de curta
duração, em vez de uma credencial: nada é emitido, nada é armazenado, e uma asserção capturada já foi
consumida.

A **Installer Key**, que também assina a requisição de admissão, serve contra abusos, não para
autenticação: toda cópia do TrustBridge tem a metade privada do produto. Uma implantação que queira
uma chave que ninguém mais tenha gera uma, informa a metade pública dela em `Admission:InstallerKeys`
(o que substitui a chave do produto) e entrega a metade privada pelo próprio instalador.

O valor da admissão é limitado, e a tela diz isso: sem um canal externo (out-of-band) com que conferir
uma impressão digital, uma máquina é notada, e não verificada. Os controles em volta dela:
`Admission:MaxPending` limita a fila, `Admission:RequestsPerAddress` limita um endereço de origem (um
endereço IPv6 conta pelo /64), `Admission:PendingExpiry` faz expirar requisições abandonadas e
`Admission:RequireHardwareBackedKeys` recusa máquinas com chave em software. A postura da chave é
declarada pela própria máquina; atestação de TPM está fora do escopo.

Uma máquina admitida também escolhe quais linhas de certificado anuncia, e é por isso que ela nunca
recebe um PIN: um anúncio pode trazer o certificado verdadeiro e público de um titular, então o
Servidor só pede a uma máquina que prove que tem o PIN, e limita as provas que falham
([Tratamento do PIN](https://docs.lacunasoftware.com/articles/trustbridge/security#tratamento-do-pin)).

A **revogação** na tela **Estações de Trabalho** recusa uma máquina permanentemente e não depende da
cooperação dela. Uma máquina cujo disco foi clonado com uma chave em software é uma identidade
clonada, e é isso que a postura de exigir hardware existe para recusar.

## Âncoras de confiança

A plataforma confia nas **raízes da ICP-Brasil** que o PKI SDK traz por padrão. Uma autoridade
certificadora privada é adicionada como **Autoridade Certificadora Confiável** (Trusted CA) no console
administrativo, passa a valer no Servidor em execução e é enviada a todas as máquinas admitidas. Quem
pode adicionar uma Autoridade Certificadora Confiável pode fazer certificados próprios serem validados
como `ACTIVE` e, onde o Acesso com Certificado está ativado, entrar no console como qualquer conta cujo
CPF vinculado coloque num deles. Por isso a ação é de um Administrador e é auditada, e por isso uma
autoridade descoberta pela web, a partir de uma URL indicada pelo próprio certificado não confiável, é
sinalizada para conferência da impressão digital antes de ser confirmada.

Em uma estação de trabalho, os arquivos de âncora em `C:\ProgramData\TrustBridge\anchors\` são o
equivalente, protegidos por uma ACL que pertence ao instalador, e são desconsiderados enquanto a
máquina tiver um conjunto não vazio recebido do Servidor.

Dois interruptores ampliam a confiança e merecem atenção: `UseMachineRootStore` (todas as ACs públicas
do programa de raízes do Windows, em uma estação de trabalho) e `UseLacunaTestPki` (**somente para
desenvolvimento**: a Lacuna publica as chaves privadas desses certificados de exemplo, e um Servidor
com ele ligado exibe um banner de aviso em todas as páginas administrativas).

`Certificates:Validation:RevocationGraceWindow` (24 h) é a outra decisão de confiança: exatamente por
quanto tempo um certificado continua assinando depois que a AC dele parou de responder, revogado ou
não. Zero é a postura mais rígida.

## A licença da PKI

`Certificates:Validation:License` é obrigatória em todo Servidor, com ou sem cofre: um Servidor sem ela
se recusa a iniciar. Ela também é a licença com que a frota inteira funciona. **O Servidor a entrega a
cada máquina admitida no handshake**, e só ali; uma máquina pendente nunca a recebe. A máquina a guarda
**somente em memória** e a recebe de novo a cada conexão; por isso, renová-la significa trocar o valor
no Servidor e reiniciá-lo, e a frota a recebe à medida que se reconecta. Nada sobre a licença é gravado
na configuração ou no registro de uma estação de trabalho: uma licença XML é gravada num arquivo
temporário pelo tempo de um carregamento e apagada em seguida, porque o SDK só lê XML de um arquivo. O
valor é mascarado onde quer que o handshake apareça no log.

Uma licença que o SDK recusa deixa todo certificado `UNTRUSTED`, no Servidor e em cada máquina a que é
entregue, então nada consegue assinar e nenhum Acesso com Certificado funciona. Uma licença recusada na
inicialização coloca um banner em todas as páginas administrativas.

## Atualizações entregues pelo Servidor

Um Administrador pode enviar uma versão do Workstation na tela **Versões da Estação de Trabalho** e
oferecê-la às máquinas, que a instalam sem ninguém presente. O canal foi feito para que o Servidor não
consiga fazer uma máquina executar nada além de um pacote genuíno e mais novo do TrustBridge
Workstation:

- **O Servidor recusa um upload** sem assinatura, assinado por um certificado fora do **Publisher Pin**
  compilado no Servidor, ou que fale um protocolo fora da janela do Servidor. Toda versão do
  Workstation a partir da 1.2.2 é assinada com Authenticode pela Lacuna Software, com carimbo de tempo
  RFC 3161.
- **A máquina confere o pacote ela mesma, nesta ordem, e o recusa na primeira falha**, o que quer que o
  Servidor tenha dito sobre ele:
  1. o SHA-256 e o tamanho que o Servidor anunciou;
  2. a assinatura Authenticode;
  3. um carimbo de tempo RFC 3161;
  4. um assinante que esteja no Publisher Pin compilado no Service **já instalado**, e não no que está
     chegando;
  5. a revogação, em que só passa uma verificação bem-sucedida ou uma consulta que não pôde ser
     respondida;
  6. o UpgradeCode do próprio TrustBridge Workstation;
  7. uma ProductVersion igual à oferecida e acima da instalada.

  Assim, o pior que um Servidor comprometido consegue fazer por esse canal é instalar antes da hora
  uma versão genuína e mais nova: nunca outro arquivo, outro produto ou uma versão mais antiga.
- **O download é autenticado pela chave da máquina.** Cada requisição a
  `GET /workstations/releases/{version}` traz uma Workstation Assertion nova, e uma máquina só recebe a
  versão oferecida a ela. O pacote vai para `C:\ProgramData\TrustBridge\updates\`, em que só SYSTEM e
  os Administradores podem gravar.
- **O operador pode desligá-las por máquina** com a Diretiva de Grupo **Receber atualizações do
  Servidor TrustBridge**; a tela **Estações de Trabalho** passa a mostrar **Atualizações desativadas por
  diretiva**.

## Segredos e os logs

O Servidor e o Workstation Service mantêm segredos fora do que imprimem. No Servidor, senhas, códigos
do Segundo Fator, o segredo do autenticador, o valor e o hash de uma chave de API nova e a licença da
PKI entregue a uma máquina são mascarados onde quer que um comando ou um resultado fosse para o log.
Numa estação de trabalho, o PIN e qualquer Prova de PIN nunca são impressos. O Tray App não grava
arquivo de log nenhum, porque a linha de um pedido de PIN cita um CPF. Um CPF aparece, sim, em linhas
do log do Servidor e da Trilha de Auditoria sobre uma sessão ou um limite, como sempre apareceu.

## Postura de rede

- **As estações de trabalho só fazem conexões de saída**, por HTTPS até o Servidor. Nenhuma porta de
  entrada é aberta na máquina, e o canal entre o Service e o Tray é um named pipe local cuja ACL é
  todo o controle de acesso dele.
- **O Servidor termina o próprio TLS** no Docker e precisa apresentar uma cadeia em que todas as
  estações de trabalho confiem; um proxy reverso pode terminá-lo no lugar dele. No App Service, a
  plataforma o termina.
- **O endereço de quem chama só vem de proxies que você indica.** No Docker, atrás do seu próprio
  proxy, liste-o em [`ForwardedHeaders:TrustedProxies`](https://docs.lacunasoftware.com/articles/trustbridge/configuration#forwardedheaderstrustedproxies)
  (endereços ou CIDRs; no ambiente, `ForwardedHeaders__TrustedProxies__0`, `…__1`).
  `X-Forwarded-For` e `X-Forwarded-Proto` só são aceitos de um par listado; o `Host` e o caminho nunca
  são reescritos. No App Service, `ASPNETCORE_FORWARDEDHEADERS_ENABLED=true` faz o mesmo papel; fora do
  App Service, essa variável confia em quem quer que se conecte e o Servidor avisa na inicialização, e
  um Servidor com as duas definidas se recusa a iniciar. O custo de deixar um proxy sem indicação: o
  `ClientIp` da Trilha de Auditoria, o limite por endereço da admissão e o limite do Acesso com
  Certificado enxergam todos o único endereço do proxy, então qualquer pessoa que alcance a página de
  login consegue gastar as tentativas de entrada de todo mundo.
- **Oito áreas compartilham uma porta**, distinguidas pelo caminho: o contrato em `/v1`, o canal das
  estações de trabalho, a admissão de estações de trabalho, o download de Versões da Estação de
  Trabalho, a documentação publicada, a Landing Page, o health probe e as páginas administrativas. Um
  caminho fora de todas elas recebe um `401` de chave de API antes que um navegador o veja. `/healthz`,
  `/` e a documentação respondem sem credencial e, de propósito, não revelam nada sobre o estado da
  plataforma. O cookie administrativo só é aceito nos caminhos administrativos.
- **O throttle global** (`Throttle:ConcurrencyLimit`, 200) é um disjuntor (circuit breaker) sobre a
  superfície do contrato contra um cliente descontrolado e não pode ser desligado.
- **Nunca execute uma implantação com `ASPNETCORE_ENVIRONMENT=Development`**: a imagem traz um arquivo
  de configuração de desenvolvimento com uma licença de exemplo e as credenciais de um Signer de testes
  compartilhado, inofensivos apenas porque uma implantação é Production.

## O que é gravado onde

| Registro | Contém | Nunca contém |
|---|---|---|
| **Trilha de Auditoria** (banco de dados) | Ator, ids dos objetos, resultado e timestamps de cada chamada à API, evento de sessão e de assinatura, evento de estação de trabalho, de PIN e de atualização, ação administrativa e entrada no console | PINs, Provas de PIN, conteúdo de documentos, bytes de assinatura |
| **Log do Servidor** (console, arquivo rotativo, Application Insights) | O que o Servidor estava fazendo, com um id de correlação; linhas de auditoria que o banco de dados recusou, em `Critical` | PINs, Provas de PIN, senhas, códigos, material de chave, a licença da PKI |
| **Log do Workstation Service** (log de eventos Aplicativo, painel de diagnóstico do Tray) | De onde veio cada valor definido na instalação, estado da conexão, recusas, vereditos, resultados de atualização | PINs, Provas de PIN |
| **Banco de dados** | Sessões, operações, Registro de Certificados, texto cifrado do cofre, os dois chaveiros, contas administrativas (hashes de senhas e de Códigos de Recuperação, segredos do autenticador em texto claro, CPFs vinculados), Provas de PIN com falha, valores alterados nas configurações, Versões da Estação de Trabalho (os pacotes inteiros) e as ofertas delas | O Protetor do Chaveiro, qualquer documento do Signer, qualquer PIN |
| **`/tmp/trustbridge-releases`** (Servidor) | Uma cópia de cada Versão da Estação de Trabalho armazenada, de onde os downloads são servidos, e um upload enquanto é lido | Nada que já não esteja no banco de dados |
| **`C:\ProgramData\TrustBridge\`** (estação de trabalho; só Administradores e SYSTEM) | O arquivo do Cache de PIN quando `PinCache:SurviveRestart` está ligada, o conjunto de Autoridades Certificadoras Confiáveis em cache, os verificadores dos PINs do Certificado A1, os arquivos de âncora; em `updates\`, uma versão sendo instalada e os cinco logs de instalação mais recentes | A licença da PKI, qualquer PIN do Certificado A1 em si |

Nada em nenhum dos componentes grava documentos em disco. Os documentos ficam só em trânsito, em
memória, limitados a `Signing:MaxDocumentBytes` vezes `Signing:MaxBatchItems`.
