#!/usr/bin/env nu # ¿ESTE SERVIDOR ES EL SITIO, O SOLO ALGO QUE RESPONDE EN ESE PUERTO? # # Toda comprobación contra la superficie viva empieza dando por hecho lo único que nunca verifica: # que al otro lado del puerto está el sitio. `check-served-live.nu` lo dice en su cabecera — «la # superficie viva es la única publicación que hay» — y luego acepta un `--base-url` y se cree lo # que le dan. Puede medir un servidor que no es este sitio y decirlo todo en verde. # # ── QUÉ PASÓ, MEDIDO (2026-07-16) ──────────────────────────────────────────────────────────── # # Un servidor arrancado por una vía degradada —sin el entorno de run.sh— no trae RUSTELO_SITE_ROUTES, # así que NO FUSIONA las rutas que el sitio declara en site/config/routes/. Responde 200 en todo lo # que la imagen compartida trae compilado y 404 en lo que este sitio aporta. Contra ese servidor: # /conceptos daba 404 y /sobre-el-idioma daba 404. De ahí salió media sesión persiguiendo un fallo # de rutas que no existía, y dos diagnósticos falsos encadenados («las rutas están rotas», «el # conmutador de idioma manda a 404»). Las rutas estaban perfectas. El servidor no era el sitio. # # ── POR QUÉ NO COMPRUEBA LA CANONICAL, QUE SERÍA MÁS CORTO ────────────────────────────────── # # Un servidor degradado emite `canonical = http://127.0.0.1:3030` y uno de run.sh emite # `https://ontoref.dev`, porque run.sh exporta SITE_BASE_URL. Sería una línea. Y sería # `a-check-measures-the-capability-not-a-proxy` (adr-072) en estado puro: SITE_BASE_URL no es # «servir las rutas del sitio», es otra variable que resulta que hoy viaja en el mismo autobús. # El día que alguien exporte una y no la otra, la puerta dice OK sobre un servidor ciego — y lo # dirá con toda la confianza, que es lo que hace peligroso a un proxy. # # Así que se mide LA CAPACIDAD: pedir las rutas que el sitio declara, y comprobar que el servidor # las conoce. Es la pregunta entera y no su sombra. # # ── Y SE PREGUNTA CON MARCADOR POSITIVO ───────────────────────────────────────────────────── # # No «el título no es el de la 404»: en este sitio un 404 responde 200 con «ontoref — Article» # (medido hoy: /adr/999), la copia del 404 viaja incrustada en todas las páginas, y afirmar por # ausencia de un negativo es como se cuelan los falsos verdes. La ruta declara `title_key`, y el # .ftl dice qué texto es. Eso es lo que la página tiene que traer: la afirmación positiva de que # el servidor sirve ESTA página, no de que no sirve otra. # # Uso: # nu scripts/build/check-live-server.nu --base-url http://localhost:3030 --root . def main [ --base-url: string = "http://localhost:3030", --root: string = ".", ] { let routes_dir = ([$root, "site", "config", "routes"] | path join) if not ($routes_dir | path exists) { print $"check-live-server: NO MIRÉ — ($routes_dir) no existe, y es lo único que dice qué rutas" print " aporta este sitio. Sin eso no puedo distinguir un servidor bueno de uno ciego." exit 1 } # Las rutas del CONSUMIDOR, que son exactamente las que un servidor degradado se salta. Las de la # imagen compartida no sirven de testigo: las responde igual sin haber leído nada de este sitio. let declared = ( glob $"($routes_dir)/*.ncl" | each {|f| let r = (do { ^nickel export --format json $f } | complete) if $r.exit_code != 0 { print $"check-live-server: NO MIRÉ — ($f) no exporta: ($r.stderr | str trim | lines | first)" exit 1 } ($r.stdout | from json).routes } | flatten | where {|r| ($r.enabled? | default true) } ) # CERO RUTAS DECLARADAS ES UN HALLAZGO, NUNCA UN «TODO BIEN». Si el glob no encuentra nada, o el # esquema cambió y `routes` ya no se llama así, esta puerta no tiene nada que pedir — y una puerta # sin nada que pedir pasa siempre. Es `a-check-can-say-i-did-not-look` (adr-072), y es el modo en # que las puertas se mueren solas: en verde. if ($declared | is-empty) { print $"check-live-server: NO MIRÉ — ($routes_dir) no declaró ni una ruta habilitada." print " Una puerta sin nada que pedir pasa siempre. Eso no es un servidor sano: es ignorancia." exit 1 } mut bad = [] mut ok = [] for r in $declared { let lang = ($r.language? | default "") let key = ($r.title_key? | default "") if ($key | is-empty) { $bad = ($bad | append $"($r.path) — la ruta no declara title_key, así que no tengo marcador positivo que pedir") continue } # El texto que el sitio PROMETE para esa página. Se busca en su idioma: una clave resuelta # contra el .ftl equivocado compararía la página con la promesa de otro idioma. let ftl_dir = ([$root, "site", "i18n", "locales", $lang, "pages"] | path join) let want = ( glob $"($ftl_dir)/*.ftl" | each {|f| open --raw $f | lines | where {|l| $l | str starts-with $"($key) = " } } | flatten | each {|l| $l | str replace $"($key) = " "" | str trim } | get -o 0 ) if $want == null or ($want | is-empty) { $bad = ($bad | append $"($r.path) — title_key '($key)' no está en ($lang)/pages/*.ftl: la ruta promete un texto que no existe") continue } let res = (do { ^curl -s -o /tmp/cls-page.html -w "%{http_code}" $"($base_url)($r.path)" } | complete) let code = ($res.stdout | str trim) let body = (if ("/tmp/cls-page.html" | path exists) { open --raw /tmp/cls-page.html } else { "" }) let title = ($body | parse --regex '(?s)