docs: create Codigos/GPT-2

This commit is contained in:
2026-07-24 19:37:20 +00:00
committed by Bruno Santos
parent 3280545920
commit 608f37edc6

997
Codigos/GPT-2.md Normal file
View File

@@ -0,0 +1,997 @@
---
title: Gpt 2
description:
published: true
date: 2026-07-24T19:37:15.466Z
tags:
editor: markdown
dateCreated: 2026-07-24T19:37:15.466Z
---
# Guia de Estudo: Meu GPT v2 em LXC no Proxmox
Este documento descreve como evoluir o projeto original para uma aplicacao web multiusuario com:
- cadastro e login;
- usuarios salvos em banco de dados;
- historico de conversas;
- upload de arquivos;
- controle de consumo e custo por usuario;
- painel administrativo;
- hospedagem em um container LXC no Proxmox.
> Importante: a aplicacao usa a **OpenAI API**, cuja cobranca e separada da assinatura do ChatGPT. A chave da API pertence ao administrador da aplicacao e deve permanecer somente no servidor.
## 1. Resultado esperado
O usuario acessa a aplicacao pelo navegador, cria uma conta ou entra com seu login e conversa com o GPT. As conversas ficam salvas e podem ser abertas novamente. O usuario pode anexar arquivos e consultar seu consumo.
O administrador pode:
- ativar e desativar usuarios;
- definir limite mensal individual;
- consultar consumo por usuario;
- consultar quantidade de tokens e custo estimado;
- impedir novas chamadas quando o limite for atingido;
- escolher quais modelos ficam disponiveis.
## 2. Arquitetura proposta
```text
Navegador
|
| HTTPS
v
Nginx no LXC
|
v
Next.js
|-- telas React
|-- login e sessoes
|-- API de chat
|-- API de upload
|-- regras de limite
|
|----------> PostgreSQL
| |-- usuarios
| |-- conversas
| |-- mensagens
| |-- anexos
| |-- consumo
|
|----------> armazenamento privado no LXC
| |-- arquivos enviados
|
`----------> OpenAI Responses API
|-- respostas do modelo
|-- leitura de arquivos compativeis
`-- contagem de tokens
```
## 3. Tecnologias escolhidas e por que usa-las
### Next.js e React
O Next.js continua sendo a aplicacao principal. Ele permite criar as telas e as rotas de backend no mesmo projeto.
O React cuida das partes interativas da tela:
- lista de conversas;
- envio de mensagens;
- indicador de resposta;
- selecao e upload de arquivos;
- tela de consumo.
### TypeScript
O TypeScript reduz erros ao definir claramente o formato de usuarios, mensagens, anexos e registros de consumo.
Exemplo:
```ts
type Message = {
id: string;
role: "USER" | "ASSISTANT";
content: string;
};
```
### PostgreSQL
O PostgreSQL sera o banco de dados. Ele e adequado para dados relacionados, por exemplo:
- um usuario possui varias conversas;
- uma conversa possui varias mensagens;
- uma mensagem pode possuir varios anexos;
- cada chamada da API gera um registro de consumo.
Para estudo e para uma instalacao pequena, o PostgreSQL pode rodar no mesmo LXC. Em um ambiente maior, pode ser movido para outro container.
### Prisma ORM
O Prisma faz a comunicacao entre o TypeScript e o PostgreSQL.
Em vez de escrever SQL para cada operacao, o projeto pode usar:
```ts
const conversations = await prisma.conversation.findMany({
where: { userId },
orderBy: { updatedAt: "desc" },
});
```
As migrations do Prisma tambem registram as alteracoes feitas na estrutura do banco.
### Auth.js
O Auth.js sera responsavel pelo fluxo de autenticacao e pela sessao do usuario. Neste projeto:
- o usuario informa e-mail e senha;
- a aplicacao procura o usuario no PostgreSQL;
- a senha e comparada com o hash salvo;
- uma sessao assinada identifica o usuario nas proximas requisicoes.
A senha nunca deve ser salva em texto puro. Use `bcryptjs` ou `argon2` para gerar o hash.
### Armazenamento de arquivos
Na primeira versao, os arquivos podem ser armazenados em uma pasta privada do LXC:
```text
/var/lib/meu-gpt/uploads
```
Essa pasta nao deve ficar dentro de `public/`, pois isso permitiria tentar acessar o arquivo diretamente por URL.
Os metadados ficam no PostgreSQL, mas o conteudo fica no disco. Mais tarde, o armazenamento pode ser trocado por MinIO ou outro servico compativel com S3.
### Nginx, PM2 e HTTPS
- **Nginx** recebe os acessos HTTPS e encaminha para o Next.js.
- **PM2** mantem o processo do Next.js em execucao.
- **Certbot e Let's Encrypt** fornecem o certificado HTTPS.
## 4. Estrutura sugerida do projeto
```text
meu-gpt/
|-- app/
| |-- (auth)/
| | |-- login/page.tsx
| | `-- cadastro/page.tsx
| |-- (app)/
| | |-- chat/[conversationId]/page.tsx
| | |-- configuracoes/page.tsx
| | `-- consumo/page.tsx
| |-- admin/
| | |-- usuarios/page.tsx
| | `-- consumo/page.tsx
| `-- api/
| |-- auth/[...nextauth]/route.ts
| |-- register/route.ts
| |-- conversations/route.ts
| |-- conversations/[id]/messages/route.ts
| |-- upload/route.ts
| `-- admin/users/[id]/route.ts
|-- components/
|-- lib/
| |-- auth.ts
| |-- prisma.ts
| |-- openai.ts
| |-- permissions.ts
| |-- pricing.ts
| `-- storage.ts
|-- prisma/
| `-- schema.prisma
|-- private-uploads/
|-- middleware.ts
|-- .env
`-- package.json
```
Em producao, use `/var/lib/meu-gpt/uploads` em vez de `private-uploads/`.
## 5. Modelo de dados
O modelo abaixo e um ponto de partida. Ele pode ser ajustado durante a implementacao.
```prisma
enum UserRole {
USER
ADMIN
}
enum UserStatus {
ACTIVE
BLOCKED
}
enum MessageRole {
USER
ASSISTANT
SYSTEM
}
enum UsageStatus {
SUCCESS
ERROR
}
model User {
id String @id @default(cuid())
name String
email String @unique
passwordHash String
role UserRole @default(USER)
status UserStatus @default(ACTIVE)
monthlyLimitUsd Decimal @default(5.00) @db.Decimal(12, 4)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
conversations Conversation[]
usageRecords UsageRecord[]
attachments Attachment[]
}
model Conversation {
id String @id @default(cuid())
userId String
title String @default("Nova conversa")
model String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
archivedAt DateTime?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
messages Message[]
usageRecords UsageRecord[]
@@index([userId, updatedAt])
}
model Message {
id String @id @default(cuid())
conversationId String
role MessageRole
content String @db.Text
openaiResponseId String?
createdAt DateTime @default(now())
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
attachments Attachment[]
@@index([conversationId, createdAt])
}
model Attachment {
id String @id @default(cuid())
userId String
messageId String?
originalName String
storedName String
mimeType String
sizeBytes Int
sha256 String
openaiFileId String?
createdAt DateTime @default(now())
deletedAt DateTime?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
message Message? @relation(fields: [messageId], references: [id], onDelete: SetNull)
@@index([userId, createdAt])
}
model UsageRecord {
id String @id @default(cuid())
userId String
conversationId String?
model String
inputTokens Int @default(0)
cachedInputTokens Int @default(0)
outputTokens Int @default(0)
reasoningTokens Int @default(0)
totalTokens Int @default(0)
costUsd Decimal @default(0) @db.Decimal(18, 8)
status UsageStatus
requestId String?
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
conversation Conversation? @relation(fields: [conversationId], references: [id], onDelete: SetNull)
@@index([userId, createdAt])
}
```
## 6. Instalacao no LXC
### Recursos recomendados
Para poucos usuarios:
```text
Sistema: Debian 12 ou Ubuntu 24.04
CPU: 2 a 4 cores
RAM: 4 GB
Disco: 30 GB ou mais
Container nao privilegiado: sim
Inicializar no boot: sim
```
O tamanho do disco depende principalmente dos uploads e dos backups.
### Instalar os pacotes
```bash
apt update
apt upgrade -y
apt install -y curl git nginx postgresql postgresql-contrib ca-certificates
```
Instale uma versao LTS do Node.js compativel com as versoes atuais do Next.js e do Prisma escolhidas no momento da instalacao.
Confirme:
```bash
node -v
npm -v
psql --version
```
### Criar banco e usuario
Entre no PostgreSQL:
```bash
sudo -u postgres psql
```
Execute, substituindo a senha:
```sql
CREATE USER meu_gpt_user WITH ENCRYPTED PASSWORD 'COLOQUE_UMA_SENHA_FORTE';
CREATE DATABASE meu_gpt OWNER meu_gpt_user;
\q
```
O PostgreSQL pode continuar aceitando conexoes somente do proprio LXC.
### Instalar dependencias do projeto
Dentro da pasta do projeto:
```bash
npm install openai next-auth bcryptjs zod
npm install prisma @prisma/client
npm install -D @types/bcryptjs
```
Bibliotecas opcionais:
```bash
npm install file-type
```
`zod` valida os dados recebidos. `file-type` ajuda a conferir o tipo real do arquivo, em vez de confiar somente no nome informado pelo navegador.
## 7. Variaveis de ambiente
Exemplo de `.env`:
```env
DATABASE_URL="postgresql://meu_gpt_user:SENHA_FORTE@127.0.0.1:5432/meu_gpt"
AUTH_SECRET="GERE_UMA_CHAVE_LONGA_E_ALEATORIA"
AUTH_URL="https://gpt.seudominio.com"
OPENAI_API_KEY="SUA_CHAVE_DA_API"
OPENAI_MODEL="MODELO_PERMITIDO_PELA_SUA_CONTA"
UPLOAD_DIR="/var/lib/meu-gpt/uploads"
MAX_UPLOAD_BYTES="10485760"
DEFAULT_MONTHLY_LIMIT_USD="5.00"
```
Gere o segredo da autenticacao com:
```bash
openssl rand -base64 32
```
Regras:
- nao envie `.env` para Git;
- nunca use variavel iniciada por `NEXT_PUBLIC_` para a chave da OpenAI;
- deixe o arquivo legivel apenas pelo usuario que executa a aplicacao;
- troque imediatamente qualquer segredo que tenha sido exposto.
## 8. Cadastro e login
### Cadastro
O endpoint de cadastro deve:
1. validar nome, e-mail e senha com `zod`;
2. normalizar o e-mail para letras minusculas;
3. exigir uma senha com tamanho minimo;
4. verificar se o e-mail ja existe;
5. gerar o hash da senha;
6. criar o usuario com limite mensal padrao;
7. nunca devolver `passwordHash` na resposta.
Exemplo do hash:
```ts
import bcrypt from "bcryptjs";
const passwordHash = await bcrypt.hash(password, 12);
```
### Login
No login:
1. procure o usuario pelo e-mail;
2. verifique se ele esta ativo;
3. compare a senha informada com o hash;
4. crie uma sessao contendo somente os identificadores necessarios;
5. redirecione para a tela de chat.
```ts
const validPassword = await bcrypt.compare(password, user.passwordHash);
```
Proteja todas as rotas de chat, upload, historico e consumo. O backend deve obter o `userId` da sessao; nunca aceite um `userId` enviado pelo navegador como prova de identidade.
### Cadastro publico ou controlado
Para uma aplicacao pessoal ou empresarial, e mais seguro escolher uma destas opcoes:
- somente o administrador cria usuarios;
- cadastro exige um codigo de convite;
- cadastro publico exige verificacao de e-mail.
Nao deixe cadastro publico ilimitado em uma aplicacao que usa sua chave da API.
## 9. Historico de conversas
### Fluxo
1. O usuario cria uma conversa.
2. A aplicacao cria um registro `Conversation`.
3. A mensagem do usuario e salva em `Message`.
4. O backend carrega as mensagens anteriores daquela conversa.
5. O backend chama a OpenAI.
6. A resposta e salva como outra `Message`.
7. O registro de consumo e salvo.
8. A tela atualiza a lista e o horario da conversa.
### Regra de propriedade
Toda consulta deve combinar o identificador da conversa com o usuario autenticado:
```ts
const conversation = await prisma.conversation.findFirst({
where: {
id: conversationId,
userId: session.user.id,
},
});
```
Buscar somente pelo `conversationId` criaria uma falha de seguranca: um usuario poderia tentar abrir a conversa de outro usuario alterando a URL.
### Contexto enviado ao modelo
Nao envie para a API todas as mensagens de uma conversa sem limite. Conversas grandes:
- aumentam o custo;
- ficam mais lentas;
- podem ultrapassar o limite de contexto do modelo.
Uma estrategia inicial e enviar as mensagens mais recentes. Depois, implemente resumo automatico das mensagens antigas e armazene esse resumo na conversa.
## 10. Upload de arquivos
### Fluxo seguro
1. exigir usuario autenticado;
2. limitar o tamanho;
3. permitir somente extensoes e tipos necessarios;
4. conferir o tipo real do arquivo;
5. gerar nome aleatorio para armazenamento;
6. calcular SHA-256;
7. salvar fora da pasta publica;
8. registrar os metadados no banco;
9. enviar para a OpenAI apenas quando for usado em uma mensagem;
10. apagar arquivos temporarios e arquivos remotos quando nao forem mais necessarios.
Exemplo de nome fisico:
```text
/var/lib/meu-gpt/uploads/usuario-id/550e8400-e29b-41d4-a716-446655440000.pdf
```
O nome original fica no banco para ser exibido na interface, mas nao deve ser usado diretamente como caminho no disco.
### Tipos iniciais recomendados
Comece com poucos formatos:
- PDF;
- TXT;
- CSV;
- DOCX, se o fluxo escolhido oferecer suporte adequado;
- imagens PNG e JPEG, se o modelo selecionado aceitar imagens.
Defina um limite menor na propria aplicacao, por exemplo 10 MB, mesmo que a API aceite arquivos maiores. Isso protege o disco, a memoria e o custo.
### Dois usos diferentes de arquivos
**Arquivo anexado a uma pergunta:** o documento e enviado como entrada daquela mensagem. E a opcao mais simples para a primeira versao.
**Biblioteca permanente de documentos:** exige busca nos documentos, controle de permissoes, indexacao e normalmente uma estrategia de RAG ou busca em arquivos. Deve ser uma segunda fase.
## 11. Controle de custo por usuario
### Como medir
A resposta da OpenAI informa dados de uso, incluindo tokens de entrada, saida e total. O backend deve salvar esses valores em `UsageRecord`.
Exemplo conceitual:
```ts
const usage = response.usage;
await prisma.usageRecord.create({
data: {
userId,
conversationId,
model: response.model,
inputTokens: usage?.input_tokens ?? 0,
cachedInputTokens: usage?.input_tokens_details?.cached_tokens ?? 0,
outputTokens: usage?.output_tokens ?? 0,
reasoningTokens: usage?.output_tokens_details?.reasoning_tokens ?? 0,
totalTokens: usage?.total_tokens ?? 0,
costUsd: calculatedCost,
status: "SUCCESS",
requestId: response.id,
},
});
```
Os nomes exatos dos campos devem ser conferidos na versao do SDK instalada.
### Como calcular
Mantenha no backend uma tabela de precos por modelo:
```ts
type ModelPrice = {
inputUsdPerMillion: number;
cachedInputUsdPerMillion?: number;
outputUsdPerMillion: number;
};
```
Formula geral:
```text
custo de entrada =
tokens de entrada cobraveis / 1.000.000 x preco de entrada
custo de entrada em cache =
tokens em cache / 1.000.000 x preco de cache
custo de saida =
tokens de saida / 1.000.000 x preco de saida
custo total =
entrada + cache + saida
```
Nao grave valores monetarios usando `float`. Use `Decimal` no banco para evitar erros de arredondamento.
Os precos mudam. Por isso:
- nao espalhe precos pelo codigo;
- mantenha uma unica tabela de configuracao;
- registre o modelo usado em cada chamada;
- revise os precos na pagina oficial antes de atualizar;
- trate o valor mostrado como estimativa interna e reconcilie-o periodicamente com o painel da OpenAI.
### Verificacao do limite
Antes de chamar a API:
```ts
const startOfMonth = new Date(
new Date().getFullYear(),
new Date().getMonth(),
1,
);
const usage = await prisma.usageRecord.aggregate({
where: {
userId,
status: "SUCCESS",
createdAt: { gte: startOfMonth },
},
_sum: { costUsd: true },
});
```
Se o total for maior ou igual ao limite, a API deve responder:
```json
{
"error": "Limite mensal atingido"
}
```
Use o status HTTP `429` para indicar que o limite de uso foi atingido.
### Evitar que chamadas simultaneas ultrapassem o limite
Uma simples verificacao antes da chamada nao e suficiente quando o mesmo usuario envia varias requisicoes ao mesmo tempo.
Para um limite mais rigido:
- permita somente uma geracao ativa por usuario; ou
- reserve um valor estimado antes da chamada em uma transacao;
- ao terminar, substitua a reserva pelo custo real;
- libere a reserva se a chamada falhar.
Tambem defina `max_output_tokens` para limitar o tamanho e o custo maximo da resposta.
### O painel de consumo
Mostre ao usuario:
- consumo do mes;
- limite mensal;
- percentual utilizado;
- tokens de entrada e saida;
- consumo por conversa;
- modelo utilizado;
- data de renovacao do limite.
O administrador deve visualizar os mesmos dados para todos os usuarios.
## 12. Fluxo da rota de chat
Uma rota segura segue esta ordem:
```text
1. Validar a sessao
2. Validar os dados recebidos
3. Confirmar que a conversa pertence ao usuario
4. Confirmar que o usuario esta ativo
5. Conferir o limite mensal
6. Salvar a mensagem do usuario
7. Preparar contexto e anexos
8. Chamar a OpenAI
9. Salvar a resposta
10. Salvar tokens e custo
11. Devolver a resposta ao navegador
```
Pseudoimplementacao:
```ts
export async function POST(request: Request) {
const session = await requireSession();
const input = chatSchema.parse(await request.json());
const conversation = await findOwnedConversation(
input.conversationId,
session.user.id,
);
await assertUserCanSpend(session.user.id);
const userMessage = await saveUserMessage(conversation.id, input);
try {
const response = await createOpenAIResponse({
conversation,
userMessage,
});
const calculatedCost = calculateCost(response.model, response.usage);
await saveAssistantMessageAndUsage({
userId: session.user.id,
conversationId: conversation.id,
response,
calculatedCost,
});
return Response.json({ text: response.output_text });
} catch (error) {
await saveFailedUsage(session.user.id, conversation.id);
throw error;
}
}
```
No codigo real, salve a mensagem do assistente e o consumo na mesma transacao do banco.
## 13. Painel administrativo
Crie uma area acessivel somente quando:
```ts
session.user.role === "ADMIN"
```
Funcoes iniciais:
- listar usuarios;
- bloquear e desbloquear;
- alterar limite mensal;
- promover um usuario a administrador;
- consultar consumo por periodo;
- consultar erros;
- excluir ou anonimizar um usuario;
- apagar anexos e conversas conforme a politica definida.
Toda alteracao administrativa importante deve gerar um registro de auditoria em uma futura tabela `AuditLog`.
## 14. Seguranca essencial
Antes de publicar:
- use HTTPS;
- mantenha a chave da OpenAI somente no servidor;
- use hash forte de senha;
- aplique limite de tentativas no login;
- aplique limite de requisicoes no chat e upload;
- valide todos os dados com `zod`;
- confira a propriedade de cada conversa e arquivo;
- limite tamanho e tipo dos uploads;
- use nomes aleatorios no disco;
- nao renderize HTML recebido do modelo sem sanitizacao;
- configure cookies como `HttpOnly`, `Secure` e `SameSite`;
- bloqueie usuarios desativados em todas as APIs;
- mantenha dependencias atualizadas;
- faca backup criptografado;
- nunca inclua segredos nos logs;
- defina politica de retencao e exclusao de dados.
Se a aplicacao ficar acessivel somente por VPN, a superficie de ataque diminui, mas login e autorizacao continuam necessarios.
## 15. Preparar armazenamento no LXC
Exemplo:
```bash
mkdir -p /var/lib/meu-gpt/uploads
chown -R meu-gpt:meu-gpt /var/lib/meu-gpt
chmod 750 /var/lib/meu-gpt
chmod 750 /var/lib/meu-gpt/uploads
```
O usuario Linux `meu-gpt` deve ser o mesmo que executa o processo da aplicacao.
Evite executar a aplicacao como `root`.
## 16. Migrations e primeira conta administrativa
Depois de configurar o Prisma:
```bash
npx prisma generate
npx prisma migrate dev --name auth_history_upload_usage
```
Em producao, aplique migrations ja criadas:
```bash
npx prisma migrate deploy
```
Crie um script de seed para a primeira conta administrativa. A senha deve vir de uma variavel de ambiente temporaria, ser transformada em hash e nunca aparecer no repositorio.
## 17. Build e execucao
```bash
npm run build
pm2 start npm --name meu-gpt -- start
pm2 save
pm2 startup
```
Use o comando exibido pelo `pm2 startup` para ativar o inicio automatico.
Consulte logs:
```bash
pm2 logs meu-gpt
```
Os logs devem conter IDs de requisicao e mensagens de erro, mas nao senhas, tokens de sessao, chave da API ou conteudo confidencial dos arquivos.
## 18. Nginx
Exemplo basico:
```nginx
server {
listen 80;
server_name gpt.seudominio.com;
client_max_body_size 10M;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
O limite do Nginx deve ser igual ou ligeiramente maior que o limite configurado na aplicacao.
Depois:
```bash
nginx -t
systemctl reload nginx
certbot --nginx -d gpt.seudominio.com
```
## 19. Backup
O backup precisa incluir:
- banco PostgreSQL;
- pasta de uploads;
- arquivos de configuracao;
- migrations do Prisma.
Exemplo de backup do banco:
```bash
sudo -u postgres pg_dump -Fc meu_gpt > /var/backups/meu-gpt-db.dump
```
Nao basta criar o backup. Teste periodicamente a restauracao em outro banco ou container.
Considere snapshots do LXC como protecao adicional, mas mantenha tambem backups independentes do Proxmox.
## 20. Ordem recomendada de implementacao
### Fase 1: banco e login
- instalar PostgreSQL;
- adicionar Prisma;
- criar `User`;
- criar cadastro controlado;
- implementar login e logout;
- proteger as rotas.
### Fase 2: historico
- criar `Conversation` e `Message`;
- criar lista lateral;
- abrir, renomear, arquivar e excluir conversa;
- validar propriedade em todas as rotas.
### Fase 3: consumo
- criar `UsageRecord`;
- registrar tokens retornados pela OpenAI;
- centralizar precos;
- exibir consumo mensal;
- bloquear chamadas acima do limite;
- tratar requisicoes simultaneas.
### Fase 4: arquivos
- criar `Attachment`;
- adicionar upload privado;
- validar arquivo;
- anexar arquivo a uma mensagem;
- configurar exclusao e retencao.
### Fase 5: administracao e operacao
- criar painel administrativo;
- adicionar auditoria;
- configurar backups;
- configurar rate limit;
- revisar logs e alertas;
- testar restauracao.
## 21. Testes necessarios
### Autenticacao
- cadastro com e-mail duplicado;
- senha incorreta;
- usuario bloqueado;
- rota privada sem sessao;
- usuario comum tentando abrir o painel administrativo.
### Autorizacao
- usuario A tentando abrir conversa do usuario B;
- usuario A tentando baixar anexo do usuario B;
- alteracao manual de IDs na URL e no corpo da requisicao.
### Consumo
- chamada registra tokens;
- custo usa o modelo correto;
- limite bloqueia nova chamada;
- mudanca de mes reinicia a soma;
- duas chamadas simultaneas nao ultrapassam o limite rigido;
- erro da OpenAI nao e cobrado incorretamente pelo sistema.
### Upload
- arquivo acima do limite;
- extensao permitida com conteudo de outro tipo;
- nome contendo `../`;
- arquivo vazio;
- arquivo de outro usuario;
- exclusao do arquivo local e do registro correspondente.
## 22. Melhorias futuras
- verificacao de e-mail;
- recuperacao de senha;
- autenticacao em dois fatores;
- login corporativo;
- streaming da resposta;
- busca nas conversas;
- exportacao de conversa;
- RAG para biblioteca de documentos;
- MinIO para armazenamento;
- Redis para rate limit e controle de concorrencia;
- antivirus para uploads;
- alertas de consumo;
- observabilidade e auditoria;
- separacao do PostgreSQL em outro LXC.
## 23. O que muda em relacao ao projeto original
| Parte | Projeto original | Projeto v2 |
|---|---|---|
| Acesso | Uma senha compartilhada | Conta individual e sessao |
| Usuarios | Nao possui | Salvos no PostgreSQL |
| Conversas | Somente na tela | Salvas no banco |
| Arquivos | Nao possui | Upload privado e metadados |
| Custos | Sem controle individual | Tokens e custo por usuario |
| Administracao | Nao possui | Usuarios, limites e consumo |
| Seguranca | Basica | Autenticacao, autorizacao e rate limit |
| Backup | Nao detalhado | Banco, arquivos e restauracao |
## 24. Referencias para estudo
- [OpenAI: inicio rapido da API](https://platform.openai.com/docs/quickstart)
- [OpenAI: referencia da Responses API](https://platform.openai.com/docs/api-reference/responses)
- [OpenAI: arquivos](https://platform.openai.com/docs/api-reference/files)
- [OpenAI: uso da API](https://platform.openai.com/docs/api-reference/usage)
- [OpenAI: precos da API](https://openai.com/api/pricing/)
- [OpenAI: controles e retencao de dados](https://platform.openai.com/docs/models/default-usage-policies-by-endpoint)
- [Next.js: Route Handlers](https://nextjs.org/docs/app/getting-started/route-handlers)
- [Prisma: integracao com Next.js](https://www.prisma.io/docs/guides/frameworks/nextjs)
- [Auth.js: documentacao](https://authjs.dev/)
- [PostgreSQL: documentacao](https://www.postgresql.org/docs/)
## 25. Resumo
A evolucao principal e transformar uma pagina de chat protegida por senha em um sistema multiusuario.
O Next.js continua cuidando das telas e do backend. O PostgreSQL passa a guardar usuarios, conversas, mensagens, anexos e consumo. O Prisma facilita o acesso ao banco. O Auth.js cuida do login e da sessao. Os arquivos ficam em uma pasta privada, e cada resposta da OpenAI gera um registro de tokens e custo.
A melhor ordem de aprendizado e:
```text
login -> historico -> consumo -> upload -> painel administrativo
```
Essa ordem permite testar cada parte antes de adicionar a proxima e reduz a dificuldade de encontrar erros.