CipherVault 1.4 — RBAC vault-aware, cofres pessoais e UI gating por permissão
Release focada em RBAC vault-aware, cofres pessoais por usuário e gating de UI por permissão (sidebar, settings, route guards). 10 commits desde v1.3.0.
✨ Novidades
Cofres pessoais (RBAC tenant-internal)
Cada user ganha um vault is_personal=true auto-criado em três fluxos:
- Criação via admin (
POST /users) - Self-signup (
/auth/register) - Fallback no primeiro login (
ensurePersonalVault)
Migration 0024_personal_vault.sql adiciona is_personal BOOL +
owner_user_id INT.
Privacidade absoluta:
- Personal vault: somente o owner acessa — admin global NÃO bypassa
- Não aceita membros
- UI: badge "Pessoal" no card; botão Excluir desabilitado
Hierarquia de roles em vaults compartilhados
Tabela vault_members(vault_id, user_id, role) com role ∈ {reader, contributor, owner}:
| Role | Permite |
|---|---|
reader | Ler vault + revelar secrets (POST /secrets/:id/view) |
contributor | Reader + criar/editar/deletar secrets do vault |
owner | Contributor + editar metadata + gerenciar membros |
Lib backend/src/lib/vaultAccess.js: canAccessVault(),
requireVaultAccess() middleware, listAccessibleVaultIds(),
actionRequires(). Endpoints GET/POST/PATCH/DELETE /vaults/:id/members
com auditoria.
Vault-aware secret/fortress access
Lib backend/src/lib/secretAccess.js com helpers
listVisibleSecretIds(), listVisibleFortressIds(), canAccessSecret().
Regras aplicadas em GET /secrets, GET /fortress, GET /:id,
POST /:id/view:
- Personal vault → somente o owner
- Shared vault → membros (qualquer role)
- Orphan (sem vault) → admin OU
created_by(criador acessa o que criou)
Admin perdeu bypass em shared vaults — precisa ser membro explícito;
mantém apenas list (metadata) pra governance.
IAM permission-based UI gating
GET /auth/me/permissionsresolve permissões doiam_groupdo user- Catálogo de grupos vive em
account_settings.iam_groupsdo primeiro admin do tenant (source of truth tenant-wide) AuthContextcarregapermissions: Set+admin_bypassem paralelo ao/auth/me; expõehasPermission(p)- Sidebar (
Layout.jsx) e abas internas de Settings escondem páginas/seções sem permissão - Grupo padrão "User" criado automaticamente; novos users sem grupo explícito caem nele
Vault selector no Fortress create
- POST
/fortressaceitavault_idopcional, validado viacanAccessVault('write')antes de cifrar - UI
CreateDialogganha<Select>listando cofres acessíveis (pessoal marcado com ★)
Route guards no frontend
<RouteGuard pageName=...> em App.jsx bloqueia acesso direto via URL —
sem o guard, sidebar oculta mas /Fortress digitado na barra entrava.
Redireciona pra /Settings (Perfil sempre liberado).
PAGE_PERMISSION exportado de Layout.jsx é a fonte de verdade compartilhada
entre sidebar e router.
🐛 Correções
- JSONB containment incorreto:
vault.fortress_secret_idsarmazena integers mas checks usavam operador?(text-only). Resultado: secrets atribuídos a cofre apareciam como orphan e admin via tudo. Trocado?::textpor@> to_jsonb()(type-aware) emsecretAccess.jse no UPDATE dofortress.jsPOST. - iam_group resolution: lookup lia
account_settings.iam_groupsdo user, mas catálogo vive no admin do tenant. Corrige bug onde "atribuir grupo DevOps tornava user admin". - Personal vault edit bloqueado:
disabled={vault.is_personal}no botão Editar bloqueava o owner. Removido — owner do personal pode editar metadata. - Pepper rotation sem re-deploy: novo endpoint admin pra rotacionar
FORTRESS_PEPPERem runtime, com re-encryption das versões ativas.
🧪 Testes
181 cases passando em 16 suites. Novos:
vaultAccess.test.js— RBAC personal/shared, hierarquia, admin bypass restrito alistsecretAccess.test.js— orphan creator, personal isolation, fortress kind
⚠️ Breaking changes
- Admin não acessa mais shared vaults sem ser membro explícito (exceto
listde metadata). Promoção de admin para owner é viaPOST /vaults/:id/memberspor outro owner. - Admin não vê secrets de personal vaults de outros users (privacidade absoluta).