# Agenda demonstrativa NÍTIDA

Este projeto é fictício. A avaliação inicial dura 60 minutos ilustrativos; os valores são sob consulta. Nome e telefone devem ser dados de teste. Não há atendimento confirmado, pagamento ou envio de mensagens.

## Uso local

Execute `npm ci`, `npm run check`, `npm test` e `npm run build`. `npm run dev` abre o servidor Astro. A agenda usa `nitida:demo-bookings:v1` no armazenamento deste navegador. A visão `/demo` compartilha esses registros, filtra profissionais e conta registros e cancelamentos, sem receita. Cancelar libera o intervalo. Apagar remove os dados locais; não exclui registros remotos. Abas recebem alterações pelo evento de armazenamento. Navegadores sem Web Locks recusam gravações para preservar a coordenação. Armazenamento negado ou corrompido não é tratado como sucesso.

Os horários seguem segunda=1, domingo=7, no fuso America/Sao_Paulo, dentro de 21 datas civis a partir de hoje. Não há exclusão automática de feriados. Catálogo, recorrência, textos e campos estão em `content/site.json`; mídia e alternativas de texto estão em `assets/media-manifest.json`.

## Apps Script opcional

Copie `gas/Code.gs` em um projeto Apps Script. Execute `setup()` no editor: cria a planilha se ainda não houver `SPREADSHEET_ID`, inicializa `Records` e gera `OPS_TOKEN` e `CANCEL_SECRET` em Script Properties. `initialize()` preserva dados existentes e recusa cabeçalhos incompatíveis. Defina o fuso do projeto como America/Sao_Paulo. Compartilhe a planilha apenas com os administradores autorizados.

Colunas: Id, RequestId, Fingerprint, ServiceId, ProfessionalId, Date, Time, DurationMinutes, Name, Phone, Status, CreatedAt, CancelHash. Name e Phone são dados de teste; datas e horários são texto. O servidor valida o catálogo e schema 1.1.0, rejeita campos excedentes, normaliza o telefone e serializa operações com ScriptLock. RequestId oferece idempotência: um retry conserva o identificador; dados diferentes exigem nova tentativa.

Publique como aplicativo web executado pelo proprietário somente depois de definir retenção, acesso e exclusão da planilha. Configure a URL `/exec` em `PUBLIC_DEMO_GAS_ENDPOINT`. Essa variável contém somente o endereço público, jamais tokens. A configuração precisa permitir leitura de JSON pelo navegador; respostas opacas e `no-cors` não comprovam gravação. Valide disponibilidade, criação, conflito, retry e cancelamento com dados de teste antes de disponibilizar o envio. O repositório não inclui um endpoint ativo.

GET oferece somente disponibilidade sem dados pessoais. POST também oferece disponibilidade; criação usa o payload documentado em `content/integration.md`. Cancelamento requer a capacidade específica devolvida com o registro. O cliente mantém essa capacidade apenas em memória: recarregar a página encerra a possibilidade de cancelar remotamente por essa sessão. Não há lista pública por ID. A operação privada `operations` exige OPS_TOKEN no corpo POST; o token fica em Script Properties e nunca em URL, exportação ou bundle público.

O endpoint tem limite de corpo de 4096 caracteres e espera de lock de 10 segundos. Quotas de Apps Script e Sheets limitam uso; este desenho não é sistema de produção clínica nem oferece proteção contra abuso de endpoint público. Defina controles e políticas antes de uso externo. Falha remota conserva a tentativa e não troca silenciosamente para local. A mudança explícita para local não exclui uma gravação remota cujo resultado seja desconhecido.

## Distribuição

`npm run package` sincroniza o catálogo GAS e prepara `/downloads/Code.gs`, `/downloads/guia-agenda.md` e o ZIP de fontes com lista permitida. Execute antes do build final. O ZIP inclui fontes, dependências declaradas, catálogo, tokens, licenças e mídia web; exclui `.env`, configurações CLI, originais, capturas, QA, node_modules e dist. `downloads/hashes.json` registra SHA-256 dos arquivos públicos. A revisão visual e funcional precede qualquer publicação.
