Skip to content
This repository was archived by the owner on Jul 10, 2026. It is now read-only.

docs(RLS): plano seguro + prova no DB (TKT-026) — não habilitado por não ser verificável offline - #117

Merged
danzeroum merged 3 commits into
mainfrom
claude/optimistic-mendel-cwuuno
Jun 22, 2026
Merged

docs(RLS): plano seguro + prova no DB (TKT-026) — não habilitado por não ser verificável offline#117
danzeroum merged 3 commits into
mainfrom
claude/optimistic-mendel-cwuuno

Conversation

@danzeroum

Copy link
Copy Markdown
Owner

RLS (TKT-026): plano seguro + prova no DB — não habilitado (por integridade)

A investigação de RLS encontrou um risco que impede ligar ingenuamente:

scoped_conn usa set_config('app.workspace_id', $1, **FALSE**) — nível de sessão numa conexão do pool. O valor persiste quando a conexão volta ao pool. Com RLS lendo current_setting, uma query não-scoped numa conexão reusada herdaria o workspace do request anterior → vazamento/quebra cruzada entre tenants. Isso não dá para verificar sem rodar o app sob concorrência — então não mergeio isolamento de dados que não consigo validar.

Entregue (plano + prova de DB, em vez de migration arriscada)

  • docs/rls-plan.md — caminho seguro: (1) GUC transaction-local (SET LOCAL em transação) em todo caminho tenant; (2) migration estrita por tabela; (3) cleanup defensivo no retorno ao pool. Política usa NULLIF(current_setting('app.workspace_id', true), '')::uuid.
  • Prova no Postgres local (role não-superuser, pois superuser bypassa RLS): SET app.workspace_id=A vê só A, =B só B, nunca-setado/após-RESET → 0 linhas, sem erro. Valida a política e o isolamento estrito.
  • Gotcha capturado: após RESET, current_setting(...,true) retorna '' (não NULL) e ''::uuid dá erro — por isso o NULLIF.

Para habilitar: implementar o passo (1) e validar com o app rodando sob concorrência (o ponto não-verificável offline). O roadmap marca TKT-026 como planejado + provado no DB, não habilitado no app.

🤖 Generated with Claude Code


Generated by Claude Code

claude added 3 commits June 21, 2026 13:46
- P-01 vLLM vs Ollama: RESOLVIDO — runtime Ollama externo, ADR-001 atualizado;
  vLLM = profile GPU (depende de P-06).
- P-07 Redis: RESOLVIDO (parcial) — redis no compose + throttle de login usa
  Redis; falta so confirmar recursos da VPS de producao.
- P-09: remove referencia ao SHA antigo de main.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AcsaeS7c9zJ4vkNtxqBcnc
…rator rejeitado)

Investigacao revelou que varios apontamentos da auditoria estavam desatualizados
e que ha codigo morto confundindo o crate `api`:

- removidos 5 arquivos de rota ORFAOS no api (nao declarados em routes/mod.rs,
  zero refs): usage.rs, webhooks.rs, search.rs (duplicatas mortas das rotas reais
  que vivem no crate api-public) + chat.rs, feedback.rs (stubs que importavam
  `ai_orchestrator`, um nao-dependency — nem compilariam).

Correcoes de entendimento (roadmap):
- TKT-018/019 (linkar ai-orchestrator): REJEITADO. O crate e dead code para outra
  arquitetura (vLLM, RAG rag-searcher, tabela training_interactions, SSE proprio,
  sem basic-auth nem OLLAMA_MOCK). Linka-lo quebraria o chat atual + 11 testes.
- TKT-020 (rag-searcher): REJEITADO (RAG do orchestrator); api::rag ja faz 4
  estagios com rerank.
- TKT-041 (Swagger): JA real (ApiDoc utoipa 40+ paths + SwaggerUi em /docs).
- TKT-042 (usage tokens): o caminho VIVO (admin_service.get_usage_metrics, usado
  pelo dashboard via /api/admin/metrics) JA soma tokens de usage_events. O "0 //
  TODO" estava no api/routes/usage.rs MORTO (deletado). PR #113 editou esse
  arquivo morto — superado por esta remocao.

Verificacao local: cargo build -p api -p api-public OK apos as remocoes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AcsaeS7c9zJ4vkNtxqBcnc
Investigacao de RLS revelou um risco que impede habilitar ingenuamente:
scoped_conn usa set_config('app.workspace_id', $1, FALSE) — nivel de SESSAO
numa conexao do POOL. O valor persiste apos a conexao voltar ao pool; com RLS
usando current_setting, uma query nao-scoped numa conexao reusada herdaria o
workspace anterior -> vazamento/quebra cruzada. Nao da p/ verificar isso sem
rodar o app sob concorrencia.

Entrega (por integridade, plano + prova de DB em vez de migration arriscada):
- docs/rls-plan.md: caminho seguro — (1) GUC transaction-local (SET LOCAL em
  transacao) em TODO caminho tenant; (2) migration estrita por tabela; (3)
  cleanup defensivo. Politica usa NULLIF(current_setting(...),'') p/ evitar erro
  de cast de string vazia apos RESET.
- Prova no Postgres local (role nao-superuser): SET app.workspace_id=A ve so A,
  =B ve so B, unset/RESET -> 0 linhas sem erro. Valida a politica e o isolamento.

Roadmap atualizado: TKT-026 = planejado + provado no DB, NAO habilitado no app.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AcsaeS7c9zJ4vkNtxqBcnc
@danzeroum
danzeroum merged commit 0754567 into main Jun 22, 2026
1 check failed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants