feat(sprint-4/etapa-5): modelo de privacidad RLS granular + UI de visibilidad

- SQL 010: tablas user_groups y group_memberships con RLS
- SQL 011: tabla process_access para acceso explícito a procesos
- SQL 012: función is_platform_admin() + políticas granulares (select/insert/update/delete) en processes
- types.ts: Process.ownerId (requerido)
- process-repo: fromRow mapea owner_id→ownerId; toRow preserva ownerId en updates; setShared() no-op documentado
- ImportPage: asigna ownerId: user.id al crear proceso
- LibraryPage: toggle Todos/Míos, OwnershipBadge (🔒/👤) en cada tarjeta, opción "Compartir con equipo" en menú de proceso propio con toast de confirmación
- Tests: ownerId: 'test-user' agregado a todos los fixtures de Process

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 22:37:37 -03:00
parent 025393cd43
commit d426791a53
20 changed files with 281 additions and 28 deletions

View File

@@ -14,7 +14,8 @@ function toRow(process: Process, userId: string) {
automation_investment: process.automationInvestment,
group_id: process.groupId,
tags: process.tags,
owner_id: userId,
// owner_id se preserva del valor existente en el proceso; solo se inicializa con userId en creates
owner_id: process.ownerId || userId,
created_by: userId,
updated_by: userId,
updated_at: new Date().toISOString(),
@@ -36,6 +37,7 @@ function fromRow(row: Record<string, unknown>): Process {
tags: Array.isArray(row.tags) ? (row.tags as string[]) : [],
createdAt: new Date(row.created_at as string).getTime(),
updatedAt: new Date(row.updated_at as string).getTime(),
ownerId: (row.owner_id as string) ?? '',
}
}
@@ -69,4 +71,10 @@ export const supabaseProcessRepo = {
const { error } = await supabase.from('processes').delete().eq('id', id)
if (error) throw error
},
// No-op en Sprint 4: la implementación real (insertar en process_access) llega cuando existan guests.
// El método existe para que la UI de "Compartir con equipo" funcione sin escritura a DB.
async setShared(_processId: string, _shared: boolean): Promise<void> {
return
},
}