Este Web App, é um aplicativo web "cliente leve" (light-client).
O Painel Web funciona como uma interface de visualização segura e de facilitando interações de um aplicativo móvel nativo. O "Mobile App" é a única fonte de verdade para chaves privadas e lógica de assinatura.
A arquitetura é projetada com uma restrição de segurança primária, que é inegociável:
O cliente web NUNCA deve, sob NENHUMA circunstância, lidar com chaves privadas, mnemônicas (frases-semente) ou qualquer lógica de assinatura de transação.
Todo o fluxo de autenticação e execução de ações sensíveis é "assistido", exigindo que o usuário aprove as ações explicitamente no Mobile App.
A implementação técnica utilizará as seguintes tecnologias:
- Linguagem Frontend: TypeScript
- Framework Principal: Next.js (Usando o App Router)
- Roteamento: Next.js App Router (roteamento baseado em sistema de arquivos)
- Estilização: Tailwind CSS
- Comunicação API: axios
- Geração de QR Code: qrcode.react
- Plataforma de Hospedagem: Cloudflare Pages (Hospedagem de site estático + Funções de back-end)
- Lógica de API (Backend): Cloudflare Workers (executados via rotas /api/)
- Linguagem Backend: TypeScript (para os Workers)
- Banco de Dados:
- Cloudflare KV: (Uso principal) Ideal para armazenar os "desafios" de autenticação (tokens de QR Code), que são temporários e de alta leitura.
- Cloudflare D1: (Opcional) Para armazenamento de dados de usuário mais complexos ou relacionais, se necessário.
Esta é a lógica que deve ser implementada no back-end (Cloudflare Workers) para suportar o fluxo de autenticação.
Endpoint: GET /api/auth/challenge
- Propósito: Gerar um desafio único para o QR Code.
- Lógica do Worker:
- Gerar uma string de desafio única e segura (ex:
crypto.randomUUID()). - Criar um registro no Cloudflare KV com o
challengecomo chave. - O valor do registro deve ser:
{ status: "pending", timestamp: Date.now() }. - Definir um tempo de expiração (TTL) no registro do KV (ex: 5 minutos).
- Retornar (200 OK) com
{ challenge: "string_unica_gerada" }.
- Gerar uma string de desafio única e segura (ex:
Endpoint: POST /api/auth/scan (Para o App Nativo)
- Propósito: (A SER CHAMADO PELO "COFRE") Validar o desafio escaneado.
- Lógica do Worker:
- Receber
{ challenge: "...", signedData: "...", userPublicKey: "..." }. - Verificar a assinatura
signedDatausando auserPublicKey. - Se a assinatura for válida:
- Buscar o registro do
challengeno KV. - Se existir e estiver "pending":
- Atualizar o registro no KV para:
{ status: "completed", user: { ...dados do usuário... } }. - Manter o TTL original (ou definir um novo TTL curto).
- Retornar (200 OK) ao app nativo.
- Atualizar o registro no KV para:
- Se não existir ou não estiver "pending", retornar (404 Not Found) ou (410 Gone).
- Buscar o registro do
- Se a assinatura for inválida, retornar (401 Unauthorized).
- Receber
Endpoint: POST /api/auth/status (Para o Painel Web)
- Propósito: (A SER CHAMADO PELO PAINEL WEB) Verificar o status do desafio.
- Lógica do Worker:
- Receber
{ challenge: "..." }no corpo. - Buscar o registro do
challengeno KV. - Se não existir: Retornar (200 OK) com
{ status: "expired" }. - Se existir:
status: "pending": Retornar (200 OK) com{ status: "pending" }.status: "completed":- Gerar um Token de Sessão (JWT) para o usuário (armazenado no KV em
{ user: ... }). - Opcional: Limpar o registro do KV.
- Retornar (200 OK) com
{ status: "completed", token: "jwt_gerado", user: { ...dados do usuário... } }.
- Gerar um Token de Sessão (JWT) para o usuário (armazenado no KV em
- Receber