Commita governance, user-wizard, operational-feed e catálogo RBAC; adiciona deploy-desk-full.sh, smoke-desk.sh e regra anti-deploy parcial; documenta credencial VM112 @betinplace. Co-authored-by: Cursor <cursoragent@cursor.com>
420 lines
21 KiB
Markdown
420 lines
21 KiB
Markdown
# Spec 039 — Catálogo Mestre de Autorização Ligbox OPS
|
||
|
||
**Criado:** 2026-06-29
|
||
**Solicitado por:** Roger
|
||
**Status:** Aprovado Roger 2026-06-29 — catálogo completo (TODAS superfícies)
|
||
**Prioridade:** P0 (governança — pré-requisito da UI Matriz + Controle de acesso)
|
||
**Estende:** Spec **003** (RBAC base), **027** (matriz por função), **015** (módulos Desk), **019** (Console)
|
||
**Sistemas:** VM122 Desk · VM123 Console/Finance · VM112 Onboard · VM104 Wazuh · Infra (Proxmox, Traefik, pfSense)
|
||
|
||
---
|
||
|
||
## 1. Problema (demanda Roger)
|
||
|
||
Hoje sabemos que **root / `super_admin`** faz tudo (criar, autorizar, gerir, trocar senha), mas **não está documentado nem exposto na UI** o mapa completo de:
|
||
|
||
- O que **cada função** (`SU`, `CO`, `TEC`, `NOC`, …) pode fazer
|
||
- **Porquê** (regra de negócio / risco)
|
||
- **Onde** (Desk, Console, FOSS, Odoo, OpenPanel, VM112, APIs internas)
|
||
- **A nível de ação** (não só “módulo ON/OFF”): ex. deletar instância OpenPanel, atualizar processo, purge domínio, aprovar runbook A7
|
||
|
||
Sem este catálogo, a **Matriz de Acesso** e o **Controle de acesso** mostram toggles e módulos, mas **não fecham o mapa** de atribuições por posição.
|
||
|
||
**Objetivo desta spec:** ser a **fonte única de verdade** para enumerar operações × funções × ambientes, alimentar a Matriz UI (Spec 027-UI) e implementação RBAC (`permissions.py`, bindings Odoo-style, provisionamento VM123).
|
||
|
||
---
|
||
|
||
## 2. Relação com specs existentes
|
||
|
||
| Documento | Nível | O que falta para Matriz completa |
|
||
|-----------|-------|----------------------------------|
|
||
| [Spec 027](../027-desk-rbac-function-matrix/spec.md) | Função × módulo × ambiente (✅🔒🔗) | Granularidade por **ação** dentro de cada módulo/produto |
|
||
| [Spec 027 UI](../027-desk-rbac-function-matrix/ui-access-matrix.md) | Wireframes Matriz | Dados estruturados (YAML) por ação |
|
||
| [vm123-product-roles](../027-desk-rbac-function-matrix/contracts/vm123-product-roles.md) | FOSS/Odoo/OpenPanel grupos | Lista exaustiva endpoints FOSS + OpenPanel CE |
|
||
| `platform_role_catalog.py` | Bindings por função | Sincronizar com catálogo 039 |
|
||
| `permissions.py` | ~30 helpers `can_*` | Um helper por `action_id` do catálogo |
|
||
| Controle de acesso (UI) | Toggles informativos | Persistência + ligação a `action_id` |
|
||
|
||
**Regra:** Spec 039 **não substitui** 027 — **detalha** cada célula da matriz 027 em linhas de ação auditáveis.
|
||
|
||
---
|
||
|
||
## 3. Taxonomia de autorização
|
||
|
||
### 3.1 Camadas
|
||
|
||
```text
|
||
FUNÇÃO (desk_role) ex.: super_admin, ops_lead → código UI: SU, CO, TEC
|
||
└── MÓDULO / PRODUTO ex.: admin-users, foss.client, openpanel.site
|
||
└── AÇÃO ex.: user.create, domain.purge, instance.delete
|
||
└── RECURSO ex.: desk_user, vm112_domain, openpanel_vhost
|
||
```
|
||
|
||
### 3.2 Níveis de efeito (`access_level`)
|
||
|
||
| Código | Significado | UI Matriz |
|
||
|--------|-------------|-----------|
|
||
| `full` | CRUD / executar sem aprovação | ✅ |
|
||
| `approve` | Executar após aprovação humana | 🟡 |
|
||
| `read` | Só leitura (pode mascarar PII) | 🔒 |
|
||
| `link` | Deep-link / abrir consola externa | 🔗 |
|
||
| `api` | Só via API Desk (M2M ou token) | ⚙️ |
|
||
| `system` | Conta sistema / agente | 🤖 |
|
||
| `none` | Proibido | ❌ |
|
||
|
||
### 3.3 Superfícies (`surface`)
|
||
|
||
| ID | Descrição | Host |
|
||
|----|-----------|------|
|
||
| `desk` | Ligbox Ops Desk (VM122 UI + API) | desk.ligbox.com.br |
|
||
| `console` | Ligbox Ops Console (Spec 019) | console.ligbox.com.br |
|
||
| `vm112` | Wizard + Carbonio + API onboard | onboard.ligbox.com.br |
|
||
| `vm123_foss` | FOSSBilling Admin API | financeiro.ligbox.com.br |
|
||
| `vm123_odoo` | Odoo 16 XML-RPC | financeiro.ligbox.com.br/odoo |
|
||
| `vm123_openpanel` | OpenPanel / OpenAdmin / bridge | openpanel.ligbox.com.br |
|
||
| `infra` | Proxmox, Traefik, pfSense, SSH hosts | LAN |
|
||
| `agents` | Agentes A0–A7 | VM122 agentic |
|
||
|
||
### 3.4 Identificador de ação (`action_id`)
|
||
|
||
Formato: `{surface}.{domain}.{verb}` — exemplos:
|
||
|
||
- `desk.auth.user.create`
|
||
- `desk.auth.user.freeze`
|
||
- `vm112.domain.purge`
|
||
- `vm123_openpanel.instance.delete`
|
||
- `vm123_foss.invoice.void`
|
||
- `console.case.runbook.execute`
|
||
|
||
---
|
||
|
||
## 4. Catálogo de funções (códigos UI)
|
||
|
||
| Código | `desk_role` | Categoria | Mandato resumido |
|
||
|--------|-------------|-----------|------------------|
|
||
| **RO** | `root` (utilizador) | Sistema | Conta física dono — bypass humano; não é role atribuível |
|
||
| **SU** | `super_admin` | Ops | Tudo no Desk + purge + users + módulos + agentes |
|
||
| **CO** | `ops_lead` | Ops | Operação diária, audit, domínios, tickets, aprovações ops |
|
||
| **TEC** | `technician` | Ops | Tickets atribuídos, assist/takeover, migração e-mail |
|
||
| **NOC** | `noc` | Ops | Monitorização read-only, Wazuh, dados mascarados |
|
||
| **SAD** | `sales_admin` | Comercial | Pipeline, billing validation, FOSS/Odoo manager |
|
||
| **SSU** | `sales_support` | Comercial | CRM, pedidos, clientes — sem validar billing |
|
||
| **FIN** | `finance` | Negócio | FOSS/Odoo fiscal, faturas, inadimplência |
|
||
| **MKT** | `marketing` | Negócio | Campanhas, produtos FOSS, leads |
|
||
| **SEO** | `seo` | Negócio | DNS, sites OpenPanel, performance |
|
||
| **DEV** | `developer` | Plataforma | Código, GitHub, APIs, deploy Desk |
|
||
| **DVO** | `devops` | Plataforma | Infra, Proxmox, OpenAdmin, SSH |
|
||
| **SOC** | `security_analyst` | Plataforma | Incidentes, Wazuh rules, resposta |
|
||
| **CMS** | `content_editor` | Plataforma | Sites clientes OpenPanel |
|
||
| **AIO** | `agentic_operator` | Plataforma | Aprovar runbooks A7, findings |
|
||
| **SVC** | `api_service` | Sistema | M2M webhooks, provisionamento |
|
||
| **AGT** | `agent_system` | Sistema | Agentes IA autónomos |
|
||
| **PTR** | `partner` | Comercial | Revendedor — clientes próprios, OpenPanel Reseller, FOSS scoped |
|
||
|
||
### 4.1 Funções RBAC custom (UI)
|
||
|
||
Funções criadas via `POST /rbac/roles` **MUST** herdar de um único template:
|
||
|
||
| Template permitido | `desk_role` base | Uso |
|
||
|--------------------|------------------|-----|
|
||
| **CO** | `ops_lead` | Coordenação, aprovações ops, purge (sem gestão users) |
|
||
| **TEC** | `technician` | Suporte restrito — tickets assigned, assist |
|
||
|
||
**Proibido:** herdar de SU, FIN, DVO ou escolha livre de permissões avulsas no MVP.
|
||
|
||
---
|
||
|
||
## 5. Inventário de ações — Controle de identidade (Desk VM122)
|
||
|
||
### 5.1 Gestão de utilizadores (`desk.auth.*`)
|
||
|
||
| action_id | Descrição | SU | CO | Demais | API / UI |
|
||
|-----------|-----------|:--:|:--:|:------:|----------|
|
||
| `desk.auth.user.list` | Listar utilizadores Desk | full | none | none | GET `/v1/auth/users` |
|
||
| `desk.auth.user.create` | Criar utilizador (directo) | full | none | none | *gap — hoje só via registo+aprovação* |
|
||
| `desk.auth.user.approve_registration` | Aprovar pedido cadastro | full | **full** | none | POST `/v1/auth/registration-requests/{id}/approve` |
|
||
| `desk.auth.user.reject_registration` | Rejeitar pedido | full | **full** | none | POST `.../reject` |
|
||
| `desk.auth.user.edit` | Editar nome, role, display | full | none | none | PATCH `/v1/auth/users/{username}` |
|
||
| `desk.auth.user.freeze` | Desactivar conta (`active=false`) | full | none | **SSU: none** | PATCH `active` |
|
||
| `desk.auth.user.password.reset` | Definir nova senha (admin) | full | none | none | PATCH `password` |
|
||
| `desk.auth.user.2fa.reset` | Reset TOTP + backup codes | full | none | none | POST `.../reset-2fa` |
|
||
| `desk.auth.user.delete` | Remover utilizador | none | none | none | *não implementado — usar freeze* |
|
||
| `desk.auth.user.groups.assign` | Ligar grupos/bindings VM123 | full | none | none | Fase 3 `vm123/identity` |
|
||
| `desk.auth.role.create` | Criar função custom RBAC | full | none | none | POST `/rbac/roles` |
|
||
| `desk.auth.role.clone` | Clonar função | full | none | none | POST `/rbac/roles/{id}/clone` |
|
||
| `desk.auth.role.freeze` | Pausar função | full | none | none | PATCH `/rbac/roles/{id}/status` |
|
||
| `desk.auth.modules.toggle` | Activar/desactivar módulos Desk | full | none | none | PATCH `/v1/modules/{id}` |
|
||
|
||
**Porquê:** credenciais humanas Ligbox = superfície de ataque máxima. **Excepção Roger:** CO aprova cadastros; freeze/reset senha permanece **SU only**; **SSU nunca congela**.
|
||
|
||
### 5.2 Conta própria (`desk.account.*`)
|
||
|
||
| action_id | Descrição | Quem |
|
||
|-----------|-----------|------|
|
||
| `desk.account.password.change` | Trocar própria senha + 2FA | Qualquer autenticado |
|
||
| `desk.account.2fa.setup` | Configurar TOTP | Qualquer autenticado |
|
||
| `desk.account.console_handoff` | Token para Console | Staff com acesso Console |
|
||
|
||
---
|
||
|
||
## 6. Inventário — Módulos Desk (por `module_id`)
|
||
|
||
Cada módulo (Spec 015 `registry.py`) decompõe-se em **acções UI + API**. Resumo por módulo:
|
||
|
||
### 6.1 `core` — Dashboard, Tickets, Conta
|
||
|
||
| action_id | Descrição | SU | CO | TEC | NOC | SAD | SSU |
|
||
|-----------|-----------|:--:|:--:|:---:|:---:|:---:|:---:|
|
||
| `desk.ticket.list` | Ver tickets | full | full | full | read* | full | full |
|
||
| `desk.ticket.read` | Detalhe ticket | full | full | full | read* | full | full |
|
||
| `desk.ticket.patch` | Actualizar estado/notas | full | full | assigned | none | full | full |
|
||
| `desk.ticket.assign` | Atribuir responsável | full | full | self | none | full | full |
|
||
| `desk.ticket.close` | Fechar ticket | full | full | assigned | none | full | full |
|
||
| `desk.dashboard.kpi` | KPIs resumo | full | full | full | read | full | full |
|
||
|
||
\* NOC: dados sensíveis mascarados (Spec 003).
|
||
|
||
### 6.2 `overview-home` — Serviços IaaS (Spec 018)
|
||
|
||
| action_id | Descrição | SU | CO | TEC | DVO | FIN |
|
||
|-----------|-----------|:--:|:--:|:---:|:---:|:---:|
|
||
| `desk.services.client.list` | Listar clientes/domínios | full | full | full | read | read |
|
||
| `desk.services.catalog.read` | Catálogo cPanel/serviços | full | full | full | read | read |
|
||
| `desk.services.process.update` | Actualizar processo onboard | full | full | read | api | none |
|
||
| `desk.purge.auth.generate` | Gerar código purge (root pwd) | full | none | none | none | none |
|
||
|
||
### 6.3 `vm112-domains` + purge (Spec 017, 032)
|
||
|
||
| action_id | Descrição | SU | CO | TEC | DVO |
|
||
|-----------|-----------|:--:|:--:|:---:|:---:|
|
||
| `vm112.domain.list` | Listar domínios orquestrados | full | full | read | read |
|
||
| `vm112.domain.read` | Detalhe domínio | full | full | read | read |
|
||
| `vm112.domain.purge` | Purge completo domínio | full | full | none | approve |
|
||
| `vm112.purge.job.recover` | Recuperar job purge falhado | full | full | none | full |
|
||
|
||
### 6.4 `assist` — Wizard takeover (Spec 010)
|
||
|
||
| action_id | Descrição | SU | CO | TEC |
|
||
|-----------|-----------|:--:|:--:|:---:|
|
||
| `desk.assist.session.list` | Sessões activas wizard | full | full | full |
|
||
| `desk.assist.takeover` | Assumir sessão cliente | full | full | assigned |
|
||
| `desk.assist.handoff` | Passar sessão | full | full | full |
|
||
| `desk.assist.action.execute` | Acções assist aprovadas | full | full | assigned |
|
||
|
||
### 6.5 `billing-recurrence` (Spec 023)
|
||
|
||
| action_id | Descrição | SU | CO | FIN | SAD | SSU |
|
||
|-----------|-----------|:--:|:--:|:---:|:---:|:---:|
|
||
| `desk.billing.account.read` | Ficha conta cliente | full | full | full | full | read |
|
||
| `desk.billing.state.validate` | Validar billing_state | full | full | full | full | none |
|
||
| `desk.billing.link.foss` | Deep-link FOSS | full | full | full | full | link |
|
||
|
||
### 6.6 `email-migration` (Spec 013, 019)
|
||
|
||
| action_id | Descrição | SU | CO | TEC | DVO |
|
||
|-----------|-----------|:--:|:--:|:---:|:---:|
|
||
| `desk.migration.job.create` | Criar job imapsync | full | full | full | read |
|
||
| `desk.migration.job.cancel` | Cancelar job | full | full | assigned | none |
|
||
| `desk.migration.dns.gate` | Gate DNS pré-migração | full | full | full | read |
|
||
|
||
### 6.7 `infra` / `infra2-soc` (Spec 033)
|
||
|
||
| action_id | Descrição | SU | CO | DVO | SOC | DEV |
|
||
|-----------|-----------|:--:|:--:|:---:|:---:|:---:|
|
||
| `desk.infra.stack.read` | Stack health VMs | full | full | full | full | read |
|
||
| `desk.infra.stack.probe` | Executar probe serviço | full | full | full | read | api |
|
||
| `desk.infra.deploy` | Deploy API/frontend | full | none | full | none | full |
|
||
|
||
### 6.8 `agentic-ops` (Spec 029, 030)
|
||
|
||
| action_id | Descrição | SU | CO | AIO | SOC | DEV |
|
||
|-----------|-----------|:--:|:--:|:---:|:---:|:---:|
|
||
| `desk.agent.finding.read` | Ver findings | full | full | full | full | full |
|
||
| `desk.agent.runbook.approve` | Aprovar remediação A7 | full | full | full | scope | none |
|
||
| `desk.agent.binding.toggle` | UI/Focus/Approve agente×função | full | none | none | none | none |
|
||
|
||
### 6.9 `events`, `leads`, `audit`, `dns`
|
||
|
||
Ver matriz Spec 027 §3.2 — cada endpoint `main.py` mapeia para `action_id` (anexo A em `contracts/action-catalog.yaml`).
|
||
|
||
---
|
||
|
||
## 7. Inventário — VM123 produtos (granular)
|
||
|
||
### 7.1 FOSSBilling (`vm123_foss.*`)
|
||
|
||
Módulos API: `client`, `order`, `invoice`, `product`, `service`, `staff`, `support`, `extension`, hosting→OpenPanel.
|
||
|
||
| action_id | sales_admin | sales_support | finance | marketing | developer |
|
||
|-----------|:-----------:|:-------------:|:-------:|:---------:|:---------:|
|
||
| `vm123_foss.client.create` | full | full | full | none | api |
|
||
| `vm123_foss.client.delete` | full | none | full | none | none |
|
||
| `vm123_foss.order.create` | full | full | read | none | api |
|
||
| `vm123_foss.invoice.create` | full | read | full | none | none |
|
||
| `vm123_foss.invoice.void` | full | none | full | none | none |
|
||
| `vm123_foss.product.edit` | full | read | read | full | api |
|
||
| `vm123_foss.staff.manage` | none | none | read | none | api |
|
||
| `vm123_foss.hosting.provision` | full | full | read | none | api |
|
||
|
||
Detalhe endpoints: [vm123-product-roles.md §2](../027-desk-rbac-function-matrix/contracts/vm123-product-roles.md).
|
||
|
||
### 7.2 Odoo 16 (`vm123_odoo.*`)
|
||
|
||
| action_id | sales_admin | sales_support | finance |
|
||
|-----------|:-----------:|:-------------:|:-------:|
|
||
| `vm123_odoo.partner.read` | full | full | full |
|
||
| `vm123_odoo.partner.write` | full | full | full |
|
||
| `vm123_odoo.sale.order.create` | full | full | read |
|
||
| `vm123_odoo.invoice.post` | full | none | full |
|
||
| `vm123_odoo.account.move.validate` | none | none | full |
|
||
|
||
Grupos: `group_sale_manager`, `group_sale_salesman`, `account.group_account_manager`.
|
||
|
||
### 7.3 OpenPanel (`vm123_openpanel.*`)
|
||
|
||
| action_id | Descrição | SU | **CO** | SAD | SSU | SEO | CMS | DVO |
|
||
|-----------|-----------|:--:|:--:|:---:|:---:|:---:|:---:|:---:|
|
||
| `vm123_openpanel.site.create` | Novo site/vhost | full | full | full | full | full | full | full |
|
||
| `vm123_openpanel.site.delete` | **Remover instância** | full | **full** | none | none | none | none | **none** |
|
||
| `vm123_openpanel.ssl.manage` | Certificados LE | full | full | link | link | full | full | full |
|
||
| `vm123_openpanel.db.create` | Base de dados | full | full | link | link | full | full | full |
|
||
| `vm123_openpanel.cron.manage` | Cron jobs | full | full | none | none | read | full | full |
|
||
| `vm123_openpanel.backup.restore` | Restaurar backup | full | full | none | none | none | read | full |
|
||
| `vm123_openpanel.openadmin.access` | Painel OpenAdmin :2087 | full | full | link | none | link | none | full |
|
||
| `vm123_openpanel.autologin.client` | Login cliente (bridge) | full | full | full | full | full | full | link |
|
||
|
||
**Gap actual:** Desk não expõe toggles por `action_id` OpenPanel — só deep-links e provisionamento M2M.
|
||
|
||
---
|
||
|
||
## 8. Inventário — Console (Spec 019)
|
||
|
||
**Decisão Roger:** Console na **mesma Matriz** do Desk (superfície `console`, aba dedicada, RBAC herda role Desk via handoff).
|
||
|
||
| action_id | Descrição | SU | CO | TEC | SOC | AIO |
|
||
|-----------|-----------|:--:|:--:|:---:|:---:|:---:|
|
||
| `console.case.create` | Abrir chamado CH-* | full | full | full | full | read |
|
||
| `console.case.assign` | Assumir chamado | full | full | full | full | none |
|
||
| `console.case.timeline.read` | Timeline correlacionada | full | full | full | full | full |
|
||
| `console.discover.search` | Discover (estilo Wazuh) | full | full | read | full | read |
|
||
| `console.runbook.execute` | Executar runbook | full | full | none | scope | approve |
|
||
| `console.wizard.assist.view` | Passo actual wizard | full | full | full | read | read |
|
||
| `console.link.wazuh` | Deep-link VM104 | full | full | read | full | read |
|
||
|
||
Console autentica via **handoff** Desk (`/v1/auth/console-handoff`) — RBAC herda role Desk.
|
||
|
||
---
|
||
|
||
## 9. Inventário — Partner / Revendedor (`partner` · PTR)
|
||
|
||
| action_id | Descrição | PTR | Notas |
|
||
|-----------|-----------|:---:|-------|
|
||
| `desk.partner.dashboard.read` | Dashboard revendedor (clientes próprios) | full | Módulo `partner-portal` |
|
||
| `vm123_foss.client.create` | Criar cliente FOSS (scoped) | full | Só tenants do partner |
|
||
| `vm123_foss.order.create` | Pedidos FOSS | full | |
|
||
| `vm123_foss.invoice.read` | Ver faturas clientes | read | Sem void |
|
||
| `vm123_openpanel.site.create` | Provisionar hosting cliente | full | Via bridge |
|
||
| `vm123_openpanel.autologin.client` | Painel cliente | full | |
|
||
| `vm123_openpanel.site.delete` | Deletar instância | none | Só SU/CO Ligbox |
|
||
| `desk.auth.*` | Qualquer gestão Desk | none | |
|
||
| `console.*` | Console ops | none | |
|
||
|
||
**OpenPanel nativo:** role `reseller` (Spec 028). **FOSS:** grupo `ligbox-partner` (criar no Admin).
|
||
|
||
---
|
||
|
||
## 10. Inventário — VM112 Wizard
|
||
|
||
| action_id | Descrição | SU | CO | TEC | DEV |
|
||
|-----------|-----------|:--:|:--:|:---:|:---:|
|
||
| `vm112.wizard.session.read` | Estado sessão onboard | full | full | assigned | read |
|
||
| `vm112.carbonio.mailbox.create` | Criar caixa mail | api | api | api | api |
|
||
| `vm112.carbonio.block.release` | Libertar ACCOUNT_EXISTS | full | full | none | api |
|
||
| `vm112.dns.verify` | Verificar DNS wizard | full | full | read | read |
|
||
| `vm112.api.webhook.emit` | Emitir evento (sistema) | system | system | system | system |
|
||
|
||
---
|
||
|
||
## 11. Matriz resumida — Quem faz o quê (visão Roger)
|
||
|
||
| Área | Quem manda | Porquê |
|
||
|------|------------|--------|
|
||
| Criar/editar/freeze utilizadores Desk | **SU** | Credenciais internas |
|
||
| **Aprovar cadastros** | **SU**, **CO** | Roger — CO autónomo |
|
||
| **Congelar users** | **SU only** — **SSU nunca** | Segregação comercial |
|
||
| Purge domínio / dados cliente | **SU**, **CO** (DVO recover job) | Irreversível — Spec 032 |
|
||
| Validar billing / faturação | **SU**, **CO**, **FIN**, **SAD** | Segregação comercial vs financeira |
|
||
| FOSS pedidos e clientes | **SAD**, **SSU**, **PTR** (scoped) | Linha de frente |
|
||
| FOSS faturas / void | **FIN**, **SU** | Risco fiscal |
|
||
| **OpenPanel delete instance** | **SU**, **CO only** | Downtime — Roger 2026-06-29 |
|
||
| OpenPanel conteúdo sites | **CMS**, **SEO**, **MKT** | Operação editorial |
|
||
| Tickets / assist | **TEC** (assigned), **CO**, **SU** | Menor privilégio |
|
||
| Infra / deploy | **DVO**, **DEV**, **SU** | Separação código vs infra |
|
||
| Agentes A7 remediação | **AIO**, **CO**, **SU** | Human-in-the-loop |
|
||
| Módulos Desk ON/OFF | **SU** | Feature flags globais |
|
||
| **Console** | Mesma matriz Desk | Handoff — Roger |
|
||
| **RBAC custom** | Herda **CO** ou **TEC** | Templates only |
|
||
|
||
---
|
||
|
||
## 12. Implementação — fechar o mapa na UI
|
||
|
||
### Fase A — Catálogo (esta spec) ✅
|
||
|
||
- [x] Taxonomia `action_id`
|
||
- [x] Inventário por superfície (Desk + VM123 + Console + VM112 + Partner)
|
||
- [x] Decisões Roger validadas (§13)
|
||
|
||
### Fase B — `contracts/action-catalog.yaml` ✅ v1.1
|
||
|
||
- Lista machine-readable: `action_id`, `label`, `surface`, `roles{}`, `api_route`, `spec_ref`
|
||
- Gerar toggles Controle de acesso + export CSV Matriz
|
||
|
||
### Fase C — API RBAC
|
||
|
||
- `GET /rbac/actions` — catálogo completo
|
||
- `PATCH /rbac/roles/{id}/actions` — persistir overrides (só SU)
|
||
- `permissions.py`: `can_action(role, action_id)` único entry point
|
||
|
||
### Fase D — UI
|
||
|
||
- Aba **Controle de acesso**: toggles ligados a YAML (não só informativos)
|
||
- Abas Matriz: filtrar por `surface` (Desk | FOSS | Odoo | OpenPanel | Console)
|
||
- Sidebar função: mostrar **contagem de acções** full/read/none
|
||
|
||
---
|
||
|
||
## 13. Decisões Roger (2026-06-29) — FECHADAS
|
||
|
||
| # | Pergunta | Decisão |
|
||
|---|----------|---------|
|
||
| 1 | `sales_support` congela utilizadores? | **Não** — só SU |
|
||
| 2 | `ops_lead` aprova cadastros sem SU? | **Sim** — CO autónomo |
|
||
| 3 | Deletar instância OpenPanel | **SU + CO only** (não DVO) |
|
||
| 4 | Console na mesma Matriz? | **Sim** — mesma matriz Desk |
|
||
| 5 | RBAC custom herda de? | **CO ou TEC only** |
|
||
| 6 | Partner/revendedor | **Nesta spec** — função `partner` (PTR) |
|
||
| 7 | Prioridade granularidade | **TODOS** — Desk + FOSS + Odoo + OpenPanel + Console |
|
||
|
||
**Implementação código (parcial):** `can_approve_registration`, `can_openpanel_delete` → SU+CO; rotas registo actualizadas.
|
||
|
||
---
|
||
|
||
## 14. Critérios de aceite
|
||
|
||
- **FR-039-001**: Cada `action_id` MUST ter exactamente uma linha no catálogo YAML.
|
||
- **FR-039-002**: Cada função humana MUST ter coluna em todas as tabelas §5–9.
|
||
- **FR-039-003**: UI Controle de acesso MUST reflectir catálogo (não lista hardcoded).
|
||
- **FR-039-004**: Alteração de permissão MUST gerar audit log (`rbac_audit`).
|
||
- **FR-039-005**: RO/root MUST NOT aparecer como role atribuível — só nota §4.
|
||
- **FR-039-006**: Função `partner` MUST estar no catálogo com scope tenant isolado.
|
||
- **FR-039-007**: RBAC custom MUST declarar `inherits_from: ops_lead | technician`.
|
||
|
||
---
|
||
|
||
## Anexos
|
||
|
||
- `contracts/action-catalog.yaml` — inventário estruturado (geração automática)
|
||
- `../027-desk-rbac-function-matrix/spec.md` — matriz macro
|
||
- `../../projects/ops-desk/api/app/platform_role_catalog.py` — bindings código
|
||
- `../../projects/ops-desk/api/app/permissions.py` — guards actuais
|