Mirror all SPECs and construction docs from pizza-digital, add hub/sidebar links and bidirectional sync scripts.
169 lines
6.4 KiB
Markdown
169 lines
6.4 KiB
Markdown
# SPEC — Matriz de Acesso (MVP)
|
||
|
||
| Campo | Valor |
|
||
|-------|--------|
|
||
| **Produto** | Pizza Digital |
|
||
| **Versão** | 0.1.0 |
|
||
| **Data** | 2026-10-19 |
|
||
| **Owner** | Roger / iTecnologys |
|
||
| **UI** | `/acessos` · Admin |
|
||
| **API** | `/api/access/*` |
|
||
| **Protótipo visual** | `acessos.html` (Codex 2026-10-19) — referência UX, **não** localStorage como auth |
|
||
| **Regras** | `matriz-de-acesso-mvp.md` + este doc |
|
||
|
||
---
|
||
|
||
## 1. Objetivo
|
||
|
||
Gestão de **permissões administrativas** do tenant (loja) selecionado: matriz Perfil × Capacidade, com rascunho, dependências, salvamento atômico e auditoria.
|
||
|
||
**Fora desta entrega:** Cozinha, Balcão, Despacho, Delivery, Estoque operacional · suporte irrestrito multi-tenant.
|
||
|
||
---
|
||
|
||
## 2. Modelo no Pizza Digital (estado real do repo)
|
||
|
||
| Conceito PRD / proposta | Implementação atual |
|
||
|-------------------------|---------------------|
|
||
| Tenant / loja | `Store` |
|
||
| Identity global | **Proposta futura.** MVP: credencial em `User` (email+hash) por loja |
|
||
| Vínculo funcionário–tenant | `User` (`storeId` + email único na loja) |
|
||
| Sessão | JWT com `sub`, `storeId`, `role` operacional — **capabilities são reconsultadas no Core** |
|
||
| Core = fonte da verdade | API Nest + Postgres |
|
||
| Admin (borda) | App React `apps/web` |
|
||
|
||
`UserRole` (`gestor` \| `pdv` \| `kds` \| `despacho`) permanece para **operação** (PDV/KDS). A matriz MVP **não** define essas permissões operacionais.
|
||
|
||
---
|
||
|
||
## 3. Capacidades (propostas → contrato MVP)
|
||
|
||
| ID | Área | Label PT-BR |
|
||
|----|------|-------------|
|
||
| `menu.view` | Cardápio | Visualizar cardápio |
|
||
| `menu.manage` | Cardápio | Editar cardápio |
|
||
| `staff.view` | Equipe | Visualizar funcionários |
|
||
| `staff.manage` | Equipe | Gerenciar funcionários comuns |
|
||
| `permissions.manage` | Equipe | Gerenciar permissões |
|
||
| `owners.manage` | Equipe | Gerenciar Donos |
|
||
| `finance.view` | Financeiro | Visualizar dashboard financeiro |
|
||
|
||
**Nota:** “Consultar auditoria do cardápio” **acompanha** `menu.view` — não é capability separada.
|
||
|
||
---
|
||
|
||
## 4. Perfis = **modelos de preenchimento** (não contrato fechado do PRD)
|
||
|
||
O PRD nomeia só **Dono**. Gestor / Cardápio / Financeiro são **propostas** desta implementação.
|
||
|
||
| Capacidade | Dono | Gestor | Cardápio | Financeiro |
|
||
|------------|:----:|:------:|:--------:|:----------:|
|
||
| `menu.view` | ■ | ■ | ■ | |
|
||
| `menu.manage` | ■ | ■ | ■ | |
|
||
| `staff.view` | ■ | ■ | | |
|
||
| `staff.manage` | ■ | ■ | | |
|
||
| `permissions.manage` | ■ | | | |
|
||
| `owners.manage` | ■ | | | |
|
||
| `finance.view` | ■ | ■ | | ■ |
|
||
|
||
### Como o modelo é aplicado ao vínculo
|
||
|
||
1. Matriz edita a **definição do modelo** por tenant (`AccessProfileTemplate`).
|
||
2. Permissões **efetivas** ficam em `UserCapability` (vínculo).
|
||
3. **Aplicar modelo** a um ou mais usuários é ação **explícita** (`POST /api/access/apply-template`) — nunca silenciosa ao salvar a matriz.
|
||
4. `User.profileTemplateKey` guarda só o último modelo aplicado (rótulo); mudar o template **não** atualiza quem já o usou até reaplicar.
|
||
|
||
---
|
||
|
||
## 5. Dependências (Core valida o conjunto completo)
|
||
|
||
1. `menu.manage` ⇒ exige `menu.view`
|
||
2. `staff.manage` \| `permissions.manage` \| `owners.manage` ⇒ exigem `staff.view`
|
||
3. `staff.manage` **não** implica promover, conceder permissões nem gerir Donos
|
||
4. Autor só concede capacidades que **ele próprio** possui (reconsulta Core)
|
||
5. `permissions.manage` **não** implica `owners.manage`
|
||
6. Último vínculo com `owners.manage` ativo **não** pode perder essa cap / ser desativado
|
||
7. Mudança de template/perfil que deixaria o tenant sem Dono → rejeitada **atomicamente**
|
||
8. Admin de tenant **não** altera email global nem define/redefine senhas (fora deste módulo; documentado)
|
||
9. `User.active=false` ⇒ sem acesso àquele tenant
|
||
|
||
UI explica auto-concessão/remoção de dependentes; servidor revalida no save.
|
||
|
||
---
|
||
|
||
## 6. API
|
||
|
||
| Método | Rota | Auth |
|
||
|--------|------|------|
|
||
| `GET` | `/api/access/me` | sessão — caps efetivas (sempre do DB) |
|
||
| `GET` | `/api/access/matrix` | `permissions.manage` |
|
||
| `PUT` | `/api/access/matrix` | `permissions.manage` · body + `If-Match` / `version` |
|
||
| `POST` | `/api/access/apply-template` | `permissions.manage` (+ caps do autor) |
|
||
|
||
`PUT` salva só **templates**. Efetivos mudam só via apply (ou seed inicial).
|
||
|
||
---
|
||
|
||
## 7. Persistência
|
||
|
||
- `AccessProfileTemplate` — storeId + key + capabilities[]
|
||
- `UserCapability` — userId + capability (efetivo)
|
||
- `User.profileTemplateKey` — opcional
|
||
- `AccessAuditLog` — autor, storeId, target, before/after, createdAt (**proposta** se PRD não fechou auditoria)
|
||
|
||
---
|
||
|
||
## 8. UI `/acessos`
|
||
|
||
- Colunas: perfis · Linhas: permissões agrupadas por área
|
||
- Busca · filtros área/perfil · célula toggle · contagem pendente
|
||
- Descartar / Salvar · loading / erro / sucesso / vazio / 403
|
||
- Responsivo, teclado, toque · PT-BR
|
||
|
||
localStorage **não** autoriza.
|
||
|
||
---
|
||
|
||
## 9. Migração (instruções — não rodar em produção sem revisão)
|
||
|
||
```bash
|
||
# lab / VM125
|
||
cd pizza-digital
|
||
docker compose exec api npx prisma migrate deploy
|
||
docker compose exec api npx prisma db seed # backfill caps do gestor
|
||
```
|
||
|
||
Arquivo: `apps/api/prisma/migrations/20261019190000_access_matrix/`
|
||
|
||
---
|
||
|
||
## 10. Decisões pendentes
|
||
|
||
1. Separar Identity global (email único multi-loja) do vínculo — ainda acoplado em `User`.
|
||
2. Colunas da matriz: só modelos vs. também funcionários (2ª vista).
|
||
3. Auditoria de permissões: proposta implementada; confirmar se PRD exige retenção/export.
|
||
4. Conjunto Dono “protegido” na UI vs. editável no Core — MVP: editável no Core com regra do último Dono; UI marca coluna Dono como sensível.
|
||
5. Aprovar nomes Gestor/Cardápio/Financeiro no PRD oficial.
|
||
|
||
---
|
||
|
||
## 11. Critérios de aceite → cobertura
|
||
|
||
| Critério | Como |
|
||
|----------|------|
|
||
| Autorizado consulta matriz | `GET /matrix` + UI |
|
||
| Sem permissão: UI + API | Guard `permissions.manage` |
|
||
| Busca/filtros não perdem rascunho | state local React |
|
||
| Descartar restaura | reload snapshot |
|
||
| Salvar só após 2xx | PUT atômico |
|
||
| Falha preserva rascunho | não limpa draft |
|
||
| Dependências FE+BE | `normalizeCapabilities` |
|
||
| Sem escalada via staff | staff.manage ≠ permissions/owners |
|
||
| Revogação na próxima ação | `/access/me` + guards |
|
||
| Sem ficar sem Dono | check atômico |
|
||
| Sem cross-tenant | sempre `storeId` da sessão |
|
||
| Teclado/tablet/mobile | UI matrix |
|
||
|
||
---
|
||
|
||
*Documento vivo. Versão produto pai: SPEC.md.*
|