diff --git a/agents.md b/agents.md index d21b4a2..362b841 100644 --- a/agents.md +++ b/agents.md @@ -37,12 +37,21 @@ 1) Coleta perfil (hostname/OS/MAC/seriais/métricas). 2) Provisiona via `POST /api/machines/register` com `MACHINE_PROVISIONING_SECRET`, solicitando o **perfil de acesso** (Colaborador ou Gestor) e os dados do usuário associado. O backend garante a vinculação única da máquina ao colaborador ou gestor informado. 3) Envia heartbeats a cada 5 min para `/api/machines/heartbeat` com inventário básico + estendido (discos, GPUs, serviços, softwares). - 4) Abre `APP_URL/machines/handshake?token=...&redirect=...` para autenticar a sessão: colaboradores são direcionados ao portal (`/portal`), gestores ao painel completo (`/dashboard`). + 4) Abre `APP_URL/machines/handshake?token=...&redirect=...` para autenticar a sessão: colaboradores são direcionados ao portal (`/portal`), gestores ao painel completo (`/dashboard`). A rota de handshake é pública no middleware para permitir a criação da sessão sem login prévio. - Segurança: token salvo no cofre do SO (Keyring). Store guarda apenas metadados não sensíveis. - Endpoint extra: `POST /api/machines/inventory` (atualiza inventário por token ou provisioningSecret). - Atualizações automáticas: o plugin `@tauri-apps/plugin-updater` verifica `latest.json` nos releases do GitHub. Publicar uma nova release com manifestos atualiza os clientes sem reinstalação manual. - Ajustes administrativos: em **Admin ▸ Máquinas** é possível vincular ou alterar o perfil (colaborador/gestor) e e-mail associado através do botão “Ajustar acesso”. +### Sessão "machine" no frontend +- Ao autenticar como `machine`, o frontend consulta `/api/machines/session` e popula `machineContext` (assignedUserId, email, name, persona). +- O Portal usa `machineContext.assignedUserId` como `viewerId` ao abrir chamados, permitindo que o colaborador/gestor abra tickets pelo desktop. +- Na UI interna, o menu do usuário (canto inferior do sidebar) oculta o botão "Encerrar sessão" quando a sessão é de máquina. + +### Sinalizador de desktop (opcional – futuro) +- Podemos adicionar um cookie (ex.: `desktop_shell=1`) no handshake para diferenciar acessos do app desktop de acessos web convencionais. +- Esse cookie permitiria customizações de UI específicas (ex.: ocultar "Sair" apenas no desktop) sem depender de heurísticas do ambiente. + ## Desenvolvimento local — boas práticas (atualizado) - Ambientes separados: mantenha seu `.env.local` só para DEV e o `.env` da VPS só para PROD. Nunca commitar arquivos `.env`. - Convex em DEV: rode `pnpm convex:dev` e aponte o front para `http://127.0.0.1:3210` via `NEXT_PUBLIC_CONVEX_URL`. diff --git a/apps/desktop/README.md b/apps/desktop/README.md index ecf8383..8567747 100644 --- a/apps/desktop/README.md +++ b/apps/desktop/README.md @@ -28,7 +28,25 @@ VITE_API_BASE_URL= - Build executável (bundle): - `pnpm -C apps/desktop tauri build` -Saída dos pacotes: `apps/desktop/src-tauri/target/release/bundle/` (AppImage/deb/msi/dmg conforme SO). +Saída dos pacotes: `apps/desktop/src-tauri/target/release/bundle/`. + +### Windows (NSIS) — instalação e dados +- Instalador NSIS com suporte a “perMachine” (Arquivos de Programas) e diretório customizável (ex.: `C:\Raven`). +- Atalho é criado na Área de Trabalho apontando para o executável instalado. +- Dados do app (token/config) ficam em AppData local do usuário (via `@tauri-apps/plugin-store` com `appLocalDataDir`). + +Build rápido e leve em dev: +```bash +pnpm -C apps/desktop tauri build --bundles nsis +``` + +Assinatura do updater (opcional em dev): +```powershell +$privB64 = '' +$env:TAURI_SIGNING_PRIVATE_KEY = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($privB64)) +$env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD = 'SENHA_AQUI' +pnpm -C apps/desktop tauri build --bundles nsis +``` ## Pré‑requisitos Tauri - Rust toolchain instalado. diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 9f8a208..26b1024 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -38,16 +38,20 @@ "bundle": { "active": true, "createUpdaterArtifacts": true, - "targets": [ - "deb", - "rpm", - "nsis" - ], + "targets": ["nsis", "deb", "rpm"], "icon": [ "icons/icon.ico", "icons/icon.icns", "icons/icon.png", "icons/Raven.png" - ] + ], + "windows": { + "nsis": { + "installMode": "perMachine", + "allowToChangeInstallDirectory": true, + "installDirName": "Raven", + "createDesktopShortcut": true + } + } } } diff --git a/apps/desktop/src/main.tsx b/apps/desktop/src/main.tsx index 57c07d9..3b33e93 100644 --- a/apps/desktop/src/main.tsx +++ b/apps/desktop/src/main.tsx @@ -3,6 +3,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react" import { createRoot } from "react-dom/client" import { invoke } from "@tauri-apps/api/core" import { Store } from "@tauri-apps/plugin-store" +import { appLocalDataDir } from "@tauri-apps/api/path" import { ExternalLink, Eye, EyeOff, GalleryVerticalEnd, Loader2, RefreshCw } from "lucide-react" import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs" import { cn } from "./lib/utils" @@ -103,7 +104,8 @@ const appUrl = normalizeUrl(import.meta.env.VITE_APP_URL, DEFAULT_APP_URL) const apiBaseUrl = normalizeUrl(import.meta.env.VITE_API_BASE_URL, appUrl) async function loadStore(): Promise { - return await Store.load(STORE_FILENAME) + const dir = await appLocalDataDir() + return await Store.load(STORE_FILENAME, { dir }) } async function readToken(store: Store): Promise { diff --git a/docs/OPERACAO-PRODUCAO.md b/docs/OPERACAO-PRODUCAO.md index b0693da..031221a 100644 --- a/docs/OPERACAO-PRODUCAO.md +++ b/docs/OPERACAO-PRODUCAO.md @@ -11,6 +11,12 @@ - Seeds prontos (Better Auth e dados demo Convex). - Seeds Better Auth automáticos: o container do web executa `pnpm auth:seed` após `prisma migrate deploy`, garantindo usuários padrão em toda inicialização (sem resetar senha existente por padrão). +### Sessão de máquina (Desktop/Tauri) +- A rota `GET /machines/handshake?token=...&redirect=/portal|/dashboard` é pública no middleware para permitir a criação da sessão "machine" a partir do agente desktop, mesmo sem login prévio. +- Após o handshake, o servidor grava cookies de sessão (Better Auth) e um cookie `machine_ctx` com o vínculo (persona, assignedUser*, etc.). Em seguida, o App carrega `/api/machines/session` para preencher o contexto no cliente (`machineContext`). +- Com esse contexto, o Portal exibe corretamente o nome/e‑mail do colaborador/gestor no cabeçalho e permite abrir chamados em nome do usuário vinculado. +- Em sessões de máquina, o botão "Encerrar sessão" no menu do usuário é ocultado por padrão na UI interna. + ## Requisitos - VPS com Docker/Swarm e Traefik já em execução na rede externa `traefik_public`. - Portainer opcional (para gerenciar a stack “sistema”).