{"id":11826,"date":"2026-05-08T15:00:31","date_gmt":"2026-05-08T13:00:31","guid":{"rendered":"https:\/\/bitacora.eniac2000.com\/?p=11826"},"modified":"2026-05-08T15:00:33","modified_gmt":"2026-05-08T13:00:33","slug":"correccion-de-bugs-en-plugins-wordpress-con-claude-code-un-caso-de-asistencia-experta-para-administracion-de-sistemas-it","status":"publish","type":"post","link":"https:\/\/bitacora.eniac2000.com\/?p=11826","title":{"rendered":"Correcci\u00f3n de bugs en plugins WordPress con Claude Code. Un caso de asistencia experta para administraci\u00f3n de sistemas IT"},"content":{"rendered":"\n<p>Hay un tipo de bug que es especialmente molesto: el que no impide que las cosas funcionen, pero s\u00ed que funcionen bien. En este caso era la b\u00fasqueda de esta misma bit\u00e1cora. Buscabas, por ejemplo, \u00abtelemetr\u00eda\u00bb, y la primera p\u00e1gina de resultados aparec\u00eda perfectamente. Pero al intentar navegar a la segunda p\u00e1gina, WordPress devolv\u00eda cero resultados. La URL que generaba el enlace de paginaci\u00f3n inclu\u00eda un car\u00e1cter extra (un <code>%2F<\/code>, la codificaci\u00f3n URL de una barra <code>\/<\/code>)al final del t\u00e9rmino de b\u00fasqueda, con lo que el sistema interpretaba que estabas buscando \u00abtelemetr\u00eda\/\u00bb en vez de \u00abtelemetr\u00eda\u00bb. Un car\u00e1cter. Una barra. Suficiente para romper la paginaci\u00f3n de todo el buscador.<\/p>\n\n\n\n<p>Lo que hace interesante este caso no es tanto el bug en s\u00ed \u2014 que resulta ser un fallo cl\u00e1sico de una funci\u00f3n de WordPress aplicada donde no deb\u00eda \u2014 sino el proceso para encontrarlo y corregirlo, que realic\u00e9 \u00edntegramente asistido por Claude Code, la herramienta de l\u00ednea de comandos de Anthropic. Y m\u00e1s que el resultado, lo que merece documentarse es la metodolog\u00eda: c\u00f3mo preparar el contexto, c\u00f3mo dejar que el agente investigue y, sobre todo, c\u00f3mo mantener el control humano en todo momento para evitar que la soluci\u00f3n sea peor que el problema.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">El punto de partida: darle al agente un mapa del territorio<\/h2>\n\n\n\n<p>La primera lecci\u00f3n que he aprendido trabajando con agentes de IA en tareas de infraestructura es que <strong>el contexto lo es todo<\/strong>. Un agente sin contexto es como un consultor externo al que sueltas en una sala de servidores sin documentaci\u00f3n: puede ser brillante, pero perder\u00e1 el tiempo haciendo preguntas que t\u00fa ya sabes responder.<\/p>\n\n\n\n<p>Antes de pedirle que diagnosticara nada, le proporcion\u00e9 a Claude Code una descripci\u00f3n precisa de la arquitectura:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Un servidor de <em>frontend<\/em> que act\u00faa como <em>reverse proxy<\/em> con nginx, terminando SSL y reenviando peticiones al <em>backend<\/em>.<\/li>\n\n\n\n<li>Un servidor de <em>backend<\/em> con nginx y PHP-FPM donde corre WordPress f\u00edsicamente.<\/li>\n\n\n\n<li>Una salida a Internet dom\u00e9stica con NAT, y dos nombres de dominio que apuntan al mismo WordPress: <code>www.eniac2000.com<\/code> y <code>bitacora.eniac2000.com<\/code>.<\/li>\n\n\n\n<li>Acceso SSH sin contrase\u00f1a a ambos servidores desde mi Mac Mini M4, con usuarios espec\u00edficos para cada m\u00e1quina.<\/li>\n<\/ul>\n\n\n\n<p>Tambi\u00e9n le describ\u00ed el s\u00edntoma con precisi\u00f3n: la URL de la primera p\u00e1gina de b\u00fasqueda era correcta (<code>\/?s=telemetr%C3%ADa<\/code>), pero los enlaces de paginaci\u00f3n generaban URLs con un <code>%2F<\/code> al final del par\u00e1metro <code>s<\/code> (<code>\/?paged=2&amp;s=telemetr%C3%ADa%2F<\/code>). Y le dije d\u00f3nde sospechaba que estaba el problema: en alguno de los dos nginx.<\/p>\n\n\n\n<p>Este paso de preparaci\u00f3n del contexto no es trivial. Es, probablemente, el paso m\u00e1s importante de todo el proceso. Si le hubiera dicho simplemente \u00abla b\u00fasqueda de mi WordPress no funciona bien\u00bb, el agente habr\u00eda necesitado varias iteraciones exploratorias para entender la topolog\u00eda de red, los roles de cada servidor y c\u00f3mo fluye una petici\u00f3n desde el navegador hasta PHP. D\u00e1ndole el mapa completo desde el inicio, pudo empezar a investigar directamente.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">La investigaci\u00f3n: c\u00f3mo trabaja un agente de diagn\u00f3stico<\/h2>\n\n\n\n<p>Lo primero que hizo Claude Code fue lanzar, en paralelo, la lectura de las configuraciones de nginx de ambos servidores. Conect\u00f3 por SSH a las dos m\u00e1quinas simult\u00e1neamente y ley\u00f3 los ficheros de configuraci\u00f3n de los <em>virtual hosts<\/em>, el <code>nginx.conf<\/code> principal, los par\u00e1metros de FastCGI y los <em>snippets<\/em> de PHP-FPM. En una primera pasada recopil\u00f3 toda la informaci\u00f3n de infraestructura disponible sin modificar absolutamente nada.<\/p>\n\n\n\n<p>A continuaci\u00f3n, realiz\u00f3 una prueba que result\u00f3 ser la clave del diagn\u00f3stico: lanz\u00f3 un <code>curl<\/code> directamente contra el <em>backend<\/em>, sin pasar por el <em>frontend<\/em>, y comprob\u00f3 si los enlaces de paginaci\u00f3n segu\u00edan incluyendo el <code>%2F<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -s -H \"Host: bitacora.eniac2000.com\" \\\n     -H \"X-Forwarded-Proto: https\" \\\n     \"http:\/\/192.168.0.x\/?s=telemetr%C3%ADa\" \\\n     | grep -oP 'href=\"&#91;^\"]*paged&#91;^\"]*\"'<\/code><\/pre>\n\n\n\n<p>El resultado fue revelador: la barra sobrante aparec\u00eda tambi\u00e9n en el acceso directo al <em>backend<\/em>. En un solo comando, el agente descart\u00f3 completamente al nginx de <em>frontend<\/em> como causante del problema. Toda la investigaci\u00f3n se concentr\u00f3 entonces en el <em>backend<\/em>.<\/p>\n\n\n\n<p>A partir de ah\u00ed, el proceso de investigaci\u00f3n fue met\u00f3dico, y desde luego, m\u00e1s r\u00e1pido de lo que hubiera sido una investigaci\u00f3n manual sin el agente. Claude Code ley\u00f3 la configuraci\u00f3n de WordPress \u2014 la estructura de permalinks (planos, sin <em>pretty URLs<\/em>), las URLs del sitio en la base de datos, la versi\u00f3n de WordPress (6.9.4) \u2014 y examin\u00f3 el c\u00f3digo fuente de las funciones de paginaci\u00f3n de WordPress (<code>get_pagenum_link()<\/code>, <code>add_query_arg()<\/code>). Pero lo que hizo el clic fue cuando inspeccion\u00f3 la lista de <em>plugins<\/em> activos y encontr\u00f3 uno llamado <strong>Multiple Domain Mapping on single site<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">La causa ra\u00edz: <code>trailingslashit()<\/code> donde no deb\u00eda<\/h2>\n\n\n\n<p>El <em>plugin<\/em> Multiple Domain Mapping permite servir el mismo WordPress bajo distintos dominios. En mi caso, ten\u00eda configurado un mapeo de <code>bitacora.eniac2000.com<\/code> a la ra\u00edz <code>\/<\/code>. El problema estaba en un m\u00e9todo aparentemente inocente del <em>plugin<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private function setCurrentURI($uri){\n    $this-&gt;currentURI = trailingslashit( $uri );\n}<\/code><\/pre>\n\n\n\n<p>La funci\u00f3n <code>trailingslashit()<\/code> de WordPress hace exactamente lo que su nombre indica: a\u00f1ade una barra al final de una cadena si no la tiene. Est\u00e1 pensada para trabajar con <em>paths<\/em> del sistema de ficheros o rutas URL. Pero este <em>plugin<\/em> se la aplicaba a la URI completa, incluyendo el <em>query string<\/em>. Cuando la URI era <code>bitacora.eniac2000.com\/?s=telemetr\u00eda<\/code>, la funci\u00f3n la convert\u00eda en <code>bitacora.eniac2000.com\/?s=telemetr\u00eda\/<\/code>. La barra se a\u00f1ad\u00eda al final del valor del par\u00e1metro de b\u00fasqueda.<\/p>\n\n\n\n<p>Y el efecto domin\u00f3 era el siguiente: el <em>plugin<\/em>, al detectar que el dominio coincid\u00eda con su mapeo, reconstru\u00eda <code>$_SERVER['REQUEST_URI']<\/code> usando esa URI ya contaminada. WordPress, al generar los enlaces de paginaci\u00f3n, le\u00eda ese <code>REQUEST_URI<\/code> modificado y constru\u00eda la URL de la p\u00e1gina 2 con el t\u00e9rmino de b\u00fasqueda corrupto. Un <code>%2F<\/code> inofensivo para un humano, letal para una b\u00fasqueda.<\/p>\n\n\n\n<p>Claude Code identific\u00f3 dos puntos exactos donde aplicar la correcci\u00f3n: el m\u00e9todo <code>setCurrentURI()<\/code> y la l\u00ednea de <code>parse_request()<\/code> que reconstru\u00eda el <code>REQUEST_URI<\/code>. En ambos casos, la soluci\u00f3n era la misma: separar el <em>path<\/em> del <em>query string<\/em> antes de aplicar <code>trailingslashit()<\/code>, y reensamblar despu\u00e9s.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Validaci\u00f3n cruzada: el abogado del diablo<\/h2>\n\n\n\n<p>Antes de tocar una sola l\u00ednea de c\u00f3digo en producci\u00f3n, quise una segunda opini\u00f3n. A trav\u00e9s de un servidor MCP de ChatGPT, le ped\u00ed a un modelo o3 que actuara como director de ingenier\u00eda y abogado del diablo: que revisara cr\u00edticamente el diagn\u00f3stico, evaluara si las correcciones eran seguras, y buscara efectos colaterales que pudieran hab\u00e9rseme pasado por alto.<\/p>\n\n\n\n<p>La revisi\u00f3n confirm\u00f3 varios puntos clave:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>El diagn\u00f3stico era correcto y no hab\u00eda otros factores que explicaran el fallo.<\/li>\n\n\n\n<li><strong>Ambas correcciones eran necesarias<\/strong>: la primera sola no bastaba, porque <code>parse_request()<\/code> reintroduc\u00eda el problema.<\/li>\n\n\n\n<li>No hab\u00eda efectos colaterales significativos: la funci\u00f3n <code>uriMatch()<\/code> del propio <em>plugin<\/em> aplicaba internamente su propio <code>trailingslashit()<\/code> para las comparaciones, de modo que la l\u00f3gica de detecci\u00f3n de mapeos no se ve\u00eda afectada.<\/li>\n\n\n\n<li>No exist\u00edan otros puntos en el <em>plugin<\/em> con el mismo problema.<\/li>\n<\/ul>\n\n\n\n<p>Solo con esta doble validaci\u00f3n -diagn\u00f3stico del agente m\u00e1s revisi\u00f3n adversarial de un segundo modelo- proced\u00ed a preparar la correcci\u00f3n.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">El humano en el bucle: por qu\u00e9 el agente no ten\u00eda <em>root<\/em><\/h2>\n\n\n\n<p>Y aqu\u00ed est\u00e1 el punto que considero m\u00e1s importante de todo el proceso. Claude Code ten\u00eda acceso SSH a ambos servidores, pero <strong>sin privilegios de superusuario<\/strong>. Pod\u00eda leer las configuraciones de nginx, consultar la base de datos de WordPress, examinar el c\u00f3digo PHP del <em>plugin<\/em>. Pero no pod\u00eda modificar ficheros que pertenecieran a <code>www-data<\/code>, no pod\u00eda reiniciar servicios, y no pod\u00eda ejecutar nada con <code>sudo<\/code>.<\/p>\n\n\n\n<p>Esto no fue un accidente, sino una decisi\u00f3n consciente de dise\u00f1o. Los ficheros de configuraci\u00f3n de nginx y los <em>plugins<\/em> de WordPress son propiedad de <code>www-data<\/code>. El usuario SSH no tiene permisos para modificarlos directamente. Para hacer cualquier cambio en producci\u00f3n, el agente necesitaba mi intervenci\u00f3n expl\u00edcita.<\/p>\n\n\n\n<p>Lo que Claude Code hizo fue generar <em>scripts<\/em> de <em>shell<\/em> autocontenidos que yo pudiera revisar, copiar al servidor y ejecutar manualmente con <code>sudo<\/code>. Cada <em>script<\/em> inclu\u00eda:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Verificaci\u00f3n previa<\/strong>: comprobaci\u00f3n del MD5 del fichero original para asegurar que nadie lo hab\u00eda modificado entre el diagn\u00f3stico y la correcci\u00f3n.<\/li>\n\n\n\n<li><strong>Copia de seguridad autom\u00e1tica<\/strong> con <em>timestamp<\/em>, antes de tocar nada.<\/li>\n\n\n\n<li><strong>Aplicaci\u00f3n del parche<\/strong> usando reemplazos PHP exactos (no <code>sed<\/code>, dado que el c\u00f3digo conten\u00eda comillas, caracteres especiales y tabuladores que hac\u00edan los reemplazos con expresiones regulares poco fiables).<\/li>\n\n\n\n<li><strong>Verificaci\u00f3n posterior<\/strong>: b\u00fasqueda en el fichero modificado de las cadenas clave que confirmaran que el parche se hab\u00eda aplicado. Si la verificaci\u00f3n fallaba, el <em>script<\/em> restauraba autom\u00e1ticamente el <em>backup<\/em> y abortaba.<\/li>\n\n\n\n<li><strong>Validaci\u00f3n de sintaxis<\/strong>: <code>php -l<\/code> contra el fichero modificado.<\/li>\n\n\n\n<li><strong>Restauraci\u00f3n del propietario<\/strong>: <code>chown www-data:www-data<\/code> para que los permisos quedaran exactamente como estaban.<\/li>\n\n\n\n<li><strong>Reinicio del servicio<\/strong>: <code>systemctl restart php8.4-fpm<\/code>.<\/li>\n\n\n\n<li><strong>Comando de <em>rollback<\/em><\/strong>: al final del <em>script<\/em>, se mostraba el comando exacto para revertir todo el cambio si algo sal\u00eda mal.<\/li>\n<\/ul>\n\n\n\n<p>El ciclo era siempre el mismo: el agente generaba el <em>script<\/em>, yo lo copiaba al servidor con <code>scp<\/code>, lo ejecutaba con <code>sudo bash<\/code>, y le comunicaba el resultado. Si algo fallaba, el agente ajustaba su enfoque y generaba una nueva versi\u00f3n. En ning\u00fan momento tuvo capacidad de ejecutar nada con privilegios elevados por su cuenta.<\/p>\n\n\n\n<p>Este patr\u00f3n de trabajo (agente que diagnostica y prepara, humano que ejecuta y valida) no es una limitaci\u00f3n, es una <strong>garant\u00eda<\/strong>. En un entorno de producci\u00f3n donde un error puede tumbar un sitio web p\u00fablico, la separaci\u00f3n de privilegios entre el agente y el operador humano es la diferencia entre un proceso controlado y una cat\u00e1strofe potencial.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">La correcci\u00f3n aplicada<\/h2>\n\n\n\n<p>La correcci\u00f3n final consisti\u00f3 en dos cambios en el fichero <code>multidomainmapping.php<\/code> del <em>plugin<\/em>:<\/p>\n\n\n\n<p><strong>Correcci\u00f3n 1<\/strong>: el m\u00e9todo <code>setCurrentURI()<\/code>, que ahora separa el <em>path<\/em> del <em>query string<\/em> antes de aplicar <code>trailingslashit()<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private function setCurrentURI($uri){\n    $qpos = strpos($uri, '?');\n    if ($qpos !== false) {\n        $this-&gt;currentURI = trailingslashit(substr($uri, 0, $qpos))\n                          . substr($uri, $qpos);\n    } else {\n        $this-&gt;currentURI = trailingslashit( $uri );\n    }\n}<\/code><\/pre>\n\n\n\n<p><strong>Correcci\u00f3n 2<\/strong>: la reconstrucci\u00f3n del <code>REQUEST_URI<\/code> en <code>parse_request()<\/code>, que ahora preserva el <em>query string<\/em> intacto:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$tail = substr(\n    str_ireplace('www.', '', $this-&gt;getCurrentURI()),\n    strlen(str_ireplace('www.', '',\n        $this-&gt;getCurrentMapping()&#91;'match']&#91;'domain']))\n);\n$tail_parts = explode('?', $tail, 2);\n$tail_path  = $tail_parts&#91;0];\n$tail_query = isset($tail_parts&#91;1]) ? '?' . $tail_parts&#91;1] : '';\n$newRequestURI = trailingslashit(\n    $this-&gt;getCurrentMapping()&#91;'match']&#91;'path'] . $tail_path\n) . $tail_query;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Validaci\u00f3n autom\u00e1tica del resultado<\/h2>\n\n\n\n<p>Una vez ejecutados los <em>scripts<\/em>, Claude Code valid\u00f3 el resultado lanzando la misma prueba que hab\u00eda servido para diagnosticar el problema: un <code>curl<\/code> contra la URL de b\u00fasqueda, extrayendo los enlaces de paginaci\u00f3n del HTML devuelto:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># ANTES (bug presente):\nhref=\"https:\/\/bitacora.eniac2000.com\/?paged=2&amp;s=telemetr%C3%ADa%2F\"\n\n# DESPU\u00c9S (bug corregido):\nhref=\"https:\/\/bitacora.eniac2000.com\/?paged=2&amp;s=telemetr%C3%ADa\"<\/code><\/pre>\n\n\n\n<p>Tambi\u00e9n verific\u00f3 que la segunda p\u00e1gina de resultados devolviera un HTTP 200 limpio, sin redirecciones ni errores. El ciclo completo \u2014 desde el diagn\u00f3stico inicial hasta la validaci\u00f3n final \u2014 se complet\u00f3 en una sola sesi\u00f3n de trabajo, sin interrupciones de servicio y con la certeza de que cada paso era reversible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Lecciones aprendidas<\/h2>\n\n\n\n<p>De todo este proceso, me quedo con varias ideas que creo que aplican a cualquier uso de agentes de IA para tareas de infraestructura:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>El contexto inicial determina la calidad del resultado<\/strong>. Describir la arquitectura completa \u2014 servidores, roles, IPs, flujo de red, accesos \u2014 ahorra iteraciones y evita diagn\u00f3sticos incorrectos. El agente no puede adivinar lo que t\u00fa sabes sobre tu infraestructura.<\/li>\n\n\n\n<li><strong>La separaci\u00f3n de privilegios no es opcional<\/strong>. Que el agente no tenga <code>sudo<\/code> no es un inconveniente: es un cortafuegos. Genera <em>scripts<\/em>, t\u00fa los ejecutas. Si algo sale mal, la responsabilidad y el control est\u00e1n donde tienen que estar.<\/li>\n\n\n\n<li><strong>Un agente que investiga bien vale m\u00e1s que uno que ejecuta r\u00e1pido<\/strong>. El valor real estuvo en la capacidad de Claude Code para leer configuraciones en paralelo, descartar hip\u00f3tesis con pruebas concretas y trazar el flujo del bug a trav\u00e9s de varias capas (nginx, PHP, WordPress, <em>plugin<\/em>). La ejecuci\u00f3n del parche fue la parte trivial.<\/li>\n\n\n\n<li><strong>La validaci\u00f3n cruzada con un segundo modelo aporta confianza<\/strong>. Pedir a un modelo diferente que act\u00fae como adversario del diagn\u00f3stico no es redundancia: es ingenier\u00eda. Si dos modelos independientes llegan a la misma conclusi\u00f3n por caminos distintos, la probabilidad de que el diagn\u00f3stico sea correcto aumenta significativamente.<\/li>\n\n\n\n<li><strong>Todo <em>script<\/em> de correcci\u00f3n debe ser reversible<\/strong>. Backup autom\u00e1tico, verificaci\u00f3n de MD5, restauraci\u00f3n en caso de fallo, comando de <em>rollback<\/em> expl\u00edcito. No es paranoia: es profesionalidad.<\/li>\n<\/ul>\n\n\n\n<p>Un car\u00e1cter. Una barra. Un <code>%2F<\/code> que se colaba por una funci\u00f3n aplicada donde no deb\u00eda. Lo encontr\u00e9 gracias a un agente de IA que sab\u00eda leer configuraciones, descartar hip\u00f3tesis y preparar correcciones sin tocar nada que no le correspondiera. Y lo correg\u00ed yo, con <code>sudo<\/code> y con los ojos bien abiertos. Que es como tienen que ser estas cosas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hay un tipo de bug que es especialmente molesto: el<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1845,13],"tags":[1984,1959,517,824,1983,1287,1794],"series":[],"class_list":["post-11826","post","type-post","status-publish","format-standard","hentry","category-generado-con-ia","category-informatica","tag-chatgpt","tag-claude-code","tag-debian","tag-ia","tag-mcp","tag-plugin","tag-wordpress"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts\/11826","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11826"}],"version-history":[{"count":1,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts\/11826\/revisions"}],"predecessor-version":[{"id":11827,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts\/11826\/revisions\/11827"}],"wp:attachment":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11826"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11826"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11826"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fseries&post=11826"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}