---
title: "Configuração da estação de trabalho"
description: "Todas as configurações do Workstation Service do TrustBridge e como uma instalação na frota as fornece, incluindo as atualizações entregues pelo Servidor, os PINs de Certificado A1 e as provas de PIN; o Tray App não tem arquivo de configuração."
canonical: "https://docs.lacunasoftware.com/articles/trustbridge/workstation-configuration"
locale: "pt-BR"
product: "TrustBridge"
last_updated: "2026-10-13"
---

# Configuração da estação de trabalho

Todas as configurações que o Workstation Service aceita e como uma instalação na frota as fornece. As
configurações do Servidor estão em [Configuração do Servidor](https://docs.lacunasoftware.com/articles/trustbridge/configuration); os dois hosts não
compartilham nenhuma configuração. **O Tray App não tem nenhum arquivo de configuração** (veja a
[última seção](https://docs.lacunasoftware.com/articles/trustbridge/workstation-configuration#o-tray-app-não-lê-nenhum-arquivo-de-configuração)). Esta página descreve a
**Workstation 1.5.0**.

Todo valor aqui tem um padrão, e **a maioria das máquinas da frota não altera nenhum deles**. Três
valores chegam pelo Registro, dois deles pelo MSI e um só pela Diretiva de Grupo; os demais ficam no
arquivo de configuração que o MSI instala ao lado dos binários.

## Como um valor chega a uma máquina

A última fonte a definir uma chave prevalece:

| | Fonte | O que a fornece |
|---|---|---|
| 1 | `appsettings.json` ao lado dos binários | Instalado pelo MSI em `Program Files`. Nada no serviço o regrava. |
| 2 | `appsettings.Development.json`, user secrets | Somente a execução de um desenvolvedor no console. O MSI não instala esse arquivo. |
| 3 | `HKLM\Software\TrustBridge`, a **preferência** | O MSI, a partir de `SERVER_URL` e `INSTALLER_KEY`. Um reparo ou uma gravação manual com elevação grava os mesmos valores no mesmo lugar. |
| 4 | Variáveis de ambiente, `__` no lugar de `:` | Uma execução no console ou um wrapper de serviço. Não é assim que uma instalação na frota funciona. |
| 5 | Argumentos de linha de comando | Somente uma execução no console. |
| 6 | `HKLM\Software\Policies\TrustBridge`, a **diretiva** | A Diretiva de Grupo, por meio do modelo ADMX fornecido. Somente o mecanismo de diretivas pode gravar ali. |

Três valores chegam pelo Registro. Em qualquer um dos locais, `ServerUrl` vira `Server:Url` e
`InstallerKey` vira `Server:InstallerKey`. `ServerUpdates` vira `ServerUpdates:Enabled` e é lido
**somente no local da diretiva**: nenhuma propriedade do MSI o grava, e um `ServerUpdates` colocado
manualmente em `HKLM\Software\TrustBridge` não é lido. Um valor de string publicado com o tipo de
Registro errado (um `REG_DWORD` onde se esperava uma string) **impede a inicialização, citando o
local**; um `ServerUpdates` que não seja um `REG_DWORD` com `0` ou `1` é lido como desligado (veja
[a entrada dele](https://docs.lacunasoftware.com/articles/trustbridge/workstation-configuration#serverupdatesenabled)). **Os dois locais do Registro são lidos uma vez, na
inicialização**: uma atualização de GPO entra em vigor na próxima inicialização do serviço.

**A licença da PKI não é um deles.** O Servidor a fornece no handshake; veja
[`Certificates:Validation:License`](https://docs.lacunasoftware.com/articles/trustbridge/workstation-configuration#certificatesvalidationlicense).

**Não há segredo que uma instalação entregue a uma máquina para que ela entre na plataforma.** Uma
máquina gera a própria Chave da Estação de Trabalho, se anuncia e aguarda ser **admitida** por um
Administrador. Nada nesta página é enviado pelo Servidor. O que o Servidor envia a uma máquina é a
licença da PKI, o conjunto de Autoridades Certificadoras Confiáveis dele e, quando um Administrador
oferece uma, uma Versão da Estação de Trabalho; nada disso altera uma chave daqui.

Os formatos de valor são os do Servidor: `:` em um arquivo e `__` no ambiente, durações como
`[d.]hh:mm:ss`, com a armadilha dos vinte e quatro dias, e tamanhos como inteiros simples.

## Acessando o Servidor

```json
{
  "Server": {
    "Url": "https://trustbridge.example.com",
    "InstallerKey": "MIGHAgEAMBMGByqGSM49…",
    "InitialReconnectDelay": "00:00:01",
    "MaxReconnectDelay": "00:01:00"
  }
}
```

### `Server:Url`

**Padrão** não definido · **Instalação na frota** o MSI grava `SERVER_URL` em `HKLM\Software\TrustBridge\ServerUrl`; a Diretiva de Grupo o sobrepõe em `HKLM\Software\Policies\TrustBridge\ServerUrl` · **Valor inválido** impede a inicialização

Onde fica o Servidor desta máquina. **Obrigatório, e precisa ser um URI absoluto.** O MSI recusa
primeiro um valor vazio ou sem esquema, na condição de inicialização dele; a verificação do serviço na
inicialização é a segunda barreira. O Tray App mostra essa URL e nunca pode defini-la: quem a grava
decide onde a máquina pede para ser admitida, então a gravação fica atrás de uma barreira de elevação.

### `Server:InstallerKey`

**Padrão** a chave do próprio produto · **Instalação na frota** o MSI grava `INSTALLER_KEY` em `HKLM\Software\TrustBridge\InstallerKey`, somente em uma implantação que gerou uma chave própria · **Valor inválido** impede a inicialização

A Installer Key com que esta máquina assina a requisição de admissão, além da própria chave: PKCS#8
DER em base64, ECDSA P-256. Ela mostra que a requisição veio do produto genuíno e **não autentica
nada**; toda cópia do TrustBridge tem a metade privada do produto. Uma implantação que queira uma
chave própria configura a metade pública no Servidor, em `Admission:InstallerKeys`, e entrega a
metade privada aqui. Defina-a nas máquinas **antes** que o Servidor deixe de confiar na chave antiga.
Não é um segredo. Fica de fora do modelo ADMX, de propósito.

### `Server:InitialReconnectDelay` e `Server:MaxReconnectDelay`

**Padrão** 1 s e 1 min · **Instalação na frota** nunca alterados · **Valor inválido** um valor não positivo, ou um teto abaixo do piso, impede a inicialização

Onde começa o backoff de reconexão depois que o canal cai, e o teto até onde ele sobe. **Uma máquina
que não consegue acessar o Servidor tenta de novo nesse ritmo indefinidamente.** Duas falhas são
registradas no log em `Error`, para que possam ser distinguidas de uma instabilidade passageira: o
Servidor respondeu 401 no canal (admissão retirada ou revogada), e o Servidor recusou a requisição de
admissão (revogada, Installer Key não confiável, requisições demais do endereço ou fila cheia; o log
cita as quatro). Aguardar a admissão não é uma falha e é registrado uma vez em `Information`.

### Keep-alive

Não é uma configuração, mas decide em quanto tempo uma máquina que sumiu aparece como offline. **O
serviço envia um ping ao Servidor a cada 5 s** quando não enviou mais nada, e desiste do Servidor
depois de três dos pings que o Servidor diz enviar (15 s). O Servidor, por sua vez, desconecta uma
máquina de que não ouve nada por `Workstations:ClientTimeout` (30 s por padrão). Toda versão a partir
da 1.2.0 envia ping a cada 5 s, então, quando a frota inteira estiver na 1.2.0 ou posterior, essa
configuração do Servidor pode ser reduzida para 15 s; veja
[Configuração do Servidor](https://docs.lacunasoftware.com/articles/trustbridge/configuration#o-canal-das-estações-de-trabalho).

## Atualizações pelo Servidor

```json
{
  "ServerUpdates": {
    "Enabled": true
  }
}
```

### `ServerUpdates:Enabled`

**Padrão** `true` · **Instalação na frota** somente a Diretiva de Grupo, em `HKLM\Software\Policies\TrustBridge\ServerUpdates`: um `REG_DWORD`, `0` para desligado e `1` para ligado, que a diretiva **Receber atualizações do Servidor TrustBridge** fornecida grava quando é desabilitada ou habilitada · **Valor inválido** na diretiva, qualquer coisa que não seja um `REG_DWORD` com `0` ou `1` é lida como desligada e registrada em `Error`; em um arquivo de configuração, impede a inicialização

Se esta máquina recebe as Versões da Estação de Trabalho que o Servidor dela lhe oferece. **Ligado, a
menos que uma diretiva o desligue**, inclusive em uma frota cuja primeira instalação veio pela
Diretiva de Grupo. Não há propriedade do MSI nem valor de preferência para ele: uma frota que queira o
canal desligado tem a Diretiva de Grupo.

**Desligado, a máquina não baixa nem instala nada**, seja o que for que o Servidor lhe ofereça: ela
nunca aguarda o atraso aleatório, nunca pede um pacote e nunca inicia o `msiexec`
([Atualizações entregues pelo Servidor](https://docs.lacunasoftware.com/articles/trustbridge/workstation-installation#atualizações-entregues-pelo-servidor)
é o que ligado significa). O log de inicialização avisa isso uma vez. **A máquina avisa o Servidor a
cada handshake** que está desligado, o Servidor não lhe oferece nada, e a tela **Estações de
Trabalho** a mostra como **Atualizações desativadas por diretiva**, e não como atrasada. Ela continua
informando como terminou a última atualização entregue pelo Servidor.

**Um valor de diretiva que ela não consegue ler a desliga, em vez de impedir a inicialização.** Um
`REG_SZ` com `"0"`, por exemplo, que um item de Registro das Preferências de Diretiva de Grupo grava
com mais facilidade que o `REG_DWORD` do ADMX, deixa a máquina assinando e sem receber versão nenhuma,
com uma linha `Error` citando o local. Impedir a inicialização derrubaria a assinatura em toda a frota
por causa de uma chave que só controla atualizações.

**Lido uma vez, na inicialização**, como todo valor do Registro.

## Detecção de certificados

```json
{
  "Certificates": {
    "SweepInterval": "00:01:00",
    "ValidationInterval": "01:00:00",
    "ChangeDebounce": "00:00:02"
  }
}
```

| Chave | Padrão | Significado |
|---|---|---|
| `Certificates:SweepInterval` | 1 min | A varredura de reconciliação, sempre ativa: uma enumeração com comparação de todos os repositórios, que cobre um gatilho de mudança perdido ou um token que nunca aparece como smart card. Um valor não positivo impede a inicialização. |
| `Certificates:ValidationInterval` | 1 h | A frequência com que todo certificado presente é validado de novo por completo, para que uma revogação, uma expiração ou o fim de uma janela de tolerância apareça dentro de um intervalo. Um valor não positivo impede a inicialização. |
| `Certificates:ChangeDebounce` | 2 s | Quanto tempo o pipeline aguarda depois de um sinal de mudança antes de enumerar, para que a chegada de um cartão seja agrupada e o middleware tenha tempo de tornar os certificados legíveis. Fora do intervalo de zero a 5 minutos, impede a inicialização. Um valor baixo demais custa uma varredura inteira; um alto demais custa um segundo de latência. |

## Os repositórios de certificados

```json
{
  "Certificates": {
    "WindowsStore": { "Enabled": true },
    "Pkcs11": { "Modules": "C:\\Windows\\System32\\eTPKCS11.dll;C:\\Vendors\\uncommon-p11.dll" }
  }
}
```

**O que os leitores anunciam.** Um certificado é uma identidade de assinatura quando tem chave privada
e um titular ICP-Brasil legível: um **e-CPF**, ou um **e-CNPJ** com o CPF do responsável e a
**Empresa** (CNPJs alfanuméricos incluídos). Todo o resto é ignorado. Um e-CNPJ é anunciado, com a
Empresa, somente a um Servidor cujo handshake diga que os aceita (Servidor 1.13.0), e nunca como o
e-CPF do responsável. Com um Servidor mais antigo, o Tray App lista o e-CNPJ como não anunciado, com o
motivo. A lista e o detalhe de certificados do Tray App mostram a Empresa, e a solicitação de PIN de
uma sessão de uma Empresa mostra em nome de qual Empresa se está assinando.

### `Certificates:WindowsStore:Enabled`

**Padrão** `true` · **Instalação na frota** decisão do administrador · **Valor inválido** impede a inicialização

Se o repositório de certificados do Windows da máquina (`LocalMachine\My`) é lido em busca de
certificados A1. Ligado, um A1 instalado ali é enumerado, validado e anunciado como qualquer outro
certificado da máquina. A notificação de mudanças do repositório fica aberta, para que uma importação
seja anunciada dentro de `ChangeDebounce`. Desligado, nada na máquina abre esse repositório. Lido uma
vez, na inicialização.

**Um Certificado A1 assina depois que um PIN do Certificado A1 é definido para ele naquela máquina.**
Alguém no console da máquina o define no Tray App (**Definir PIN do Certificado A1…** e, depois,
**Alterar PIN do Certificado A1…**, que pede o atual); um A1 recém-detectado sem PIN pede uma vez ao
titular que defina um. A partir daí, o PIN de uma aplicação cliente é conferido com esse PIN do
Certificado A1 da mesma forma que o PIN de um token é conferido com o Cache de PIN, e o serviço assina
com a chave do certificado sem ninguém junto à máquina. Até que um seja definido, o certificado é
anunciado e listado, e as sessões sobre ele terminam em `PIN_NOT_AVAILABLE`.

O serviço nunca guarda o PIN do Certificado A1 em si, só um verificador PBKDF2, em
`C:\ProgramData\TrustBridge\`, com as permissões do Cache de PIN. Um PIN do Certificado A1 atual errado
conta para [`Tray:MaxConsecutivePinFailures`](https://docs.lacunasoftware.com/articles/trustbridge/workstation-configuration#o-canal-entre-o-service-e-o-tray). Um PIN do Certificado
A1 é excluído quando o certificado some do repositório por duas varreduras seguidas, e na hora se um
token aparecer com o mesmo certificado. Uma atualização o mantém; uma desinstalação de verdade o
exclui. Nada disso é configurado: a chave controla se o repositório é lido, e o PIN do Certificado A1
é por certificado, por máquina, definido por quem estiver no console primeiro.

### `Certificates:Pkcs11:Modules`

**Padrão** não definido, o que significa a lista de fabricantes fornecida · **Instalação na frota** nunca alterado em uma máquina com middleware comum · **Valor inválido** um módulo que não carrega é uma falha desse repositório no log, e não uma inicialização recusada

Os módulos PKCS#11 dos fabricantes, por meio dos quais os tokens A3 são lidos, como **uma única
string de caminhos absolutos separados por ponto e vírgula**. Três estados:

- **Não definido** é a lista padrão fornecida: SafeNet Authentication Client, SafeSign IC, Watchdata
  PROTON, Feitian ePass2003, Idemia AWP e Thales IDPrime, nos caminhos em que esses fabricantes os
  instalam, verificados pela existência do arquivo. **Frotas comuns têm detecção de tokens sem
  nenhuma configuração.**
- **Definido** é exatamente o que está na lista, por inteiro; nada é verificado e nenhum padrão é
  mantido. Um módulo listado que não existe, é da arquitetura errada ou não é um módulo PKCS#11 conta
  como falha desse repositório, com o motivo no log. É assim que se adiciona um middleware incomum, ao
  custo de também listar os comuns de que a máquina precisa.
- **Definido como vazio** desliga a detecção de A3. Por variável de ambiente, desligado é
  `Certificates__Pkcs11__Modules=";"`, porque uma variável que não existe é lida como não definida.

Cada módulo é um repositório próprio e eles falham isoladamente: um middleware com falha custa apenas
os certificados daquele fabricante, que passam a `STALE` ao longo da janela de tolerância. A
enumeração nunca envolve um PIN e não consome nada do contador de tentativas de um token. Lido uma
vez, na inicialização.

**A aba Tokens do Tray App é onde se confere o resultado.** Ela mostra um cartão por token que a
última varredura de detecção viu (rótulo, número de série, modelo, o middleware que o leu, se há PIN
armazenado, os certificados nele), os middlewares consultados pelo serviço e os que falharam, e uma
linha citando qualquer leitora com um cartão que nenhum middleware instalado lê, ou um cartão que não
responde.

## Validação de certificados e a licença do PKI SDK

O mesmo nome de seção e a mesma política que o Servidor lê. Quatro coisas são diferentes em uma
estação de trabalho, e cada uma é destacada abaixo.

```json
{
  "Certificates": {
    "Validation": {
      "UseIcpBrasil": true,
      "UseMachineRootStore": false,
      "UseLacunaTestPki": false,
      "UseServerTrustedCas": true,
      "TrustedRootPaths": ["C:\\ProgramData\\TrustBridge\\anchors\\your-root.pem"],
      "RevocationGraceWindow": "1.00:00:00",
      "RevocationTimeout": "00:00:05",
      "CheckTimeout": "00:00:30"
    }
  }
}
```

### `Certificates:Validation:License`

**Padrão** não definido · **Instalação na frota** nunca definida na máquina: o Servidor compartilha a própria licença com toda máquina Admitida a cada handshake · **Valor inválido** uma licença vencida ou corrompida gera uma linha `Critical`, nunca uma inicialização recusada

**Obrigatória em todas as máquinas, essa é a primeira diferença em relação ao Servidor, e é o
Servidor que a fornece.** Aqui, o SDK é o que lê qualquer certificado; sem licença, **todo
certificado da máquina aparece como `UNTRUSTED`** e a máquina não assina nada. Uma máquina Admitida
recebe a própria [`Certificates:Validation:License`](https://docs.lacunasoftware.com/articles/trustbridge/configuration#certificatesvalidationlicense) do
Servidor na resposta a cada handshake e a aplica antes de anunciar qualquer certificado. Ela fica só
em memória, nunca é gravada no disco da máquina e substitui qualquer valor definido aqui.

**Nada que uma instalação na frota grava fornece uma, e isso é proposital.** Nenhuma propriedade do
MSI e nenhum valor de Diretiva de Grupo traz uma licença. Renová-la é uma alteração e um reinício no
Servidor, que toda máquina conectada adota ao se reconectar, e uma máquina offline no próximo
handshake. Uma máquina revogada ou devolvida a Pendente mantém a licença que recebeu até o serviço
dela reiniciar.

**O que a máquina informa.** Sem nada definido aqui, a linha de inicialização é `Information`,
aguardando o Servidor, que é a inicialização normal de uma máquina instalada. Uma licença enviada pelo
Servidor que o SDK recusa gera `Critical` uma vez por valor distinto, assim como um Servidor que aceita
o handshake mas não envia nenhuma. O Tray App mostra uma linha acima da lista de certificados dizendo
por que a máquina está sem licença: aguardando o Servidor (Pendente, nunca admitida ou offline desde a
inicialização), a licença do Servidor foi recusada, o Servidor não enviou nenhuma, ou uma licença que
esta máquina não conseguiu aplicar.

Um valor definido aqui, em um arquivo de configuração ou como `Certificates__Validation__License`, é
só para a execução de um desenvolvedor no console: a licença em base64 em uma linha, que a do Servidor
substitui assim que ele responde.

### As fontes de âncoras

| Chave | Padrão | Significado |
|---|---|---|
| `Certificates:Validation:UseIcpBrasil` | `true` | As raízes da ICP-Brasil que o SDK traz. Desligá-la é uma decisão de confiança. |
| `Certificates:Validation:UseMachineRootStore` | `false` | **A segunda diferença: aqui ela tem efeito.** Confia em todas as ACs públicas do programa de raízes do Windows, um conjunto muito mais amplo que a ICP-Brasil. |
| `Certificates:Validation:UseLacunaTestPki` | `false` | Confia também na PKI de testes da Lacuna. **Somente para desenvolvimento**: a Lacuna publica as chaves privadas correspondentes. O serviço avisa isso em `Critical` a cada inicialização. |

### `Certificates:Validation:UseServerTrustedCas`

**Padrão** `true` · **Instalação na frota** o arquivo de configuração que o MSI instala (esta chave não tem valor no Registro, então nenhuma GPO a alcança) · **Valor inválido** impede a inicialização

**A terceira diferença: esta chave só tem efeito em uma máquina.** Define se a máquina incorpora as
**Autoridades Certificadoras Confiáveis** do Servidor ao próprio conjunto de âncoras. Ligada, a
máquina pede o conjunto ao Servidor depois de cada handshake e pede de novo quando o Servidor avisa
que ele mudou; assim, uma AC que um Administrador adiciona na tela **Autoridades Certificadoras
Confiáveis** chega aos vereditos desta máquina em segundos. O último conjunto recebido fica em cache
localmente e continua valendo enquanto o Servidor estiver inacessível: um Servidor que não responde
não disse nada, e só um Servidor respondendo, inclusive respondendo *nenhuma Autoridade Certificadora
Confiável*, substitui o que a máquina tem.

**Enquanto esta máquina tiver um conjunto não vazio recebido do Servidor, `TrustedRootPaths` é
totalmente desconsiderado**, e o serviço avisa isso em `Critical`, citando os caminhos descartados. Um
controle que só acrescentasse confiança nunca conseguiria retirá-la.

Desligada, a máquina nunca pede e valida apenas contra a própria configuração, `TrustedRootPaths`
incluído: é a postura para uma frota com um pipeline próprio de âncoras, sob controle de mudanças.
Desligá-la é uma alteração no arquivo de configuração de cada máquina, que convém fazer **antes** de a
máquina se conectar ao Servidor pela primeira vez. De qualquer forma, a máquina informa em qual postura
está a cada conexão, e a tela **Estações de Trabalho** a mostra por máquina.

### `Certificates:Validation:TrustedRootPaths`

**Padrão** vazio · **Instalação na frota** decisão do administrador, implantada junto com os arquivos de âncora · **Valor inválido** um arquivo ilegível gera uma linha `Critical`, e não uma inicialização recusada

Como uma AC privada é adicionada a partir de um arquivo nesta máquina. **Não é mais a palavra
final**: a forma suportada de confiar em uma AC privada em toda a frota é uma Autoridade Certificadora
Confiável adicionada uma vez no Servidor. Esta chave ainda decide a resposta inteira em uma máquina em
que `UseServerTrustedCas` está desligado, em uma que nunca teve contato com um Servidor ou em uma cujo
Servidor não tem Autoridades Certificadoras Confiáveis.

**A quarta diferença: estes precisam ser caminhos absolutos.** Quem consegue adicionar um arquivo aqui
consegue fazer um certificado próprio ser validado como `ACTIVE`, então os arquivos devem ficar em
`C:\ProgramData\TrustBridge\anchors\`, cuja ACL pertence ao instalador. Sem nenhuma âncora, o serviço
ainda inicia e todo certificado aparece como `UNTRUSTED`, com uma linha `Critical` citando as
configurações (e não a licença); arquivos de âncora que contêm só intermediárias geram uma segunda
linha, diferente.

### Os limites de revogação

| Chave | Padrão | Significado |
|---|---|---|
| `Certificates:Validation:RevocationGraceWindow` | 24 h (`1.00:00:00`) | Por quanto tempo a última verificação de revogação bem-sucedida mantém um certificado `ACTIVE` enquanto a AC dele está inacessível; depois disso, o certificado passa a `STALE`. Ampliar este valor é ampliar o tempo durante o qual um certificado revogado continua assinando enquanto a AC dele está inacessível. Um valor negativo impede a inicialização. |
| `Certificates:Validation:RevocationTimeout` | 5 s | Quanto tempo o download de uma LCR ou a busca de um emissor pode levar antes de a AC ser considerada inacessível. Um valor não positivo impede a inicialização. |
| `Certificates:Validation:CheckTimeout` | 30 s | O limite externo da verificação inteira de um certificado. As validações são feitas em série na máquina, então uma verificação sem limite trava todos os certificados atrás dela. Zero espera indefinidamente. |

### Enquanto o Servidor e esta máquina estão em versões diferentes

O handshake é onde esta máquina recebe a licença da PKI e o conjunto de Autoridades Certificadoras
Confiáveis, então uma diferença de versão decide se a máquina consegue ler um certificado. A
Workstation 1.5.0 fala o **protocolo 5**, no qual o Servidor deixa de enviar a qualquer máquina o PIN
da aplicação cliente: ele desafia a máquina com um nonce, e a máquina responde com uma **prova de PIN**
(PIN Proof) calculada sobre o PIN que tem em cache, ou sobre o verificador de um PIN do Certificado A1,
para o Servidor conferir. Um Servidor aceita o próprio protocolo e o anterior.

- **Esta máquina à frente do Servidor: ela não se conecta.** Um Servidor anterior ao 1.13.0 recusa o
  handshake (*Protocol version 5 is newer than this server's supported window (3–4); update the Server
  first*). Este serviço registra esse veredito no log, desconecta e tenta de novo com backoff. Sem um
  Servidor que lhe entregue a licença, todo certificado desta máquina aparece como `UNTRUSTED`, e ela
  **não consegue assinar** até que o Servidor seja atualizado.
- **Um Servidor à frente de uma máquina: ela se conecta e não atende a novas sessões.** Um Servidor
  1.13.0 ainda deixa uma máquina na Workstation 1.4.x (protocolo 4) fazer o handshake, receber a
  licença, buscar o conjunto de Autoridades Certificadoras Confiáveis, assinar pelas sessões já
  vinculadas a ela e receber uma oferta de versão. Ele nunca lhe envia um desafio de PIN nem uma
  solicitação, então, para a criação de sessões, essa máquina conta como offline. A atualização que o
  Servidor lhe oferece é o que a traz de volta. Uma máquina na 1.3.0 ou anterior (protocolo 3) é
  recusada com *update required*.

Por isso, para esta versão, a regra é **atualizar o Servidor e a frota juntos**: veja
[Qual Servidor uma versão exige](https://docs.lacunasoftware.com/articles/trustbridge/workstation-installation#qual-servidor-uma-versão-exige). Os PINs
em cache e os PINs de Certificado A1 passam pela atualização como estão, e a 1.5.0 não adicionou,
renomeou nem removeu nenhuma chave desta página.

## O canal entre o Service e o Tray

O canal por named pipe entre o serviço e o Tray App. A ACL dele admite usuários interativos, e esse é
todo o controle de acesso dele. **Uma instalação na frota não mexe em nada disto.**

```json
{
  "Tray": {
    "PipeName": "TrustBridge.WorkstationService",
    "PromptTimeout": "00:01:30",
    "MaxConsecutivePinFailures": 3,
    "PinFailureCooldown": "00:05:00",
    "LogBufferSize": 500
  }
}
```

| Chave | Padrão | Significado |
|---|---|---|
| `Tray:PipeName` | `TrustBridge.WorkstationService` | O pipe em que o serviço escuta. Configurável só para que um desenvolvedor possa executar uma segunda instância; o Tray App se conecta ao nome conhecido e não tem configuração própria. Um valor em branco impede a inicialização. |
| `Tray:PromptTimeout` | 90 s | O limite da própria máquina para uma solicitação de PIN. **O `Sessions:PinPromptTimeout` do Servidor (60 s) é o que normalmente encerra uma solicitação**: quando ele se esgota, o Servidor retira a solicitação da máquina. Esta janela, mais folgada, é o que encerra uma solicitação que o Servidor não consegue mais alcançar, como uma em uma máquina que perdeu a conexão, e também limita quanto tempo uma digitação aguarda o veredito do Servidor sobre a prova dela. Mantenha-a mais longa que a do Servidor. Um valor não positivo impede a inicialização. |
| `Tray:MaxConsecutivePinFailures` | 3 | Quantos PINs podem ser rejeitados seguidamente para um certificado antes que as entradas para ele sejam recusadas sem ser verificadas: um token que os rejeita ou, para um Certificado A1, PINs do Certificado A1 errados (inclusive um PIN atual errado ao alterá-lo). Limita um processo que tenta milhares de vezes, não uma pessoa: o usuário ainda pode bloquear o próprio token digitando errado. Zero impede a inicialização. |
| `Tray:PinFailureCooldown` | 5 min | Por quanto tempo as entradas para um certificado são recusadas depois que esse limite é atingido. Não é um estado do token; nenhum PUK está envolvido, e a espera se encerra sozinha, para um token e para um A1. |
| `Tray:LogBufferSize` | 500 | Quantas entradas recentes de log o serviço guarda para a aba **Log** do Tray. Somente em memória. |

## O Cache de PIN

**Local e controlado pelo administrador.** O Servidor não envia nada para cá, e nenhuma chamada do
Tray ou da API pode alterá-lo. Uma linha a cada inicialização informa em qual postura a máquina está.

**O PIN nunca vem do Servidor.** Um PIN só chega ao cache pelo titular, no Tray App desta máquina,
depois que o token o aceitou. Na criação de uma sessão, o Servidor envia um nonce, e a máquina responde
com uma prova calculada com o PIN em cache; o Servidor decide se ela confere com o PIN da aplicação
cliente e avisa a máquina quando uma sessão foi vinculada por meio dela.

```json
{
  "PinCache": {
    "SurviveRestart": false,
    "Ttl": "08:00:00",
    "SweepInterval": "00:05:00",
    "StorePath": "C:\\ProgramData\\TrustBridge\\pin-cache.dat",
    "KeyRingPath": "C:\\ProgramData\\TrustBridge\\keys"
  }
}
```

### `PinCache:SurviveRestart`

**Padrão** `false` · **Instalação na frota** decisão do administrador, e um desvio documentado

Se os PINs em cache sobrevivem a um reinício do serviço ou da máquina, inclusive ao reinício causado
por uma atualização entregue pelo Servidor. **Desligado**, as entradas são criptografadas com um
chaveiro que só existe no processo em execução, então parar o serviço destrói o meio de lê-las.
**Ligado**, o chaveiro é persistido em `KeyRingPath`, protegido com DPAPI no escopo da máquina, e o
texto cifrado vai para `StorePath`, em um arquivo cuja ACL admite apenas SYSTEM e Administradores. Em
qualquer caso, o TTL fica selado dentro do texto cifrado, então um reinício não consegue zerá-lo e
editar o arquivo não consegue estendê-lo.

Ligá-lo é um desvio documentado do gatilho de encerramento do requisito de middleware da ICP-Brasil
(REQUISITO-MW II.27), que o TrustBridge trata como uma diretriz porque fica acima do middleware do
fabricante. Uma máquina com ele ligado avisa isso em `Warning` a cada inicialização.

Os PINs de Certificado A1 não fazem parte do Cache de PIN e não são afetados por esta chave: eles
ficam no disco até o certificado sair da máquina ou o pacote ser desinstalado.

### O restante do Cache de PIN

| Chave | Padrão | Significado |
|---|---|---|
| `PinCache:Ttl` | 8 h | Quanto tempo uma entrada vive **sem ser usada**. Deslizante: cada sessão vinculada por meio dela renova a expiração, então um usuário ativo todo dia nunca é solicitado de novo. Um valor não positivo impede a inicialização. |
| `PinCache:SweepInterval` | 5 min | A frequência com que entradas inativas são removidas da memória. De qualquer forma, nada consegue obter um PIN expirado. |
| `PinCache:StorePath` | `%ProgramData%\TrustBridge\pin-cache.dat` | Onde o texto cifrado é gravado. Nunca é gravado enquanto a sobrevivência estiver desligada. |
| `PinCache:KeyRingPath` | `%ProgramData%\TrustBridge\keys` | Onde fica o chaveiro persistido. Não é usado enquanto a sobrevivência estiver desligada. |

## Logs

A configuração do próprio framework, no mesmo formato da do Servidor. O arquivo fornecido define
`Default` como `Information` e reduz duas categorias do cliente SignalR a `Warning`. Duas linhas que
um administrador deve reconhecer no nível padrão: em qual postura do Cache de PIN a máquina está (a
cada inicialização) e que o mecanismo de tokens falsos para desenvolvimento está ativo (a cada
inicialização, em qualquer máquina com uma seção `FakeTokens`). **Uma seção `FakeTokens` não deve
existir em uma máquina em que alguém assine**: ela faz certificados fabricados serem validados como
`ACTIVE`.

## O Tray App não lê nenhum arquivo de configuração

Não há `appsettings.json` para o Tray App. As opções dele são construídas no código: o nome do pipe e
a versão de protocolo a que ele se conecta, o intervalo de reconexão e a tolerância de expiração da
solicitação são compilados, e o idioma que ele exibe vem da cultura de interface do Windows do usuário
conectado, e não de uma configuração. O que molda o canal entre os dois é a seção `Tray` acima, que é
lida pelo **serviço**.

Ele também não grava arquivo de log, de propósito: a linha de log de uma solicitação cita um CPF, e um
arquivo no perfil de cada usuário fica onde uma desinstalação não alcança. O que o Tray App registra
fica em memória e aparece na aba **Log**, ao lado das linhas do serviço, e só sai da máquina pelo
**Exportar…** dessa aba. As linhas dele terminam quando o Tray App termina, então exporte antes que
alguém o reinicie.
