# Especificação Técnica — Sistema de Geração de QR Code (SaaS)

Stack: **PHP 8.2+ / Laravel 11 / MySQL 8** — hospedagem em VPS próprio (Nginx + PHP-FPM + Supervisor).

---

## 1. Visão Geral

Plataforma multiusuário onde:
- Um **Admin master** gerencia todos os clientes, cotas e usuários da plataforma.
- Cada **Cliente** possui uma conta com logo, dados cadastrais e uma cota de QR Codes.
- Cada Cliente pode ter **Editores** vinculados, que criam/editam QR Codes em nome da conta.
- QR Codes podem ser **dinâmicos** (o destino pode ser alterado sem reimprimir o código) ou **estáticos**.

---

## 2. Papéis e Permissões

| Ação | Admin master | Cliente | Editor |
|---|---|---|---|
| Login no sistema | ✅ | ✅ | ✅ |
| Ver todos os clientes | ✅ | ❌ | ❌ |
| Ver/editar cota de QR Codes | ✅ | ❌ (vê só "restam X de Y" se você decidir expor) | ❌ |
| Cadastrar novo cliente | ✅ | ❌ | ❌ |
| Cadastrar editores na própria conta | ✅ | ✅ | ❌ |
| Criar/editar/excluir QR Code | ✅ | ✅ (dentro da cota) | ✅ (dentro da cota da conta) |
| Ver QR Codes de outras contas | ✅ | ❌ | ❌ |
| Baixar SVG | ✅ | ✅ | ✅ |
| Ver estatísticas de leitura (scans) | ✅ | ✅ | ✅ |

> Observação de segurança: a cota (`qrcode_quota` / `qrcode_used`) **nunca** deve ser retornada pela API para usuários com papel `cliente` ou `editor` — isso é reforçado tanto no Policy quanto no Resource/Transformer da API (ver seção 6).

---

## 3. Modelo de Dados

### 3.1 `users`
| Campo | Tipo | Observação |
|---|---|---|
| id | bigint PK | |
| name | varchar | |
| email | varchar unique | login |
| password | varchar | hash bcrypt |
| phone | varchar | telefone/WhatsApp, formato E.164 |
| document | varchar | CPF ou CNPJ — **criptografado em repouso** (cast `encrypted`) |
| document_type | enum(cpf,cnpj) | |
| logo_path | varchar nullable | caminho do SVG da logo |
| role | enum(admin_master,cliente,editor) | |
| parent_client_id | bigint FK nullable → users.id | preenchido quando `role = editor`, aponta para o Cliente dono da conta |
| qrcode_quota | int default 0 | só admin master edita/visualiza |
| qrcode_used | int default 0 | contador, atualizado a cada criação |
| is_active | boolean default true | permite bloquear conta sem excluir |
| email_verified_at | timestamp nullable | |
| timestamps | | |

### 3.2 `qr_codes`
| Campo | Tipo | Observação |
|---|---|---|
| id | bigint PK | |
| owner_id | bigint FK → users.id | Cliente dono (mesmo se criado por um editor) |
| created_by | bigint FK → users.id | quem efetivamente criou/editou por último |
| type | enum | `url, vcard, wifi, whatsapp, pix, text, pdf, social_links` |
| title | varchar | nome interno do QR ("Cardápio - Loja Centro") |
| short_code | varchar(10) unique | usado na URL curta de redirecionamento (base62) |
| target_payload | json | dados específicos do tipo (ver seção 4) |
| is_dynamic | boolean default true | dinâmico = redireciona via short_code; estático = payload direto no QR |
| design | json | cor primária/secundária, estilo dos "olhos", nível de correção de erro, logo_id |
| svg_cache_path | varchar nullable | último SVG gerado, para download rápido |
| is_active | boolean default true | permite pausar um QR sem excluir |
| expires_at | timestamp nullable | expiração opcional |
| scans_count | int default 0 | contador desnormalizado para listagem rápida |
| timestamps | | |

### 3.3 `qr_code_scans` (analytics)
| Campo | Tipo |
|---|---|
| id | bigint PK |
| qr_code_id | FK |
| ip_address | varchar |
| user_agent | varchar |
| referrer | varchar nullable |
| country / city | varchar nullable (via geoip opcional) |
| scanned_at | timestamp |

### 3.4 Relacionamentos
- `User` 1—N `QrCode` (via `owner_id`)
- `User` (cliente) 1—N `User` (editores, via `parent_client_id`)
- `QrCode` 1—N `QrCodeScan`

---

## 4. Tipos de QR Code (payload em `target_payload`)

Boas práticas de mercado consideradas:

| Tipo | Conteúdo | Observação |
|---|---|---|
| **URL dinâmica** | `{ "url": "https://..." }` | redireciona via `short_code`; permite trocar destino sem reimprimir |
| **Cartão de visita (vCard)** | nome, empresa, cargo, telefones, e-mail, site | gera `.vcf`; ao escanear, salva contato direto na agenda |
| **WhatsApp (click-to-chat)** | número + mensagem pré-preenchida | formato `https://wa.me/55XXXXXXXXXXX?text=...` |
| **Wi-Fi** | SSID, senha, tipo de criptografia (WPA/WEP/nenhuma) | formato padrão `WIFI:T:WPA;S:ssid;P:senha;;` |
| **PIX (Brasil)** | payload copia-e-cola do BR Code | validar CRC16 do payload |
| **Texto simples** | texto livre | |
| **PDF / Cardápio / Documento** | upload do arquivo, o QR aponta para URL do storage | |
| **Social links / bio link** | lista de links (Instagram, site, WhatsApp) | página intermediária tipo "linktree" servida pelo próprio sistema |

**Todos os tipos acima devem preferencialmente ser dinâmicos** (exceto Wi-Fi e vCard estático simples), pois:
1. Permite trocar o destino sem reimprimir material físico.
2. Permite métricas de leitura (scans, data/hora, dispositivo aproximado).
3. Permite pausar/expirar o código remotamente.

---

## 5. Geração do SVG com logo (boas práticas)

- Biblioteca recomendada: **`endroid/qr-code`** (PHP), writer SVG nativo.
- **Nível de correção de erro: `H` (30%)** sempre que houver logo sobreposta — é o único nível que tolera obstrução central sem perda de leitura.
- Logo ocupando **no máximo ~20–22% da área total** do QR Code, centralizada, com margem (quiet zone) de segurança contra os módulos do QR.
- Se a logo do cliente for SVG, embutir como elemento `<image>` com o SVG codificado em base64 dentro do SVG final (mantém escalabilidade infinita, ideal para impressão).
- Manter **quiet zone mínima de 4 módulos** nas bordas (evita falhas de leitura por scanners de baixa qualidade).
- Garantir **contraste mínimo** entre cor de frente e fundo (recomendação: razão de contraste ≥ 4.5:1, evitar combinações claras sobre claras).
- Cachear o SVG gerado (`svg_cache_path`) e regenerar apenas quando design/logo/dados mudarem — evita reprocessamento a cada download.

Serviço de referência: `app/Services/QrCodeGeneratorService.php` (incluído no protótipo).

---

## 6. Rotas / API (resumo)

```
POST   /login
POST   /logout

# Admin master
GET    /admin/clients                  # lista todos os clientes + cota
POST   /admin/clients                  # cria cliente
PUT    /admin/clients/{id}/quota        # ajusta cota
PUT    /admin/clients/{id}              # edita cadastro

# Conta (cliente/editor)
GET    /users                          # lista editores da própria conta (só cliente)
POST   /users                          # cria editor (só cliente)

# QR Codes
GET    /qrcodes                        # lista (escopo automático por conta)
POST   /qrcodes                        # cria (valida cota antes)
PUT    /qrcodes/{id}                   # edita destino/design
DELETE /qrcodes/{id}
GET    /qrcodes/{id}/download-svg      # baixa SVG final com logo

# Redirecionamento público (sem autenticação)
GET    /r/{short_code}                 # registra scan + redireciona (301/302 conforme tipo)
```

A checagem de escopo (um cliente só vê os próprios QR Codes, e a cota nunca aparece para cliente/editor) é feita via **Laravel Policies** (`QrCodePolicy`, `UserPolicy`) e **API Resources** que omitem campos sensíveis conforme `auth()->user()->role`.

---

## 7. Segurança e Conformidade (LGPD)

- CPF/CNPJ armazenado com cast `encrypted` do Laravel (AES-256 via `APP_KEY`).
- Logs de acesso a dados de cadastro (quem visualizou/editou CPF/CNPJ de quem).
- Rate limiting nas rotas de login (`throttle:5,1`) e no redirecionamento público (`throttle:120,1` por IP) para mitigar scraping/abuso.
- 2FA opcional para Admin master (recomendado, não obrigatório no MVP).
- Backups diários do banco (mysqldump) + retenção de 30 dias no VPS.
- Termo de consentimento no cadastro, informando finalidade do uso de CPF/CNPJ e telefone.

---

## 8. Roadmap sugerido

1. **MVP**: auth, cadastro de cliente/editor, CRUD de QR Code tipo URL dinâmica e vCard, geração SVG com logo, redirecionamento com contagem de scans.
2. **V1.1**: tipos Wi-Fi, WhatsApp, PIX, PDF.
3. **V1.2**: dashboard de estatísticas (gráfico de scans por dia, dispositivo, localização aproximada).
4. **V1.3**: página "bio link" (social_links) hospedada no próprio domínio.
5. **V2**: planos/faturamento automático vinculado à cota, domínio customizado por cliente para os links curtos.

---

## 9. Próximos passos técnicos (para você no VPS)

```bash
composer create-project laravel/laravel qrcode-saas
cd qrcode-saas
composer require endroid/qr-code laravel/sanctum
# copiar os arquivos do protótipo anexado por cima desta estrutura
php artisan migrate
php artisan serve
```
