feat(crm,workspace): alta de organizaciones y usuarios vía Hub

Nueva sección "Workspace" (Organizaciones + Usuarios) que orquesta el Hub
reenviando el token del usuario autenticado. Sin secretos en el CRM ni
bypass: la autorización la impone el Hub (hub_admin para tenants;
hub_admin o admin del tenant para invitaciones).

- Organizaciones: listar (GET /api/v1/hub/tenants) y crear
  (POST /api/v1/hub/tenants → tenant + realm Keycloak).
- Usuarios: invitación de un solo uso (POST /api/v1/hub/invites) con
  enlace copiable si el correo no llega.
- Se descarta /auth/provision-user (PROVISION_SECRET, machine-to-machine)
  en favor del flujo de invitación con token de admin.
- Helpers puros (slug, validación, extracción de errores del Hub) con
  tests unitarios; estado "requiere permisos" ante 403 y fallback a slug
  manual para admin de tenant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ernesto Herrera
2026-07-16 13:19:21 -06:00
parent 45f128a551
commit a613a7a6aa
8 changed files with 774 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ import {
Briefcase,
Ship,
Receipt,
Building2,
} from '@lucide/svelte';
export type SystemContext = 'fixed_asset' | 'inventory';
@@ -69,6 +70,15 @@ export function getNavMain(): NavMainItem[] {
{ title: 'Facturas y cobranza', url: '/dashboard/fin/facturas' },
],
},
{
title: 'Workspace',
url: '/dashboard/workspace/organizaciones',
icon: Building2,
items: [
{ title: 'Organizaciones', url: '/dashboard/workspace/organizaciones' },
{ title: 'Usuarios (invitaciones)', url: '/dashboard/workspace/usuarios' },
],
},
{
title: 'Usuarios',
url: '/dashboard/users',