Skip to content

Contas e acesso ​

Desde 14 de outubro de 2026, todas as rotas da aplicação exigem uma sessão. Continuam públicas a página inicial (/, /en, /pt), esta documentação, os avisos legais (/privacidad, /terminos) e a página de vagas. Não há senhas: a conta é criada na primeira vez que a pessoa entra.

Como se entra ​

Uma só tela, /login:

  1. Escreve o seu e-mail. Enviamos um código de 6 dígitos e um link na mesma mensagem; qualquer um serve e ambos expiram em 5 minutos. A resposta é idêntica exista ou não a conta.
  2. Digita o código (ou abre o link). Se o e-mail não tinha conta, ela é criada nesse momento. Três tentativas falhadas invalidam o código; peça outro.

O acesso é só por e-mail (código ou link), enviado de acceso@futuros.xyz via AgentMail. Não há início de sessão com Google: o botão e o vínculo em /cuenta ficam desligados, a menos que quem implanta os ative (VITE_AUTH_GOOGLE=1 mais credenciais do Google).

Depois de entrar volta à página que pedia (?next=), validada como rota do próprio site; qualquer outro valor leva a /atlas.

Primeiro acesso ​

Um passo, opcional: nome visível, idioma, e uma nota sobre o que guardamos e como pedir a exclusão. Pode ser pulado e não volta a aparecer nesse dispositivo.

O que guardamos ​

DadoOndePara quê
E-mail, nome visível, idioma, foto de perfil (só se o Google for ativado)Neon Postgres, AWS São Paulo (sa-east-1)Identificá-lo e enviar o código
Sessões ativas (navegador, IP, data)Mesma baseEncerrá-las; expiram após 30 dias sem atividade
Códigos e tokens de linkMesma base, como hash, uso únicoVerificar o acesso
Eventos de acesso (início, encerramento, códigos falhados, limites) com o IP em hashMesma baseSegurança; guardados 12 meses
Preferências, itens guardados (lista de acompanhamento, vistas, bandejas de comparação, portfólios) e atos cívicos (posições, emendas, comentários, respostas de consenso, votos em pilotos)Mesma baseAcompanhar você entre dispositivos; participação identificada
auth_login, auth_signup, auth_onboarding, preferences_migrated, saved_item_created, civic_action, account_export_requested, account_deletedPostHogMedir o funil; sem e-mail

O que não guardamos: senhas (não existem), o e-mail em logs ou analítica, o código em claro.

O detalhe legal está no aviso de privacidade (§2, §5, §8, §9).

Seu espaço de trabalho ​

Com a sessão aberta, suas preferências, itens guardados e atos cívicos vivem na sua conta e acompanham você entre dispositivos:

O quêOnde
Idioma, tour, modelo de chat, ajustes de interface, aviso de instalaçãouser_preference (lista fechada de chaves; cada valor é validado e reescrito no servidor)
Lista de acompanhamento de /mercados, vistas de /explorar, bandejas de comparação de pilotos e personas, portfólios de pilotossaved_item (até 200 por tipo)
Posições e emendas de propostas, respostas de /consenso, comentários, votos em pilotoscivic_action (ver Participação identificada)

Migração única do que você já tinha no navegador. A primeira conta que entra em um navegador envia o que havia no localStorage (lista de acompanhamento, vistas, bandejas, portfólios e preferências) e depois o remove ou o renomeia para <chave>.migrated. É sempre "inserir se não existir": um dispositivo novo, vazio ou desatualizado nunca sobrescreve o que a conta já tem. Uma segunda conta no mesmo navegador não herda nada. As chaves recusadas pelo servidor (valores alterados ou grandes demais) são descartadas; uma falha transitória de rede é repetida na próxima inicialização. Os votos, emendas e respostas anônimas de antes não podem ser atribuídos e não são migrados; as chaves com e-mails em claro (futuros_comments_v1, futuros_comment_gate_v1) são apagadas. Seguem locais, de propósito: o idioma, o modelo de chat e as marcas do tour como cache de inicialização (lidos antes de a sessão carregar), o feedback do chat e as filas de demonstração.

Sessões, exportação e exclusão ​

Tudo fica em /cuenta; em qualquer página, o avatar do cabeçalho abre o menu com Sua conta e Sair (em telas estreitas, no topo do menu ≡).

Sessões. A página lista cada navegador com sessão aberta (navegador e sistema inferidos do User-Agent, última atividade). Cada sessão pode ser fechada separadamente; Sair em todos os dispositivos apaga todas as linhas de session do usuário, inclusive a atual. As sessões duram 30 dias e se renovam com o uso. Se quem implanta ativar o Google, ele pode ser vinculado e desvinculado na mesma página (a entrada por código continua disponível).

Exportação. Pedir exportação (POST /api/account/export) monta um arquivo JSON com perfil, conversas e mensagens (com as citações tal como exibidas), preferências, itens guardados, atos cívicos e eventos de auditoria, e envia ao e-mail da conta um link assinado válido por 24 horas. Para baixar são necessárias as duas coisas: o link sem alterações e a sessão aberta da mesma conta para a qual foi emitido (com outra conta, ou sem sessão, nada é entregue). Acima de 4 MB o arquivo é dividido em partes (a primeira com tudo menos as conversas; as seguintes, conversas inteiras) e o e-mail traz um link por parte. Uma exportação por hora por pessoa.

Exclusão. Excluir minha conta (POST /api/account/delete) exige digitar o e-mail da conta (maiúsculas e espaços são ignorados). Se você é a única pessoa proprietária de uma organização que tem outros integrantes, o pedido é recusado (409) até que você transfira a propriedade. Ao confirmar:

MomentoO que acontece
Imediatodeleted_at é fixado; todas as sessões são fechadas; as chaves de API são desativadas e os tokens de embed revogados; qualquer tentativa de login é recusada; o evento account_deleted é registrado na analítica com um pseudônimo, nunca com o e-mail.
7 dias depois (cron diário /api/account-purge, protegido por CRON_SECRET)Perfil, sessões, conta Google vinculada, preferências, atos cívicos, conversas privadas com suas mensagens e itens guardados privados são apagados. Conversas e itens compartilhados com uma organização ficam nela com dono vazio ("ex-integrante"). Os eventos de auditoria ficam com ator vazio e o identificador substituído por um hash.

O mesmo cron apaga os eventos de auditoria com mais de 12 meses. Não há "desfazer": durante os 7 dias a conta está fechada, não suspensa. Os recibos do fundo fiduciário de dados não são apagados (são o registro de proveniência da própria pessoa, já pseudônimo).

Organizações ​

Uma organização reúne uma equipe: compartilha conversas e itens salvos entre seus integrantes. Gerencia-se em /cuenta/organizacion; o seletor do cabeçalho (ou a folha do menu ≡ em telas estreitas) define o espaço ativo, e Pessoal é o espaço sem organização.

PapelPode
ProprietárioTudo: mudar papéis, transferir a propriedade, excluir a organização, além do que o administrador pode.
AdministradorEditar nome e identificador, convidar, cancelar convites, remover integrantes (não administradores nem proprietários) e editar ou apagar o que foi compartilhado, inclusive o de ex-integrantes.
IntegranteVer o que foi compartilhado, criar o próprio e compartilhá-lo.
  • Criar. Qualquer pessoa; fica como proprietária. O identificador (a parte da URL) pode ser mudado uma única vez. Limites: 5 organizações criadas por pessoa por dia e 20 por conta.
  • Convidar. Proprietário ou administrador informa um e-mail e um papel (administrador ou integrante). O convite chega por e-mail (no idioma da pessoa convidada se ela já tem conta, ou no de quem convida) com um link para /invite/<id>, expira em 7 dias e só pode ser aceito pela conta com esse mesmo e-mail. No máximo 50 pendentes por organização e, contra abusos, 20 convites por hora por pessoa e 30 por hora por organização. Se o e-mail não puder ser enviado, o convite é cancelado e você é avisado.
  • Compartilhar. Cada conversa ou item salvo é privado até que seu autor o compartilhe com a organização ativa (chave em /cuenta/organizacion, ou na barra lateral de /chat para conversas). Só se compartilha com uma organização à qual você pertence. Autor, proprietários e administradores podem editá-lo ou apagá-lo; os demais só o veem.
  • Sair ou ser removido. O que você compartilhou fica na organização, sem dono, e aparece como de um ex-integrante; o privado continua seu. O último proprietário não pode sair nem mudar o próprio papel: primeiro transfira a propriedade (a regra roda dentro de uma única instrução SQL, então dois proprietários saindo ao mesmo tempo não deixam a organização sem dono).
  • Excluir a organização (só proprietário, digitando o identificador). A organização, seus integrantes e convites são excluídos. As conversas e os itens que cada integrante compartilhou voltam a ser privados do autor; os de ex-integrantes são excluídos com a organização. Não há como desfazer.
  • Auditoria. Criação, edições, convites (criação, cancelamento, aceite), mudanças de papel, transferências, saídas e remoções ficam no registro de auditoria, sem e-mails.

Chaves de API e tokens de embed ​

Fora do navegador não há cookie, então usam-se credenciais que você mesmo emite:

  • Chaves de API (ft_live_<48 hex>, /cuenta/claves): para a API pública /api/v1/* (e /data.json, /feeds/*), o servidor MCP /api/mcp e o chat via API /api/chat. Mostradas uma única vez e guardadas com hash. Teto de 600 solicitações por minuto por chave (cobrado em cada solicitação) e 500 mensagens de chat por dia por conta. O chat por chave é guardado no seu histórico, em uma conversa intitulada pelo cliente ou "API". No máximo 20 chaves ativas. Guias: API pública, MCP.
  • Tokens de embed (ft_embed_…, /cuenta/embeds): para iframes /embed/stat, /embed/chart e /embed/board em outros sites. Você escolhe as rotas permitidas e a validade (365 dias por padrão, máximo 730); abrem só essas rotas e os arquivos de dados que esses widgets leem. No máximo 25 ativos. Guia: Embeds.

Revogar uma chave ou um token vale em menos de um minuto. Se você excluir sua conta, suas chaves são desativadas e seus tokens revogados na hora.

O muro de acesso (para operadores) ​

A fronteira de segurança é o Routing Middleware da Vercel (middleware.ts, lógica em server/auth/wall.ts), não a interface. Para cada pedido fora da lista pública:

  • Lê o cookie de sessão e valida-o com uma chamada interna ao /api/auth/get-session do mesmo deploy. Um resultado positivo é lembrado 60 s em memória (chave: hash do token); um negativo nunca.
  • Sem sessão válida: uma navegação de documento recebe 302 /login?next=<rota>; qualquer fetch, API, embed ou MCP recebe 401 {"error":"auth_required"} com WWW-Authenticate: Bearer.
  • Se a validação falha por erro (tempo limite de 3 s, 500, JSON inválido), fecha: 302/401 e uma linha [auth] nos logs. Nunca deixa passar nem devolve um 500.
  • Credenciais de máquina: as chaves de API (Authorization: Bearer ft_live_… ou X-Api-Key) são aceitas em /api/v1/*, /data.json, /feeds/*, /api/mcp e /api/chat; os tokens de embed (?et= ou X-Embed-Token) em /embed/* e nos arquivos de dados que esses widgets leem. Uma credencial na superfície errada é recusada sem consulta. O muro as verifica com uma chamada interna a /api/machine-verify do mesmo deploy (origem da plataforma, nunca o Host da requisição), guarda o veredito positivo por 60 s e nunca um negativo. O teto por chave é cobrado em cada solicitação, inclusive com veredito guardado. Se a verificação não for possível (sem segredo interno, banco fora do ar), fecha: 503 com Retry-After, nunca uma passagem.
  • /api/machine-verify está na lista pública apenas para que o muro possa chamá-lo; a própria função responde 401 a qualquer requisição que não traga AUTH_INTERNAL_SECRET (comparação em tempo constante). Não usa o cabeçalho de isenção do observador de scraping, que é derivável quando SCRAPE_INTERNAL_TOKEN não está definido.

Lista pública exata: /, /en, /pt, /login, /invite/*, /privacidad, /terminos, /roles*, /api/auth/*, /api/health, /manifest.webmanifest, /sw.js, /robots.txt, /sitemap*.xml, /favicon*, /assets/*, /fonts/*, /og/*, /.well-known/*, /icons/*, o deck de investidores (/deck, /deck.html, /api/deck-access, /api/deck-slide), o salto de outreach /o/* (/api/o), e os endpoints com segredo próprio: /api/alerts-digest (cron), /api/access-webhook (Stripe), /api/questions e /api/chat-turns (token de operador). Pedidos OPTIONS passam.

Variáveis de ambiente:

VariávelEfeito
AUTH_WALL_DISABLED=1Interruptor de emergência: desativa o muro por completo. Registado nos logs em cada arranque a frio. Deve estar ausente em produção.
AUTH_INTERNAL_SECRETObrigatória para chaves de API e tokens de embed (16 ou mais caracteres; produção e preview). Sem ela, toda credencial de máquina recebe 503.
EMBED_TOKEN_PEPPERPimenta do hash dos tokens de embed. Sem ela não se criam nem se verificam tokens (503).
API_KEY_MAX_PER_MINUTE, CHAT_USER_DAILY_MAXTetos ajustáveis: 600 por chave por minuto, 500 mensagens de chat por conta por dia.
AUTH_INTERNAL_ORIGINOrigem que o muro chama para validar a sessão; por padrão, a do próprio deploy.
VERCEL_AUTOMATION_BYPASS_SECRETSe definido, o muro reenvia-o para que uma preview protegida possa validar-se a si mesma.
AUTH_SIGNUP_DISABLED, AUTH_GOOGLE_DISABLEDAlavancas do servidor de autenticação; /login mostra o erro correspondente.

Estado ​

CapacidadeEstado
Muro de acesso, /login por código e link (e-mail via AgentMail), onboardingAo vivo
Histórico de chat por contaAo vivo
Preferências e itens guardados por conta, participação identificada, painel /cuenta (perfil, sessões, exportar, excluir)Ao vivo
Organizações (papéis, convites, compartilhamento), chaves de API, tokens de embedNo ar

Cada número com sua fonte — a rastreabilidade é o contrato.