pizza-digital/docs/SPEC-MATRIZ-ACESSO.md
Admin d669f56398 Import Pizza Digital SPECs and docs from Obsidian vault sync
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-09 19:52:34 +00:00

169 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.*