[P2606] WebServer NGINX: plan actualizado, ficha nodo, HTTPS operativo

- P2606: Plan v1.1 EN EJECUCIÓN. Fases 1-3 completadas.
- Ficha nodo srvv-nginx-rm.md. P2606 en adn/07_proyectos.md.
- Incluye cambios acumulados de sesiones anteriores.
This commit is contained in:
Ricardo Monla
2026-03-28 12:18:42 -03:00
parent 97d9b777b4
commit 160da47f96
78 changed files with 6461 additions and 624 deletions
+87 -36
View File
@@ -14,38 +14,41 @@ module ADN
end
def ejecutar
parser = OptionParser.new do |opts|
opts.banner = "Uso: ./adn/tools/run salud [OPCIONES]"
opts.separator ""
opts.separator "Muestra salud general del sistema ADN"
opts.separator ""
opts.separator "Opciones:"
opts.on("--dashboard", "Mostrar en formato dashboard (no implementado)") do
@opciones[:dashboard] = true
end
opts.on("--json", "Salida en formato JSON") do
@opciones[:json] = true
end
opts.on("--mejoras", "Incluir sugerencias de mejora continua") do
@opciones[:mejoras] = true
end
opts.on("-h", "--help", "Mostrar esta ayuda") do
puts opts
exit 1
end
opts.on("-h", "--help", "Mostrar esta ayuda") do
puts opts
exit
end
end
opts = { dashboard: false, json: false, mejoras: false, ambito: nil }
begin
parser.parse!(@args)
rescue OptionParser::InvalidOption => e
@logger.error("Opción inválida: #{e.message}")
puts parser
exit 1
end
if @args.include?('-h') || @args.include?('--help') || @args.empty?
require_relative '../core/help_formatter'
puts ADN::HelpFormatter.generar_help(
titulo: "Salud del Sistema ADN",
descripcion: "Muestra métricas y estado general del ecosistema (Archivos MD + DB)",
uso: "./adn/tools/run salud [opciones]",
opciones: [
{ names: ['--json'], desc: "Salida en formato JSON" },
{ names: ['--mejoras'], desc: "Sugerencias de mejora continua" },
{ names: ['--ambito AMBITO'], desc: "Filtrar estadísticas de DB por ámbito" }
],
ejemplos: [
{ cmd: "./adn/tools/run salud", desc: "Reporte general" },
{ cmd: "./adn/tools/run salud --ambito dtic-DASUTEN", desc: "Reporte con foco en el ámbito" }
]
)
exit 0
end
parser = OptionParser.new do |opt|
opt.on("--json") { @opciones[:json] = true }
opt.on("--mejoras") { @opciones[:mejoras] = true }
opt.on("--dashboard") { @opciones[:dashboard] = true }
opt.on("--ambito NOMBRE") { |a| @opciones[:ambito] = a }
end
begin
parser.parse!(@args)
rescue OptionParser::InvalidOption => e
@logger.error("Opción inválida: #{e.message}")
puts "#{Color::YELLOW}⚠ Error: #{e.message}#{Color::RESET}"
exit 1
end
mostrar_salud
end
@@ -69,23 +72,34 @@ module ADN
datos[:sugerencias_mejora] = obtener_sugerencias_mejora
end
datos[:db] = obtener_estadisticas_db(@opciones[:ambito])
if @opciones[:json]
puts JSON.pretty_generate(datos)
return
end
if @opciones[:dashboard]
puts "#{Color::YELLOW}⚠ El dashboard será implementado en Fase 3#{Color::RESET}"
# TODO: Implementar dashboard en Fase 3
puts "#{Color::YELLOW}⚠ El dashboard interactivo estructurado será implementado en Fase 3#{Color::RESET}"
end
# Mostrar en formato legible
puts "#{Color::CYAN}🧬 Salud del Sistema ADN#{Color::RESET}"
puts "#{Color::DIM}#{'-' * 60}#{Color::RESET}"
puts " #{Color::GREEN}Hebras ADN:#{Color::RESET} #{datos[:hebras_adn]} / 7"
puts " #{Color::GREEN}Bitácoras:#{Color::RESET} #{datos[:bitacoras]}"
puts " #{Color::GREEN}Nodos registrados:#{Color::RESET} #{datos[:nodos]}"
puts " #{Color::GREEN}Proyectos activos:#{Color::RESET} #{datos[:proyectos]}"
puts " #{Color::GREEN}Bitácoras MD:#{Color::RESET} #{datos[:bitacoras]}"
puts " #{Color::GREEN}Nodos MD:#{Color::RESET} #{datos[:nodos]}"
puts " #{Color::GREEN}Proyectos MD:#{Color::RESET} #{datos[:proyectos]}"
if datos[:db]
puts ""
db_stats = datos[:db]
ambito_str = @opciones[:ambito] ? " (Ámbito: #{@opciones[:ambito]})" : " (Global)"
puts " #{Color::CYAN}Estadísticas Base de Datos#{ambito_str}:#{Color::RESET}"
puts " - Ámbitos Totales: #{db_stats[:ambitos]}" unless @opciones[:ambito]
puts " - Nodos (DB): #{db_stats[:nodos]}"
puts " - Eventos (DB): #{db_stats[:eventos]}"
end
if datos[:errores_recientes] > 0
puts " #{Color::RED}Errores recientes:#{Color::RESET} #{datos[:errores_recientes]}"
@@ -96,6 +110,19 @@ module ADN
puts "#{Color::DIM}#{'-' * 60}#{Color::RESET}"
puts "#{Color::DIM}Para más detalles: ./adn/tools/run salud --json#{Color::RESET}"
if @opciones[:mejoras] && datos[:sugerencias_mejora] && !datos[:sugerencias_mejora].empty?
puts
puts "#{Color::CYAN}💡 Sugerencias de Mejora Continua#{Color::RESET}"
puts "#{Color::DIM}#{'-' * 60}#{Color::RESET}"
datos[:sugerencias_mejora].each do |sug|
prioridad_emoji = { alta: '🔴', media: '🟡', baja: '🟢' }[sug[:prioridad]] || '⚪'
puts " #{prioridad_emoji} #{sug[:tipo].to_s.tr('_', ' ')}"
puts " #{sug[:descripcion]}"
puts "#{sug[:accion_sugerida]}"
puts
end
end
@logger.exito("Reporte de salud generado")
end
@@ -120,6 +147,30 @@ module ADN
Dir.glob(File.join(ADN::NODOS_DIR, "*.md")).count
end
def obtener_estadisticas_db(ambito_nombre = nil)
require_relative '../db/core/bitacora_db'
stats = { ambitos: 0, nodos: 0, eventos: 0 }
begin
BitacorasDB::BitacoraDB.with_connection do |db|
ambito_id = nil
if ambito_nombre
ambito = db.get_ambito(ambito_nombre)
return nil unless ambito
ambito_id = ambito['id']
else
stats[:ambitos] = db.list_ambitos.length
end
stats[:nodos] = db.list_nodos(ambito_id: ambito_id, limit: 1000).length
stats[:eventos] = db.list_entradas(ambito_id: ambito_id, limit: 10000).length
end
rescue StandardError => e
@logger.error("Error obteniendo stats DB: #{e.message}")
return nil
end
stats
end
def contar_proyectos
Dir.glob(File.join(ADN::PROYECTOS_DIR, "*.md")).count
end