---
doc_id: doc:platform:guia-equipo
title: Guia de uso para el equipo
project: platform
area: ops
kind: guide
lang: es
visibility: public
tags:
  - platform:docu-iort
  - tech:cloudflare
---

# Guia de uso para el equipo

Fecha: 2026-04-27

Esta guia explica como acceder a docu.iort y como usar sus superficies principales: web documental, chat, API, MCP y operaciones de mantenimiento. No contiene secretos. Los secretos se referencian solo por nombre de Google Secret Manager (GSM).

## 1. Entornos y URLs

| Superficie | Production | Staging | Acceso |
| --- | --- | --- | --- |
| Web documental | `https://docu.iort.io` | `https://staging.docu.iort.io` | Production publica; staging protegido por Cloudflare Access. |
| Chat | `https://chat.docu.iort.io` | `https://chat-staging.docu.iort.io` | Lectura/preguntas publicas; escritura protegida por Cloudflare Access humano. |
| API | `https://api.docu.iort.io` | `https://api-staging.docu.iort.io` | Cloudflare Access Service Auth. |
| MCP | `https://mcp.docu.iort.io/mcp` | `https://mcp-staging.docu.iort.io/mcp` | Cloudflare Access Service Auth. |
| API externa | `api-ext.docu.iort.io` | No aplica | No publicada en esta version. |
| MCP externo | `mcp-ext.docu.iort.io` | No aplica | No publicado en esta version. |

## 2. Secretos GSM de referencia

No imprimir estos valores en terminal, logs, issues ni PRs. Usarlos solo como entrada a scripts o variables locales.

| GSM secret | Uso |
| --- | --- |
| `infra_iort_io` | Token Cloudflare account-scoped usado por `scripts/bootstrap/export_cloudflare_env.sh`, Pulumi, Wrangler y scripts bootstrap. |
| `infra_iort_io_account_id` | Account ID Cloudflare que acompana al token `infra_iort_io`. `export_cloudflare_env.sh` lo carga como `CLOUDFLARE_ACCOUNT_ID`. |
| `cloudflare-api-token` | Token Cloudflare alternativo/historico. Los scripts actuales usan `infra_iort_io`. |
| `docu_iort_access_docu_iort_ci` | Service token de Cloudflare Access para CI, smoke tests y llamadas operativas a API/MCP. |
| `docu_iort_access_docu_iort_chat_internal` | Service token usado por el Worker de chat para llamar internamente a API. |
| `docu_iort_access_docu_iort_external_reader_bootstrap` | Service token reservado para futuros lectores externos read-only. `api-ext` y `mcp-ext` siguen deshabilitados. |
| `docu_iort_github_app` | JSON de GitHub App usado como `GITHUB_APP_CREDENTIALS` en API staging/production. |
| `docu_iort_logpush_r2_access_key_id` | Access Key ID R2 S3 para Logpush a `docu-iort-logs` y `docu-iort-logs-staging`. |
| `docu_iort_logpush_r2_secret_access_key` | Secret Access Key R2 S3 para Logpush. |

El `account_id` de Cloudflare se obtiene desde GSM `infra_iort_io_account_id`. No es necesario copiarlo manualmente en los comandos.

## 3. Preparar una terminal operativa

Desde la raiz del repo:

```bash
source scripts/bootstrap/export_cloudflare_env.sh
```

Ese script exporta:

- `CLOUDFLARE_ACCOUNT_ID`
- `CLOUDFLARE_ZONE_ID`
- `CLOUDFLARE_API_TOKEN`

`CLOUDFLARE_ACCOUNT_ID` sale de `infra_iort_io_account_id` y `CLOUDFLARE_API_TOKEN` sale de `infra_iort_io`.

Para preparar cabeceras de Access Service Auth sin imprimir secretos:

```bash
token_json="$(gcloud secrets versions access latest --secret=docu_iort_access_docu_iort_ci)"
client_id="$(TOKEN_JSON="$token_json" node -e 'process.stdout.write(JSON.parse(process.env.TOKEN_JSON).client_id)')"
client_secret="$(TOKEN_JSON="$token_json" node -e 'process.stdout.write(JSON.parse(process.env.TOKEN_JSON).client_secret)')"
authorization_header_json="$(TOKEN_JSON="$token_json" node -e 'process.stdout.write(JSON.parse(process.env.TOKEN_JSON).authorization_header_json)')"
```

Al terminar:

```bash
unset token_json client_id client_secret authorization_header_json
```

## 4. Web documental

La web documental publica contiene el catalogo navegable de documentos y proyectos.

Uso normal:

1. Abrir `https://docu.iort.io`.
2. Usar la navegacion lateral para ir a proyectos, arquitectura, glosario o tags.
3. Usar la busqueda de MkDocs para encontrar contenido textual.

Staging:

```text
https://staging.docu.iort.io
```

Staging esta pensado para validar cambios antes de production. Si Cloudflare Access solicita login, usar una cuenta autorizada del dominio corporativo.

## 5. Chat

El chat esta pensado para preguntas sobre la documentacion y para iniciar cambios documentales controlados.

URLs:

```text
Production: https://chat.docu.iort.io
Staging:    https://chat-staging.docu.iort.io
```

Lectura publica temporal:

- `GET /`
- `POST /api/search`
- `POST /api/ask`

Escritura protegida por Cloudflare Access humano:

- `POST /api/propose`
- `POST /api/pull-request`

### 5.1 Preguntar desde navegador

1. Abrir `https://chat.docu.iort.io`.
2. Escribir una pregunta, por ejemplo: `puedo ver en NetBox la IP de un servidor?`
3. Revisar la respuesta y las fuentes citadas.

### 5.2 Preguntar desde terminal

```bash
curl -fsS \
  -H "Content-Type: application/json" \
  -d '{"query":"puedo ver en NetBox la IP de un servidor?","limit":5}' \
  https://chat.docu.iort.io/api/ask | node -e '
let data = "";
process.stdin.on("data", (chunk) => data += chunk);
process.stdin.on("end", () => {
  const payload = JSON.parse(data);
  console.log(payload.answer);
  console.log(JSON.stringify(payload.sources, null, 2));
});'
```

### 5.3 Buscar documentos desde terminal

```bash
curl -fsS \
  -H "Content-Type: application/json" \
  -d '{"query":"NetBox","limit":5}' \
  https://chat.docu.iort.io/api/search | node -e '
let data = "";
process.stdin.on("data", (chunk) => data += chunk);
process.stdin.on("end", () => {
  const payload = JSON.parse(data);
  console.log(JSON.stringify(payload.docs, null, 2));
});'
```

### 5.4 Proponer cambios documentales

La escritura debe hacerse desde el chat autenticado con Cloudflare Access. El flujo esperado es:

1. Abrir `https://chat.docu.iort.io`.
2. Autenticarse cuando Cloudflare Access lo pida.
3. Pedir un cambio documental concreto.
4. Revisar la propuesta, diff y auditoria.
5. Crear PR si la propuesta es correcta.

El sistema debe crear ramas/PRs contra `develop`. No debe escribir en `main`.

## 6. API HTTP

La API esta protegida por Cloudflare Access Service Auth. Usar el service token `docu_iort_access_docu_iort_ci` para llamadas operativas.

Base URLs:

```text
Production: https://api.docu.iort.io
Staging:    https://api-staging.docu.iort.io
```

### 6.1 Health

Con cabeceras separadas:

```bash
curl -fsS \
  -H "CF-Access-Client-Id: $client_id" \
  -H "CF-Access-Client-Secret: $client_secret" \
  https://api.docu.iort.io/v1/health | node -e '
let data = "";
process.stdin.on("data", (chunk) => data += chunk);
process.stdin.on("end", () => {
  const payload = JSON.parse(data);
  console.log(JSON.stringify({
    ok: payload.ok,
    ai_search: payload.ai_search,
    git_auth_mode: payload.git_auth_mode,
    write_mode: payload.write_mode,
    ai_gateway: payload.ai_gateway
  }, null, 2));
});'
```

Con cabecera unica `Authorization`:

```bash
curl -fsS \
  -H "Authorization: $authorization_header_json" \
  https://api.docu.iort.io/v1/health
```

Valores esperados relevantes:

- `ai_search=true`
- `git_auth_mode=github_app`
- `write_mode=proposal_only`
- `ai_gateway.enabled=true`

### 6.2 Preguntar al RAG

```bash
curl -fsS \
  -H "CF-Access-Client-Id: $client_id" \
  -H "CF-Access-Client-Secret: $client_secret" \
  -H "Content-Type: application/json" \
  -d '{"query":"puedo ver en NetBox la IP de un servidor?","limit":5}' \
  https://api.docu.iort.io/v1/ask | node -e '
let data = "";
process.stdin.on("data", (chunk) => data += chunk);
process.stdin.on("end", () => {
  const payload = JSON.parse(data);
  console.log(payload.answer);
  console.log("retrieval.mode =", payload.retrieval?.mode);
  console.log(JSON.stringify(payload.sources, null, 2));
});'
```

Valor esperado:

```text
retrieval.mode = hybrid
```

### 6.3 Buscar documentos

```bash
curl -fsS \
  -H "CF-Access-Client-Id: $client_id" \
  -H "CF-Access-Client-Secret: $client_secret" \
  "https://api.docu.iort.io/v1/docs/search?q=NetBox&limit=5"
```

### 6.4 Endpoints de escritura

Los endpoints de escritura de API existen para el flujo del chat, pero requieren contexto humano de Access. Para uso normal del equipo, crear propuestas y PRs desde el chat, no llamando directamente a API.

## 7. MCP

El MCP expone herramientas para clientes compatibles con Model Context Protocol. Esta protegido por Cloudflare Access Service Auth.

Base URLs:

```text
Production: https://mcp.docu.iort.io/mcp
Staging:    https://mcp-staging.docu.iort.io/mcp
```

### 7.1 Ver health y herramientas

```bash
curl -fsS \
  -H "CF-Access-Client-Id: $client_id" \
  -H "CF-Access-Client-Secret: $client_secret" \
  https://mcp.docu.iort.io/mcp
```

### 7.2 Listar herramientas por JSON-RPC

```bash
curl -fsS \
  -H "CF-Access-Client-Id: $client_id" \
  -H "CF-Access-Client-Secret: $client_secret" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
  https://mcp.docu.iort.io/mcp
```

### 7.3 Usar `ask_docs`

```bash
curl -fsS \
  -H "CF-Access-Client-Id: $client_id" \
  -H "CF-Access-Client-Secret: $client_secret" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"ask_docs","arguments":{"query":"puedo ver en NetBox la IP de un servidor?","limit":5}}}' \
  https://mcp.docu.iort.io/mcp | node -e '
let data = "";
process.stdin.on("data", (chunk) => data += chunk);
process.stdin.on("end", () => {
  const payload = JSON.parse(data);
  const text = payload.result?.content?.[0]?.text || "{}";
  const parsed = JSON.parse(text);
  console.log(parsed.answer);
  console.log(JSON.stringify(parsed.sources, null, 2));
});'
```

Respuesta esperada:

- `answer`: texto de respuesta.
- `sources`: lista de fuentes documentales.

## 8. Operaciones de mantenimiento

### 8.1 Reindexar RAG

Tras cambios documentales o tras un `pulumi up` que toque API/MCP:

```bash
DEPLOY_WORKERS=1 scripts/bootstrap/reindex_ai_search.sh staging
DEPLOY_WORKERS=1 scripts/bootstrap/reindex_ai_search.sh production
```

Esto:

- construye catalogo, chunks y grafo;
- aplica migraciones y seeds D1;
- sube documentos a R2 para AI Search;
- reindexa Vectorize y AI Search;
- redeploya API/MCP con binding `AI_SEARCH`.

### 8.2 Smoke tests

Staging:

```bash
BASE_DOCS=https://staging.docu.iort.io \
BASE_CHAT=https://chat-staging.docu.iort.io \
BASE_API=https://api-staging.docu.iort.io \
BASE_MCP=https://mcp-staging.docu.iort.io/mcp \
scripts/bootstrap/09_smoke_tests.sh
```

Production:

```bash
BASE_DOCS=https://docu.iort.io \
BASE_CHAT=https://chat.docu.iort.io \
BASE_API=https://api.docu.iort.io \
BASE_MCP=https://mcp.docu.iort.io/mcp \
scripts/bootstrap/09_smoke_tests.sh
```

### 8.3 Logpush

Logpush envia `workers_trace_events` a R2:

- `docu-iort-logs-staging`
- `docu-iort-logs`

Configurar o reparar:

```bash
scripts/bootstrap/configure_logpush.sh staging
scripts/bootstrap/configure_logpush.sh production
```

El script usa destino S3-compatible porque los buckets son EU:

```text
${CLOUDFLARE_ACCOUNT_ID}.eu.r2.cloudflarestorage.com
```

### 8.4 Rate limiting

La cuenta Cloudflare solo permite una regla en `http_ratelimit`. Por eso el script configura una regla combinada para staging y production:

```bash
scripts/bootstrap/configure_rate_limits.sh production
```

Regla esperada:

```text
docu-iort-surface-all
```

Limite actual:

```text
10 requests / 10 seconds
```

## 9. Queues, Workflows y Workers internos

Workers internos:

- `docu-iort-ingest`
- `docu-iort-ingest-staging`
- `docu-iort-monitor`
- `docu-iort-monitor-staging`

Queues:

- `docu-iort-index`
- `docu-iort-write`
- `docu-iort-classify`
- equivalentes `-staging`
- DLQs correspondientes `*-dlq`

Workflows canary:

- `docu-iort-ingest`
- `docu-iort-doc-write`
- `docu-iort-maintenance`
- equivalentes `-staging`

El monitor tiene cron triggers configurados desde Pulumi.

## 10. Reglas de seguridad

- No escribir secretos en Git.
- No imprimir secretos en terminal compartida, tickets, PRs ni logs.
- No publicar `api-ext` ni `mcp-ext` sin rate limiting y scopes read-only.
- API/MCP deben permanecer protegidos por Cloudflare Access Service Auth.
- El chat puede estar publico para lectura/preguntas en esta fase, pero la escritura debe requerir Access humano.
- No escribir en `main`; los cambios documentales deben ir por PR contra `develop`.
- No cambiar el modelo de embeddings sin recrear/reindexar AI Search. Modelo oficial: `@cf/qwen/qwen3-embedding-0.6b`.
- Modelo conversacional oficial: `@cf/moonshotai/kimi-k2.6`.
