refactor: integra reconcile no boot, dedup categoria/pasta, CI, Go 1.24
ci / check (push) Successful in 4m12s

- Boot chama ReconcileBlobs com log de órfãos (era código morto)
- treeNode/validTreeName/siblingDup/moveCreatesCycle compartilhados
  entre Create/Update Category/Folder (mesma regra, um só lugar)
- mapStoreErrorFor com mensagens 404 por recurso (nota/arquivo/pasta/categoria)
- revisionHash helper + teste GET /revisions/{hash} (200 + 404)
- ReconcileBlobs com lock curto (coleta sob RLock, I/O fora do lock)
- AddFile com LimitReader no stream (cap antes de gravar, não depois)
- DeleteFile/DeleteFolder transacionais com rollback em memória
- attachmentKind único no frontend (syntax/html/preview)
- CI: gofmt, vet, test -race, node --check; go.mod 1.24 = Dockerfile
- README: notas operacionais (memória, proxy, boot, SSE, 413/400)
This commit is contained in:
lgcosta committed 2026-11-05 19:57:38 -03:00
1 parent 0e59ef23f4
commit e0bef77e31
16 files changed
+518 -126

No files matched your search

+8
View File
@@ -381,6 +381,14 @@ curl -sI -H "Authorization: Bearer $T" $B/api/files/static/<id> | grep -i dispos
- Rode atrás de TLS (reverse proxy) em produção. O modelo é **token único compartilhado**
(sem usuários múltiplos); a imagem final é `scratch` non-root (uid 65534) — sem shell para
`exec` de depuração, por design.
- **Notas operacionais.** Rate-limit e sessões vivem **em memória**: reiniciar o processo
limpa bloqueios de login e revoga todas as sessões (relogin). Atrás de proxy reverso,
todos os clientes chegam com o IP do proxy — o bloqueio passa a ser compartilhado;
só confie em cabeçalhos `X-Forwarded-*` com lista explícita de proxies confiáveis
(hoje o servidor usa `RemoteAddr` puro). O boot roda reconciliação de anexos
(remove blobs órfãos, loga metadados sem blob). SSE é stream longo sem deadline
global de escrita (renovado por keepalive). Erros de corpo acima do limite
retornam **413**; JSON malformado retorna **400**.
- Preferências do editor e abas abertas ficam em `localStorage` (dados não sensíveis, por
dispositivo/navegador); o token nunca vai para lá.
- Presença/SSE: o stream exige a mesma autenticação das rotas `/api/*` (cookie HttpOnly no