Skip to content

Commit 963f9b9

Browse files
feat: inicializar sentinel autónomo con Go + HTMX
Sistema con soporte go:embed, tooltips dinámicos y Makefile optimizado.
0 parents  commit 963f9b9

18 files changed

Lines changed: 905 additions & 0 deletions

File tree

.github/workflows/main.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: CI-CD-2026
2+
on: [push]
3+
jobs:
4+
quality-gate:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- uses: actions/checkout@v4
8+
- name: Set up Go
9+
uses: actions/setup-go@v4
10+
with: {go-version: '1.24'}
11+
- name: Linter & Format
12+
run: |
13+
go fmt ./...
14+
go vet ./...
15+
- name: Unit Tests
16+
run: go test -v ./...

.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Ejecutables de Go
2+
*.exe
3+
*.exe~
4+
*.dll
5+
*.so
6+
*.dylib
7+
decade_sentinel
8+
sentinel_pro
9+
10+
# Herramientas de compilación
11+
bin/
12+
obj/
13+
14+
# Dependencias
15+
vendor/
16+
17+
# Logs y temporales
18+
*.log
19+
.tmp/
20+
21+
# IDEs
22+
.vscode/
23+
.idea/
24+
*.swp

Dockerfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# ETAPA 1: Construcción (El taller)
2+
FROM golang:1.24-alpine AS builder
3+
WORKDIR /app
4+
COPY . .
5+
RUN go mod download
6+
RUN CGO_ENABLED=0 GOOS=linux go build -o main api/main.go
7+
8+
# ETAPA 2: Ejecución (El cohete ligero)
9+
FROM scratch
10+
WORKDIR /root/
11+
# Solo copiamos el binario y los archivos visuales (Máxima seguridad y mínimo peso)
12+
COPY --from=builder /app/main .
13+
COPY --from=builder /app/static ./static
14+
EXPOSE 8080
15+
CMD ["./main"]

Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Variables
2+
BINARY_NAME=sentinel_pro.exe
3+
PORT=8080
4+
5+
.PHONY: all build run clean dev
6+
7+
all: build run
8+
9+
# Regla de Desarrollo: Limpia, Compila y Corre
10+
dev: clean build run
11+
12+
# Compilar el motor (Go)
13+
build:
14+
@echo "🔨 Compilando binario autónomo..."
15+
go build -o $(BINARY_NAME) ./api/main.go
16+
17+
# Encender el motor
18+
run:
19+
@echo "🚀 Sentinel 2026 activo en http://localhost:$(PORT)"
20+
./$(BINARY_NAME)
21+
22+
# Limpiar restos (Matar proceso y borrar exe)
23+
clean:
24+
@echo "🧹 Limpiando procesos y binarios..."
25+
-taskkill //F //IM $(BINARY_NAME) //T 2>/dev/null || true
26+
-rm -f $(BINARY_NAME)

README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# 🛰️ Decade Sentinel 2026
2+
3+
![Go](https://img.shields.io/badge/Go-00ADD8?style=for-the-badge&logo=go&logoColor=white)
4+
![HTMX](https://img.shields.io/badge/htmx-3366CC?style=for-the-badge&logo=htmx&logoColor=white)
5+
![License](https://img.shields.io/badge/License-MIT-green?style=for-the-badge)
6+
7+
**Decade Sentinel** es una aplicación web autónoma y ultra-ligera que explora la evolución tecnológica entre 2016 y 2026. Construida con **Go** para el motor de backend y **HTMX** para una experiencia de usuario dinámica sin la sobrecarga de pesados frameworks de JavaScript.
8+
9+
## 🚀 Características Clave
10+
- **Binario Autónomo:** Utiliza `go:embed` para incluir HTML, CSS y JS dentro del ejecutable.
11+
- **UX Fluida:** Tooltips dinámicos con telemetría de carga simulada mediante HTMX.
12+
- **Arquitectura Limpia:** Middleware de seguridad integrado (CSP, XSS Protection).
13+
- **Estética Cyberpunk:** Interfaz de terminal de comando optimizada para legibilidad y performance.
14+
15+
## 🛠️ Tecnologías
16+
- **Backend:** Go (Golang) 1.2x
17+
- **Frontend:** HTMX, CSS3 (Variables y Animaciones), HTML5.
18+
- **Despliegue:** Makefile optimizado para entornos Windows/Linux.
19+
20+
## 📦 Instalación y Uso
21+
22+
1. Clona el repositorio:
23+
```bash
24+
git clone [https://github.com/santiagourdaneta/decade-sentinel-2026.git](https://github.com/santiagourdaneta/decade-sentinel-2026.git)
25+
cd decade-sentinel-2026
26+
27+
2. Ejecuta el entorno de desarrollo (requiere Make):
28+
29+
make dev
30+
31+
3. Abre tu navegador en: http://localhost:8080
32+
33+
🛡️ Seguridad
34+
35+
El servidor incluye un SecurityMiddleware que implementa:
36+
37+
Content Security Policy (CSP) restrictivo.
38+
39+
Protección contra Sniffing de tipos (X-Content-Type-Options).
40+
41+
Prevención de Clickjacking (X-Frame-Options).
42+
43+
Desarrollado con ❤️ por Santiago Urdaneta
44+
45+
#Golang #HTMX #CSS3 #JavaScript #WebDevelopment #SoftwareArchitecture #Sentinel2026 #Coding #CyberpunkUI

api/logic.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package main
2+
3+
// GetHito devuelve el hito tecnológico de un año específico.
4+
// Esta función está aislada para poder testearla sin levantar un servidor.
5+
func GetHito(year int) string {
6+
details := map[int]string{
7+
2016: "Auge de Docker y Microservicios. .NET Core se lanza como Open Source.",
8+
2017: "Publicación del paper 'Attention is All You Need'. Nace la arquitectura Transformer.",
9+
2018: "Lanzamiento de React Hooks. El estándar ES2018 revoluciona JavaScript.",
10+
2019: "HTTP/3 basado en QUIC empieza a estandarizarse. El Edge Computing despega.",
11+
2020: "Aceleración masiva de Cloud. Apple silicon (M1) cambia la arquitectura de CPUs portátiles.",
12+
2021: "Consolidación de eBPF para observabilidad. GitHub Copilot introduce la IA al desarrollo.",
13+
2022: "Aparición de ChatGPT y modelos estables. La ingeniería de prompts se vuelve un rol.",
14+
2023: "Boom de bases de datos vectoriales. HTMX revive el server-driven UI.",
15+
2024: "IA Agentic: Los modelos ya no solo escriben, sino que ejecutan tareas complejas.",
16+
2025: "Soberanía de Datos: Privacidad por diseño (GDPR 2.0) y Edge AI local.",
17+
2026: "Sistemas Autónomos: El software se adapta al humano, Zero-trust real.",
18+
}
19+
20+
if val, ok := details[year]; ok {
21+
return val
22+
}
23+
return "Año fuera del rango de la década 2016-2026."
24+
}

api/logic_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"strings"
5+
"testing"
6+
)
7+
8+
func TestYearHitos(t *testing.T) {
9+
// Definimos casos de prueba
10+
tests := []struct {
11+
year int
12+
want string
13+
}{
14+
{2016, "Auge de Docker"},
15+
{2023, "HTMX"},
16+
{2026, "Sistemas Autónomos"},
17+
}
18+
19+
for _, tt := range tests {
20+
t.Run(string(rune(tt.year)), func(t *testing.T) {
21+
got := GetHito(tt.year)
22+
if !strings.Contains(got, tt.want) {
23+
t.Errorf("GetHito(%d) = %q; want it to contain %q", tt.year, got, tt.want)
24+
}
25+
})
26+
}
27+
}

api/main.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package main
2+
3+
import (
4+
"embed"
5+
"fmt"
6+
"io/fs"
7+
"log"
8+
"log/slog"
9+
"net/http"
10+
"time"
11+
)
12+
13+
// Base de datos de la cronología
14+
var details = map[string]string{
15+
"2016": "Docker estandariza el envío de software. Se acaba el 'en mi máquina funciona'.",
16+
"2017": "Aparece el paper 'Attention is All You Need'. Los Transformers cambian el futuro.",
17+
"2018": "Serverless y Edge Computing. El código se ejecuta cerca del usuario.",
18+
"2019": "Microservicios masivos. El reto es entender cómo se comunican.",
19+
"2020": "La nube se vuelve el cimiento de la sociedad ante la crisis global.",
20+
"2021": "GitHub Copilot: La IA empieza a escribir funciones reales.",
21+
"2022": "ChatGPT y Stable Diffusion rompen la barrera técnica.",
22+
"2023": "HTMX revive el Server-Driven UI. Menos complejidad, más velocidad.",
23+
"2024": "Bases de datos vectoriales: La IA ahora tiene memoria a largo plazo.",
24+
"2025": "GDPR 2.0 y Edge AI local. Soberanía total del dato.",
25+
"2026": "Sistemas auto-curables y Zero-Trust real. El software es autónomo.",
26+
}
27+
28+
func SecurityMiddleware(next http.Handler) http.Handler {
29+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
30+
w.Header().Set("X-Frame-Options", "DENY")
31+
w.Header().Set("X-Content-Type-Options", "nosniff")
32+
33+
// CSP PERMISIVO PARA HTMX (Permite estilos inline y scripts de unpkg)
34+
w.Header().Set("Content-Security-Policy",
35+
"default-src 'self' unpkg.com; " +
36+
"style-src 'self' 'unsafe-inline' unpkg.com; " +
37+
"script-src 'self' 'unsafe-inline' unpkg.com; " +
38+
"connect-src 'self';")
39+
40+
next.ServeHTTP(w, r)
41+
})
42+
}
43+
44+
func handleYearDetails(w http.ResponseWriter, r *http.Request) {
45+
// ⏳ RETRASO ARTIFICIAL: 600ms para que luzca la telemetría
46+
time.Sleep(300 * time.Millisecond)
47+
48+
year := r.URL.Query().Get("year")
49+
val, ok := details[year]
50+
51+
if !ok {
52+
slog.Warn("🚨 INTENTO DE ACCESO A AÑO INEXISTENTE", "año", year)
53+
w.WriteHeader(http.StatusNotFound)
54+
fmt.Fprintf(w, "<div class='error-alert'>⚠️ ERROR: Año %s fuera de los registros.</div>", year)
55+
return
56+
}
57+
58+
w.Header().Set("Content-Type", "text/html")
59+
fmt.Fprintf(w, "<strong>> Detalles: %s:</strong><br>%s", year, val)
60+
}
61+
62+
//go:embed all:static
63+
var staticFiles embed.FS
64+
65+
func main() {
66+
mux := http.NewServeMux()
67+
68+
// Servir CSS, JS e Imágenes
69+
staticContent, _ := fs.Sub(staticFiles, "static")
70+
mux.Handle("/css/", http.FileServer(http.FS(staticContent)))
71+
mux.Handle("/js/", http.FileServer(http.FS(staticContent)))
72+
mux.Handle("/img/", http.FileServer(http.FS(staticContent)))
73+
74+
// Ruta principal
75+
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
76+
if r.URL.Path != "/" {
77+
http.NotFound(w, r)
78+
return
79+
}
80+
index, err := staticFiles.ReadFile("static/index.html")
81+
if err != nil {
82+
http.Error(w, "Error interno: index.html no encontrado en embed", 500)
83+
return
84+
}
85+
w.Header().Set("Content-Type", "text/html; charset=utf-8")
86+
w.Write(index)
87+
})
88+
89+
mux.HandleFunc("/api/details", handleYearDetails)
90+
91+
fmt.Println("🚀 Sentinel 2026 AUTÓNOMO: http://localhost:8080")
92+
log.Fatal(http.ListenAndServe(":8080", SecurityMiddleware(mux)))
93+
}

api/main_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package main
2+
3+
import (
4+
"net/http"
5+
"net/http/httptest"
6+
"testing"
7+
)
8+
9+
func TestSecurityHeaders(t *testing.T) {
10+
// Usamos un grabador de respuestas para no necesitar el servidor encendido
11+
handler := SecurityMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
12+
req := httptest.NewRequest("GET", "http://localhost:8080", nil)
13+
w := httptest.NewRecorder()
14+
15+
handler.ServeHTTP(w, req)
16+
17+
resp := w.Result()
18+
if resp.Header.Get("X-Frame-Options") != "DENY" {
19+
t.Error("Seguridad Crítica: X-Frame-Options ausente")
20+
}
21+
}

0 commit comments

Comments
 (0)