La SUPERFICIE — el reconocimiento, y cómo ponerla a la par del sustrato
Fecha: 2026-08-15. El sustrato de gobernanza está medido pieza a pieza; la cara no
lo estaba. Este documento es el censo —no una impresión— y el plan que se deduce de él.Regla de la casa: cada hecho lleva el comando que lo demuestra.
Censo:scripts/governance/sup0-censo-de-superficie.ts· acoplamiento de roles:
scripts/governance/g3-acoplamiento-de-roles.ts
0 · El desnivel, en una línea
El sustrato de gobernanza está vivo y medido; su cara es una maqueta. Toda la superficie
de gobernanza —políticas, roles, tags— es estado local sembrado, salvo users.
1 · El censo, medido
42 pantallas · 501 rutas de API
✅ vivas 27 llaman a una API real
🟡 maquetas 6 estado local sembrado (5 lo declaran, 1 NO)
⛔ huérfanas 3 llaman a una API que NO EXISTE en el repo
⚪ estáticas 6 sin datos
⚠️ La primera pasada dio 14 pantallas y era falsa. Contaba sólo page.tsx, y esta app
usa un shell con pestañas: la mayoría de las superficies son componentes
(components/workspace/tabs/, ~20 secciones), no rutas. Un censo que mide el 5 % y no lo
dice es peor que no censar. ⇒ Regla: antes de censar, comprobar que la unidad que cuentas
es la unidad que existe.
2 · Las debilidades, por orden de daño
⛔⛔ 2·1 · Tres pantallas llaman a APIs que no existen
components/workspace/tabs/bi → /api/bi/reports
components/workspace/tabs/modelmanager → /api/model/auto-detect
components/workspace/tabs/semantic → /api/semantic/observability
Es la peor de las tres clases: parecen vivas y fallan en producción. Una maqueta al menos es honesta.
⛔⛔ 2·2 · Hay TRES vocabularios de «rol», y no se hablan
| dónde | qué es | ejemplos |
|---|---|---|
/api/organization/roles | roles de Clerk (la organización) | admin, member |
principal_roles (Index) | roles del catálogo | ws-admin, sql-editor, etl-engines |
SEED_ROLES (la UI nueva) | roles inventados para la maqueta | data_steward, viewer, editor |
⇒ La pantalla de Roles enseña un vocabulario que no existe en ningún sitio, y la de Users enseña otro distinto. El día que se conecten, uno de los tres tiene que ganar — y conviene decidirlo antes de construir encima.
⛔ 2·3 · No existe NINGUNA API de gobernanza
Buscadas: grants, privilegios, políticas, tags de catálogo. Cero. Lo único que hay es
/api/organization/roles, que es Clerk.
⇒ Toda la superficie de gobernanza que hay construida no tiene con quién hablar. No es que esté mal conectada: es que no hay puerto.
⚠️ 2·4 · Una maqueta que no se declara
components/workspace-carbon/home usa estado sembrado y no lo dice en su cabecera. Las
otras cinco sí. La disciplina existe; ésta se saltó.
⚠️ 2·5 · El acoplamiento de roles hace insegura la primera concesión
Medido (g3): sólo 2 de 7 catalog_roles son exclusivos. Los demás están compartidos, y
el arrastre es total:
ws-viewer → arrastra a query-engines, sql-editor, ws-editor
ws-editor → arrastra a query-engines, sql-editor, ws-viewer
⇒ Un GRANT MODIFY TO ws-editor escrito en el catalog_role compartido se lo daría también
a ws-viewer. No es un cuello de botella: es escalada de privilegios en silencio.
⚠️ Y no es un defecto del modelo de Polaris —la relación catalog_role↔principal_role es
muchos-a-muchos por diseño—: es que hay que crear catalog_roles con propósito, no
reutilizar los compartidos.
3 · El plan — cada fase con su gate
| qué | gate | |
|---|---|---|
| SUP·1 | Cerrar las 3 huérfanas: crear la API o retirar la llamada. Nada que finja estar vivo | el censo da huérfanas 0 · trinquete en CI |
| SUP·2 | Un solo vocabulario de rol. Decidir cuál manda y proyectar los otros. ⭐ El candidato es principal_roles: es el que gobierna de verdad y del que ya se derivan los grants | la pantalla de Roles y la de Users enseñan los mismos nombres, leídos del mismo sitio |
| SUP·3 | La API de gobernanza, la mínima que la UI ya pide: GET/POST/DELETE de grants por objeto | conceder desde la UI cambia lo que un principal puede leer — medido por runQuery, no por la propia UI |
| SUP·4 | El aplicador con catalog_role DEDICADO (§2·5) | conceder a ws-editor no aparece en los grants de ws-viewer |
| SUP·5 | Roles de negocio: crear/borrar roles. Hoy hay 0 | un rol creado desde la UI recibe un grant y un miembro, y el gate lo ve aplicar |
| SUP·6 | Retirar las maquetas conforme se conecten, y declarar la que no lo hace (§2·4) | el censo da maquetas sólo donde se quiere que las haya |
⚠️ SUP·2 antes que SUP·3, y no al revés. Construir la API sobre un vocabulario que va a cambiar es escribir dos veces la misma cosa — y la segunda con datos ya guardados.
⚠️ SUP·4 antes de la primera concesión real. Si se concede algo con el acoplamiento vivo, el permiso de más ya está dado y hay que auditarlo para quitarlo.
4 · Lo que este censo NO dice
- Si una pantalla viva muestra datos correctos. Sólo dice que habla con alguien. La corrección la dice un gate.
- Si una API existente hace lo que la pantalla cree. El censo casa rutas, no contratos.
- Nada sobre las 27 vivas más allá de que lo están. Auditarlas es otro trabajo.