---
doc_id: doc:netbox:como-documentar
title: Cómo documentar y mantener sistemas en NetBox
project: netbox
area: ops
kind: guide
lang: es
visibility: public
tags:
  - project:netbox
  - area:ops
---

# Cómo documentar y mantener sistemas en NetBox

Guía operativa para incorporar recursos nuevos y actualizar recursos existentes en el inventario de NetBox de `iort`.

---

## Índice

1. [Antes de empezar](#1-antes-de-empezar)
2. [Cómo autenticarse en la API](#2-como-autenticarse-en-la-api)
3. [Decidir qué objeto NetBox crear](#3-decidir-que-objeto-netbox-crear)
4. [Campos obligatorios mínimos](#4-campos-obligatorios-minimos)
5. [Custom fields disponibles](#5-custom-fields-disponibles)
6. [Tags disponibles y cuándo usarlas](#6-tags-disponibles-y-cuando-usarlas)
7. [Flujo de trabajo para LLMs y operadores](#7-flujo-de-trabajo-para-llms-y-operadores)
8. [Plantillas por tipo de sistema](#8-plantillas-por-tipo-de-sistema)
9. [Qué no meter en NetBox](#9-que-no-meter-en-netbox)
10. [Referencia de IDs útiles](#10-referencia-de-ids-utiles)
11. [Checklist final para LLMs](#11-checklist-final-para-llms)

---

## 1. Antes de empezar

NetBox en `iort` es el **inventario estructurado**, no la fuente de verdad operativa de todo.

Antes de crear cualquier objeto, responde estas preguntas:

| Pregunta                            | Fuente real                                          |
| ----------------------------------- | ---------------------------------------------------- |
| ¿Cómo se desplegó?                  | Pulumi stack                                         |
| ¿Dónde están los secretos?          | Google Secret Manager (proyecto `iort-secrets`)      |
| ¿Dónde está el código?              | Repo git local o GitHub                              |
| ¿Quién es el responsable operativo? | Definir owner en NetBox                              |
| ¿A qué tenant pertenece?            | Ver [tenants disponibles](#10-referencia-de-ids-utiles) |

NetBox debe recoger: **identidad, relaciones, owner, tenant, estado, clasificación y enlaces externos**. No duplicar lo que ya está en esas otras fuentes.

---

## 2. Cómo autenticarse en la API

### URL base

```
https://iort-netbox.tailf75db9.ts.net
```

Solo accesible desde la tailnet de Tailscale. Verificar conectividad con:

```bash
curl -Ik "https://iort-netbox.tailf75db9.ts.net/api/"
```

Comportamiento esperado sin autenticación:

```bash
curl -Ik "https://iort-netbox.tailf75db9.ts.net/api/"
```

Devuelve `403`, que en este despliegue significa que la API está accesible por HTTPS dentro de la tailnet pero exige autenticación.

### Autenticación por token v2 (recomendada)

En NetBox `4.5.2` los tokens v2 sí se usan por cabecera HTTP. El formato correcto es:

```text
Authorization: Bearer nbt_<key>.<token>
```

Ejemplo de lectura:

```bash
NETBOX_TOKEN="nbt_<key>.<token>"

curl -s "https://iort-netbox.tailf75db9.ts.net/api/dcim/sites/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Accept: application/json" \
  | python3 -m json.tool
```

Ejemplo de escritura:

```bash
curl -s -X POST "https://iort-netbox.tailf75db9.ts.net/api/dcim/sites/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{...}'
```

Con autenticación por token no hace falta `X-CSRFToken`.

### Autenticación por sesión (opcional)

Si ya estás operando desde navegador o necesitas reproducir el flujo web con cookies, también puedes usar sesión:

```bash
CSRF="<valor_csrftoken>"
SESSION="<valor_sessionid>"
COOKIES="csrftoken=$CSRF; sessionid=$SESSION"

# Para peticiones de escritura (POST/PATCH/DELETE), añadir siempre:
#    -H "X-CSRFToken: $CSRF"
#    -H "Referer: https://iort-netbox.tailf75db9.ts.net/"
```

### Patrón recomendado para LLMs y agentes

Dentro de la tailnet, el patrón correcto es este:

1. usar `MCP` para leer, explorar y localizar el objeto canónico;
2. usar la `REST API` con token v2 para crear o editar;
3. volver a leer tras la escritura y verificar que el resultado final es el esperado;
4. añadir una entrada de `journal` con el contexto del cambio.

`MCP` en este despliegue es de solo lectura. No lo uses como canal de escritura.

### Credenciales de admin

Las credenciales de admin están en GSM bajo el secreto `iort-netbox-prod-netbox-admin-password` del proyecto `iort-secrets`. Úsalas para entrar a la UI por Tailscale y, si hace falta, generar un token v2 dedicado para automatización.

```bash
gcloud secrets versions access latest \
  --secret=iort-netbox-prod-netbox-admin-password \
  --project=iort-secrets
```

---

## 3. Decidir qué objeto NetBox crear

| Tipo de sistema                                       | Objeto NetBox a usar                    |
| ----------------------------------------------------- | --------------------------------------- |
| VPS / instancia cloud                                 | `VirtualMachine` dentro de un `Cluster` |
| Hardware físico o robot                               | `Device`                                |
| Web/app serverless (Cloudflare Pages, Firebase, etc.) | `Site` en grupo "Cloud"                 |
| Red / prefijo / VPN                                   | `Prefix`, `IPAddress`, `Tunnel`         |
| Componente sin identidad propia                       | `InventoryItem`                         |
| Puerto/endpoint publicado sobre una VM/Device         | `Service`                               |

**Regla clave:** no crees VMs ficticias para representar aplicaciones serverless o funciones cloud. Usa `Site` como punto de anclaje para proveedores externos sin infraestructura propia.

---

## 4. Campos obligatorios mínimos

Todo objeto de producción debe tener **como mínimo**:

- `name` — identificador humano, estable
- `slug` — kebab-case, sin cambiar después de crearlo
- `status: active`
- `tenant` — a qué organización/dominio pertenece
- `description` — una línea, qué es y en qué entorno
- al menos una `tag` de clasificación (ver sección 6)
- `custom_field.sot_system` — quién gestiona la fuente de verdad operativa

Y en `comments`, contexto operativo relevante (acceso, dependencias, IaC, política de secretos).

---

## 5. Custom fields disponibles

Estos custom fields están disponibles en los objetos de tipo `site`, `cluster` y `virtual_machine`:

| Campo                  | Tipo  | Qué poner                                                                               |
| ---------------------- | ----- | --------------------------------------------------------------------------------------- |
| `sot_system`           | texto | quién es la fuente de verdad operativa: `pulumi`, `cloudflare`, `scaleway`, `manual`... |
| `iac_stack`            | texto | nombre del stack: `cloudflare-pages`, `scaleway-vps`, nombre del stack Pulumi...        |
| `pulumi_stack_url`     | URL   | enlace directo al stack en Pulumi Cloud                                                 |
| `access_model`         | texto | `public`, `tailscale`, `vpn`, `private`                                                 |
| `service_tier`         | texto | `prod`, `staging`, `dev`                                                                |
| `gsm_secret_project`   | texto | proyecto de GSM donde están los secretos: `iort-secrets`                                |
| `gsm_secret_prefix`    | texto | prefijo del bundle de secretos: p.ej. `iort-netbox-prod-`                               |
| `backup_policy`        | texto | descripción de la política de backup                                                    |
| `runbook_ref`          | texto | ruta o URL al runbook operativo                                                         |
| `operator_portal_url`  | URL   | dashboard del proveedor o UI de gestión                                                 |
| `observed_hostname`    | texto | hostname observado en runtime (solo VMs/Devices)                                        |
| `observed_public_ipv4` | texto | IP pública observada (solo VMs/Devices)                                                 |
| `tailscale_dns`        | texto | FQDN de Tailscale (solo VMs/Devices)                                                    |
| `published_endpoints`  | JSON  | endpoints públicos en formato JSON                                                      |

---

## 6. Tags disponibles y cuándo usarlas

Tags de gestión (aplicar siempre una):

| Tag                 | Cuándo usar                           |
| ------------------- | ------------------------------------- |
| `managed-by-pulumi` | El recurso se gestiona con Pulumi IaC |
| `managed-by-manual` | Documentado a mano, sin IaC           |

Tags de acceso:

| Tag                | Cuándo usar                                       |
| ------------------ | ------------------------------------------------- |
| `exposure-public`  | Accesible desde Internet sin autenticación de red |
| `access-tailscale` | Accesible solo desde la tailnet                   |

Tags de entorno:

| Tag        | Cuándo usar |
| ---------- | ----------- |
| `env-prod` | Producción  |

Tags de proveedor/plataforma:

| Tag                | Cuándo usar                        |
| ------------------ | ---------------------------------- |
| `cloudflare`       | Cualquier recurso en Cloudflare    |
| `cloudflare-pages` | Desplegado en Cloudflare Pages     |
| `scaleway`         | Infraestructura en Scaleway        |
| `tailscale`        | Recurso con conectividad Tailscale |

Tags de proyecto (añadir la del proyecto correspondiente):

`iort`, `custochef`, `visort`, `ferrol`, ...

---

## 7. Flujo de trabajo para LLMs y operadores

### Patrón general

Antes de escribir en NetBox:

1. leer primero;
2. buscar por varias claves antes de crear nada;
3. editar el objeto canónico si ya existe;
4. crear padres antes que hijos;
5. no sobrescribir `comments` ni `custom_fields` sin haber leído el estado actual;
6. dejar siempre journal de lo que se hizo.

### Contrato de trabajo recomendado para un LLM

Antes de ejecutar una escritura, el LLM debería poder responder internamente a esto:

1. qué tipo de objeto principal va a tocar;
2. si va a `crear` o `editar`;
3. cuál es el objeto canónico o por qué no existe todavía;
4. qué campos exactos va a modificar;
5. qué datos siguen siendo inciertos y por tanto no debe inventar.

Si no puede responder esas cinco preguntas con claridad, no debería escribir todavía.

### Información mínima que un LLM debe reunir

Antes de crear o editar, intenta reunir como mínimo:

- nombre estable del sistema o proyecto;
- tipo de objeto principal esperado: `Site`, `VirtualMachine`, `Device`, `Service`, `Prefix` o similar;
- tenant;
- owner o equipo responsable;
- entorno: `prod`, `staging`, `dev`;
- modelo de acceso: `public`, `tailscale`, `vpn`, `private`;
- proveedor o fuente de verdad operativa: `pulumi`, `cloudflare`, `scaleway`, `manual`;
- hostname, dominio, URL pública o FQDN de Tailscale si aplica;
- stack IaC, repo, runbook y prefijo de secretos si existen.

Si faltan varios de esos datos, es mejor parar y pedir contexto adicional que inventarlos.

### Orden recomendado de modelado

Crear o editar en este orden cuando aplique:

1. `tenant`, `owner`, `contact` si faltan;
2. `region`, `site group`, `site`;
3. `cluster`;
4. `device` o `virtual machine`;
5. interfaces, IPs, prefijos o direccionamiento;
6. `service`;
7. tags, custom fields, comments y journal.

Errores comunes:

- crear una `VM` sin `site` ni `cluster` cuando ambos existen;
- modelar una web serverless como `VirtualMachine`;
- meter el endpoint como texto libre en `comments` sin crear `Service` cuando sí hay host real;
- crear objetos hijos antes de saber cuál es el padre correcto.

### Cómo buscar sin duplicar

Si no estás seguro de si algo ya existe, busca varias veces con criterios distintos y compara resultados. Ejemplo con lectura completa y filtrado local:

```bash
curl -s "https://iort-netbox.tailf75db9.ts.net/api/dcim/sites/?limit=200" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  | python3 - <<'PY'
import json, sys

needle = "nombre-o-fragmento".lower()
data = json.load(sys.stdin)
for item in data.get("results", []):
    haystack = " ".join([
        str(item.get("name") or ""),
        str(item.get("slug") or ""),
        str(item.get("description") or ""),
    ]).lower()
    if needle in haystack:
        print(item["id"], item.get("name"), item.get("slug"))
PY
```

Repite el patrón para `sites`, `devices`, `virtual-machines` o `clusters` antes de decidir crear.

### Flujo A — documentar un proyecto nuevo

#### Paso 1 — Autenticarse

Exportar un token v2 según la sección 2.

```bash
export NETBOX_TOKEN="nbt_<key>.<token>"
```

#### Paso 2 — Buscar si ya existe algo relacionado

Antes de crear nada, buscar candidatos por:

- nombre;
- slug;
- hostname;
- dominio o URL;
- tenant;
- stack Pulumi;
- tags;
- comentarios existentes.

Patrón mínimo de lectura por API:

```bash
# Sites existentes
curl -s "https://iort-netbox.tailf75db9.ts.net/api/dcim/sites/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  | python3 -c "import sys,json; d=json.load(sys.stdin); [print(t['id'],t['name'],t['slug']) for t in d['results']]"

# Tenants
curl -s "https://iort-netbox.tailf75db9.ts.net/api/tenancy/tenants/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  | python3 -c "import sys,json; d=json.load(sys.stdin); [print(t['id'],t['name']) for t in d['results']]"
```

Si el LLM tiene acceso al MCP del workspace, este es el orden recomendado:

1. consultar por MCP si ya existe un `Site`, `VirtualMachine`, `Device` o `Service` relacionado;
2. usar la API solo cuando ya esté claro qué objeto hay que crear o editar.

#### Paso 3 — Decidir si hay que crear o editar

Crear un objeto nuevo solo si no existe ya una identidad operativa equivalente.

Normalmente se edita si:

- el proyecto es el mismo y solo cambian descripción, tags, enlaces, comentarios o custom fields;
- la VM o device sigue siendo el mismo recurso lógico;
- cambió el dominio, el runbook o el stack, pero no la identidad principal.

Normalmente se crea un objeto nuevo si:

- aparece un nuevo entorno separado;
- el hostname o identidad operativa cambia de verdad;
- se sustituye un hardware por otro con lifecycle distinto;
- antes no existía el recurso en inventario.

#### Paso 4 — Crear el objeto principal

Crear primero el objeto principal y después sus relaciones o metadatos complementarios.

Ver plantillas en la sección 8.

Si el proyecto nuevo necesita más de un objeto, orden recomendado:

- proyecto cloud/serverless: `Site` y después, si aplica, servicios o enlaces operativos;
- VPS o nodo virtual: `Site` -> `Cluster` -> `VirtualMachine` -> `Service`;
- robot o hardware edge: `Site` -> `Device` -> interfaces/IPs -> `Service`.

#### Paso 5 — Añadir entrada en el journal

Siempre añadir una entrada de journal al objeto recién creado documentando el contexto de la creación:

```bash
curl -s -X POST "https://iort-netbox.tailf75db9.ts.net/api/extras/journal-entries/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "assigned_object_type": "dcim.site",
    "assigned_object_id": <ID_DEL_OBJETO>,
    "kind": "info",
    "comments": "## Registro inicial\n\nContexto de la creación, estado actual, pendientes."
  }'
```

Los `assigned_object_type` válidos son: `dcim.site`, `dcim.device`, `virtualization.virtualmachine`, `virtualization.cluster`.

#### Paso 6 — Verificar

Tras crear:

- releer el objeto por API o MCP;
- comprobar `name`, `slug`, `tenant`, `tags`, `custom_fields` y `comments`;
- abrir la `display_url` si hace falta validación visual;
- comprobar que no se ha duplicado un objeto existente.

### Flujo B — editar un proyecto existente

#### Paso 1 — Localizar el objeto canónico

No editar “a ciegas”. Primero identifica el objeto exacto y guarda su `id`.

Busca por más de una clave si hace falta:

- `name`
- `slug`
- hostname
- FQDN de Tailscale
- URL pública
- tenant
- tags
- referencias en `comments` o `custom_fields`

#### Paso 2 — Leer el estado actual completo

Ejemplo para un `Site` existente:

```bash
SITE_ID="<id>"

curl -s "https://iort-netbox.tailf75db9.ts.net/api/dcim/sites/${SITE_ID}/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  | python3 -m json.tool
```

Haz lo mismo con la ruta del tipo correspondiente si es una VM, device o cluster.

#### Paso 3 — Definir el alcance del cambio

Antes de editar, separa:

- datos que deben mantenerse;
- datos que deben corregirse;
- datos nuevos que hay que añadir;
- datos dudosos que no deben tocarse sin confirmación.

Regla práctica: si no estás seguro de un campo, no lo “normalices” por intuición.

Además, decide si el cambio es:

- `descriptivo`: descripción, comments, enlaces, tags, custom fields;
- `estructural`: cambiar padre, tenant, site, cluster, hostname o identidad principal;
- `de limpieza`: corregir duplicados, normalizar nombres, retirar datos erróneos.

Los cambios estructurales son los más peligrosos y deben hacerse con especial cuidado.

#### Paso 4 — Aplicar un `PATCH` mínimo

Editar solo los campos necesarios. Ejemplo de `PATCH` para un `Site`:

```bash
curl -s -X PATCH "https://iort-netbox.tailf75db9.ts.net/api/dcim/sites/${SITE_ID}/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Descripción actualizada",
    "comments": "Comentarios operativos actualizados",
    "tags": [{"id": 34}, {"id": 35}, {"id": 38}],
    "custom_fields": {
      "sot_system": "cloudflare",
      "service_tier": "prod",
      "access_model": "public"
    }
  }'
```

Recomendaciones:

- no cambies `slug` si no hay una razón fuerte;
- no borres `comments` útiles: léelos antes y reescríbelos de forma deliberada;
- no elimines tags o custom fields válidos por omisión accidental;
- si el cambio es grande, haz varios `PATCH` pequeños en vez de uno enorme.

### Cómo preservar datos existentes al editar

Antes de hacer `PATCH`, inspecciona explícitamente estas partes:

- `comments`
- `tags`
- `custom_fields`
- relaciones (`tenant`, `site`, `cluster`, `device role`, `platform`)

Regla operativa:

- si un campo ya contiene información válida, fusiónalo;
- no lo sustituyas por una versión más corta salvo que sea claramente una corrección;
- si el campo tiene mezcla de información buena y basura, limpia solo la basura y conserva lo útil.

Especialmente importante:

- `comments` debe seguir siendo un resumen operativo, no un dump enorme;
- `custom_fields` debe quedar consistente y no perder claves válidas;
- `tags` no deben reducirse por accidente al set mínimo del ejemplo.

### Estrategia segura para `comments`

`comments` debe quedar legible para humanos y LLMs. Patrón recomendado:

```markdown
## <nombre del sistema>

<qué es y para qué sirve>

### Acceso
- URL o hostname principal
- FQDN de Tailscale si aplica
- vía de acceso operativa

### IaC / Código
- stack o repo
- dashboard o URL relevante

### Secretos
- proyecto GSM
- prefijo de secretos

### Notas operativas
- dependencias
- límites
- pendientes relevantes
```

No metas en `comments`:

- secretos;
- logs completos;
- salidas enteras de CLI;
- tickets temporales o notas de sprint sin valor duradero.

#### Paso 5 — Registrar journal del cambio

Tras editar, añade una entrada de `journal` con:

- qué cambió;
- por qué cambió;
- fuente de verdad usada;
- pendientes o dudas que sigan abiertas.

#### Paso 6 — Verificación posterior

Después del `PATCH`:

- relee el objeto por API;
- confirma que no se han perdido tags ni custom fields;
- si el LLM usa MCP, vuelve a consultarlo por MCP para comprobar que el inventario leído coincide con el escrito.

Abrir en el navegador (desde Tailscale) la URL `display_url` devuelta en la respuesta de creación para confirmar visualmente.

---

## 8. Plantillas por tipo de sistema

### Web/app en Cloudflare Pages (Site)

```json
{
  "name": "<nombre-legible> (Cloudflare Pages)",
  "slug": "cf-pages-<proyecto>",
  "status": "active",
  "group": 1,
  "tenant": 1,
  "description": "Descripción breve. SPA/Web desplegada en Cloudflare Pages.",
  "comments": "## <nombre> — Web\n\n**URL pública:** https://dominio.io\n\n### Cloudflare Pages\n- Proyecto: <nombre-proyecto>\n- Account ID: <id>\n- Zone ID: <id>\n\n### Código fuente\n- Repo: <ruta>\n- Build: npm run build\n- Deploy: wrangler pages deploy dist\n\n### DNS\n- dominio.io CNAME → <proyecto>.pages.dev",
  "tags": [
    {"id": 34},
    {"id": 35},
    {"id": 36},
    {"id": 37},
    {"id": 38},
    {"id": 6},
    {"id": 8}
  ],
  "custom_fields": {
    "iac_stack": "cloudflare-pages",
    "sot_system": "cloudflare",
    "access_model": "public",
    "service_tier": "prod",
    "gsm_secret_project": "iort-secrets",
    "operator_portal_url": "https://dash.cloudflare.com/<account-id>/pages/view/<proyecto>"
  }
}
```

> IDs de tags en la plantilla: `34`=managed-by-manual, `35`=cloudflare, `36`=cloudflare-pages, `37`=exposure-public, `38`=env-prod, `6`=iort, `8`=infra.
> Verificar IDs actuales antes de usar (pueden cambiar si se añaden tags).

### VPS en Scaleway (VirtualMachine)

```json
{
  "name": "<hostname>",
  "status": "active",
  "cluster": 1,
  "site": 1,
  "tenant": 1,
  "platform": null,
  "description": "Descripción del servicio en una línea.",
  "comments": "## <hostname>\n\n**IP pública:** x.x.x.x\n**Tailscale:** <hostname>.tailf75db9.ts.net\n**Acceso:** tailscale ssh root@<hostname>\n\n### IaC\n- Pulumi stack: mmiguez/prod en proyecto iort-netbox\n- URL stack: https://app.pulumi.com/mmiguez/...\n\n### Secretos\n- Prefijo GSM: <prefijo>-\n- Proyecto GSM: iort-secrets",
  "tags": [
    {"id": 1},
    {"id": 2},
    {"id": 3},
    {"id": 38}
  ],
  "custom_fields": {
    "iac_stack": "<nombre-stack-pulumi>",
    "sot_system": "pulumi",
    "access_model": "tailscale",
    "service_tier": "prod",
    "gsm_secret_project": "iort-secrets",
    "gsm_secret_prefix": "<prefijo>-prod-",
    "tailscale_dns": "<hostname>.tailf75db9.ts.net"
  }
}
```

### Patch mínimo para editar un objeto existente

Cambiar solo la URL del detalle y el payload según el tipo de objeto:

```bash
curl -s -X PATCH "https://iort-netbox.tailf75db9.ts.net/api/<ruta-del-objeto>/<ID>/" \
  -H "Authorization: Bearer $NETBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Nueva descripción",
    "comments": "Comentarios actualizados",
    "tags": [{"id": 1}, {"id": 2}, {"id": 38}],
    "custom_fields": {
      "sot_system": "pulumi",
      "service_tier": "prod",
      "access_model": "tailscale"
    }
  }'
```

Úsalo como plantilla para:

- `dcim/sites`
- `dcim/devices`
- `virtualization/virtual-machines`
- `virtualization/clusters`

### Rutas API útiles

Lectura de listas:

- `/api/dcim/sites/`
- `/api/dcim/devices/`
- `/api/virtualization/virtual-machines/`
- `/api/virtualization/clusters/`
- `/api/tenancy/tenants/`
- `/api/extras/journal-entries/`

Lectura de detalle:

- `/api/dcim/sites/<id>/`
- `/api/dcim/devices/<id>/`
- `/api/virtualization/virtual-machines/<id>/`
- `/api/virtualization/clusters/<id>/`

Escritura habitual:

- `POST` a la colección para crear;
- `PATCH` al detalle para editar;
- `POST /api/extras/journal-entries/` para registrar contexto.

---

## 9. Qué no meter en NetBox

| ❌ No meter                               | ✅ Alternativa                                            |
| ---------------------------------------- | -------------------------------------------------------- |
| Contraseñas, tokens, claves privadas     | GSM (`iort-secrets`)                                     |
| Outputs completos de CLI o logs          | Journal con resumen, enlace al log                       |
| Configuración completa de un servicio    | Repo git + enlace en `runbook_ref`                       |
| IPs y DNS de Cloudflare o CDN externo    | Sí modelar el `Site`, no hacer IPAM de infra de terceros |
| VMs ficticias para funciones serverless  | `Site` en grupo Cloud                                    |
| Estado en tiempo real (uptime, métricas) | Grafana / observabilidad externa                         |
| Tickets efímeros o TODOs de sprint       | Jira/GitHub Issues; en journal solo hitos relevantes     |

---

## 10. Referencia de IDs útiles

Verificar con `GET /api/.../?limit=50` antes de usarlos, pueden cambiar.

### Tenants

| ID  | Nombre               |
| --- | -------------------- |
| 1   | IORT Shared Services |
| 2   | CustoChef            |

### Sites

| ID  | Nombre                     | Uso                                           |
| --- | -------------------------- | --------------------------------------------- |
| 1   | ES-MAD-SCW-01              | VPS Scaleway Madrid (site principal para VMs) |
| 3   | scw-fr-par-1               | Scaleway París                                |
| 4   | iort.io (Cloudflare Pages) | Web corporativa iort.io                       |

### Site Groups

| ID  | Nombre             |
| --- | ------------------ |
| 1   | Cloud              |
| 2   | Scaleway / Dedibox |

### Clusters

| ID  | Nombre                     | Tipo                  |
| --- | -------------------------- | --------------------- |
| 1   | es-mad-scw-vps-01          | VPS (Scaleway Madrid) |
| 2   | custochef111-service-hosts | Edge Service Host     |

### Tags más usadas

| ID  | Slug              |
| --- | ----------------- |
| 1   | managed-by-pulumi |
| 2   | access-tailscale  |
| 3   | backup-restic     |
| 4   | secret-ref-gsm    |
| 6   | iort              |
| 8   | infra             |
| 32  | scaleway          |
| 33  | tailscale         |
| 34  | managed-by-manual |
| 35  | cloudflare        |
| 36  | cloudflare-pages  |
| 37  | exposure-public   |
| 38  | env-prod          |

---

## Documentos relacionados

- `../docs/netbox/information-model.md`
- `../docs/netbox/secrets.md`
- `../docs/netbox/mcp-access.md`
- `../docs/netbox/validation.md`
- [Manual de uso completo](manual-de-uso.md)

---

## 11. Checklist final para LLMs

Antes de terminar una tarea de documentación en NetBox, comprueba esto:

- he confirmado que el acceso es dentro de Tailscale;
- he identificado si la operación era `create` o `edit`;
- he buscado duplicados por más de una clave;
- he elegido el tipo de objeto correcto;
- he preservado información útil ya existente;
- he evitado meter secretos;
- he dejado tags y custom fields coherentes;
- he releído el objeto final;
- he añadido journal si hubo creación o cambio relevante.

Si una de esas respuestas es “no”, la tarea probablemente no está cerrada del todo.

## Actualizacion propuesta por docu.iort

en Netbox
donde dice: técnicos de sistemas y redes 
 por favor pon:
técnicos de sistemas, informáticos  y redes
