# Accesos del equipo: quién entra a qué, y cómo se le da de alta

> **Qué es esto.** El registro único de los accesos del equipo de MacroBase a las tres cosas
> que necesita para trabajar: **la base de datos, los tiquetes y los repositorios**. Dice qué
> da cada rol, quién tiene qué hoy, y cómo se da de alta y de baja a una persona.
>
> **Por qué existe.** Hasta el 21-ago-2026 esto vivía en tres lugares que no se hablaban:
> `oci-dr-failback-camino-a/ACCESOS-SSH-Y-BASES.md` (sólo SSH y bases, y enterrado en el repo
> del plan de desastres), un censo de Freshdesk que quedó en un artefacto de un chat, y nada
> escrito sobre GitHub. Dar de alta a alguien era acordarse de tres procedimientos distintos.
>
> **Qué NO reemplaza.** El detalle técnico de bastiones, túneles y `authorized_keys` sigue en
> [`ACCESOS-SSH-Y-BASES.md`](https://github.com/macrobasegt/oci-dr/blob/main/ACCESOS-SSH-Y-BASES.md)
> y no se duplica acá — se enlaza. Este archivo es el **quién** y el **con qué rol**; aquél es
> el **cómo**.

---

## 1. Las tres puertas, y cuál conviene en cada caso

| Puerta | Para qué | Cómo se entra | Objetivo declarado |
|---|---|---|---|
| **Base de datos** | consultar y corregir datos de clientes | panel `/sql`, o SSH con túnel | **panel**; SSH sólo infraestructura |
| **Tiquetes** | atender la cola de Freshdesk | agente de Freshdesk | ya es el único camino |
| **Repositorios** | leer y proponer código | miembro de `macrobasegt` en GitHub | ya es el único camino |

⚠️ **Para la base, el SSH es la excepción, no el camino.** El objetivo declarado por Manuel el
7-ago-2026 es **«0 SSH»**: que el acceso a servidores quede sólo para infraestructura y todo lo
demás pase por el panel. Y el 14-ago lo precisó: *«la conexión en un ambiente controlado, ya sea
una función en el panel o una petición en el chat preautorizada»*.

**La pantalla `/sql` del panel ya cubre el caso normal**: lee todas las bases del servidor de
pruebas a la vez —293 al 1-ago-2026, cuando se desplegó—, con el permiso `sql_global_leer` que
el rol `soporte` ya trae. Antes de dar una llave SSH «para consultar la base», la pregunta es si
el panel no alcanza.

⚠️ **`/sql` está desplegado sólo contra pruebas.** Para producción no hay pantalla todavía.

---

## 2. Los perfiles: qué le toca a cada rol

Un perfil es el paquete completo. **Dar de alta a alguien es aplicarle su perfil entero en las
tres puertas**, no ir puerta por puerta acordándose de lo que falta.

⚠️ **El rol del panel es el que manda, y son exactamente cinco** — están en
`mb-deploy-panel/app/usuarios.py`, no son categorías inventadas para este archivo:
`admin`, `soporte_produccion`, `soporte`, `implementacion`, `solo_llave`. Lo de GitHub, Freshdesk
y SSH de las tablas de abajo **sí es convención de este archivo**, porque el panel todavía no
sabe de esas puertas — ver el §6.

| Rol del panel | En pantalla | Base de datos | Tiquetes | Repos | SSH |
|---|---|---|---|---|---|
| `solo_llave` | Sólo su llave de Freshdesk | **nada** | agente | — | — |
| `implementacion` | Implementación | ver, validar, desplegar y crear en **pruebas** | agente | `write` | nominal **sin `sudo`**, sólo si hace falta |
| `soporte` | Soporte | lo de implementación + producción (ver, desplegar, usuarios) + **`sql_global_leer`** | agente | `read` | — |
| `soporte_produccion` | Soporte + parámetros de producción — **el escalón que hoy usa todo soporte** | lo de soporte + `produccion_permisos` y `produccion_parametros` | agente | `read` | — |
| `admin` | Administrador | todo, incluido crear proyectos reales y tocar Apache | agente | `admin` | nominal **con `sudo`** |

Tres cosas que no se ven en la tabla y hay que saber:

- **`solo_llave` existe para gente que NO trabaja en el panel** pero necesita que Claude trabaje
  sus tiquetes con su usuario — Ventas, por ejemplo. Entra, registra su llave de Freshdesk y no
  puede hacer nada más, ni ver los sitios.
- ⚠️ **`soporte_produccion` nació para probarse con una sola persona y hoy son cinco.** Se creó
  como rol aparte, y no como un permiso más de `soporte`, justamente para probarlo a fondo antes
  de dárselo al equipo — el comentario del código todavía lo dice así. Ya se extendió, así que la
  decisión que quedó pendiente (fundirlo con `soporte` o dejarlo) está vencida. **Y nadie tiene
  `soporte` a secas**: los cinco están en el escalón de arriba.
- **Ni `soporte` ni `soporte_produccion` llevan `estructura_bd`**: eso corre migraciones sobre la
  base del cliente y un error ahí no se deshace con un botón.

### El SSH no es un rol, es una excepción

No hay un rol «infraestructura» en el panel. **Tener `sudo` por SSH es una excepción nominal**, y
hoy son tres personas: Manuel, María y Christian.

> ⚠️ **La excepción de María está medida, no es un favor**: es la única del equipo cuyo uso de
> SSH es sobre todo *editar archivos* — 753 ediciones contra 64 actualizaciones de sitio, cuando
> el resto es casi sólo actualizar y navegar. Lo que ella hace a mano es justo lo que el panel
> tiene que aprender a reproducir antes de que «0 SSH» sea posible.

---

## 3. Quién tiene qué hoy

### 3a. Tiquetes — Freshdesk (medido el 21-ago-2026)

**19 agentes activos de 23.** El offboarding acá sí se hace: Alan García, Javier Morales,
Ingrid de De Bustamante y Gabriel Lucas ya están desactivados.

⚠️ **Dos de los 19 activos no son de MacroBase, son de Freshworks**, el proveedor, y tienen el
mismo acceso a los tiquetes que el equipo:

| Agente | Correo | Última entrada |
|---|---|---|
| Dharani Dharan | `dharanidharan.s@freshworks.com` | sin entrar desde feb-2026 |
| «Soporte Macrobase» | `adhithyan.suresh@freshworks.com` | sin entrar desde jun-2026 |

⚠️ **Para saber si un agente está activo se mira `deactivated`, NO `contact.active`.** Ese
segundo campo describe el contacto y sigue en `true` en agentes ya dados de baja.

### 3b. Repositorios — GitHub, organización `macrobasegt` (medido el 21-ago-2026)

**8 miembros.** El permiso de la columna es el efectivo sobre `mbinv`:

| Usuario de GitHub | Persona | Rol en la org | Permiso en `mbinv` |
|---|---|---|---|
| `mbustamante59` | Manuel | **admin** | admin |
| `abustamanteMB` | **María** (no «Andrea» — ver abajo) | **admin** | admin |
| `berickp` | Erick Pineda | member | write |
| `EmiliaGiron1` | Emilia Girón | member | write |
| `jdeleon-mb` | Josué de León | member | write |
| `mbCV593` | Christian Velásquez | member | write |
| `sgarciamacro` | Saraí García | member | write |
| `JPerez-mb` | Jorge Andrés Pérez | member | **read** |

⚠️ **`abustamanteMB` es María**, aunque su nombre completo lleve Andrea y Freshdesk la muestre
como «Andrea Bustamante». **«Andrea» o «Andreita» es Andrea Mancilla, otra persona**, de primera
línea de soporte. Decirle «Andrea» a `abustamante` apunta a la otra.

### 3c. Servidores — SSH (medido el 21-ago-2026)

`clave`: **P**=activa, **L**=bloqueada. `llaves`: cuántas hay en su `authorized_keys`.

**Bastión de Ashburn** — `mb-oracle-public-access`, `132.226.40.48:22`

| Cuenta | clave | llaves | sudo |
|---|---|---|---|
| `macrobase` | P | 4 | **sí** |
| `ubuntu` | L | 8 | **sí** |
| `maria` | L | 1 | **sí** |
| `josue_cert` | P | 0 | **sí** |
| `opc` | L | 1 | no |

**Producción — `app4-mayo-2-2026`**, por `132.226.40.48:4072`

| Cuenta | clave | llaves | sudo |
|---|---|---|---|
| `macrobase` | P | 5 | **sí** |
| `ubuntu` | L | 6 | **sí** |
| `maria` | P | 1 | **sí** |
| `manuel` | P | 0 | **sí** |
| `erick` | P | 0 | **sí** |
| `christian` | P | 0 | **sí** |
| `emilia` | L | 0 | sí (bloqueada) |
| `joel` | L | 0 | sí (bloqueada) |
| `josue` | L | 0 | sí (bloqueada) |
| `opc` | L | 4 | no |

**Pruebas — `mb-oracle-pruebas` (10.0.1.14)**, por `132.226.40.48:4074`

| Cuenta | clave | llaves | sudo |
|---|---|---|---|
| `macrobase` | P | 7 | **sí** |
| `ubuntu` | L | 9 | **sí** |
| **`erick`** | P | **1** | **no** ← nominal, 21-ago-2026 |
| `maria` | L | 1 | **sí** |
| `manuel` | P | 0 | **sí** |
| `programacion` | P | 0 | **sí** |
| `sarai` | P | 0 | **sí** |
| `servidordatos` | P | 0 | **sí** |
| `josue` | L | 0 | sí (bloqueada) |
| `opc` | L | 1 | no |

**Bitácora — `mb-oracle-pruebas-bitacora`**, por `132.226.40.48:4073`

Sólo `macrobase` (P, 4 llaves, sudo), `ubuntu` (L, 3, sudo) y `opc` (L, 1). Nadie del equipo
tiene cuenta nominal ahí.

### 3d. Panel de despliegues — quién tiene qué rol

Medido el 21-ago-2026 contra la tabla `equipo` de la base del panel, que es la fuente — **no la
semilla `EQUIPO_INICIAL` del repo**, que ya no coincide con nada. El panel corre en `oci-mbinv`,
con la base en `/var/lib/mb-deploy-panel/panel.db`.

| Rol | Quiénes | Número |
|---|---|---|
| `admin` | `abustamante` (María), `mbustamante` (Manuel) | 00, — |
| `soporte_produccion` | `epineda`, `jdeleon`, `egiron`, `ltomas`, `jiquite` | 01, 02, 17, 07, 12 |
| `implementacion` | `amancilla`, `cvelasquez`, `jperez`, `lbustamante`, `sgarcia` | 13, 14, 51, 05, 50 |
| `solo_llave` | `bgarcia`, `iguzman`, `ksolano` | 90, 91, 92 |

Cómo se comprueba:

```bash
ssh oci-mbinv
sudo sqlite3 -header -column /var/lib/mb-deploy-panel/panel.db \
  "SELECT usuario, rol, numero FROM equipo ORDER BY rol, usuario;"
```

Tres cosas que dice esta tabla y conviene no pasar por alto:

- ⚠️ **`soporte_produccion` ya no es «una sola persona en prueba».** El comentario del código
  dice que se creó como rol aparte para probarlo con una persona antes de dárselo al equipo, y
  **hoy son cinco**. Toca decidir lo que ese comentario dejó pendiente: fundirlo con `soporte` o
  dejarlo.
- **Nadie tiene el rol `soporte` a secas.** Los cinco de soporte están en el escalón de arriba.
- **`jdeleon` tiene `soporte_produccion` en el panel y la cuenta de SSH bloqueada en los cuatro
  servidores.** Ése es exactamente el modelo de «0 SSH» funcionando: se le quitó el servidor y
  se le dio la pantalla.

### 3e. Base de datos — MySQL

⚠️ **Este bloque es del 14-ago-2026 y NO se re-midió el 21-ago.** La credencial guardada en el
servidor (`manuel@10.0.1.38`) da `Access denied` contra `prod.db.interno` y `pruebas.db.interno`,
así que hace falta otra para volver a contarlo. **Tratarlo como fechado, no como vigente.**

En **producción (3309)** había **10 cuentas activas, todas con `SELECT INSERT UPDATE DELETE DROP
GRANT CREATE USER` desde `%`**: `manuel`, `erick`, `maria`, `josue`, `emilia`, `christian`,
`joel`, más los servicios `Macrored`, `macrobase` y `macroapps`.

⚠️ **`joel` no corresponde a ningún agente de Freshdesk** y se seguía conectando a producción con
poder total. Es la única cuenta sin dueño identificable.

⚠️ **En pruebas (3310) hay cuentas con nombre de CLIENTE con permisos totales sobre todo el
servidor**: `sally`, `cookieshop`, `servidordatos`, `usuario_sha2`. En producción esas mismas
cuentas sí están acotadas a su base, o sea es descuido del servidor de pruebas, no regla de la
casa.

---

## 4. Cómo se da de alta a alguien, hoy

**Hoy son tres procedimientos separados y manuales.** El §6 dice qué haría falta para que sea uno
solo.

1. **Tiquetes.** Crear el agente en Freshdesk y meterlo en su grupo.
2. **Repos.** Invitarlo a la organización `macrobasegt` con el permiso de su perfil.
   `read` para soporte, `write` para programación.
3. **Base.** Crear su usuario en el panel con el rol de su perfil (`/equipo`, permiso
   `cuentas_equipo`). **Ese es el camino normal y no necesita SSH.**
4. **SSH, sólo si el perfil lo lleva.** Nunca metiendo la llave en `macrobase`:

   ```bash
   ./24-crear-cuenta-persona.sh --ver   <cuenta> <destino> <archivo.pub>   # primero mirar
   ./24-crear-cuenta-persona.sh --hacer <cuenta> <destino> <archivo.pub>
   ```

   `<destino>` es `bastion` | `4072` (producción) | `4073` (bitácora) | `4074` (pruebas).
   El guion vive en el repo `oci-dr`.

### Las reglas que no se saltan

- **La persona genera su propio par**, con `ssh-keygen -t ed25519`. La llave privada no sale de
  su máquina y **nunca se manda por correo ni por WhatsApp**. Manda sólo el `.pub`.
- **El comentario de la llave ES el registro.** Convención: `<persona-o-servicio>@<para-qué>`,
  en minúsculas, sin rutas y sin nombres de máquina de Windows. Hoy hay llaves vivas cuyo
  comentario es la ruta del archivo en el disco de Manuel, y **nadie sabe de quién son**.
- **Nunca en la cuenta compartida.** `macrobase` es root sin contraseña (`%sudo NOPASSWD:ALL`) y
  **la comparten clientes**. Meter a alguien ahí lo pone en la misma cuenta que ellos, y la
  bitácora dice «entró macrobase», no quién. ⚠️ **Y no son los mismos clientes en cada máquina**,
  así que sacar a uno de un servidor no lo saca del otro (medido el 21-ago-2026):

  | Servidor | Llaves de cliente dentro de `macrobase` |
  |---|---|
  | Bastión | 3 — Megacentro, Honduras y Servir |
  | Pruebas | 3 — Megacentro, Servirsa y Vistares |

  Sólo **Megacentro** está en las dos. Los comentarios completos de cada llave están en
  `ACCESOS-SSH-Y-BASES.md` y en los servidores; acá va el conteo a propósito, para no repartir
  correos y nombres de máquina de terceros por un repo que leen ocho personas.
- **Cuenta nominal sin `sudo` salvo que el perfil lo pida.** Y ⚠️ **quitar `sudo` puede ser dos
  cosas**: sacar del grupo (`deluser <u> sudo`) **y** borrar `/etc/sudoers.d/<u>` si existe —
  hoy existe para `maria`. Se comprueba con `sudo -l -U <usuario>`, que es el resultado y no el
  test.
- **Comprobarlo desde la máquina de la persona**, no desde la de Manuel.

## 5. Cómo se da de baja

**Bloquear la contraseña ES el control**, porque casi ninguna cuenta tiene `authorized_keys`:

```bash
sudo passwd -l <usuario>        # bloquear
sudo passwd -S <usuario>        # P=activa, L=bloqueada, NP=sin clave
sudo lastlog -u <usuario>       # último acceso real
```

⚠️ **Pero a quien SÍ tiene llave, bloquearle la contraseña no le quita nada.** Ahí hay que sacar
la llave del `authorized_keys` además. Hoy eso aplica a `maria` y a `erick`.

⚠️ **Y hay que recorrer los cuatro servidores, no uno.** El cierre de accesos del 14-ago-2026
estaba bien hecho en producción y **se había olvidado `mb-oracle-pruebas`**, donde Josué siguió
entrando hasta el 10-ago. Es el error que produce tener tres «pruebas» distintos.

**La baja completa son ocho lugares:** los **cuatro** servidores (bastión, producción, pruebas y bitácora), el panel, Freshdesk, GitHub y la
base de datos.

---

## 6. Lo que falta: el perfil que da todo de una

Pedido por Manuel el 21-ago-2026: *«crear un perfil de usuario que cuando se le dé de alta a un
agente le dé todos los permisos y privilegios del rol»*.

**Hoy no existe.** El panel ya tiene la mitad: `/equipo`, el permiso `cuentas_equipo` y
`registrar_cuenta(persona, correo, usuario)` con enlace de alta. Lo que falta es que ese alta
dispare las otras tres puertas.

Lo que habría que construir, en orden de lo que menos cuesta:

1. **Que el alta del panel lleve el perfil**, no sólo el rol del panel: elegir `SOPORTE` y que
   quede registrado que a esa persona le corresponde `read` en GitHub y agente en Freshdesk.
2. **Que el panel muestre el desvío.** Comparar lo que el perfil dice contra lo medido en cada
   puerta, y marcar en rojo lo que no coincide. Esto solo ya resuelve el problema real, que no es
   dar de alta sino **enterarse de lo que sobró**.
3. **Que el alta lo aplique**: invitación a GitHub por API, agente de Freshdesk por API, y la
   cuenta nominal por SSH con `24-crear-cuenta-persona.sh`.
4. **Y la baja igual**, que es la mitad que siempre se olvida.

⚠️ **El censo de este archivo se va a desactualizar solo.** La tabla equivalente en
`ACCESOS-SSH-Y-BASES.md` dice «12-ago, revisado el 17-ago» y ya estaba vieja el 21. Lo que no se
mide, se supone. **El paso 2 de arriba es el que arregla eso de verdad**; mientras no exista, hay
que volver a medir antes de creerle a estas tablas.

---

## 7. Hallazgos abiertos al 21-ago-2026

Ninguno de éstos se arregló; están acá para que no se pierdan.

1. **`macrobase` es root sin contraseña y lo comparten clientes**, en el bastión y también en
   `mb-oracle-pruebas` (`(ALL:ALL) NOPASSWD: ALL`, verificado). Cada llave de esa lista es acceso
   total, y **los clientes no son los mismos en las dos máquinas** — ver la tabla del §4.
2. **Las ocho cuentas de `mb-oracle-pruebas` estaban en el grupo `sudo`** — incluida
   `servidordatos`, que es nombre de cliente. Ahí **no existe una cuenta de sólo consulta**: dar
   cuenta propia no acota nada si no se saca del grupo a propósito. Erick ya está fuera; los
   demás no.
3. **`josue_cert` entra por contraseña de verdad** en el bastión. Apagar
   `PasswordAuthentication` le corta el acceso sin aviso. Orden propuesto: `fail2ban` → pasarlo a
   llave → recién ahí apagar la contraseña.
4. **`joel` sigue sin dueño** y con poder total sobre la base de producción (dato del 14-ago).
5. **Dos agentes de Freshworks** tienen el mismo acceso a los tiquetes que el equipo.
6. **Los puertos de bases no pasan por `sshd`** — son reenvíos de nginx —, así que una conexión
   a `132.226.40.48:3309` **no deja rastro en `auth.log`**. Que una llave no se use en un mes no
   significa que esa persona no entre: puede estar entrando sólo a la base.

---

## Ver también

- [`ACCESOS-SSH-Y-BASES.md`](https://github.com/macrobasegt/oci-dr/blob/main/ACCESOS-SSH-Y-BASES.md)
  — bastiones, túneles, puertos y el procedimiento técnico de llaves.
- [`REGLAS-EQUIPO.md`](REGLAS-EQUIPO.md) — cómo se reparte el trabajo.
- [`CONVENCIONES-CLAUDE.md`](CONVENCIONES-CLAUDE.md) — cómo se trabaja con Claude.
