-- 0042 — compartilhar uma conversa por link
--
-- O QUE O LINK E, E O QUE ELE NAO E
--
-- Ele identifica a conversa. Ele NAO autentica ninguem.
--
-- Essa e a decisao inteira, e ela e o que mantem o produto no lugar. Quem abre
-- um link compartilhado precisa de uma sessao PROPRIA, emitida pelo servidor do
-- cliente como qualquer outra -- e o servidor confere que essa sessao alcanca o
-- mesmo escopo da conversa antes de mostrar uma linha.
--
-- O link encaminhado por engano, colado num grupo, indexado por um buscador,
-- nao abre nada. Nao ha caminho novo para o dado sair: a conversa carrega
-- resposta consolidada de varias empresas, e um link publico seria exatamente o
-- vazamento que `ScopeResolver` -> `datasetAllowlist` -> `SqlGuard` existe para
-- impedir, so que pela porta da frente.
--
--
-- O QUE MUDA, ENTAO, SE O LINK NAO DA ACESSO
--
-- Muda o DONO. Hoje uma conversa e privada de quem a criou: `alcancavelPor()`
-- confere quatro coisas -- tenant, DONO, alcance e projeto. Compartilhar
-- relaxa UMA delas, a do dono, e mantem as outras tres intactas.
--
-- Por isso o dominio ganha um metodo SEPARADO (`visivelCompartilhadaPara`) em
-- vez de um parametro no que ja existe: um booleano no metodo privado seria uma
-- linha de codigo entre "so o dono ve" e "qualquer um do tenant ve", e um dia
-- alguem passaria `true` sem querer.
--
--
-- SOMENTE LEITURA
--
-- Quem abre uma conversa compartilhada LE. Nao pergunta nela, nao renomeia, nao
-- apaga. Duas pessoas escrevendo na mesma conversa e outro produto -- tem
-- concorrencia, tem "quem falou por ultimo", tem mensagem que aparece no meio
-- do que o outro estava lendo. Quem quiser seguir a partir dali abre a propria
-- conversa e pergunta.
--
--
-- REVOGAR E APAGAR O TOKEN
--
-- Nao ha coluna de "revogado": o token volta a NULL e o link morre. Um estado a
-- menos, e nenhuma duvida sobre o que significa uma linha com token preenchido
-- e revogado=1.
--
-- Compartilhar de novo gera um token NOVO -- de proposito. Se o mesmo token
-- voltasse, revogar nao teria revogado nada para quem ja o tinha guardado.

ALTER TABLE embed_conversations
  -- `ctxc_` + 40 hex, no molde do token de sessao (`ctxs_`). O prefixo existe
  -- para quem ler um log saber o que e aquilo sem procurar.
  ADD COLUMN share_token VARCHAR(64) NULL AFTER agent_slug,

  -- Quem compartilhou, e quando. Nao e auditoria de acesso -- e a resposta para
  -- "quem abriu isso para o time?", que e a primeira pergunta quando alguem
  -- descobre uma conversa que nao devia ter sido compartilhada.
  ADD COLUMN shared_by VARCHAR(190) NULL AFTER share_token,
  ADD COLUMN shared_at DATETIME NULL AFTER shared_by;

-- UNIQUE, e nao so KEY: o token e o identificador da conversa no link, e dois
-- iguais fariam a busca devolver a conversa errada -- de OUTRO cliente, se o
-- azar fosse completo. A UNIQUE torna isso impossivel em vez de improvavel.
--
-- Com NULL a UNIQUE nao restringe, que e exatamente o que se quer aqui: milhares
-- de conversas nao compartilhadas convivem sem colidir.
ALTER TABLE embed_conversations
  ADD UNIQUE KEY uq_embed_conv_share (share_token);
