---
title: "Configuração do Servidor"
description: "Todas as chaves que o Servidor do TrustBridge lê: o padrão, se um Administrador pode alterá-la em tempo de execução, se exige reinício e de onde ela vem."
canonical: "https://docs.lacunasoftware.com/articles/trustbridge/configuration"
locale: "pt-BR"
product: "TrustBridge"
last_updated: "2026-10-12"
---

# Configuração do Servidor

Todas as chaves que o Servidor lê, o padrão de cada uma, se um Administrador pode alterá-la em tempo
de execução e se uma alteração exige reinício. O Workstation Service e o Tray App são configurados à
parte: veja [Configuração das estações de trabalho](https://docs.lacunasoftware.com/articles/trustbridge/workstation-configuration).

## De onde vem um valor

Seis fontes, da menor para a maior precedência. Uma fonte posterior prevalece sobre uma anterior,
chave por chave:

| | Fonte | Onde existe |
|---|---|---|
| 1 | `appsettings.json` | Embutido na imagem. Não é um arquivo que a implantação edita. |
| 2 | `appsettings.{ASPNETCORE_ENVIRONMENT}.json` | O `appsettings.Development.json` está na imagem e fica inerte porque uma implantação não é o ambiente Development. **Nunca execute uma implantação como `Development`**: esse arquivo contém a licença de exemplo do PKI SDK e as credenciais de um Signer de teste compartilhado. |
| 3 | User secrets | Somente na máquina de um desenvolvedor. |
| 4 | Variáveis de ambiente | O container: o `environment:` do Compose ou os application settings do App Service. `__` substitui `:`. |
| 5 | Linha de comando | Nenhum dos dois cenários usa. |
| 6 | **Os overrides que um Administrador salvou** | Uma tabela no banco de dados da plataforma, lida na inicialização e relida sempre que uma configuração é salva na tela **Configurações e usuários**. |

**A fonte 6 é silenciosa e prevalece.** Se você define uma das sete chaves que aceitam override na
implantação e o valor não tem efeito, alguém salvou um valor na tela **Configurações e usuários**; o
seu valor é o padrão para o qual a chave volta quando o override é limpo.

| Chave que um Administrador pode sobrescrever | Padrão |
|---|---|
| `Sessions:DefaultDuration` | 1 h |
| `Sessions:MaxDuration` | 24 h |
| `Sessions:PinPromptTimeout` | 60 s |
| `Sessions:MaxPinFailures` | 5 |
| `Sessions:PinFailureWindow` | 15 min |
| `Signing:WorkstationReconnectGrace` | 15 s |
| `Audit:RetentionDays` | 365 |

Essas sete entram em vigor sem reinício. Uma linha salva com qualquer outra chave é ignorada, e não
aplicada. **Trate todas as outras chaves desta página como exigindo reinício.**

## Como escrever uma chave

`:` num arquivo, `__` no ambiente:

```json
{ "Sessions": { "MaxDuration": "12:00:00" } }
```

```yaml
environment:
  Sessions__MaxDuration: "12:00:00"
```

```bash
az webapp config appsettings set -g <rg> -n <app> --settings Sessions__MaxDuration=12:00:00
```

- Um único sublinhado não faz nada: `Sessions_MaxDuration` é uma variável que o Servidor nunca lê.
- **Uma lista é indexada**, e o índice faz parte da chave: `KeyRingProtector__RetiredCertificates__0__Certificate`.
- **Uma duração é `[d.]hh:mm:ss`, e as horas precisam ficar abaixo de 24.** `24:00:00` são vinte e
  quatro *dias*; um dia é `1.00:00:00`.
- Um tamanho é uma contagem simples de bytes. Um booleano é `true` ou `false`, em minúsculas.
- Uma categoria de log mantém os pontos: `Logging__LogLevel__TrustBridge.Server.Common.Vault`.

## Banco de dados e chaveiros

### `ConnectionStrings:TrustBridge`

**Padrão** uma string local com autenticação do Windows, só para desenvolvimento · **Override pelo Administrador** não · **Exige reinício** sim

O único banco de dados da plataforma: schema, Trilha de Auditoria, os dois chaveiros e os overrides do
Administrador. O padrão da imagem não funciona no Linux, então uma implantação que esquecer esta chave
tem a inicialização recusada depois de cerca de noventa segundos de tentativas.

```yaml
# Docker on Linux, SQL Server beside it
ConnectionStrings__TrustBridge: >-
  Server=sqlserver,1433;Database=TrustBridge;User Id=sa;
  Password=${MSSQL_SA_PASSWORD};Encrypt=True;TrustServerCertificate=True
```

```bash
# Azure App Service, managed identity
ConnectionStrings__TrustBridge="Server=tcp:<sqlserver>.database.windows.net,1433;Database=TrustBridge;Authentication=Active Directory Managed Identity;Encrypt=True"
```

### `Database:MigrateOnStart`

**Padrão** `true` · **Override pelo Administrador** não · **Exige reinício** sim

Se o Servidor aplica as migrações pendentes ao banco de dados na inicialização, antes de atender
qualquer coisa. `false` não significa "iniciar mesmo assim": uma migração pendente, nesse caso,
**recusa a inicialização**, citando as migrações e o comando a executar. Dois estados recusam a
inicialização qualquer que seja o valor: um banco de dados com migrações que este build não contém, e
um banco de dados que não pode ser acessado em cerca de noventa segundos. Aplicar migrações exige
`db_ddladmin`; um banco de dados atualizado não precisa de nenhum DDL.

Três limites de tempo são constantes, e não chaves: cerca de noventa segundos para o banco de dados
começar a responder, cinco minutos para a migração de outro processo terminar e **trinta minutos para
cada comando de uma migração**. No Azure App Service, o `WEBSITES_CONTAINER_START_TIME_LIMIT` (padrão
de 230 s) é atingido primeiro; aumente-o para 1800.

### `KeyRingProtector:Certificate`

**Padrão** não definido · **Override pelo Administrador** não · **Exige reinício** sim

**Obrigatória em toda implantação**, inclusive numa que não guarda certificados próprios. Um
**PKCS#12 codificado em base64, numa única linha e sem cabeçalho PEM**, com uma chave privada **RSA**.
Não é um caminho nem um thumbprint. Quatro recusas impedem o host de iniciar: não configurada, não é
base64, não pôde ser aberta (senha errada ou não é um PKCS#12) e nenhuma chave privada RSA utilizável.
Veja [Segurança](https://docs.lacunasoftware.com/articles/trustbridge/security#o-protetor-do-chaveiro).

```yaml
environment:
  KeyRingProtector__Certificate: ${KEY_RING_PROTECTOR_CERTIFICATE:?set KEY_RING_PROTECTOR_CERTIFICATE in .env}
```

```bash
# App Service: an app setting, or better, a Key Vault reference
KeyRingProtector__Certificate="@Microsoft.KeyVault(SecretUri=https://<vault>.vault.azure.net/secrets/<name>/)"
```

### `KeyRingProtector:CertificatePassword`

**Padrão** não definido · **Override pelo Administrador** não · **Exige reinício** sim

A senha que abre o protetor. Ausente significa que o PKCS#12 não precisa de senha, que é o padrão
honesto para um protetor fornecido como configuração.

### `KeyRingProtector:RetiredCertificates:{n}:Certificate` e `…:{n}:CertificatePassword`

**Padrão** vazio · **Override pelo Administrador** não · **Exige reinício** sim

Protetores que esta implantação já usou para selar, mantidos para que o material de chave selado com
um deles continue legível. **Só para decifrar**, e mantidos **permanentemente**: a rotação nunca
re-cifra as chaves armazenadas. É uma lista de objetos, porque cada PKCS#12 aposentado tem a própria
senha, pareada pelo índice. **Não coloque uma entrada vazia em templates**: uma entrada cujo
`Certificate` resulta numa string vazia recusa a inicialização.

```yaml
environment:
  KeyRingProtector__Certificate: <the new one>
  KeyRingProtector__RetiredCertificates__0__Certificate: <the one it replaced>
  KeyRingProtector__RetiredCertificates__0__CertificatePassword: <if that one had a password>
```

## Logs

### `Logging:LogLevel:{category}`

**Padrão** `Information`, com `Microsoft.AspNetCore` em `Warning` · **Override pelo Administrador** não · **Exige reinício** sim

Os níveis de log do framework, e o único lugar em que um nível é decidido: o console, o arquivo
rotativo e o Application Insights recebem exatamente as linhas que esses níveis deixam passar. Seis
categorias trazem as linhas que vale a pena reconhecer, todas em `Information` ou acima, então o
padrão já as mostra:

| Categoria | O que informa |
|---|---|
| `TrustBridge.Server.Common.Persistence.SchemaUpgrade` | Quais migrações foram aplicadas nesta inicialização, ou por que o schema foi recusado |
| `TrustBridge.Server.Common.Persistence.SchemaGate` | Que os overrides do Administrador não puderam ser relidos depois da etapa do schema |
| `TrustBridge.Server.Common.KeyRings.KeyRingPosture` | Qual protetor está selando agora, com o thumbprint e o número de aposentados |
| `TrustBridge.Server.Common.Vault.VaultReadiness` | Se o cofre está desligado, aberto ou travado fechado |
| `TrustBridge.Server.Common.Audit.AuditLog` | Uma linha de auditoria que não conseguiu chegar ao banco de dados, em `Critical`, com a própria linha |
| `TrustBridge.Pki.Validation.LacunaPkiRuntime` | Que a licença do PKI SDK está ausente ou vencida |

Aumente o nível de uma categoria, não o nível mínimo geral: o log de debug do framework soterra essas
seis linhas.

### `Logging:File:Directory`

**Padrão** `trustbridge-logs` no diretório temporário do processo (`/tmp/trustbridge-logs`) · **Override pelo Administrador** não · **Exige reinício** sim

Onde o arquivo rotativo em JSON compacto é gravado, um por dia, com nova rotação ao passar de um
gigabyte. A tela **Log do Servidor** do console administrativo lê esse arquivo. **Vazio desliga o
arquivo**, que é o que um sistema de arquivos somente leitura define. Um diretório que o Servidor não
consegue criar deixa o arquivo desligado durante toda a vida do processo, com um `Warning`; o console
não é afetado.

### `Logging:File:RetainedDays`

**Padrão** 14 · **Override pelo Administrador** não · **Exige reinício** sim

Quantos dias de arquivos são mantidos. Abaixo de 1, a inicialização é recusada. É um limite de uso de
disco, e não uma política de retenção: o pipeline do console é o registro.

### `Logging:ApplicationInsights:ConnectionString`

**Padrão** não definido · **Override pelo Administrador** não · **Exige reinício** sim

Uma connection string do Application Insights. Quando definida, toda linha também é enviada para lá
como um trace, com o id de correlação e a categoria como dimensões personalizadas. **Quando não
definida, `APPLICATIONINSIGHTS_CONNECTION_STRING` é lida no lugar dela**, então um workspace associado
pelo portal do App Service não precisa de uma segunda configuração. Um valor que não seja uma
connection string recusa a inicialização.

### `AllowedHosts`

**Padrão** `*` · **Override pelo Administrador** não · **Exige reinício** sim

O filtro de header Host do framework. Nenhum dos dois cenários precisa dele.

## O serviço de assinatura

Onde fica o Lacuna Signer e como o TrustBridge se autentica nele. **As duas coisas ou nenhuma**: um
Signer não configurado é uma implantação suportada, em que `/v1/signatures` recusa as chamadas e todo
o resto funciona; um endereço sem chave **recusa a inicialização**.

```yaml
environment:
  Signer__BaseAddress: https://signer.example.com
  Signer__ApiKey: My Application|43fc0da834e48b4b840fd6e8c371…
  Signer__ApplicationName: My Application    # only for a key that is the secret half alone
  Signer__FolderId: f81d4fae-7dec-11d0-a765-00a0c91e6bf6
  Signer__RequestTimeout: "00:00:10"
```

| Chave | Padrão | Significado |
|---|---|---|
| `Signer:BaseAddress` | não definido | O endereço base do Signer. Defini-lo torna `ApiKey` obrigatória. |
| `Signer:ApiKey` | não definido | A única chave de API do Signer que o TrustBridge guarda em nome de todas as Aplicações Cliente, na forma completa `application\|secret` que o Signer publica. |
| `Signer:ApplicationName` | não definido | A parte da aplicação, só para uma chave que traga apenas o secret. Ignorada quando a chave contém `\|`. |
| `Signer:FolderId` | não definido | A pasta do Signer em que todos os documentos são colocados, como GUID. Não definida, é a raiz da organização. |
| `Signer:RequestTimeout` | 10 s | O limite de uma chamada ao Signer. Um valor não positivo recusa a inicialização. |

Todas exigem reinício, e nenhuma aceita override.

## Sessões de Assinatura

Cinco das sete chaves que aceitam override do Administrador estão aqui. `Sessions:SignatureAllowance`
não tem padrão e está ausente do exemplo de propósito.

```yaml
environment:
  Sessions__DefaultDuration: "01:00:00"
  Sessions__MaxDuration: "1.00:00:00"
  Sessions__MaxPinFailures: "5"
  Sessions__PinFailureWindow: "00:15:00"
  Sessions__PinPromptTimeout: "00:01:00"
  Sessions__PinRelayTimeout: "00:00:05"
  Sessions__ExpirySweepInterval: "00:05:00"
```

| Chave | Padrão | Override | Reinício | Significado |
|---|---|---|---|---|
| `Sessions:DefaultDuration` | 1 h | **sim** | não | A janela de ociosidade concedida quando o cliente não pede nenhuma. Um valor não positivo recusa a inicialização. |
| `Sessions:MaxDuration` | 24 h (`1.00:00:00`) | **sim** | não | A maior janela que um cliente pode pedir; um pedido maior é reduzido a esse limite, e o valor reduzido é devolvido. Abaixo de `DefaultDuration`, recusa a inicialização. |
| `Sessions:MaxPinFailures` | 5 | **sim** | não | Comparações de PIN com falha, dentro da janela, que bloqueiam um CPF para criação de sessão, contadas por CPF somando todas as chaves de API. Zero recusa a inicialização. |
| `Sessions:PinFailureWindow` | 15 min | **sim** | não | A janela deslizante do bloqueio e o tempo de espera. |
| `Sessions:PinPromptTimeout` | 60 s | **sim** | não | Por quanto tempo um pedido de PIN no Tray App fica na tela antes de a criação desistir. O `Tray:PromptTimeout` da própria estação de trabalho (90 s) é mais folgado de propósito, porque um Servidor que já desistiu não consegue tirar o pedido da tela. |
| `Sessions:PinRelayTimeout` | 5 s | não | sim | O prazo de todo o repasse do PIN por todos os certificados candidatos, no caminho com cache. |
| `Sessions:ExpirySweepInterval` | 5 min | não | sim | A frequência com que a varredura encerra no registro as sessões vencidas. Não muda nenhum veredito. Não é validada na inicialização. |

### `Sessions:SignatureAllowance`

**Padrão** não definido (sem limite) · **Override pelo Administrador** não · **Exige reinício** sim

Quantas **chamadas** de assinatura uma Sessão de Assinatura pode fazer antes de terminar como
**Esgotada** (*Exhausted*), o que vier primeiro entre seus dois limites. Uma unidade por chamada, não
por documento: um lote de cinquenta gasta uma, e uma chamada cujos documentos falharam todos antes de o
certificado assinar não gasta nenhuma. Uma franquia de `1` reproduz a sessão de uso único da
implementação de referência. Zero ou menos recusa a inicialização. É concedida na criação, então uma
alteração só governa as sessões criadas depois dela. O protocolo não informa o saldo restante; a tela
**Sessões de Assinatura** mostra o quanto foi gasto.

## A superfície de assinatura

```yaml
environment:
  Signing__RequestBudget: "00:01:00"
  Signing__HashSignTimeout: "00:00:25"
  Signing__SignerCancelBudget: "00:00:03"
  Signing__StrandedAfter: "00:10:00"
  Signing__StrandedSweepInterval: "00:05:00"
  Signing__WorkstationReconnectGrace: "00:00:15"
  Signing__ReconnectPollInterval: "00:00:00.250"
  Signing__MaxDocumentBytes: "10485760"
  Signing__TransportHeadroomBytes: "65536"
  Signing__MaxBatchItems: "50"
  Signing__SignerConcurrency: "32"
```

| Chave | Padrão | Override | Significado |
|---|---|---|---|
| `Signing:RequestBudget` | 60 s | não | Toda uma assinatura síncrona, da admissão da requisição até os bytes assinados. Estourar esse prazo responde `SIGN_TIMEOUT`. `HashSignTimeout` mais `WorkstationReconnectGrace` precisam caber nele, ou a inicialização é recusada. |
| `Signing:HashSignTimeout` | 25 s | não | Quanto tempo uma assinatura de hash despachada pode levar antes de a máquina ser considerada inacessível. Bem acima dos cerca de 340 ms que um token gasta, porque a máquina pode estar ocupada com o documento de outra pessoa. |
| `Signing:SignerCancelBudget` | 3 s | não | Quanto tempo a limpeza pode levar quando uma execução que não assinou nada encerra o documento no Signer. |
| `Signing:StrandedAfter` | 10 min | não | Quanto tempo uma Operação de Assinatura pode ficar em `Pending` antes de a varredura encerrá-la como `Failed`, com `RUN_STRANDED`. Precisa ser maior que `RequestBudget` mais `SignerCancelBudget`. |
| `Signing:StrandedSweepInterval` | 5 min | não | A frequência dessa varredura. Uma passagem também roda na inicialização. Não é validada na inicialização. |
| `Signing:WorkstationReconnectGrace` | 15 s | **sim** | Quanto tempo uma assinatura espera a estação de trabalho vinculada voltar antes de responder `WORKSTATION_OFFLINE`. Zero recusa na hora e é válido; um valor negativo recusa a inicialização. |
| `Signing:ReconnectPollInterval` | 250 ms | não | A frequência com que essa tolerância verifica de novo a presença. Um valor não positivo recusa a inicialização. |
| `Signing:MaxDocumentBytes` | 10 MB (`10485760`) | não | O maior documento que o Servidor assina, medido nos bytes **decodificados**. Acima do limite, responde 413 no envelope do contrato. Limita a memória, não o armazenamento. Os limites de transporte subjacentes são derivados dele. |
| `Signing:TransportHeadroomBytes` | 64 KB | não | Folga, além do documento codificado, para o restante do corpo da requisição. |
| `Signing:MaxBatchItems` | 50 | não | Quantos documentos uma chamada em lote pode citar. Uma chamada com mais é recusada antes de qualquer documento ser assinado. Junto com `MaxDocumentBytes`, define o que um lote em andamento pode ocupar: 500 MB com os padrões. |
| `Signing:SignerConcurrency` | 32 | não | Quantas execuções de assinatura podem estar em andamento no Signer ao mesmo tempo, em todo o Servidor. Um lote maior roda em ondas. Zero recusa a inicialização. |

Todas exigem reinício, exceto `WorkstationReconnectGrace`.

## O throttling global

Um limite para quantas chamadas do contrato o Servidor executa ao mesmo tempo, com uma fila curta à
frente dele. Uma chamada descartada responde `429 SERVER_BUSY`, sem `Retry-After`. Ele vale somente
para a superfície do SignSession Contract; o canal das estações de trabalho, o console administrativo,
o probe de saúde, a página inicial, a documentação e a admissão de estações de trabalho ficam fora dele.
Os padrões ficam quase sete vezes acima da carga projetada: é um disjuntor (circuit breaker), não um
teto de vazão.

| Chave | Padrão | Significado |
|---|---|---|
| `Throttle:ConcurrencyLimit` | 200 | Quantas chamadas do contrato podem rodar ao mesmo tempo. Zero recusa a inicialização; de propósito, não há como desligá-lo. É `Signing:SignerConcurrency`, e não este, que molda a vazão de assinaturas. |
| `Throttle:QueueLimit` | 50 | Quantas chamadas podem esperar por uma vaga antes de a seguinte ser descartada. Zero é válido e significa sem fila; um valor negativo recusa a inicialização. |

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

Quais máquinas podem pedir para entrar, quanto da fila um desconhecido pode ocupar e por quanto tempo
um pedido abandonado permanece. Uma implantação padrão não define nenhuma destas. Todas exigem
reinício, e nenhuma está na tela **Configurações e usuários**.

```yaml
environment:
  Admission__InstallerKeys__0: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE…"
  Admission__MaxPending: "500"
  Admission__RequestsPerAddress: "300"
  Admission__RequestWindow: "00:01:00"
  Admission__PendingExpiry: "7.00:00:00"
  Admission__RequireHardwareBackedKeys: "false"
```

| Chave | Padrão | Significado |
|---|---|---|
| `Admission:InstallerKeys` | A Installer Key distribuída com o TrustBridge | As Installer Keys com que este Servidor aceita pedidos de admissão assinados, cada uma um `SubjectPublicKeyInfo` DER em base64 de uma chave pública ECDSA P-256. **Definir esta chave substitui o padrão, em vez de somar a ele.** Liste duas durante uma troca: adicione a nova ao lado da antiga, atualize a frota e então remova a entrada antiga. Um valor que não pode ser interpretado recusa a inicialização. |
| `Admission:MaxPending` | 500 | Quantas máquinas podem estar aguardando um Administrador ao mesmo tempo. Acima disso, o pedido de uma máquina que este Servidor nunca viu é recusado. Zero recusa a inicialização. |
| `Admission:RequestsPerAddress` | 300 | Quantos pedidos de admissão um endereço de origem pode fazer por janela. É um limite contra incômodo; atrás de NAT, um escritório inteiro é um único endereço, e nenhum header de encaminhamento é considerado. |
| `Admission:RequestWindow` | 1 min | A janela fixa do limite acima. |
| `Admission:PendingExpiry` | 7 dias | Quanto tempo o pedido de uma máquina fica na fila depois da última vez que o Servidor teve notícias dela. É contado a partir do **último** pedido, então uma máquina que continua pedindo nunca expira. A expiração não é uma recusa. |
| `Admission:RequireHardwareBackedKeys` | `false` | Se a admissão de uma máquina cuja Chave da Estação de Trabalho não está em hardware deve ser recusada. Essa máquina continua aparecendo na fila, e a tela explica por que o controle **Admitir** a recusa. A postura é uma declaração da própria máquina; nada a atesta. |

## O console administrativo

```yaml
environment:
  Admin__Bootstrap__Email: admin@example.com
  Admin__Bootstrap__Password: ${ADMIN_BOOTSTRAP_PASSWORD}
  Admin__Bootstrap__DisplayName: Platform Administrator
  Admin__SecondFactor__Required: "true"
```

### `Admin:Bootstrap:Email`, `Admin:Bootstrap:Password`, `Admin:Bootstrap:DisplayName`

**Padrão** não definido · **Override pelo Administrador** não · **Exige reinício** sim

O primeiro Administrador. Lidas num Servidor cuja tabela de contas está **vazia**, e inertes em todas
as inicializações seguintes: uma senha configurada nunca recria uma conta excluída nem redefine uma
existente. A senha precisa atender às regras de senha da identidade, ou a conta não é criada e o motivo
é registrado no log. Remova as duas depois de entrar. Com elas não definidas e a tabela vazia, o
Servidor registra um `Warning` e não cria nada; ninguém consegue entrar no console até que algo
coloque uma conta lá.

### `Admin:SecondFactor:Required`

**Padrão** `true` · **Override pelo Administrador** **não, de propósito** · **Exige reinício** sim

Se uma Conta Administrativa precisa apresentar um segundo fator além da senha. **Configuração da
implantação, e nunca uma tela**: uma opção que desativa o segundo fator, ao alcance de dentro do
console que ele protege, é uma opção que um invasor desliga no caminho. Uma linha salva no banco de
dados com esta chave é ignorada. Vale para toda a plataforma, sem exceção por conta.

É também o **acesso de emergência (break-glass)** para um Administrador que perdeu o autenticador; o
procedimento está em [Segurança](https://docs.lacunasoftware.com/articles/trustbridge/security#acesso-de-emergência-break-glass-autenticador-perdido). A postura
enfraquecida é anunciada a cada inicialização enquanto a opção estiver desligada.

## A Trilha de Auditoria

### `Audit:RetentionDays`

**Padrão** 365 · **Override pelo Administrador** **sim** · **Exige reinício** não

Por quanto tempo os eventos de auditoria são mantidos; uma limpeza diária exclui as linhas mais
antigas. Abaixo de 1, a inicialização é recusada: uma retenção de zero apagaria toda a trilha na
passagem seguinte.

Não há configuração para o destino de uma gravação de auditoria que falhou. Uma entrada que o banco de
dados não aceita é gravada no Log do Servidor no nível `Critical`, com a própria linha, e o console
administrativo mostra um alerta. Ela chega até você pelo pipeline de logs que a implantação tiver,
então o fallback da auditoria faz parte da sua **retenção de logs**, e não dos seus backups.

## Idiomas

```yaml
environment:
  Language__DefaultCulture: pt-BR
  Language__SupportedCultures__0: en
  Language__SupportedCultures__1: pt-BR
```

| Chave | Padrão | Significado |
|---|---|---|
| `Language:DefaultCulture` | `en` | O idioma em que é respondida uma requisição sem um `Accept-Language` utilizável. Não é um idioma de toda a implantação: a preferência do navegador do leitor e o seletor de idioma prevalecem. Um valor fora do conjunto suportado, ou um erro de digitação, recusa a inicialização. |
| `Language:SupportedCultures` | vazio, o que significa `en` e `pt-BR` | Todos os idiomas em que as páginas respondem. Informar um conjunto substitui o padrão. |

A superfície do contrato, os logs e a Trilha de Auditoria ficam permanentemente em inglês.

## A documentação publicada

### `Documentation:ApiReferenceEnabled`

**Padrão** `true` · **Override pelo Administrador** não · **Exige reinício** sim

Se a referência navegável é servida em `/scalar`. O documento legível por máquina em
`/openapi/v1.json` é o contrato de integração, é sempre servido e não é afetado. Os dois respondem sem
credencial.

## O canal das estações de trabalho

Como uma máquina admitida prova que é ela mesma a cada conexão: uma asserção de curta duração assinada
pela Chave da Estação de Trabalho. Nenhuma das duas chaves é algo que uma implantação saudável precise
mexer.

| Chave | Padrão | Significado |
|---|---|---|
| `Workstations:ClockSkewTolerance` | 60 s | A diferença máxima entre o relógio do Servidor e o de uma estação de trabalho antes que essa máquina não consiga se conectar. Aplicada nas duas pontas. O log do Servidor cita a máquina com o relógio desviado e a diferença (`A workstation assertion was refused: Expired` ou `NotYetValid`). Um valor negativo ou acima de uma hora recusa a inicialização. |
| `Workstations:MaxAssertionLifetime` | 5 min | A maior janela de validade aceita numa asserção; uma declaração mais longa é recusada. Limita o cache de nonces, que guarda no máximo 100.000 nonces e, quando cheio, recusa em vez de esquecer. Um valor não positivo ou acima de uma hora recusa a inicialização. |

O canal está no **protocolo 2**. O Servidor aceita os protocolos N e N-1. Veja
[Operação](https://docs.lacunasoftware.com/articles/trustbridge/operations#ordem-de-atualização-primeiro-o-servidor-depois-a-frota).

## O Cofre de Certificados

```yaml
environment:
  Vault__Enabled: "true"
  Vault__RevalidationInterval: "01:00:00"
```

### `Vault:Enabled`

**Padrão** `false` · **Override pelo Administrador** **não, de propósito** · **Exige reinício** sim

Se o Cofre de Certificados existe neste Servidor, isto é, se ele pode guardar uma chave privada
própria. Desligado por padrão porque esse nível torna condicional a premissa fundadora da plataforma;
o operador decide ativá-lo. Uma linha salva no banco de dados com esta chave é ignorada, pelo mesmo
motivo de `Admin:SecondFactor:Required`. Ligá-lo coloca a licença do PKI SDK no caminho crítico e
traz junto a trava do cofre. Desligá-lo não exclui nada: as linhas permanecem, a revalidação para, e
os caminhos que as leriam respondem que este Servidor não tem chaveiro.

### `Vault:RevalidationInterval`

**Padrão** 1 h · **Override pelo Administrador** não · **Exige reinício** sim

A frequência com que o Servidor verifica de novo o veredito do que o cofre guarda. Não é validada na
inicialização: um valor não positivo é informado no nível `Critical`, e o worker não roda.

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

O mesmo nome de seção que o Workstation Service lê, com duas chaves que só fazem sentido lá. No
Servidor, só uma implantação com o cofre ligado resolve a licença e o conjunto de âncoras; os timeouts
e a janela de tolerância são validados em toda inicialização, de qualquer forma.

```yaml
environment:
  Certificates__Validation__License: ${PKI_LICENSE}
  Certificates__Validation__UseIcpBrasil: "true"
  Certificates__Validation__UseMachineRootStore: "false"
  Certificates__Validation__UseLacunaTestPki: "false"
  Certificates__Validation__RevocationGraceWindow: "1.00:00:00"
  Certificates__Validation__RevocationTimeout: "00:00:05"
  Certificates__Validation__CheckTimeout: "00:00:30"
```

### `Certificates:Validation:License`

**Padrão** não definido · **Override pelo Administrador** não · **Exige reinício** sim

**Na prática obrigatória quando o cofre está ligado.** O `LacunaPkiLicense.config` inteiro que a
Lacuna emite, codificado em base64 numa única linha, e não um caminho. A imagem não traz licença, então
uma renovação é uma alteração de configuração e um reinício, e não um novo build.

```bash
base64 -w0 LacunaPkiLicense.config
```

```powershell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("LacunaPkiLicense.config"))
```

Uma implantação com cofre e sem licença **inicia**: uma linha `Critical`, todos os Certificados do
Cofre informando `UNTRUSTED` e as importações recusadas de imediato. Licença ausente, malformada ou
vencida, todas levam a essa mesma linha. Coloque o vencimento dela no calendário que acompanha as
renovações de certificados. O SDK só lê uma licença a partir de um arquivo, então o valor é gravado em
`/tmp/trustbridge-pki` e excluído na mesma chamada; um sistema de arquivos somente leitura sem um
`/tmp` gravável não consegue carregar a licença.

### As fontes de âncoras

| Chave | Padrão | Significado |
|---|---|---|
| `Certificates:Validation:UseIcpBrasil` | `true` | Confiar nas raízes da ICP-Brasil que o PKI SDK traz: o conjunto de âncoras de produção, embutido, sem download. Desligar é uma decisão de confiança. |
| `Certificates:Validation:UseMachineRootStore` | `false` | Confiar também no repositório de raízes da própria máquina. No Servidor, um container Linux, não faz nada; é uma opção da estação de trabalho. |
| `Certificates:Validation:UseLacunaTestPki` | `false` | Confiar também na PKI de teste da Lacuna. **Somente para desenvolvimento**: a Lacuna publica as chaves privadas desses certificados de exemplo. Um Servidor com esta opção ligada registra `Critical` na inicialização e mostra um **banner de aviso em todas as páginas administrativas**. |
| `Certificates:Validation:UseServerTrustedCas` | `true` | Uma opção da **estação de trabalho**. Inerte no Servidor. |
| `Certificates:Validation:TrustedRootPaths` | vazio | **Não é considerada no Servidor.** Um Servidor que a encontra definida inicia mesmo assim e registra uma linha `Critical` citando a chave e a página administrativa que a substituiu. Em vez dela, adicione uma **Autoridade Certificadora Confiável** em `/admin/trusted-cas`. |

Duas linhas `Critical` descrevem um conjunto de âncoras que não ancora nada: nenhuma âncora, e âncoras
que são só intermediárias, sem raiz autoassinada, de modo que nenhuma cadeia consegue terminar. As duas
situações tornam todo certificado `UNTRUSTED`.

### 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; passado esse prazo, o certificado vira `STALE`. **Esta é a decisão de confiança**: exatamente por quanto tempo um certificado continua assinando depois que a AC parou de responder, revogado ou não. Zero é válido e é o mais rigoroso; um valor negativo recusa a inicialização. |
| `Certificates:Validation:RevocationTimeout` | 5 s | Quanto tempo um download de LCR ou uma busca de emissor pode levar antes de a AC ser considerada inacessível. Também limita cada busca do percurso AIA da descoberta de Autoridades Certificadoras Confiáveis. Um valor não positivo recusa a inicialização. |
| `Certificates:Validation:CheckTimeout` | 30 s | O limite externo de toda a verificação de um certificado, incluindo o fallback para OCSP do SDK, que não tem limite próprio. Zero espera indefinidamente e não é recusado. |

## Configurações que não são chaves de appsettings

| Configuração | Pertence a | Onde |
|---|---|---|
| `ASPNETCORE_ENVIRONMENT` | O framework | **Não definida nos dois cenários**, e não definida significa `Production`, o que mantém o `appsettings.Development.json` inerte. |
| `ASPNETCORE_URLS` | Kestrel | `https://+:8443` no Docker, somente HTTPS. Não definida no App Service. |
| `Kestrel__Certificates__Default__Path` / `__Password` | Kestrel | O certificado TLS do próprio Servidor no Docker. Nada a definir no App Service. |
| `WEBSITES_PORT` | App Service | `8080`. |
| `WEBSITES_CONTAINER_START_TIME_LIMIT` | App Service | `1800`, para que uma migração longa não seja encerrada e reiniciada em loop. |
| `ASPNETCORE_FORWARDEDHEADERS_ENABLED` | O framework | `true` atrás de qualquer proxy que termine o TLS, ou toda linha de auditoria registra o proxy em vez de quem fez a chamada. |
| `APPLICATIONINSIGHTS_CONNECTION_STRING` | App Service | Lida quando `Logging:ApplicationInsights:ConnectionString` não está definida. |
| `TMPDIR` | O processo | Move os dois diretórios temporários. De propósito, não existe configuração do TrustBridge para isso. |
