diff --git a/.claude/helpers/graft-hooks.cjs b/.claude/helpers/graft-hooks.cjs new file mode 100644 index 0000000..4bf9d1d --- /dev/null +++ b/.claude/helpers/graft-hooks.cjs @@ -0,0 +1,67 @@ +#!/usr/bin/env node +const path = require('path'); +const fs = require('fs'); +const { pathToFileURL } = require('url'); +const { execFileSync } = require('child_process'); +const dir = process.env.CLAUDE_PROJECT_DIR || process.cwd(); +const BAKED = "C:\\Users\\Puper\\AppData\\Roaming\\npm\\node_modules\\@nanonets\\graft\\dist\\claude"; + +// The dist/claude dir of @nanonets/graft resolved from a base whose node_modules is searched. +function fromPkg(base) { + try { + const pkg = require.resolve('@nanonets/graft/package.json', { paths: [base] }); + return path.join(path.dirname(pkg), 'dist', 'claude'); + } catch { return null; } +} + +// The global node_modules dir per npm (handles Homebrew/Windows/volta). Queried on demand. +function globalRoot() { + try { + const root = execFileSync('npm', ['root', '-g'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], shell: process.platform === 'win32' }).trim(); + return root || null; + } catch { return null; /* npm unavailable */ } +} + +// The version of the package a dist/claude dir belongs to, or null if unreadable. +function versionOf(distClaude) { + try { + return JSON.parse(fs.readFileSync(path.join(distClaude, '..', '..', 'package.json'), 'utf8')).version || null; + } catch { return null; } +} + +// Numeric-dotted compare of the release part; an unreadable version loses to any known one. +function newer(a, b) { + if (!a) return false; + if (!b) return true; + const p = (v) => String(v).split('-')[0].split('.').map((n) => Number(n) || 0); + const pa = p(a), pb = p(b); + for (let i = 0; i < Math.max(pa.length, pb.length); i++) { + const d = (pa[i] || 0) - (pb[i] || 0); + if (d !== 0) return d > 0; + } + return false; +} + +// The highest-versioned dir in `dirs` that actually contains `name`, or null. +function best(dirs, name) { + let bestDir = null, bestVer = null; + for (const d of dirs) { + if (!d || !fs.existsSync(path.join(d, name))) continue; + const v = versionOf(d); + if (bestDir === null || newer(v, bestVer)) { bestDir = d; bestVer = v; } + } + return bestDir; +} + +function entry(name) { + // Cheap candidates first, and only shell out to npm when every one of them misses. + const cheap = [BAKED, fromPkg(dir), fromPkg(path.join(path.dirname(process.execPath), '..', 'lib'))]; + const hit = best(cheap, name); + if (hit) return path.join(hit, name); + const gr = globalRoot(); + const global = gr && path.join(gr, '@nanonets', 'graft', 'dist', 'claude'); + if (global && fs.existsSync(path.join(global, name))) return path.join(global, name); + return path.join(dir, 'dist', 'claude', name); // last-ditch; import will no-op if absent +} + +import(pathToFileURL(entry("hooks.js")).href).then((m) => m.main(process.argv[2])).catch(() => { /* graft unavailable — no-op */ }); diff --git a/.claude/helpers/graft-statusline.cjs b/.claude/helpers/graft-statusline.cjs new file mode 100644 index 0000000..a9c4399 --- /dev/null +++ b/.claude/helpers/graft-statusline.cjs @@ -0,0 +1,67 @@ +#!/usr/bin/env node +const path = require('path'); +const fs = require('fs'); +const { pathToFileURL } = require('url'); +const { execFileSync } = require('child_process'); +const dir = process.env.CLAUDE_PROJECT_DIR || process.cwd(); +const BAKED = "C:\\Users\\Puper\\AppData\\Roaming\\npm\\node_modules\\@nanonets\\graft\\dist\\claude"; + +// The dist/claude dir of @nanonets/graft resolved from a base whose node_modules is searched. +function fromPkg(base) { + try { + const pkg = require.resolve('@nanonets/graft/package.json', { paths: [base] }); + return path.join(path.dirname(pkg), 'dist', 'claude'); + } catch { return null; } +} + +// The global node_modules dir per npm (handles Homebrew/Windows/volta). Queried on demand. +function globalRoot() { + try { + const root = execFileSync('npm', ['root', '-g'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], shell: process.platform === 'win32' }).trim(); + return root || null; + } catch { return null; /* npm unavailable */ } +} + +// The version of the package a dist/claude dir belongs to, or null if unreadable. +function versionOf(distClaude) { + try { + return JSON.parse(fs.readFileSync(path.join(distClaude, '..', '..', 'package.json'), 'utf8')).version || null; + } catch { return null; } +} + +// Numeric-dotted compare of the release part; an unreadable version loses to any known one. +function newer(a, b) { + if (!a) return false; + if (!b) return true; + const p = (v) => String(v).split('-')[0].split('.').map((n) => Number(n) || 0); + const pa = p(a), pb = p(b); + for (let i = 0; i < Math.max(pa.length, pb.length); i++) { + const d = (pa[i] || 0) - (pb[i] || 0); + if (d !== 0) return d > 0; + } + return false; +} + +// The highest-versioned dir in `dirs` that actually contains `name`, or null. +function best(dirs, name) { + let bestDir = null, bestVer = null; + for (const d of dirs) { + if (!d || !fs.existsSync(path.join(d, name))) continue; + const v = versionOf(d); + if (bestDir === null || newer(v, bestVer)) { bestDir = d; bestVer = v; } + } + return bestDir; +} + +function entry(name) { + // Cheap candidates first, and only shell out to npm when every one of them misses. + const cheap = [BAKED, fromPkg(dir), fromPkg(path.join(path.dirname(process.execPath), '..', 'lib'))]; + const hit = best(cheap, name); + if (hit) return path.join(hit, name); + const gr = globalRoot(); + const global = gr && path.join(gr, '@nanonets', 'graft', 'dist', 'claude'); + if (global && fs.existsSync(path.join(global, name))) return path.join(global, name); + return path.join(dir, 'dist', 'claude', name); // last-ditch; import will no-op if absent +} + +import(pathToFileURL(entry("statusline.js")).href).then((m) => m.main()).catch(() => { /* graft unavailable — no-op */ }); diff --git a/.claude/napkin.md b/.claude/napkin.md new file mode 100644 index 0000000..9743b51 --- /dev/null +++ b/.claude/napkin.md @@ -0,0 +1,37 @@ +# Napkin Runbook + +## Curation Rules +- Re-prioritize on every read. +- Keep recurring, high-value notes only. +- Max 10 items per category. +- Each item includes date + "Do instead". + +## User Directives +1. **[2026-10-20] Responder en español** + Do instead: escribe al usuario en español. Caveman en nivel lite, con artículos, porque el nivel full rompe la gramática. +2. **[2026-10-20] No dar la razón sin contraste** + Do instead: si el encargo choca con el repo o con otra regla del mismo encargo, dilo y aplica la variante que conserve el código estable. +3. **[2026-10-20] No inventar** + Do instead: si un comando, servidor MCP o skill no está, dilo. No rellenes con una configuración supuesta. +4. **[2026-10-20] Una funcionalidad, una rama** + Do instead: crea la rama antes de editar código de producto. No mezcles documentación de agente con un cambio de `lib/` en el mismo diff si el usuario pidió las dos cosas por separado. + +## Execution & Validation (Highest Priority) +1. **[2026-10-20] Graft antes de abrir fuentes** + Do instead: `graft ask`, `graft grep`, `graft skeleton`, `graft callers` o `graft map`. Abre solo el tramo `file:line` que el grafo no haya cerrado. +2. **[2026-10-20] Plan en fichero** + Do instead: crea `docs/workflow/plans/AAAA-MM-DD-tema.md` antes de editar código. +3. **[2026-10-21] Git con dueño dudoso** + Do instead: no ejecutes `git config --global`. Usa `git -c safe.directory=D:/Scripts/BreakingLab` en el comando. `tea` dentro de esta carpeta falla por lo mismo: lánzalo desde otro directorio. +4. **[2026-10-21] Gitea antes que GitHub** + Do instead: el primer remoto es `https://gitea.tiizss.internal/tiizss/BreakingLab`. GitHub (`origin`, `TiiZss/BreakingLab`) va después. SSH al puerto 22 está cerrado; usa HTTPS. +5. **[2026-10-21] Correo de los commits hacia GitHub** + Do instead: no cambies `git config`. En el comando de commit exporta `GIT_AUTHOR_EMAIL` y `GIT_COMMITTER_EMAIL` a `9557246+TiiZss@users.noreply.github.com`. `github@tiizss.com` hace que GitHub rechace el push con `GH007`. +6. **[2026-10-20] Copia antes de reescribir lógica** + Do instead: copia los ficheros afectados a `.backups/AAAA-MM-DD/`. No archives el repo entero. + +## Domain Behavior Guardrails +1. **[2026-10-20] Laboratorios vulnerables a propósito** + Do instead: el lanzador puede arrancar imágenes vulnerables. No añadas exploits ni copies skills ofensivas al repo. Una auditoría mira el script, los hooks y la exposición de red. +2. **[2026-10-20] Sin Python y sin UI** + Do instead: no crees `pyproject.toml` ni apliques skills de frontend. `uv` queda escrito para el día en que haya Python. diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..cfda485 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,78 @@ +{ + "statusLine": { + "type": "command", + "command": "node \"${CLAUDE_PROJECT_DIR:-.}/.claude/helpers/graft-statusline.cjs\"" + }, + "subagentStatusLine": { + "type": "command", + "command": "node \"${CLAUDE_PROJECT_DIR:-.}/.claude/helpers/graft-statusline.cjs\"" + }, + "hooks": { + "PostToolUse": [ + { + "matcher": "Write|Edit|MultiEdit", + "hooks": [ + { + "type": "command", + "command": "node \"${CLAUDE_PROJECT_DIR:-.}/.claude/helpers/graft-hooks.cjs\" post-edit", + "timeout": 10000 + } + ] + }, + { + "matcher": "Bash|mcp__graft__|Read|Grep|Glob", + "hooks": [ + { + "type": "command", + "command": "node \"${CLAUDE_PROJECT_DIR:-.}/.claude/helpers/graft-hooks.cjs\" tool-savings", + "timeout": 8000 + } + ] + } + ], + "UserPromptSubmit": [ + { + "hooks": [ + { + "type": "command", + "command": "node \"${CLAUDE_PROJECT_DIR:-.}/.claude/helpers/graft-hooks.cjs\" prompt", + "timeout": 15000 + } + ] + } + ], + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "node \"${CLAUDE_PROJECT_DIR:-.}/.claude/helpers/graft-hooks.cjs\" session-start", + "timeout": 8000 + } + ] + } + ], + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "node \"${CLAUDE_PROJECT_DIR:-.}/.claude/helpers/graft-hooks.cjs\" stop", + "timeout": 8000 + } + ] + } + ] + }, + "footerLinksRegexes": [ + "graft/[\\w./-]+\\.md" + ], + "permissions": { + "allow": [ + "Bash(graft:*)", + "Bash(npx graft:*)", + "Bash(graft-dev:*)", + "Bash(node dist/cli.js:*)" + ] + } +} diff --git a/.cursor/hooks.json b/.cursor/hooks.json new file mode 100644 index 0000000..e93baae --- /dev/null +++ b/.cursor/hooks.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "hooks": { + "postToolUse": [ + { + "matcher": "Read|Grep|Glob|Search|Shell", + "command": "node \"D:\\Scripts\\BreakingLab\\.cursor\\hooks\\graft-hooks.cjs\" cursor-post-tool" + } + ], + "afterMCPExecution": [ + { + "command": "node \"D:\\Scripts\\BreakingLab\\.cursor\\hooks\\graft-hooks.cjs\" cursor-mcp" + } + ], + "sessionEnd": [ + { + "command": "node \"D:\\Scripts\\BreakingLab\\.cursor\\hooks\\graft-hooks.cjs\" cursor-session-end" + } + ] + } +} diff --git a/.cursor/hooks/graft-hooks.cjs b/.cursor/hooks/graft-hooks.cjs new file mode 100644 index 0000000..4bf9d1d --- /dev/null +++ b/.cursor/hooks/graft-hooks.cjs @@ -0,0 +1,67 @@ +#!/usr/bin/env node +const path = require('path'); +const fs = require('fs'); +const { pathToFileURL } = require('url'); +const { execFileSync } = require('child_process'); +const dir = process.env.CLAUDE_PROJECT_DIR || process.cwd(); +const BAKED = "C:\\Users\\Puper\\AppData\\Roaming\\npm\\node_modules\\@nanonets\\graft\\dist\\claude"; + +// The dist/claude dir of @nanonets/graft resolved from a base whose node_modules is searched. +function fromPkg(base) { + try { + const pkg = require.resolve('@nanonets/graft/package.json', { paths: [base] }); + return path.join(path.dirname(pkg), 'dist', 'claude'); + } catch { return null; } +} + +// The global node_modules dir per npm (handles Homebrew/Windows/volta). Queried on demand. +function globalRoot() { + try { + const root = execFileSync('npm', ['root', '-g'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], shell: process.platform === 'win32' }).trim(); + return root || null; + } catch { return null; /* npm unavailable */ } +} + +// The version of the package a dist/claude dir belongs to, or null if unreadable. +function versionOf(distClaude) { + try { + return JSON.parse(fs.readFileSync(path.join(distClaude, '..', '..', 'package.json'), 'utf8')).version || null; + } catch { return null; } +} + +// Numeric-dotted compare of the release part; an unreadable version loses to any known one. +function newer(a, b) { + if (!a) return false; + if (!b) return true; + const p = (v) => String(v).split('-')[0].split('.').map((n) => Number(n) || 0); + const pa = p(a), pb = p(b); + for (let i = 0; i < Math.max(pa.length, pb.length); i++) { + const d = (pa[i] || 0) - (pb[i] || 0); + if (d !== 0) return d > 0; + } + return false; +} + +// The highest-versioned dir in `dirs` that actually contains `name`, or null. +function best(dirs, name) { + let bestDir = null, bestVer = null; + for (const d of dirs) { + if (!d || !fs.existsSync(path.join(d, name))) continue; + const v = versionOf(d); + if (bestDir === null || newer(v, bestVer)) { bestDir = d; bestVer = v; } + } + return bestDir; +} + +function entry(name) { + // Cheap candidates first, and only shell out to npm when every one of them misses. + const cheap = [BAKED, fromPkg(dir), fromPkg(path.join(path.dirname(process.execPath), '..', 'lib'))]; + const hit = best(cheap, name); + if (hit) return path.join(hit, name); + const gr = globalRoot(); + const global = gr && path.join(gr, '@nanonets', 'graft', 'dist', 'claude'); + if (global && fs.existsSync(path.join(global, name))) return path.join(global, name); + return path.join(dir, 'dist', 'claude', name); // last-ditch; import will no-op if absent +} + +import(pathToFileURL(entry("hooks.js")).href).then((m) => m.main(process.argv[2])).catch(() => { /* graft unavailable — no-op */ }); diff --git a/.cursor/mcp.json b/.cursor/mcp.json new file mode 100644 index 0000000..8b3db9f --- /dev/null +++ b/.cursor/mcp.json @@ -0,0 +1,12 @@ +{ + "mcpServers": { + "graft": { + "command": "npx", + "args": [ + "-y", + "@nanonets/graft", + "mcp" + ] + } + } +} diff --git a/.cursor/rules/graft.mdc b/.cursor/rules/graft.mdc new file mode 100644 index 0000000..c6dbc01 --- /dev/null +++ b/.cursor/rules/graft.mdc @@ -0,0 +1,43 @@ +--- +description: Use the Graft context graph in graft/ before exploring source +alwaysApply: true +--- +## Graft — repo context graph + +This repo is indexed in `graft/`: small linked markdown nodes that explain each +system and carry exact file:line spans, kept in sync with the code through git. + +For ANY task here — understanding how something works, finding where code lives, +or scoping a change — get context from the graph before grepping or opening +source files. Re-ask freely (it's cheap) and reuse literal identifiers you +already have (symbol, error string, file name) as the query. New to this repo? +Run `graft map` first — a token-budgeted orientation (dir clusters, hubs, +hotspots), no LLM, no key. + +- Run `graft ask "" --source` → ranked nodes with the relevant + code spans inlined (each hit's ≤8-line crux by default; `--full` for whole + definitions when the crux isn't enough). Match the tool to the task shape: + for understanding or editing, the top node IS the answer — cite its + `covers:` file:line spans and edit straight from `--source`. For + exhaustive tasks ("every occurrence / every caller of this pattern"), ranked + results are top-N, not complete — run `graft grep ""` instead + (exhaustive over indexed files, grouped by enclosing symbol), falling back + to raw `grep -rn` only for unindexed files. +- `graft skeleton ` → every definition's signature + span, ~10× cheaper + than reading the file; use it to skim an API surface. +- `graft callers ` gives precomputed, exact edges — who calls this. + Add `--direction out` for what it calls, or `--depth N` to walk + transitively for the full blast radius. For structural questions, skip + ranking and use this directly. +- Or browse: `graft/INDEX.md` lists every node; follow the links. +- Monorepos and folders of multiple repos rank fairly across sub-projects — + hits carry `[scope/]` labels naming which one they're from. Narrow with + `graft ask "" --in /` once you know where you're working. + +If a returned span is truncated ("+N more lines"), open the file at that exact +range before finalizing. Only open source files when a node genuinely lacks a +needed detail, and then at the exact file:line the node points to — never +re-read whole files. + +After big code changes, refresh the graph with `graft build` (deterministic, +no API key, $0). diff --git a/.cursor/rules/workflow.mdc b/.cursor/rules/workflow.mdc new file mode 100644 index 0000000..47d8a5d --- /dev/null +++ b/.cursor/rules/workflow.mdc @@ -0,0 +1,24 @@ +--- +description: Mapa de trabajo de BreakingLab. Léelo en cada sesión. +alwaysApply: true +--- + +# Comportamiento del agente + +El mapa completo está en `CLAUDE.md`. Léelo antes de un cambio que no sea trivial. Esto es lo que no puede perderse si no abres ese archivo. + +- BreakingLab es Bash y Docker. Entrada: `breakinglab.sh`. No hay frontend propio ni Python. +- Graft antes de leer fuentes: `graft ask`, `graft grep`, `graft skeleton`, `graft callers` o `graft map`, el que encaje. Una llamada suele bastar. +- Plan en `docs/workflow/plans/` antes de codificar. La sesión no es el archivo del plan. +- Lee `.claude/napkin.md` al empezar. Ahí están las directrices que se repiten. +- Copia en `.backups/AAAA-MM-DD/` los ficheros cuya lógica vayas a reescribir. Una funcionalidad, una rama. +- No reescribas comportamiento que ya funciona si el encargo no lo pide. Lo nuevo entra al lado, en UTF-8. +- Python, si llega: `uv` y virtualenv. Hoy no hay Python; no añadas proyecto Python vacío. +- Skills útiles, sin copiarlas al repo: ECC `docker-patterns`, `security-review`, `security-scan`, `git-workflow`, `github-ops`, `verification-loop`, `terminal-ops`. Las 818 skills de `Anthropic-Cybersecurity-Skills` solo para auditar este lanzador con permiso. Nada de skills de UI hasta que exista UI. +- MCP que hay que usar cuando la tarea lo pida: GitHub, Context7, Playwright, Filesystem, Sentry si el servidor responde. `markitdown` no está conectado: no inventes el servidor. +- Caveman lite en español. Napkin en `.claude/napkin.md`. Diagram Design solo para un diagrama pedido. Prosa nueva según `D:\Scripts\Z-externos\humanizer`. +- Cuestiona el encargo cuando choque con el repo o con otra regla de este mismo encargo. No completes un hueco con un dato no comprobado. +- Agente más estrecho y con menos tokens que sirva. Sin subagente para un arreglo local. +- Memoria en `docs/workflow/MEMORY.md`, lecciones en `LEARNINGS.md`, decisiones en `decisions.md`. +- Publica primero en `https://gitea.tiizss.internal/tiizss/BreakingLab` y después en GitHub. Push, tag, release y merge a `main` solo con ShellCheck en verde, problemas del cambio corregidos y docs alineadas. Si el CI falla, se corrige antes de fusionar. +- Si git dice `dubious ownership`, no ejecutes `git config --global`. Usa `git -c safe.directory=D:/Scripts/BreakingLab` en ese comando. diff --git a/.gemini/settings.json b/.gemini/settings.json new file mode 100644 index 0000000..8b3db9f --- /dev/null +++ b/.gemini/settings.json @@ -0,0 +1,12 @@ +{ + "mcpServers": { + "graft": { + "command": "npx", + "args": [ + "-y", + "@nanonets/graft", + "mcp" + ] + } + } +} diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..f19a289 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,45 @@ + +## Graft — repo context graph + +This repo is indexed in `graft/`: small linked markdown nodes that explain each +system and carry exact file:line spans, kept in sync with the code through git. + +For ANY task here — understanding how something works, finding where code lives, +or scoping a change — get context from the graph before grepping or opening +source files. Re-ask freely (it's cheap) and reuse literal identifiers you +already have (symbol, error string, file name) as the query. New to this repo? +Run `graft map` first — a token-budgeted orientation (dir clusters, hubs, +hotspots), no LLM, no key. + +- Run `graft ask "" --source` → ranked nodes with the relevant + code spans inlined (each hit's ≤8-line crux by default; `--full` for whole + definitions when the crux isn't enough). Match the tool to the task shape: + for understanding or editing, the top node IS the answer — cite its + `covers:` file:line spans and edit straight from `--source`. For + exhaustive tasks ("every occurrence / every caller of this pattern"), ranked + results are top-N, not complete — run `graft grep ""` instead + (exhaustive over indexed files, grouped by enclosing symbol), falling back + to raw `grep -rn` only for unindexed files. +- `graft skeleton ` → every definition's signature + span, ~10× cheaper + than reading the file; use it to skim an API surface. +- `graft callers ` gives precomputed, exact edges — who calls this. + Add `--direction out` for what it calls, or `--depth N` to walk + transitively for the full blast radius. For structural questions, skip + ranking and use this directly. +- Or browse: `graft/INDEX.md` lists every node; follow the links. +- Monorepos and folders of multiple repos rank fairly across sub-projects — + hits carry `[scope/]` labels naming which one they're from. Narrow with + `graft ask "" --in /` once you know where you're working. + +If a returned span is truncated ("+N more lines"), open the file at that exact +range before finalizing. Only open source files when a node genuinely lacks a +needed detail, and then at the exact file:line the node points to — never +re-read whole files. + +After big code changes, refresh the graph with `graft build` (deterministic, +no API key, $0). + + +## Mapa de trabajo + +El mapa está en `CLAUDE.md`. Cursor lo aplica con `.cursor/rules/workflow.mdc`. Memoria, lecciones y decisiones están en `docs/workflow/`. Las notas que se repiten están en `.claude/napkin.md`. diff --git a/.github/prompts/plan-breakingLab-compact.prompt.md b/.github/prompts/plan-breakingLab-compact.prompt.md new file mode 100644 index 0000000..f102e9b --- /dev/null +++ b/.github/prompts/plan-breakingLab-compact.prompt.md @@ -0,0 +1,59 @@ +# BreakingLab Plan 60-90 días + +## Executive Summary +BreakingLab no necesita una reescritura, sino una secuencia disciplinada de estabilización. El orden correcto es: asegurar el core, formalizar el contrato de configuración, controlar supply chain y runtime, convertir updates y CI en flujos confiables, y gobernar los labs embebidos según ownership real. + +## Decisión recomendada +Ejecutar un roadmap de 90 días centrado en core, configuración, runtime, update/release y gobierno de labs. No abrir modernización profunda de labs de terceros hasta cerrar seguridad, contrato, rollback y validación multiplataforma. + +## Prioridades +1. P0: runtime safety, ejecución dinámica, contrato de configuración, rollback y validación Linux/WSL2. +2. P1: pinning de imágenes, rendimiento del runtime, migración del contrato, red configurable y pruebas mínimas. +3. P2: modularización del core, logging/observabilidad y auditoría más profunda de labs propios. + +## Guardrails +1. Las rutas normales no pueden instalar paquetes ni añadir repositorios. +2. No se cierra ningún cambio de configuración sin migración y modo legacy temporal. +3. No se cierra ningún cambio de update sin rollback probado. +4. No se asume compatibilidad Linux/WSL2 sin evidencia. +5. `archive/` queda fuera del roadmap operativo. + +## Roadmap +1. Baseline y gobierno: inventario, ownership, Definition of Done y rollback mínimo. +2. Policy gates: runtime safety, lane Linux/WSL2 y control de alcance. +3. Seguridad del core: hosts, hooks, menú, rutas públicas y ejecución dinámica. +4. Configuración y migración: contrato, validador y retirada planificada del modo legacy. +5. Supply chain y runtime: pinning, política de import, caché Docker, healthchecks, red y recursos. +6. Operación y calidad: doctor, validate, verify, dry-run, update seguro, CI real y tests mínimos. +7. Labs y documentación: ownership, drift, auditoría prioritaria y runbook operativo. + +## Hitos +1. Hito 1: core seguro y contrato definido. +2. Hito 2: runtime más rápido y reproducible. +3. Hito 3: update, CI y soporte confiables. +4. Hito 4: core mantenible y labs gobernados. + +## Riesgos a controlar +1. Auto-instalación de dependencias desde flujos normales. +2. Persistencia de eval/source inseguros en rutas no cubiertas. +3. Cambio de contrato sin migración real. +4. Validación incompleta en WSL2. +5. Scope creep sobre `archive/` o sobre labs de terceros. + +## Backlog núcleo +1. Gobierno: BL-00, BL-01, BL-25. +2. Seguridad: BL-02, BL-03, BL-07. +3. Configuración: BL-04, BL-05. +4. Runtime: BL-06, BL-08, BL-09, BL-10, BL-11, BL-13. +5. Release y calidad: BL-14, BL-15, BL-16, BL-17, BL-18, BL-19, BL-24. +6. Labs y docs: BL-20, BL-21, BL-22, BL-23. + +## Verificación final +1. Configuración validable antes de runtime. +2. Linux y WSL2 cubiertos en rutas críticas. +3. Update con rollback y validación post-cambio. +4. Menú y arranque con mejora medible. +5. Labs con ownership y policy de update. + +## Criterio de éxito ejecutivo +El plan habrá funcionado si BreakingLab sigue siendo simple de usar, pero pasa a ser claramente más seguro, más predecible de actualizar, más medible en runtime y más gobernable como producto. \ No newline at end of file diff --git a/.github/prompts/plan-breakingLab-en.prompt.md b/.github/prompts/plan-breakingLab-en.prompt.md new file mode 100644 index 0000000..7014d8d --- /dev/null +++ b/.github/prompts/plan-breakingLab-en.prompt.md @@ -0,0 +1,59 @@ +# BreakingLab 60-90 Day Plan + +## Summary +BreakingLab needs layered stabilization, not a rewrite. The correct priority is to harden the core, formalize the configuration contract, separate normal user flows from privileged operations, validate Linux and WSL2 as an explicit workstream, and make updates, CI, and rollback predictable. + +## Recommended Decision +Run a 90-day roadmap focused on core hardening, configuration governance, runtime reliability, update/release safety, and embedded-lab governance. Do not open deep modernization of third-party labs before security, contract migration, rollback, and platform validation are closed. + +## Executive Priorities +1. P0: runtime safety, dynamic execution containment, configuration contract, rollback, and Linux/WSL2 validation. +2. P1: image pinning, runtime performance, contract migration, configurable networking, and minimum test coverage. +3. P2: core modularization, better logging/observability, and deeper first-party lab audits. + +## Policy Gates +1. No normal usage path may install packages, add repositories, or mutate persistent host state outside install, doctor, or update flows. +2. Any mitigation of dynamic execution must cover breakinglab.sh, lib/menu.sh, lib/utils.sh, config/projects.conf, and scripts/hooks. +3. No configuration contract change may be closed without migration, temporary compatibility, and legacy mode retirement criteria. +4. Any change touching Docker, privileges, URL opening, installation, or update must be explicitly validated on Linux and WSL2. +5. archive/ is out of operational scope unless explicitly justified. + +## Roadmap +1. Baseline and governance: inventory, ownership, Definition of Done, and rollback minimums. +2. Policy gates: runtime safety, Linux/WSL2 lane, and scope control. +3. Core security: hosts, hooks, menu paths, public-start paths, and dynamic execution. +4. Configuration and migration: contract, validator, and planned legacy retirement. +5. Supply chain and runtime: pinning, import policy, Docker state caching, healthchecks, networking, and resource profiles. +6. Operational quality: doctor, validate, verify, dry-run, safer updates, CI, and minimum tests. +7. Embedded labs and docs: ownership, drift resolution, targeted audits, and operational runbook. + +## 90-Day Milestones +1. Milestone 1: secure core and defined configuration contract. +2. Milestone 2: faster and more reproducible runtime. +3. Milestone 3: reliable updates, CI, and operational support. +4. Milestone 4: maintainable core and governed labs. + +## Delivery Rules +1. Do not mix deep core refactors with deep lab changes in the same delivery. +2. Do not close update work without tested rollback. +3. Do not close configuration work without migration evidence. +4. Do not claim platform compatibility without Linux and WSL2 validation. +5. Keep the roadmap, backlog, and execution artifacts aligned at all times. + +## Main Backlog +1. Governance: BL-00, BL-01, BL-25. +2. Security: BL-02, BL-03, BL-07. +3. Configuration: BL-04, BL-05. +4. Runtime: BL-06, BL-08, BL-09, BL-10, BL-11, BL-13. +5. Release and quality: BL-14, BL-15, BL-16, BL-17, BL-18, BL-19, BL-24. +6. Labs and docs: BL-20, BL-21, BL-22, BL-23. + +## Verification +1. Configuration validation before runtime execution. +2. Linux and WSL2 coverage for critical flows. +3. Update flow with rollback and post-change validation. +4. Measurable menu and startup improvements. +5. Embedded labs with ownership and update policy. + +## Executive Success Criteria +The plan succeeds if BreakingLab remains easy to use while becoming measurably safer, more predictable to update, more reliable at runtime, and easier to govern as an evolving product. \ No newline at end of file diff --git a/.github/prompts/plan-breakingLab-execution.prompt.md b/.github/prompts/plan-breakingLab-execution.prompt.md new file mode 100644 index 0000000..492b18d --- /dev/null +++ b/.github/prompts/plan-breakingLab-execution.prompt.md @@ -0,0 +1,137 @@ +Eres un agente técnico encargado de ejecutar la mejora de BreakingLab en un horizonte de 60-90 días. Trabaja sobre el repo actual y prioriza primero el core, después release/CI y finalmente los labs embebidos. No propongas reescrituras amplias salvo que una limitación estructural lo haga imprescindible. Tu objetivo es reducir riesgo real, mejorar velocidad del runtime, aumentar escalabilidad operativa, reforzar la funcionalidad de soporte y formalizar el proceso de actualización. + +Modo de trabajo: +1. Avanza por fases y no saltes a fases posteriores si falta cerrar policy gates o contrato. +2. Antes de cambiar código, confirma el riesgo concreto y el archivo afectado. +3. Tras cada bloque relevante, produce evidencia: qué cambió, cómo se validó y qué queda pendiente. +4. Si encuentras una contradicción entre roadmap y backlog, corrige primero el plan o la issue antes de implementar. + +Reglas obligatorias: +1. Ninguna ruta de uso normal puede instalar paquetes, añadir repositorios o modificar persistencia del host fuera de install, doctor o update. +2. Toda mitigación de ejecución dinámica debe cubrir breakinglab.sh, lib/menu.sh, lib/utils.sh, config/projects.conf y scripts/hooks. +3. Ningún cambio del contrato de configuración puede cerrarse sin migración, compatibilidad temporal y criterio de retirada del modo legacy. +4. Todo cambio que toque Docker, privilegios, apertura de URLs, instalación o update debe validarse en Linux y WSL2. +5. archive/ queda fuera del alcance operativo salvo justificación explícita. +6. No mezcles en una sola entrega refactor profundo del core con cambios profundos de labs. +7. No cierres un cambio de actualización sin rollback probado. +8. No asumas compatibilidad multiplataforma sin evidencia. +9. No mezcles cambios de política, cambios de contrato y cambios de labs en una misma entrega si eso empeora la trazabilidad. +10. No trates labs de terceros como si fueran código propio salvo que exista una excepción aprobada. + +Fases obligatorias: +1. Fase 0. Inventario y ownership. +2. Fase 0.5. Policy gates y límites de alcance. +3. Fase 1. Seguridad del core. +4. Fase 2. Contrato de configuración y migración. +5. Fase 3. Supply chain, rendimiento runtime, red y recursos. +6. Fase 4. Funcionalidad operativa. +7. Fase 5. Update, release y compatibilidad. +8. Fase 6. CI, pruebas, logging y observabilidad. +9. Fase 7. Labs embebidos. +10. Fase 8. Documentación operativa y cierre. + +Orden de ejecución: +1. Inventariar el repo y clasificar componentes por ownership y estrategia de mantenimiento. +2. Cerrar policy gates y límites de alcance. +3. Endurecer seguridad del core: hosts, hooks, rutas públicas, ejecución dinámica y menú. +4. Definir el nuevo contrato de configuración y el validador asociado. +5. Diseñar la migración del contrato con compatibilidad temporal y retirada del modo legacy. +6. Formalizar supply chain, pinning de imágenes y política de import. +7. Mejorar rendimiento del runtime: caché de estado Docker, healthchecks y menor latencia del menú. +8. Hacer configurable la red y añadir perfiles de recursos por lab. +9. Rehacer la estrategia de compose sanitization con casos soportados claros. +10. Añadir comandos operativos: doctor, validate, verify, dry-run, lock y update-lab. +11. Rediseñar update/install con backup, rollback y validación post-cambio. +12. Extender CI a validación real y pruebas mínimas. +13. Formalizar logging, observabilidad básica y diagnóstico. +14. Auditar y gobernar labs embebidos según ownership. +15. Cerrar documentación operativa, runbook y Definition of Done común. + +Prioridades: +- P0: seguridad del core, runtime safety, contrato de configuración, rollback, validación multiplataforma. +- P1: rendimiento del runtime, supply chain, CI mínima, migración del contrato, red configurable. +- P2: modularización del core, logging mejorado, auditoría profunda de labs propios. +- P3: modernización extensa de labs o mejoras opcionales de UX no bloqueantes. + +Entregables mínimos: +1. Backlog priorizado con épicas, historias, estimaciones y dependencias. +2. Roadmap de 90 días con hitos. +3. Validaciones mínimas para seguridad, runtime, update y plataforma. +4. Criterios de aceptación y Definition of Done comunes. +5. Política de mantenimiento por lab. + +Formato de salida esperado en cada iteración importante: +1. Contexto confirmado. +2. Riesgo o problema que se va a tratar. +3. Cambio propuesto o ejecutado. +4. Evidencia de validación. +5. Riesgo residual. +6. Siguiente paso. + +Plantilla obligatoria por fase: +1. Fase actual. +2. Objetivo de la fase. +3. Issues BL-* cubiertas. +4. Archivos afectados. +5. Cambios planeados o ejecutados. +6. Validación Linux. +7. Validación WSL2. +8. Rollback. +9. Riesgos residuales. +10. Criterio de salida de fase. + +Checklist de salida de fase: +- El objetivo de la fase quedó cumplido o explícitamente acotado. +- Las issues asociadas están alineadas con el backlog. +- Existe evidencia de validación suficiente. +- El rollback es conocido si la fase toca seguridad, config o update. +- La documentación impactada quedó identificada. + +Anti-goals: +1. No optimizar primero UX si runtime safety y contrato siguen abiertos. +2. No introducir nueva complejidad técnica sin beneficio medible. +3. No usar compatibilidad hacia atrás indefinida; toda excepción legacy debe tener fecha o criterio de retirada. +4. No ampliar scope a archive/ ni a reingeniería interna de labs de terceros. +5. No cerrar fases por percepción; solo por evidencia comprobable. + +Criterios de éxito: +1. Menú y status más rápidos y medibles. +2. Configuración validable antes de ejecución. +3. Updates con rollback definido y probado. +4. CI con validación real, no solo lint. +5. Linux y WSL2 verificados en rutas críticas. +6. Labs clasificados por ownership y estrategia de update. + +Archivos clave: +- d:\Scripts\BreakingLab\breakinglab.sh +- d:\Scripts\BreakingLab\install.sh +- d:\Scripts\BreakingLab\lib\utils.sh +- d:\Scripts\BreakingLab\lib\hosts.sh +- d:\Scripts\BreakingLab\lib\menu.sh +- d:\Scripts\BreakingLab\lib\yaml_utils.sh +- d:\Scripts\BreakingLab\config\projects.conf +- d:\Scripts\BreakingLab\config\projects.d +- d:\Scripts\BreakingLab\scripts\hooks +- d:\Scripts\BreakingLab\README.md +- d:\Scripts\BreakingLab\CHANGELOG.md +- d:\Scripts\BreakingLab\test_awk.sh +- d:\Scripts\BreakingLab\test_gh_fetch.sh +- d:\Scripts\BreakingLab\.github\workflows\shellcheck.yml +- d:\Scripts\BreakingLab\projects\dvws-node-2 +- d:\Scripts\BreakingLab\projects\dvwsnode2 +- d:\Scripts\BreakingLab\projects\vulpy5 + +Reglas de cierre: +1. Toda tarjeta crítica debe tener validación manual, impacto en documentación y rollback. +2. Toda tarjeta de config debe referenciar el contrato y la migración. +3. Toda tarjeta de plataforma debe incluir evidencia Linux/WSL2. +4. Toda tarjeta de labs debe indicar si el componente es propio, fork mantenido, snapshot o vendorizado. +5. Toda entrega debe dejar el backlog y el documento maestro alineados. + +Resultado final esperado: +1. Un core más seguro y menos implícito. +2. Un contrato de configuración validable y migrado. +3. Un runtime más rápido y estable. +4. Un proceso de update/release con rollback real. +5. Un pipeline de calidad útil. +6. Una política clara para labs embebidos. diff --git a/.github/prompts/plan-breakingLab.prompt.md b/.github/prompts/plan-breakingLab.prompt.md new file mode 100644 index 0000000..5d10626 --- /dev/null +++ b/.github/prompts/plan-breakingLab.prompt.md @@ -0,0 +1,161 @@ +## Plan: BreakingLab 60-90 días + +Este documento es la versión maestra del plan de mejora de BreakingLab. Su propósito es ordenar prioridades, fijar límites de alcance, alinear backlog y roadmap, y servir como referencia para decisiones técnicas y operativas durante los próximos 60-90 días. + +La tesis del plan es simple: BreakingLab no necesita una reescritura, necesita una secuencia disciplinada de estabilización. El mayor riesgo está en el core Bash, en la ejecución dinámica, en la mutación del host, en la fragilidad del contrato de configuración y en la falta de un proceso robusto de actualización y validación. Por eso la prioridad correcta es endurecer el runtime, formalizar la configuración, hacer reproducible la operación y gobernar los labs embebidos según ownership real. + +**Document Map** +- Este archivo: versión maestra, estratégica y operativa. +- `.github/prompts/plan-breakingLab-execution.prompt.md`: versión orientada a ejecución estricta por fases. +- `.github/prompts/plan-breakingLab-compact.prompt.md`: versión ejecutiva resumida. +- `.github/prompts/plan-breakingLab-en.prompt.md`: versión equivalente en inglés. +- `docs/plan-breakingLab-roadmap.md`: versión publicable del roadmap y marco de trabajo. +- `docs/rfc-breakingLab-roadmap.md`: resumen corto de decisión y contexto. +- `docs/github-planning-conventions.md`: convención de labels, epics, issues y PRs. +- `docs/issue-batch-1.md`: primer lote priorizado de trabajo listo para abrir. +- `docs/planning-handoff.md`: punto de reentrada para retomar el trabajo en otra sesión. +- `docs/README.md`: índice de documentación de planificación. + +**Kanban** +- Backlog: trabajo identificado pero aún no preparado. +- Ready: historia con alcance, criterio de aceptación y archivos afectados claros. +- In Progress: implementación activa con rama y prueba local definida. +- Blocked: dependencias externas, decisiones de producto o limitaciones de upstream. +- Review: cambios listos con pruebas, revisión técnica y validación manual. +- Done: mergeado, documentado, liberado y con rollback definido. + +**Policy Gates** +- Runtime safety: ninguna ruta de uso normal puede instalar paquetes, añadir repositorios del sistema o mutar persistencia del host fuera de flujos explícitos de install/doctor/update. +- Dynamic execution scope: toda eliminación o encapsulado de ejecución dinámica debe incluir breakinglab.sh, lib/menu.sh, lib/utils.sh, config/projects.conf y scripts/hooks. +- Contract migration: ningún cambio del contrato de configuración puede desplegarse sin estrategia de migración, compatibilidad temporal y criterio de retirada del modo legacy. +- Platform validation: todo cambio que toque Docker, apertura de URLs, instalación, update o privilegios debe validarse explícitamente en Linux y WSL2. +- Scope control: archive/ queda fuera del roadmap operativo salvo referencia histórica o necesidad excepcional justificada. + +**Strategic Priorities** +1. P0: runtime safety, ejecución dinámica, contrato de configuración, rollback y validación Linux/WSL2. +2. P1: pinning de imágenes, rendimiento del runtime, migración del contrato, red configurable y pruebas mínimas. +3. P2: modularización del core, observabilidad útil y auditoría más profunda de labs propios. +4. P3: modernización extensa de labs o mejoras de UX no bloqueantes. + +**Steps** +1. Fase 0. Baseline y gobierno del plan. Congelar alcance de 60-90 días, clasificar todo el repo en core propio vs labs vendorizados vs labs propios, y crear un inventario con owner, criticidad, tipo de mantenimiento y estrategia de actualización. Esto bloquea todas las fases posteriores. +2. Fase 0.5. Policy gates. Formalizar reglas no negociables para runtime safety, validación Linux/WSL2, control de alcance sobre archive/ y separación entre flujos de uso normal frente a install/update/doctor. Esto debe quedar cerrado antes de tocar seguridad o updates. +3. Definir reglas de priorización kanban. Prioridad P0 para seguridad operativa y reproducibilidad, P1 para rendimiento y escalabilidad del core, P2 para funcionalidad y UX, P3 para modernización profunda de labs. Esto puede hacerse en paralelo con el paso 1, pero no debe cerrar sprint sin inventario. +4. Fase 1. Seguridad crítica del core. Sustituir ejecución peligrosa y validación débil en d:\Scripts\BreakingLab\breakinglab.sh, d:\Scripts\BreakingLab\lib\hosts.sh, d:\Scripts\BreakingLab\lib\utils.sh, d:\Scripts\BreakingLab\lib\menu.sh y d:\Scripts\BreakingLab\config\projects.conf. Objetivo: eliminar source ciego y eval inseguro donde sea viable, endurecer add_host, validar slug/IP/puerto, acotar permisos, separar flujos que hoy mutan el sistema desde runtime normal y normalizar hooks. Depende de 1 y 2. +5. Diseñar un esquema de configuración versionado para proyectos. Migrar el formato pipe-delimited a un formato con validación explícita o, como mínimo, introducir un validador fuerte y un version field compatible hacia atrás. Reutilizar d:\Scripts\BreakingLab\config\projects.conf y d:\Scripts\BreakingLab\config\projects.d\_template.conf.example como base de transición. Depende de 4. +6. Fase de migración del contrato. Añadir inventario de compatibilidad, migrador o asistente semiautomático, modo legacy temporal, criterio de retirada y validación de catálogo existente antes de hacer obligatorio el nuevo contrato. Depende de 5. +7. Formalizar política de supply chain. Pinning de imágenes Docker por tag o digest, política para git clone/import, allowlist de repos soportados, checksum o commit pin para labs importados, y revisión de hooks post-import. Afecta d:\Scripts\BreakingLab\breakinglab.sh, d:\Scripts\BreakingLab\config\projects.d y d:\Scripts\BreakingLab\scripts\hooks. Depende de 4 y puede avanzar en paralelo con 5. +8. Fase 2. Rendimiento del core. Reducir llamadas repetidas a docker, cachear estado, mejorar polling de arranque y refactorizar la detección de estado para no recalcular cada render del menú. Reutilizar patrones en d:\Scripts\BreakingLab\lib\menu.sh y d:\Scripts\BreakingLab\lib\utils.sh. Depende de 4. +9. Replantear asignación de red y colisiones. Hacer configurable el rango IP, reservar espacio por instancia o mover progresivamente hacia networking Docker más nativo para no depender de 127.100.0.x como único límite. Afecta d:\Scripts\BreakingLab\lib\utils.sh, d:\Scripts\BreakingLab\breakinglab.sh y las definiciones en d:\Scripts\BreakingLab\config\projects.d. Depende de 5 y 8. +10. Introducir límites de recursos y perfiles de ejecución por lab. Añadir CPU, memoria, timeout y healthcheck como metadatos de proyecto para evitar que un lab degrade todo el host. Depende de 5 y 8. +11. Carril de plataforma. Mantener una lane específica Linux/WSL2 para validar comportamiento de Docker, apertura de URLs, dependencias, permisos y update antes de cerrar cualquier fase que toque runtime o instalación. Depende de 2 y avanza en paralelo con 4, 8, 13 y 16. +12. Fase 3. Escalabilidad y mantenibilidad. Dividir responsabilidades del orquestador principal en módulos más pequeños: lifecycle, config, docker runtime, networking, import/update y UX. El objetivo es reducir complejidad en d:\Scripts\BreakingLab\breakinglab.sh y estabilizar contratos internos entre librerías. Depende de 4, 5 y 8. +13. Rehacer la sanitización de docker compose con una estrategia menos frágil que el AWK actual. Primero documentar casos soportados y no soportados; después sustituir o encapsular d:\Scripts\BreakingLab\lib\yaml_utils.sh con validación y pruebas. Depende de 5 y 8. +14. Fase 4. Funcionalidad. Crear capacidades operativas que ahora faltan: doctor, validate, dry-run, verify, lock, update-lab, start-all por lotes, estado enriquecido y diagnóstico de errores. La superficie principal estará en d:\Scripts\BreakingLab\breakinglab.sh, d:\Scripts\BreakingLab\lib\utils.sh y d:\Scripts\BreakingLab\README.md. Depende de 4, 5 y 8. +15. Mejorar UX de CLI y menú. Mantener el flujo actual, pero añadir errores accionables, estado más fiable, filtros útiles y salida no interactiva apta para scripting. Depende de 8 y puede hacerse en paralelo con 14. +16. Fase 5. Proceso de actualización y release. Rediseñar install/update para soportar prechecks, backup, rollback, migración de configs y validación post-update. Afecta d:\Scripts\BreakingLab\install.sh, d:\Scripts\BreakingLab\breakinglab.sh, d:\Scripts\BreakingLab\README.md y d:\Scripts\BreakingLab\CHANGELOG.md. Debe incluir la regla explícita de no auto-instalar dependencias desde rutas de uso normal como open/start. Depende de 5, 6, 11 y 14. +17. Formalizar versión y compatibilidad. Introducir semver real, política de deprecación, matriz de compatibilidad Bash/Docker/WSL2 y notas de migración por release. Depende de 16. +18. Extender CI desde shellcheck a validación real. Mantener d:\Scripts\BreakingLab\.github\workflows\shellcheck.yml y añadir validación de configs, tests unitarios, pruebas de integración mínimas y gates para release. Depende de 4, 5, 11 y 13; puede avanzar en paralelo con 16. +19. Fase 6. Calidad y observabilidad. Sustituir los scripts ad hoc de prueba por una suite formal, instrumentar logs con rotación, niveles de severidad y trazas de operaciones críticas, y añadir comandos de soporte para diagnóstico. Reutilizar d:\Scripts\BreakingLab\test_awk.sh, d:\Scripts\BreakingLab\test_gh_fetch.sh y d:\Scripts\BreakingLab\lib\utils.sh como punto de partida. Depende de 13, 16 y 18. +20. Fase 7. Gestión de labs embebidos. Separar labs propios de labs de terceros dentro de d:\Scripts\BreakingLab\projects. Para terceros: no reescribir funcionalidad salvo fixes de integración, seguridad de packaging y reproducibilidad. Para propios o claramente mantenidos aquí: auditar dependencias, Dockerfiles, compose files, timeouts de arranque, credenciales por defecto y healthchecks. Depende de 1, 7 y 18. +21. Crear una política de actualización por lab. Cada directorio de d:\Scripts\BreakingLab\projects debe tener estrategia explícita: vendorizado con upstream pinned, fork mantenido, o snapshot interno. Esto reduce deuda y evita cambios accidentales durante upgrades globales. Depende de 20. +22. Auditar especialmente d:\Scripts\BreakingLab\projects\dvws-node-2, d:\Scripts\BreakingLab\projects\dvwsnode2 y d:\Scripts\BreakingLab\projects\vulpy5 por duplicación, drift, dependencias antiguas, startup frágil y exposición innecesaria. Depende de 20 y puede correr en paralelo con 21. +23. Fase 8. Documentación operativa. Completar README con límites, troubleshooting y flujo de mantenimiento; añadir guía de contribución, guía de seguridad de hooks/configs y runbook de release/rollback. Depende de 14, 16, 18 y 20. +24. Fase 9. Despliegue controlado. Ejecutar primero endurecimiento en core, luego migración de configuración, luego rollout de CI y por último la modernización de labs. No mezclar refactor interno y cambios de comportamiento de actualización en el mismo lote. Depende de 4 a 23. +25. Cerrar cada tarjeta con una definición estricta de Done: pruebas automatizadas pasando, validación manual documentada, impacto en CHANGELOG, ruta de rollback y actualización de documentación. Aplica a todos los pasos. + +**Relevant files** +- d:\Scripts\BreakingLab\breakinglab.sh — orquestador principal; lifecycle, import, update, startpublic y validación general. +- d:\Scripts\BreakingLab\install.sh — instalación global, prechecks y rollback de instalación. +- d:\Scripts\BreakingLab\lib\utils.sh — docker checks, hooks, logging, WSL helpers y utilidades transversales. +- d:\Scripts\BreakingLab\lib\hosts.sh — modificación de hosts y principal superficie de privilegios. +- d:\Scripts\BreakingLab\lib\menu.sh — renderizado, consulta de estado y experiencia de usuario. +- d:\Scripts\BreakingLab\lib\yaml_utils.sh — sanitización compose y principal foco de fragilidad técnica. +- d:\Scripts\BreakingLab\config\projects.conf — carga de configuración y punto actual de source dinámico. +- d:\Scripts\BreakingLab\config\projects.d\_template.conf.example — plantilla del contrato de proyectos. +- d:\Scripts\BreakingLab\config\projects.d — catálogo real de labs, pinning y metadatos operativos. +- d:\Scripts\BreakingLab\scripts\hooks — automatizaciones per-project que requieren política de seguridad y contrato. +- d:\Scripts\BreakingLab\README.md — instalación, uso, troubleshooting y procesos operativos. +- d:\Scripts\BreakingLab\CHANGELOG.md — versionado y comunicación de cambios/migraciones. +- d:\Scripts\BreakingLab\test_awk.sh — referencia actual de pruebas manuales para compose sanitization. +- d:\Scripts\BreakingLab\test_gh_fetch.sh — referencia actual de pruebas manuales para import y fetch. +- d:\Scripts\BreakingLab\.github\workflows\shellcheck.yml — base del pipeline de calidad. +- d:\Scripts\BreakingLab\projects\dvws-node-2 — lab embebido a clasificar por ownership y mantenimiento. +- d:\Scripts\BreakingLab\projects\dvwsnode2 — lab embebido con aparente duplicidad y posible drift. +- d:\Scripts\BreakingLab\projects\vulpy5 — lab embebido con Docker/Python que debe auditarse por seguridad y reproducibilidad. +- d:\Scripts\BreakingLab\archive — referencia histórica; fuera del roadmap operativo salvo necesidad excepcional justificada. + +**Verification** +1. Inventario completo del repo con clasificación core/lab propio/lab tercero y estrategia de update para cada elemento. +2. Validación de configuración: carga de todos los projects sin source inseguro ni campos ambiguos no detectados. +3. Pruebas de seguridad sobre add_host, hooks, import y startpublic con entradas inválidas y casos de abuso conocidos. +4. Benchmark antes/después del menú y del arranque de labs representativos para medir reducción de llamadas docker y tiempo total. +5. Pruebas de integración mínimas para start, stop, status, update y import en Linux y WSL2. +6. Simulación de upgrade con backup y rollback verificando que la instalación queda consistente tras fallo parcial. +7. Auditoría de imágenes y dependencias en labs embebidos: tags, digests, paquetes críticos, puertos, credenciales por defecto y healthchecks. +8. Revisión documental: README, CHANGELOG y guías de mantenimiento alineadas con el comportamiento real. +9. Verificación explícita de que ninguna ruta de uso normal instala paquetes, añade repositorios o muta persistencia del sistema fuera de install/doctor/update. +10. Validación de migración del contrato: catálogo actual compatible, modo legacy temporal y retirada planificada. + +**Decisions** +- Incluido: todo el repo, con foco prioritario en el core y en release/CI durante los primeros sprints. +- Incluido: labs embebidos, pero con dos niveles de intervención. Los labs de terceros se tratan como componentes vendorizados y se prioriza packaging, actualización y aislamiento. Los labs propios o mantenidos localmente sí entran en refactor técnico más profundo. +- Excluido en la primera ola: reescritura completa de aplicaciones vulnerables de terceros cuyo valor del repo es didáctico y no el hardening interno de la app. +- Excluido del roadmap operativo: archive/, salvo consulta histórica o necesidad excepcional aprobada. +- Recomendación de ejecución: 4 tableros o épicas en paralelo. Seguridad y supply chain; rendimiento y escalabilidad; actualización y release; labs embebidos y documentación. Seguridad bloquea cualquier rollout amplio. + +**Further Considerations** +1. Recomendación organizativa: mantener un board con swimlanes P0, P1, P2 y una etiqueta extra de Ownership para distinguir core, config, hooks y labs. +2. Recomendación táctica: cerrar primero el contrato de configuración antes de tocar en masa scripts hooks o compose sanitization; de lo contrario, se moverán dos interfaces a la vez. +3. Recomendación de riesgo: tratar la coexistencia de d:\Scripts\BreakingLab\projects\dvws-node-2 y d:\Scripts\BreakingLab\projects\dvwsnode2 como incidencia temprana del backlog porque apunta a drift y duplicación operativa. +4. Recomendación de secuencia: insertar un mini-sprint 0.5 para policy gates y validación Linux/WSL2 antes del endurecimiento principal del core. +5. Recomendación de entrega: separar cambios de update/release de cambios de CI/testing en tracks distintos para reducir riesgo de regresión y facilitar revisión. + +**Artifacts** +- Kanban board listo para GitHub Projects/Jira con épicas, columnas, etiquetas y prioridad. +- Desglose de historias y tareas con estimación de esfuerzo. +- Sprint 1 detallado con criterios de aceptación y definición de done. +- Export CSV importable para tickets. +- Adaptación exacta a GitHub Projects con campos personalizados. +- Sprint 2 priorizado y detallado con criterios de aceptación. +- Sprint 3 priorizado y detallado con criterios de aceptación. +- CSV adaptado a importación tipo Jira. +- Descripciones completas de issues listas para pegar en GitHub/Jira. +- Descripciones completas de las 25 issues del backlog. +- Sprint 4 y roadmap consolidado a 90 días. +- Documento maestro tipo PM para seguimiento ejecutivo y técnico. +- Versiones derivadas coherentes: compacta, execution prompt e inglés. + +**Backlog Alignment** +La alineación entre roadmap y backlog debe mantenerse explícita para evitar que el documento estratégico y las issues diverjan. + +| Fase / Workstream | Objetivo | Issues principales | +|---|---|---| +| Fase 0: Inventario y gobierno | Clasificar repo, ownership y estrategia de mantenimiento | BL-00, BL-01, BL-25 | +| Fase 0.5: Policy gates | Runtime safety, alcance, Linux/WSL2, exclusiones | BL-02, BL-03, BL-24, BL-25 | +| Fase 1: Seguridad del core | Endurecer hosts, eval/source, hooks, rutas públicas y menú | BL-02, BL-03, BL-07 | +| Contrato de configuración | Definir contrato fuerte y reglas de validación | BL-04, BL-05 | +| Migración de contrato | Compatibilidad temporal, migración y retirada legacy | BL-04, BL-05, BL-15 | +| Supply chain | Pinning de imágenes e import controlado | BL-06, BL-07 | +| Fase 2: Rendimiento runtime | Cache de estado, healthchecks y menor latencia | BL-08, BL-09 | +| Red y recursos | Escalabilidad operativa, IP configurable y límites | BL-10, BL-11 | +| Fase 3: Mantenibilidad técnica | Modularización del core y compose sanitization robusta | BL-12, BL-13 | +| Fase 4: Funcionalidad operativa | doctor, validate, verify, dry-run y soporte | BL-14, BL-19 | +| Fase 5: Update y release | install/update seguros, rollback y semver | BL-15, BL-16, BL-24 | +| Fase 6: Calidad y observabilidad | CI real, pruebas mínimas, logging y diagnóstico | BL-17, BL-18, BL-19 | +| Fase 7: Labs embebidos | Ownership, drift y auditoría de labs prioritarios | BL-20, BL-21, BL-22 | +| Fase 8: Documentación operativa | README, runbook, troubleshooting y release docs | BL-23, BL-25 | + +Reglas de consistencia entre plan e issues: +1. Ninguna issue P0 debe existir sin criterio de rollback y validación manual. +2. Toda issue que toque config debe enlazar con BL-04 o BL-05 como referencia contractual. +3. Toda issue de plataforma debe enlazar con BL-24 o con la lane Linux/WSL2. +4. Toda issue que afecte labs debe indicar si el componente es propio, fork mantenido, snapshot o vendorizado. +5. Si una tarjeta no encaja en alguna fase anterior, debe revisarse su prioridad o alcance antes de entrar en sprint. + +**Use Guidance** +Usa este archivo como referencia maestra para estrategia, prioridades, dependencias, validación y alineación con backlog. Para ejecución estricta, usa `.github/prompts/plan-breakingLab-execution.prompt.md`. Para comunicación rápida, usa `.github/prompts/plan-breakingLab-compact.prompt.md`. Para compartir fuera del idioma original, usa `.github/prompts/plan-breakingLab-en.prompt.md`. Para retomar el trabajo en otra sesión, empieza por `docs/planning-handoff.md`. + +**Definition of Success** +El plan habrá funcionado si BreakingLab sigue siendo simple de usar, pero pasa a ser claramente más seguro, más predecible al actualizarse, más medible en runtime y más gobernable como producto evolutivo. + diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index 5daa585..8dbe242 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -17,3 +17,5 @@ jobs: with: scandir: './' additional_files: 'lib/*.sh' + ignore_paths: archive + check_together: "true" diff --git a/.gitignore b/.gitignore index 33f720e..cf2e943 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ docs/chat_history.md implementation_plan.md task.md + +# Copias locales previas a un cambio de lógica. No se versionan. +.backups/ + +# graft's local graph cache — regenerable, not committed (run `graft build`). +graft/ diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..8b3db9f --- /dev/null +++ b/.mcp.json @@ -0,0 +1,12 @@ +{ + "mcpServers": { + "graft": { + "command": "npx", + "args": [ + "-y", + "@nanonets/graft", + "mcp" + ] + } + } +} diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..662e204 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,2 @@ +external-sources=true +source-path=SCRIPTDIR diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..f19a289 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,45 @@ + +## Graft — repo context graph + +This repo is indexed in `graft/`: small linked markdown nodes that explain each +system and carry exact file:line spans, kept in sync with the code through git. + +For ANY task here — understanding how something works, finding where code lives, +or scoping a change — get context from the graph before grepping or opening +source files. Re-ask freely (it's cheap) and reuse literal identifiers you +already have (symbol, error string, file name) as the query. New to this repo? +Run `graft map` first — a token-budgeted orientation (dir clusters, hubs, +hotspots), no LLM, no key. + +- Run `graft ask "" --source` → ranked nodes with the relevant + code spans inlined (each hit's ≤8-line crux by default; `--full` for whole + definitions when the crux isn't enough). Match the tool to the task shape: + for understanding or editing, the top node IS the answer — cite its + `covers:` file:line spans and edit straight from `--source`. For + exhaustive tasks ("every occurrence / every caller of this pattern"), ranked + results are top-N, not complete — run `graft grep ""` instead + (exhaustive over indexed files, grouped by enclosing symbol), falling back + to raw `grep -rn` only for unindexed files. +- `graft skeleton ` → every definition's signature + span, ~10× cheaper + than reading the file; use it to skim an API surface. +- `graft callers ` gives precomputed, exact edges — who calls this. + Add `--direction out` for what it calls, or `--depth N` to walk + transitively for the full blast radius. For structural questions, skip + ranking and use this directly. +- Or browse: `graft/INDEX.md` lists every node; follow the links. +- Monorepos and folders of multiple repos rank fairly across sub-projects — + hits carry `[scope/]` labels naming which one they're from. Narrow with + `graft ask "" --in /` once you know where you're working. + +If a returned span is truncated ("+N more lines"), open the file at that exact +range before finalizing. Only open source files when a node genuinely lacks a +needed detail, and then at the exact file:line the node points to — never +re-read whole files. + +After big code changes, refresh the graph with `graft build` (deterministic, +no API key, $0). + + +## Mapa de trabajo + +El mapa está en `CLAUDE.md`. Cursor lo aplica con `.cursor/rules/workflow.mdc`. Memoria, lecciones y decisiones están en `docs/workflow/`. Las notas que se repiten están en `.claude/napkin.md`. diff --git a/CHANGELOG.md b/CHANGELOG.md index ee84fec..64115cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. +## [Unreleased] + +### Added +- Mapa de trabajo del agente en `CLAUDE.md` y `.cursor/rules/workflow.mdc`. Memoria en `docs/workflow/`. +- Documentos de planificación en `docs/` y `.github/prompts/`, enlazados desde el README. +- ShellCheck del lanzador, de `lib/` y de los hooks. `archive/` queda fuera del análisis. + ## [2.1.0] - 2026-01-03 ### Added diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..cf05ac0 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,71 @@ +# BreakingLab — mapa del agente + +Las carpetas guardan el código. Este archivo dice cómo leerlas. Cursor carga el mismo criterio en `.cursor/rules/workflow.mdc`. Gemini y Copilot llegan aquí desde `GEMINI.md` y `.github/copilot-instructions.md`. + +## Qué es este repositorio + +BreakingLab es un script Bash que arranca y para laboratorios web vulnerables con Docker. La entrada es `breakinglab.sh`. `install.sh` comprueba dependencias y puede enlazar el script. No hay frontend propio ni módulos Python. + +## Dónde está cada cosa + +- `breakinglab.sh` — entrada. +- `lib/` — `colors.sh`, `hosts.sh`, `menu.sh`, `utils.sh`, `yaml_utils.sh`. +- `config/projects.conf` y `config/projects.d/` — laboratorios declarados. +- `scripts/hooks/` — ganchos pre y post de algunos laboratorios. +- `projects/` — árboles importados (`dvws-node-2`, `dvwsnode2`, `vulpy5`). No forman el núcleo. +- `archive/` — `bl2023.sh` y `bl2024.sh`. +- `assets/` — logo. +- `docs/` — planificación. La memoria del agente está en `docs/workflow/`. +- `.github/workflows/shellcheck.yml` — el CI que hay hoy en el repositorio. + +`test_awk.sh` y `test_gh_fetch.sh` siguen en la raíz. Moverlos cambiaría rutas sin que nadie lo haya pedido. + +## Antes de tocar código + +1. Lee `.claude/napkin.md` y aplica lo que siga vigente. +2. Pregunta a graft (`graft ask`, `graft grep`, `graft skeleton`, `graft callers`, `graft map`) antes de abrir fuentes. El índice `graft/` no se versiona: se regenera con `graft build`. +3. Escribe el plan en `docs/workflow/plans/` y trabaja sobre ese fichero, no sobre la memoria de la sesión. +4. Antes de un cambio que borre o reescriba lógica, copia los ficheros afectados a `.backups/AAAA-MM-DD/`. La rama es la otra copia. No dupliques el repositorio entero. +5. Una funcionalidad, una rama. + +Si una función estable no es el objetivo del cambio, no la reescribas. Lo nuevo entra por un fichero o un gancho aparte, y el flujo anterior sigue respondiendo igual. Los ficheros nuevos van en UTF-8. + +Este repositorio no tiene Python. Si entra, el entorno será un virtualenv gestionado con `uv`, no con `pip`. Hasta entonces no añadas `pyproject.toml`. + +## Qué reutilizar + +Antes de escribir una funcionalidad, busca en GitHub un proyecto que ya la cubra. Úsalo de base cuando la licencia cuadre y el ajuste sea real. + +En esta máquina: + +- `D:\Scripts\Z-externos\ECC\skills` tiene 261 skills. Aquí aplican `docker-patterns`, `security-review`, `security-scan`, `git-workflow`, `github-ops`, `verification-loop`, `terminal-ops`, `architecture-decision-records`, `search-first`, `context-budget`, `codebase-onboarding` y `production-audit`. El resto no corresponde a un lanzador Bash. No copies el catálogo al repositorio: se lee desde esa ruta. +- `D:\Scripts\Z-externos\Anthropic-Cybersecurity-Skills\skills` tiene 818 skills de un proyecto de comunidad, con técnicas ofensivas. Úsalas solo al auditar este lanzador (shell, Docker, exposición en red) sobre sistemas propios o con permiso explícito. No las copies aquí y no las abras para una tarea de menú o de documentación. + +No hay interfaz web propia. Impeccable, Frontend Design, UI UX Pro Max, Theme Factory y las reglas visuales de Vercel esperan a que esa interfaz exista. + +## Herramientas + +- Graft, ya cableado. +- Caveman en español, nivel lite. El nivel full elimina artículos; en español la frase deja de decir lo mismo. +- Napkin en `.claude/napkin.md`. +- Diagram Design (https://github.com/cathrynlavery/diagram-design) cuando haya que dibujar. No está clonado en `D:\Scripts\Z-externos`. Si hace falta un diagrama y la skill no está disponible, dilo y para. No lo sustituyas por un esquema inventado. +- Humanizer en `D:\Scripts\Z-externos\humanizer`. La prosa nueva sigue esa guía. El comando no está en el PATH. +- MCP presentes en la sesión al escribir esto: GitHub, Context7, Playwright, Filesystem, Sentry y graft. `markitdown` no estaba conectado. No inventes su configuración. `.cursor/mcp.json` solo declara graft; los secretos no van al repositorio. + +Elige el agente más estrecho que resuelva la tarea. Un cambio de una línea no lleva subagente. + +## Publicación + +El remoto local `origin` apunta a GitHub. El repo también existe en Gitea, en `https://gitea.tiizss.internal/tiizss/BreakingLab`, y ese es el primer destino. GitHub va después, cuando Gitea ya tiene el mismo commit. + +Sube cuando ShellCheck esté en verde, el panel de problemas no marque avisos de ese cambio y la documentación tocada coincida con el código. Entonces etiqueta, publica la release y, con la rama ya fusionada y verde, deja `main` como única rama. Si el CI falla, se corrige antes de fusionar. + +Si git dice `dubious ownership`, no ejecutes `git config --global`. Para un comando concreto basta `git -c safe.directory=D:/Scripts/BreakingLab`. Esa opción no se guarda. + +## Memoria + +- `docs/workflow/MEMORY.md` — hechos que siguen siendo verdad. +- `docs/workflow/LEARNINGS.md` — lecciones reutilizables. +- `docs/workflow/decisions.md` — qué se decidió y por qué. + +Esos tres ficheros no están en la raíz. La raíz ya tiene `README.md`, `CHANGELOG.md`, `LICENSE`, `AGENTS.md`, `GEMINI.md` y este archivo. El motivo está en `docs/workflow/decisions.md`. diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000..f19a289 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,45 @@ + +## Graft — repo context graph + +This repo is indexed in `graft/`: small linked markdown nodes that explain each +system and carry exact file:line spans, kept in sync with the code through git. + +For ANY task here — understanding how something works, finding where code lives, +or scoping a change — get context from the graph before grepping or opening +source files. Re-ask freely (it's cheap) and reuse literal identifiers you +already have (symbol, error string, file name) as the query. New to this repo? +Run `graft map` first — a token-budgeted orientation (dir clusters, hubs, +hotspots), no LLM, no key. + +- Run `graft ask "" --source` → ranked nodes with the relevant + code spans inlined (each hit's ≤8-line crux by default; `--full` for whole + definitions when the crux isn't enough). Match the tool to the task shape: + for understanding or editing, the top node IS the answer — cite its + `covers:` file:line spans and edit straight from `--source`. For + exhaustive tasks ("every occurrence / every caller of this pattern"), ranked + results are top-N, not complete — run `graft grep ""` instead + (exhaustive over indexed files, grouped by enclosing symbol), falling back + to raw `grep -rn` only for unindexed files. +- `graft skeleton ` → every definition's signature + span, ~10× cheaper + than reading the file; use it to skim an API surface. +- `graft callers ` gives precomputed, exact edges — who calls this. + Add `--direction out` for what it calls, or `--depth N` to walk + transitively for the full blast radius. For structural questions, skip + ranking and use this directly. +- Or browse: `graft/INDEX.md` lists every node; follow the links. +- Monorepos and folders of multiple repos rank fairly across sub-projects — + hits carry `[scope/]` labels naming which one they're from. Narrow with + `graft ask "" --in /` once you know where you're working. + +If a returned span is truncated ("+N more lines"), open the file at that exact +range before finalizing. Only open source files when a node genuinely lacks a +needed detail, and then at the exact file:line the node points to — never +re-read whole files. + +After big code changes, refresh the graph with `graft build` (deterministic, +no API key, $0). + + +## Mapa de trabajo + +El mapa está en `CLAUDE.md`. Cursor lo aplica con `.cursor/rules/workflow.mdc`. Memoria, lecciones y decisiones están en `docs/workflow/`. Las notas que se repiten están en `.claude/napkin.md`. diff --git a/README.md b/README.md index 202d0a4..bc5e355 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,25 @@ Contributions are welcome! --- +## 🗺 Planning + +BreakingLab now includes internal planning documents to guide security hardening, runtime improvements, release process changes, and embedded-lab governance. + +- **Documentation index**: `docs/README.md` +- **Master planning prompt**: `.github/prompts/plan-breakingLab.prompt.md` +- **Execution prompt**: `.github/prompts/plan-breakingLab-execution.prompt.md` +- **Compact planning prompt**: `.github/prompts/plan-breakingLab-compact.prompt.md` +- **English planning prompt**: `.github/prompts/plan-breakingLab-en.prompt.md` +- **Roadmap document**: `docs/plan-breakingLab-roadmap.md` +- **RFC summary**: `docs/rfc-breakingLab-roadmap.md` +- **GitHub planning conventions**: `docs/github-planning-conventions.md` +- **First issue batch**: `docs/issue-batch-1.md` +- **Planning handoff**: `docs/planning-handoff.md` + +If you are contributing to architecture, runtime safety, configuration changes, CI, or release process work, review these documents before opening a large pull request. + +--- + ## 📄 License Distributed under the MIT License. See `LICENSE` for more information. diff --git a/breakinglab.sh b/breakinglab.sh index 71699de..1b9015a 100644 --- a/breakinglab.sh +++ b/breakinglab.sh @@ -71,7 +71,12 @@ start_docker_project() { if [ -n "$container_exists" ]; then echo "Container $container_exists exists. Starting..." - docker start "$container_exists" >/dev/null && echo "Started." || { echo -e "$TCR Failed to start $container_exists $TCD"; return 1; } + if docker start "$container_exists" >/dev/null; then + echo "Started." + else + echo -e "$TCR Failed to start $container_exists $TCD" + return 1 + fi else echo "Creating container $proj..." execute_hook "${proj}_post" @@ -124,10 +129,10 @@ start_public_project() { if [ -z "$proj" ]; then select_project "docker" "Start Public Project (enter number or name): " proj || return 0 - read -p "Enter Bind IP (default 0.0.0.0): " input_ip + read -r -p "Enter Bind IP (default 0.0.0.0): " input_ip [ -n "$input_ip" ] && public_ip="$input_ip" - read -p "Enter Public Port (leave empty for default): " input_port + read -r -p "Enter Public Port (leave empty for default): " input_port [ -n "$input_port" ] && public_port="$input_port" fi @@ -264,7 +269,7 @@ update_breakinglab() { git pull origin main || { echo -e "$TCR Update failed $TCD"; return 1; } echo -e "$TCG Update successful. Restarting... $TCD" sleep 1 - exec "$0" "$@" + exec "$0" else echo -e "$TCR Not a git repository. Cannot auto-update. $TCD" return 1 @@ -279,7 +284,7 @@ add_new_project() { echo "1) Manual - Docker Image (Single Container)" echo "2) Manual - Docker Compose (Stack)" echo "3) Import from GitHub" - read -p "Choice [1]: " p_type_choice + read -r -p "Choice [1]: " p_type_choice local p_type="${p_type_choice:-1}" if [ "$p_type" == "3" ]; then @@ -287,7 +292,7 @@ add_new_project() { return fi - read -p "Project Slug (e.g. my-app): " p_slug + read -r -p "Project Slug (e.g. my-app): " p_slug [[ -z "$p_slug" ]] && return 0 if [[ -n "${DOCKER_PROJECTS[$p_slug]+x}" ]]; then echo -e "$TCR Project $p_slug already exists! $TCD" @@ -298,7 +303,7 @@ add_new_project() { local p_compose="" if [ "$p_type" == "2" ]; then - read -p "Absolute Path to Compose Folder: " p_compose + read -r -p "Absolute Path to Compose Folder: " p_compose if [ ! -d "$p_compose" ] && [ ! -f "$p_compose" ]; then echo -e "$TCR Path does not exist. $TCD" return 0 @@ -306,19 +311,20 @@ add_new_project() { # Default image placeholder for config format compatibility p_image="docker-compose" else - read -p "Docker Image Name: " p_image + read -r -p "Docker Image Name: " p_image fi - read -p "Main Service Port (for browser checking): " p_port + read -r -p "Main Service Port (for browser checking): " p_port # Auto-assign IP echo "Finding available IP..." - local p_ip=$(get_next_available_ip) + local p_ip + p_ip=$(get_next_available_ip) echo -e "Assigned IP: $TCG$p_ip$TCD" - read -p "Description: " p_desc - read -p "Start Info Message: " p_info + read -r -p "Description: " p_desc + read -r -p "Start Info Message: " p_info # Construct config string # "image|ip|port|desc|http://ip|info|compose_path|pre|post" @@ -330,6 +336,7 @@ add_new_project() { echo "DOCKER_PROJECTS[\"$p_slug\"]=\"$p_image|$p_ip|$p_port|$p_desc|$p_url|$p_info|$p_compose||\"" > "$config_file" # Reload config + # shellcheck disable=SC1090 source "$config_file" echo -e "$TCG Project $p_slug added successfully! $TCD" read -n 1 -s -r -p "Press key to continue..." @@ -341,11 +348,12 @@ import_github_project() { echo -e "$TCW GitHub Import Wizard $TCD" # 1. Get URL and Path - read -p "GitHub Repository URL: " repo_url + read -r -p "GitHub Repository URL: " repo_url [ -z "$repo_url" ] && return 0 - local default_slug=$(basename "$repo_url" .git) - read -p "Project Slug / Folder Name (default: $default_slug): " p_slug + local default_slug + default_slug=$(basename "$repo_url" .git) + read -r -p "Project Slug / Folder Name (default: $default_slug): " p_slug p_slug="${p_slug:-$default_slug}" if [[ -n "${DOCKER_PROJECTS[$p_slug]+x}" ]]; then @@ -372,7 +380,7 @@ import_github_project() { compose_file="$target_path/docker-compose.yaml" else echo -e "$TCR No docker-compose.yml found in root. $TCD" - read -p "Path to docker-compose file (relative to $projects_dir/$p_slug): " rel_path + read -r -p "Path to docker-compose file (relative to $projects_dir/$p_slug): " rel_path if [ -f "$target_path/$rel_path" ]; then compose_file="$target_path/$rel_path" else @@ -385,21 +393,24 @@ import_github_project() { # 3. Port Scanning echo "Scanning for ports..." - local found_ports=$(grep -oP "^\s*-\s*\"\d+:\d+\"" "$compose_file" | tr -d ' "-' | cut -d: -f1 | tr '\n' ' ') + local found_ports + found_ports=$(grep -oP "^\s*-\s*\"\d+:\d+\"" "$compose_file" | tr -d ' "-' | cut -d: -f1 | tr '\n' ' ') + local default_port if [ -n "$found_ports" ]; then echo -e "Found ports: $TCY $found_ports $TCD" - local default_port=$(echo "$found_ports" | awk '{print $1}') + default_port=$(echo "$found_ports" | awk '{print $1}') else echo "No explicit exposed ports found in standard format." - local default_port="80" + default_port="80" fi - read -p "Main Service Port (default: $default_port): " p_port + read -r -p "Main Service Port (default: $default_port): " p_port p_port="${p_port:-$default_port}" # 4. Auto-IP echo "Assigning IP..." - local p_ip=$(get_next_available_ip) + local p_ip + p_ip=$(get_next_available_ip) echo -e "Assigned IP: $TCG$p_ip$TCD" # --- SANITIZE COMPOSE --- @@ -410,7 +421,8 @@ import_github_project() { # Extract Owner/Repo from URL # Supports: https://github.com/owner/repo or git@github.com:owner/repo.git - local gh_repo_path=$(echo "$repo_url" | sed -E 's/.*github.com[:/](.*)(\.git)?/\1/' | sed 's/\.git$//') + local gh_repo_path + gh_repo_path=$(echo "$repo_url" | sed -E 's/.*github.com[:/](.*)(\.git)?/\1/' | sed 's/\.git$//') local gh_desc="" if [ -n "$gh_repo_path" ]; then @@ -422,10 +434,10 @@ import_github_project() { if [ -n "$gh_desc" ] && [ "$gh_desc" != "null" ]; then echo -e "Found Description: $TCC $gh_desc $TCD" - read -p "Description (default: imported): " p_desc_input + read -r -p "Description (default: imported): " p_desc_input p_desc="${p_desc_input:-$gh_desc}" else - read -p "Description: " p_desc + read -r -p "Description: " p_desc fi # Sanitize description to remove newlines and pipes @@ -447,6 +459,7 @@ import_github_project() { # p_image is 'docker-compose' for type 2 echo "DOCKER_PROJECTS[\"$p_slug\"]=\"docker-compose|$p_ip|$p_port|$p_desc|$p_url|$p_info|$target_path||\"" > "$config_file" + # shellcheck disable=SC1090 source "$config_file" echo -e "$TCG Project $p_slug imported successfully! $TCD" read -n 1 -s -r -p "Press key to continue..." @@ -472,7 +485,7 @@ delete_project() { echo -e " - Remove the hosts entry" echo -e " - DELETE the configuration file: ${DIR}/config/projects.d/docker_${proj}.conf" - read -p "Are you sure? (y/N): " confirm + read -r -p "Are you sure? (y/N): " confirm if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then echo "Deletion cancelled." return 0 @@ -498,7 +511,7 @@ delete_project() { fi # Unset from current session array - unset DOCKER_PROJECTS["$proj"] + unset "DOCKER_PROJECTS[$proj]" echo -e "$TCG Project '$proj' has been deleted. $TCD" read -n 1 -s -r -p "Press key to continue..." @@ -509,7 +522,7 @@ delete_project() { main_menu() { display_logo echo -e "$TCC Options: $TCD\n1) List Projects\n2) Start Docker Project\n3) Start Public Project\n4) Stop Docker Project\n5) Status Docker Projects\n6) Start Online Project\n7) Update\n8) Add New Project\n9) Delete Project\n99) Exit" - read -p "Select an option: " choice + read -r -p "Select an option: " choice case $choice in 1) list_projects; read -n 1 -s -r -p "Press key..." ; main_menu;; 2) diff --git a/config/projects.conf b/config/projects.conf index 42a6dec..6088761 100644 --- a/config/projects.conf +++ b/config/projects.conf @@ -7,6 +7,7 @@ declare -A ONLINE_PROJECTS # Load all project configurations if [ -d "$DIR/config/projects.d" ]; then for file in "$DIR"/config/projects.d/*.conf; do + # shellcheck disable=SC1090 [ -e "$file" ] && source "$file" done fi diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..5224603 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,53 @@ +# BreakingLab Planning Docs + +## Purpose +This index groups the planning and governance documents that support the BreakingLab stabilization roadmap. + +## Documents +1. `docs/plan-breakingLab-roadmap.md` +Public-facing roadmap document for the 60-90 day plan. + +2. `docs/rfc-breakingLab-roadmap.md` +Short RFC-style summary of the decision, context, and guardrails. + +3. `.github/prompts/plan-breakingLab.prompt.md` +Master strategic and operational planning prompt. + +4. `.github/prompts/plan-breakingLab-execution.prompt.md` +Strict execution prompt for phased implementation work. + +5. `.github/prompts/plan-breakingLab-compact.prompt.md` +Compact executive summary version. + +6. `.github/prompts/plan-breakingLab-en.prompt.md` +English planning variant. + +7. `docs/github-planning-conventions.md` +Conventions for labels, epics, issue structure, and PR expectations. + +8. `docs/issue-batch-1.md` +First prioritized batch of issues ready to open. + +9. `docs/planning-handoff.md` +Resume guide for the next working session. + +10. `docs/workflow/MEMORY.md`, `docs/workflow/LEARNINGS.md`, `docs/workflow/decisions.md` +Hechos estables, lecciones y registro de decisiones del agente. El mapa que los ata está en `CLAUDE.md`. + +## Recommended reading order +1. `docs/rfc-breakingLab-roadmap.md` +2. `docs/plan-breakingLab-roadmap.md` +3. `.github/prompts/plan-breakingLab.prompt.md` +4. `.github/prompts/plan-breakingLab-execution.prompt.md` +5. `.github/prompts/plan-breakingLab-compact.prompt.md` +6. `.github/prompts/plan-breakingLab-en.prompt.md` +7. `docs/github-planning-conventions.md` +8. `docs/issue-batch-1.md` +9. `docs/planning-handoff.md` + +## Usage +1. Use the RFC and roadmap to understand direction. +2. Use the prompts to guide planning and execution. +3. Use the conventions document when creating GitHub artifacts. +4. Use the issue batch document to seed the first implementation wave. +5. Use the handoff document to resume quickly in a later session. diff --git a/docs/github-planning-conventions.md b/docs/github-planning-conventions.md new file mode 100644 index 0000000..68ac7a3 --- /dev/null +++ b/docs/github-planning-conventions.md @@ -0,0 +1,90 @@ +# GitHub Planning Conventions + +## Purpose +This document defines how BreakingLab planning should be represented in GitHub issues, epics, labels, and pull requests. + +## Naming +1. Epics should use `EP-XX` identifiers. +2. Roadmap work items should use `BL-XX` identifiers. +3. Pull requests should reference the related `EP-*` and `BL-*` items when applicable. + +## Label Sets +### Priority +1. `priority:P0` +2. `priority:P1` +3. `priority:P2` +4. `priority:P3` + +### Area +1. `area:security` +2. `area:performance` +3. `area:scalability` +4. `area:functionality` +5. `area:update-process` +6. `area:ci` +7. `area:docs` + +### Scope +1. `scope:core` +2. `scope:config` +3. `scope:hooks` +4. `scope:labs` +5. `scope:release` +6. `scope:docs` +7. `scope:platform` + +### Type +1. `type:epic` +2. `type:story` +3. `type:task` +4. `type:bug` +5. `type:chore` + +### Platform +1. `platform:linux` +2. `platform:wsl2` +3. `platform:cross-platform` + +## Epic Rules +1. Each epic must map to a roadmap phase or workstream. +2. Each epic must define scope, exclusions, acceptance criteria, and rollback expectations if relevant. +3. Each epic must identify the main BL-* items it contains. + +## Work Item Rules +1. Each BL-* item must state the problem, proposed change, affected files, validation plan, and rollback plan when relevant. +2. Any configuration change must reference the configuration contract and migration path. +3. Any platform-sensitive change must include Linux and WSL2 evidence. +4. Any lab-related item must specify whether the target is project-owned, vendored, a snapshot, or a maintained fork. + +## Pull Request Rules +1. Every PR should reference the roadmap artifact it advances. +2. Every PR should state whether runtime behavior, configuration contract, platform behavior, or release behavior changes. +3. Security-, config-, and update-related PRs require explicit rollback notes. + +## Recommended Initial Labels +1. `priority:P0` +2. `priority:P1` +3. `priority:P2` +4. `priority:P3` +5. `area:security` +6. `area:performance` +7. `area:scalability` +8. `area:functionality` +9. `area:update-process` +10. `area:ci` +11. `area:docs` +12. `scope:core` +13. `scope:config` +14. `scope:hooks` +15. `scope:labs` +16. `scope:release` +17. `scope:platform` +18. `type:epic` +19. `type:story` +20. `type:task` + +## Governance Rules +1. Do not open BL-* work without clear roadmap alignment. +2. Do not close P0 work without manual validation and rollback clarity. +3. Do not mix deep core refactors with deep lab changes in one PR unless justified. +4. Do not expand planning scope into `archive/` unless explicitly approved. diff --git a/docs/issue-batch-1.md b/docs/issue-batch-1.md new file mode 100644 index 0000000..42d3ae8 --- /dev/null +++ b/docs/issue-batch-1.md @@ -0,0 +1,54 @@ +# Issue Batch 1 + +## Purpose +This document defines the first prioritized batch of issues to open from the BreakingLab roadmap. + +## Batch Goal +Reduce the highest operational risk before moving into broader runtime, release, and lab-governance work. + +## Recommended Opening Order +1. `EP-01` Security and Runtime Safety +2. `EP-02` Configuration Contract and Migration +3. `EP-03` Release and Quality Baseline +4. `BL-00` Inventario total del repositorio +5. `BL-01` Matriz de ownership y estrategia de actualización +6. `BL-25` Definition of Done y checklist de rollback +7. `BL-02` Endurecer modificación de hosts y privilegios +8. `BL-03` Eliminar o encapsular ejecución insegura en core y hooks +9. `BL-04` Definir contrato versionado de configuración +10. `BL-05` Crear validador de slug, IP, puerto, rutas y campos + +## Why This Batch First +1. It closes the highest-risk gaps first. +2. It creates the contract and governance base for all later work. +3. It reduces the chance of rework in runtime, CI, and update flows. + +## Suggested Epic Mapping +### EP-01 Security and Runtime Safety +- BL-02 +- BL-03 + +### EP-02 Configuration Contract and Migration +- BL-04 +- BL-05 + +### EP-03 Release and Quality Baseline +- BL-00 +- BL-01 +- BL-25 + +## Suggested Labels +1. `priority:P0` +2. `type:epic` or `type:story` +3. `scope:core` or `scope:config` +4. `area:security`, `area:update-process`, or `area:docs` +5. `platform:cross-platform` or `platform:wsl2` when relevant + +## Minimum Acceptance Expectations +1. Each item must define affected files. +2. Each item must define manual validation. +3. Each security/config/update item must define rollback expectations. +4. Each item must remain aligned with the roadmap and planning prompts. + +## Next Batch Preview +The next batch should cover image pinning, runtime performance, healthchecks, configurable networking, resource profiles, and compose sanitization. diff --git a/docs/plan-breakingLab-roadmap.md b/docs/plan-breakingLab-roadmap.md new file mode 100644 index 0000000..743424b --- /dev/null +++ b/docs/plan-breakingLab-roadmap.md @@ -0,0 +1,109 @@ +# BreakingLab Roadmap 60-90 días + +> Related documents: +> - `.github/prompts/plan-breakingLab.prompt.md` +> - `.github/prompts/plan-breakingLab-execution.prompt.md` +> - `.github/prompts/plan-breakingLab-compact.prompt.md` +> - `.github/prompts/plan-breakingLab-en.prompt.md` +> - `docs/rfc-breakingLab-roadmap.md` +> - `docs/github-planning-conventions.md` +> - `docs/issue-batch-1.md` +> - `docs/planning-handoff.md` +> - `docs/README.md` + +## Resumen ejecutivo +BreakingLab necesita una estabilización por capas, no una reescritura. El riesgo principal no está en la funcionalidad visible, sino en la seguridad y previsibilidad del core, en la fragilidad del contrato de configuración, en la falta de un proceso robusto de actualización y en la ausencia de un gobierno claro sobre los labs embebidos. + +La estrategia recomendada es endurecer primero el runtime y la configuración, después mejorar rendimiento y escalabilidad operativa, luego formalizar updates, CI y rollback, y finalmente cerrar el gobierno de labs y la documentación de mantenimiento. + +## Objetivos +1. Reducir el riesgo operativo y de seguridad del core. +2. Mejorar la velocidad y fiabilidad del runtime. +3. Hacer la configuración validable, migrable y gobernable. +4. Convertir updates y releases en flujos reproducibles y reversibles. +5. Establecer una base mínima real de calidad, observabilidad y documentación. +6. Tratar los labs embebidos según ownership real: propios, forks mantenidos, snapshots o vendorizados. + +## Guardrails +1. Las rutas normales no pueden instalar paquetes ni añadir repositorios. +2. Ningún cambio de configuración se cierra sin migración y modo legacy temporal. +3. Ningún cambio de update se cierra sin rollback probado. +4. Linux y WSL2 son plataformas objetivo y deben validarse explícitamente. +5. `archive/` queda fuera del roadmap operativo salvo necesidad excepcional. + +## Roadmap +### Fase 0: Baseline y gobierno +- Inventariar el repo. +- Clasificar ownership y estrategia de mantenimiento. +- Definir Definition of Done y rollback mínimos. + +### Fase 0.5: Policy gates +- Formalizar runtime safety. +- Fijar alcance operativo y exclusiones. +- Abrir lane Linux/WSL2. + +### Fase 1: Seguridad del core +- Endurecer hosts, hooks, menú, rutas públicas y ejecución dinámica. +- Normalizar privilegios y validación de entradas. + +### Fase 2: Configuración y migración +- Definir contrato versionado de proyectos. +- Añadir validación fuerte. +- Implementar migración y retirada planificada del modo legacy. + +### Fase 3: Supply chain y runtime +- Pinning de imágenes. +- Política de import y allowlist. +- Caché de estado Docker y mejores healthchecks. +- Red configurable y perfiles de recursos. +- Estrategia robusta de compose sanitization. + +### Fase 4: Funcionalidad operativa +- Añadir doctor, validate, verify, dry-run, lock y update-lab. +- Mejorar diagnóstico operativo. +- Mejorar UX de CLI y menú donde aporte valor real. + +### Fase 5: Release y calidad +- Rediseñar install/update con backup y rollback. +- Formalizar semver y compatibilidad. +- Extender CI más allá de ShellCheck. +- Sustituir tests ad hoc por una suite mínima repetible. +- Mejorar logging y observabilidad. + +### Fase 6: Labs embebidos y documentación +- Clasificar labs por ownership. +- Resolver drift entre dvws-node-2 y dvwsnode2. +- Auditar vulpy5. +- Cerrar README, runbook y documentación de mantenimiento. + +## Hitos de 90 días +1. Hito 1: core seguro y contrato definido. +2. Hito 2: runtime más rápido y reproducible. +3. Hito 3: update, CI y soporte confiables. +4. Hito 4: core mantenible y labs gobernados. + +## Backlog núcleo +1. Gobierno: BL-00, BL-01, BL-25. +2. Seguridad: BL-02, BL-03, BL-07. +3. Configuración: BL-04, BL-05. +4. Runtime: BL-06, BL-08, BL-09, BL-10, BL-11, BL-13. +5. Release y calidad: BL-14, BL-15, BL-16, BL-17, BL-18, BL-19, BL-24. +6. Labs y documentación: BL-20, BL-21, BL-22, BL-23. + +## Verificación +1. Configuración validable antes de runtime. +2. Linux y WSL2 cubiertos en rutas críticas. +3. Update con rollback y validación post-cambio. +4. Menú y arranque con mejora medible. +5. Labs con ownership y policy de update. + +## Criterio de éxito +El plan habrá funcionado si BreakingLab sigue siendo simple de usar, pero pasa a ser más seguro, más predecible al actualizarse, más medible en runtime y más gobernable como producto evolutivo. + +## Navegación +1. Usa `.github/prompts/plan-breakingLab.prompt.md` como fuente de verdad estratégica y operativa. +2. Usa `.github/prompts/plan-breakingLab-execution.prompt.md` para ejecución estricta por fases. +3. Usa `docs/rfc-breakingLab-roadmap.md` como versión corta de decisión y contexto. +4. Usa `docs/github-planning-conventions.md` para labels, epics, issues y PRs. +5. Usa `docs/issue-batch-1.md` para abrir el primer lote priorizado de trabajo. +6. Usa `docs/planning-handoff.md` para retomar rápidamente en otra sesión. \ No newline at end of file diff --git a/docs/planning-handoff.md b/docs/planning-handoff.md new file mode 100644 index 0000000..96df14c --- /dev/null +++ b/docs/planning-handoff.md @@ -0,0 +1,47 @@ +# Planning Handoff + +## Purpose +This document exists so the planning work can be resumed quickly in a later session without depending on untitled editor state. + +## Canonical Planning Files +1. `.github/prompts/plan-breakingLab.prompt.md` +Main strategic and operational planning source of truth. + +2. `.github/prompts/plan-breakingLab-execution.prompt.md` +Strict phased execution prompt. + +3. `.github/prompts/plan-breakingLab-compact.prompt.md` +Compact executive summary version. + +4. `.github/prompts/plan-breakingLab-en.prompt.md` +English planning variant. + +5. `docs/plan-breakingLab-roadmap.md` +Public roadmap version. + +6. `docs/rfc-breakingLab-roadmap.md` +Short RFC-style decision summary. + +7. `docs/github-planning-conventions.md` +Conventions for GitHub labels, epics, work items, and PRs. + +8. `docs/issue-batch-1.md` +First prioritized batch of issues to open. + +## Recommended Resume Order +1. Read `docs/rfc-breakingLab-roadmap.md` for context. +2. Read `docs/plan-breakingLab-roadmap.md` for the phased roadmap. +3. Read `.github/prompts/plan-breakingLab.prompt.md` for the full master plan. +4. Use `.github/prompts/plan-breakingLab-execution.prompt.md` if the next session is implementation-oriented. +5. Use `docs/issue-batch-1.md` to seed the first issue wave. + +## Current Planning State +1. Planning documents are persisted in the repo. +2. GitHub issue forms and PR template are aligned with the roadmap. +3. README links to planning assets. +4. Documentation now includes roadmap, RFC, conventions, issue batch, and this handoff. + +## Natural Next Steps +1. Open the first batch of issues from `docs/issue-batch-1.md`. +2. Create the recommended GitHub labels from `docs/github-planning-conventions.md`. +3. Start implementation with BL-00 and BL-01. diff --git a/docs/rfc-breakingLab-roadmap.md b/docs/rfc-breakingLab-roadmap.md new file mode 100644 index 0000000..35a9fab --- /dev/null +++ b/docs/rfc-breakingLab-roadmap.md @@ -0,0 +1,70 @@ +# RFC: BreakingLab Stabilization Roadmap + +> Related documents: +> - `.github/prompts/plan-breakingLab.prompt.md` +> - `.github/prompts/plan-breakingLab-execution.prompt.md` +> - `.github/prompts/plan-breakingLab-compact.prompt.md` +> - `.github/prompts/plan-breakingLab-en.prompt.md` +> - `docs/plan-breakingLab-roadmap.md` +> - `docs/github-planning-conventions.md` +> - `docs/issue-batch-1.md` +> - `docs/planning-handoff.md` +> - `docs/README.md` + +## Status +Proposed + +## Context +BreakingLab delivers useful lab orchestration today, but its operational risk is concentrated in a few places: dynamic execution in the core, host mutation, fragile project configuration, weak update/rollback guarantees, and inconsistent governance over embedded labs. + +The project does not need a rewrite. It needs a staged stabilization plan that reduces real risk first and only later expands into deeper maintainability work. + +## Decision +Adopt a 60-90 day roadmap with the following execution order: +1. Inventory and governance. +2. Policy gates for runtime safety, scope control, and Linux/WSL2 validation. +3. Core security hardening. +4. Configuration contract plus migration path. +5. Supply chain and runtime reliability improvements. +6. Operational commands, release hardening, CI, and rollback. +7. Embedded-lab governance and targeted audits. +8. Documentation and runbook closure. + +## Guardrails +1. Normal runtime paths must not install packages or add repositories. +2. Configuration changes require migration, temporary compatibility, and legacy retirement criteria. +3. Update work requires tested rollback. +4. Linux and WSL2 are explicit target platforms. +5. `archive/` is out of operational scope unless explicitly approved. +6. Third-party labs are governed primarily through reproducibility, isolation, update policy, and packaging, not deep internal refactoring by default. + +## Consequences +Positive: +1. The core becomes safer and more predictable. +2. Runtime and update behavior become easier to validate. +3. The backlog becomes easier to prioritize against real risk. +4. Labs can be governed according to ownership instead of assumption. + +Tradeoffs: +1. Some visible UX work is intentionally delayed. +2. Legacy compatibility must be managed explicitly during configuration migration. +3. Platform validation adds effort to each sensitive change. + +## Success Criteria +1. Configuration is validated before runtime execution. +2. Linux and WSL2 are both covered for critical flows. +3. Update and install flows have rollback and post-change validation. +4. Runtime improvements are measurable. +5. Embedded labs have ownership and update policy defined. + +## References +1. `.github/prompts/plan-breakingLab.prompt.md` +2. `.github/prompts/plan-breakingLab-execution.prompt.md` +3. `docs/plan-breakingLab-roadmap.md` + +## Navigation +1. Read this RFC first for context and decision summary. +2. Read `docs/plan-breakingLab-roadmap.md` for the full phased roadmap. +3. Read `.github/prompts/plan-breakingLab-execution.prompt.md` when converting the roadmap into implementation work. +4. Read `docs/github-planning-conventions.md` when creating epics, issues, labels, or PRs. +5. Read `docs/planning-handoff.md` when resuming the work in a future session. diff --git a/docs/workflow/LEARNINGS.md b/docs/workflow/LEARNINGS.md new file mode 100644 index 0000000..26fce5e --- /dev/null +++ b/docs/workflow/LEARNINGS.md @@ -0,0 +1,7 @@ +# Lecciones + +- **[2026-10-20] El bloque de graft no es el mapa del proyecto.** `AGENTS.md`, `GEMINI.md` y las instrucciones de Copilot repetían solo ese bloque. El mapa de trabajo tiene que vivir en `CLAUDE.md` y en `.cursor/rules/workflow.mdc`, fuera de los marcadores `graft:start` / `graft:end`. +- **[2026-10-20] `git config --global` no es un arreglo aceptable.** El mensaje de `dubious ownership` lo propone. La regla del entorno prohíbe cambiar la configuración de git. Hay que parar y decírselo a quien usa la máquina. +- **[2026-10-20] Copiar 261 y 818 skills al repo no aporta el comportamiento.** Esas carpetas ya están en `D:\Scripts\Z-externos`. El agente las lee ahí. Vendorizarlas hincha el árbol y mezcla licencias. +- **[2026-10-20] Caveman full y el español no caben en la misma frase.** El modo full quita artículos. En español el artículo distingue el sentido. El nivel lite mantiene la frase corta y gramatical. +- **[2026-10-21] GitHub rechaza `github@tiizss.com`.** Con “Keep my email addresses private” el push de línea de comandos tiene que llevar `9557246+TiiZss@users.noreply.github.com`. No se guarda en `git config`. Se pasa en las variables del comando. diff --git a/docs/workflow/MEMORY.md b/docs/workflow/MEMORY.md new file mode 100644 index 0000000..7920e46 --- /dev/null +++ b/docs/workflow/MEMORY.md @@ -0,0 +1,15 @@ +# Memoria + +Hechos comprobados el 2026-10-20. Si uno deja de ser cierto, se corrige aquí y se anota la fecha. + +- BreakingLab gestiona laboratorios vulnerables con Docker. Entrada: `breakinglab.sh`. Librerías en `lib/`. Definiciones en `config/projects.d/`. +- El remoto documentado en el README es `https://github.com/TiiZss/BreakingLab`. La versión del changelog es 2.1.0 (2026-01-03). +- El CI en el repositorio es ShellCheck (`.github/workflows/shellcheck.yml`). +- No hay módulos Python ni aplicación web propia. `projects/` contiene árboles importados: `dvws-node-2`, `dvwsnode2`, `vulpy5`. +- Graft está instalado y el repo tiene índice. `graft/` está en `.gitignore`. +- `uv` está en el PATH. No hay proyecto Python que lo use. +- Humanizer está en `D:\Scripts\Z-externos\humanizer` y no está en el PATH. +- ECC tiene 261 skills en `D:\Scripts\Z-externos\ECC\skills`. El catálogo de ciberseguridad de comunidad tiene 818 en `D:\Scripts\Z-externos\Anthropic-Cybersecurity-Skills\skills`. +- Los MCP vistos en la sesión de esa fecha: GitHub, Context7, Playwright, Filesystem, Sentry, graft. `markitdown` no estaba. +- El remoto `origin` es `https://github.com/TiiZss/BreakingLab`. Gitea está en `https://gitea.tiizss.internal/tiizss/BreakingLab` (login `tea` `tiizss`). El 2026-10-21 las dos `main` y el HEAD local estaban en `baf498d`. El clon no tiene remoto de Gitea. SSH al puerto 22 de ese host responde `Connection refused`. +- Git avisa `dubious ownership` en `D:/Scripts/BreakingLab` para `ALMANSA4/Puper`. No se añade `safe.directory` global. El atajo de un comando es `git -c safe.directory=D:/Scripts/BreakingLab`. diff --git a/docs/workflow/decisions.md b/docs/workflow/decisions.md new file mode 100644 index 0000000..fbd36b1 --- /dev/null +++ b/docs/workflow/decisions.md @@ -0,0 +1,31 @@ +# Decisiones + +## 2026-10-20 — Mapa del agente en CLAUDE.md y en una regla de Cursor + +Claude Code lee `CLAUDE.md` en la raíz. Cursor lee `.cursor/rules/*.mdc`. Hace falta los dos. `AGENTS.md`, `GEMINI.md` y `.github/copilot-instructions.md` solo apuntan al mapa, detrás del bloque de graft, para no duplicar cinco copias que se desfasarían. + +## 2026-10-20 — MEMORY, LEARNINGS y decisions fuera de la raíz + +El encargo pedía esos tres nombres en la raíz y, en el mismo texto, una raíz con pocos ficheros. La raíz ya tiene `README.md`, `CHANGELOG.md`, `LICENSE`, `AGENTS.md`, `GEMINI.md` y `CLAUDE.md`. Los tres registros quedan en `docs/workflow/`. El 2026-10-21 se confirmó que se quedan ahí. + +## 2026-10-20 — Skills por referencia, no por copia + +ECC y el catálogo de ciberseguridad se usan desde `D:\Scripts\Z-externos`. Al repo solo entra la lista de skills que encajan con un lanzador Bash/Docker. Las skills de interfaz web no se activan: no hay interfaz. Las skills ofensivas no se copian. + +## 2026-10-20 — MCP sin secretos nuevos + +`.cursor/mcp.json` sigue declarando solo graft. GitHub, Context7, Playwright, Filesystem y Sentry ya existen a nivel de usuario. `markitdown` no estaba conectado y no se ha añadido un servidor inventado. + +## 2026-10-21 — Gitea primero, GitHub después + +El login de `tea` se llama `tiizss` y su URL es `https://gitea.tiizss.internal`. Ahí está `tiizss/BreakingLab`, rama `main`, commit `baf498d`, el mismo que `origin/main` en GitHub (`https://github.com/TiiZss/BreakingLab`). El clon local no tiene un remoto de Gitea: `origin` es solo GitHub. SSH al puerto 22 de `gitea.tiizss.internal` responde `Connection refused`. HTTPS sí responde. + +`dubious ownership` no es un rechazo de Gitea ni de GitHub. Git ve que la carpeta `D:/Scripts/BreakingLab` pertenece a otra cuenta de Windows y se niega a trabajar ahí. El mensaje propone `git config --global --add safe.directory`. Esa línea no se ejecuta. Para leer o commitear en un comando basta `-c safe.directory=D:/Scripts/BreakingLab`, que no se guarda. + +## 2026-10-20 — Sin commit, tag ni merge en este cambio + +El árbol de trabajo mezcla el mapa del agente con cambios ajenos (`README.md`, hooks de `jvl`, `projects/vulpy5` y otros ficheros sin seguimiento). No se hace un commit de todo eso junto. La copia previa del mapa está en `.backups/2026-10-20-workflow/`. + +## 2026-10-20 — Copia de seguridad acotada + +Antes de reescribir lógica se copian los ficheros afectados a `.backups/`. Esa carpeta no se versiona. No se hace un segundo árbol completo del repositorio en cada cambio: la rama cubre ese papel cuando git funciona. diff --git a/docs/workflow/plans/2026-10-20-comportamiento-agente.md b/docs/workflow/plans/2026-10-20-comportamiento-agente.md new file mode 100644 index 0000000..04614cd --- /dev/null +++ b/docs/workflow/plans/2026-10-20-comportamiento-agente.md @@ -0,0 +1,32 @@ +# Plan: comportamiento del agente + +Fecha: 2026-10-20. Hecho antes de editar las reglas. El código de `breakinglab.sh`, `lib/` y `config/` no entra en este cambio. + +## Hechos comprobados + +- El repositorio es Bash y Docker. La entrada es `breakinglab.sh`. No hay aplicación web propia ni Python. +- `AGENTS.md`, `GEMINI.md` y `.github/copilot-instructions.md` solo traían el bloque de graft. No existía `CLAUDE.md`. +- `.cursor/mcp.json` y `.mcp.json` solo declaran graft. +- En esta sesión aparecen los servidores GitHub, Context7, Playwright, Filesystem, Sentry y graft. `markitdown` no aparece. +- `D:\Scripts\Z-externos\ECC\skills` tiene 261 skills. `D:\Scripts\Z-externos\Anthropic-Cybersecurity-Skills\skills` tiene 818. +- `graft` y `uv` están en el PATH. `humanizer` está en `D:\Scripts\Z-externos\humanizer` y no está en el PATH. `napkin` y `diagram-design` no están clonados en `D:\Scripts\Z-externos`. +- Git existe (hay `.git`) y falla con `dubious ownership`. No se toca `git config`. +- El CI versionado es `.github/workflows/shellcheck.yml`. + +## Qué se escribe + +1. `CLAUDE.md` en la raíz, porque Claude Code solo carga ese nombre ahí. +2. `.cursor/rules/workflow.mdc` con `alwaysApply: true`, el equivalente en Cursor. +3. Un puntero corto, detrás del bloque de graft, en `AGENTS.md`, `GEMINI.md` y `.github/copilot-instructions.md`. +4. `.claude/napkin.md`, que es la ruta que exige Napkin. +5. `docs/workflow/MEMORY.md`, `LEARNINGS.md` y `decisions.md`. +6. Entrada en `docs/README.md` y nota `Unreleased` en `CHANGELOG.md`. +7. `.backups/` en `.gitignore`. + +## Qué no se hace en este paso + +- No se copia ECC ni el catálogo de ciberseguridad al repositorio. +- No se inventa un servidor `markitdown` ni se meten secretos en `mcp.json`. +- No se añaden skills de interfaz web: no hay interfaz que diseñar. +- No se mueve `test_awk.sh` ni `test_gh_fetch.sh`. +- No hay commit, tag, release, push ni merge. El remoto y el CI de este cambio no están verificados, y git no opera hasta resolver la propiedad del directorio sin tocar la configuración global. diff --git a/docs/workflow/plans/2026-10-21-shellcheck.md b/docs/workflow/plans/2026-10-21-shellcheck.md new file mode 100644 index 0000000..39218cb --- /dev/null +++ b/docs/workflow/plans/2026-10-21-shellcheck.md @@ -0,0 +1,22 @@ +# Plan: ShellCheck en verde + +Fecha: 2026-10-21. Rama `docs/agent-map`. + +## Hechos + +El workflow falla con 415 avisos. 316 están en `archive/bl2023.sh` y `archive/bl2024.sh`. El lanzador no los ejecuta. Reescribirlos cambiaría el archivo histórico. + +Los otros 99 están en `breakinglab.sh`, `lib/` y `scripts/hooks/`. Tres hooks no son shell válido: `mutillidae_pre.sh`, `oxninja_pre.sh` y `oxninja_post.sh`. El texto completo del arranque está en `archive/bl2024.sh`. + +## Qué se cambia + +1. `ignore_paths: archive` en el workflow. +2. `.shellcheckrc` con `external-sources=true` para que el análisis siga los `source` de `lib/`. +3. En el lanzador y en `lib/`: `read -r`, asignaciones separadas del `local`, y las comparaciones sin comillas que ShellCheck marca. No se cambia el flujo de arranque. +4. Shebang en los hooks que ya son una orden válida, y `cd ... || exit` donde el `cd` iba en una cadena `&&`. +5. `mutillidae_*.sh` y `oxninja_*.sh` vuelven a las órdenes de `bl2024.sh`. +6. Los cambios locales sin commit de `jvl` no entran en este commit. Se copian a `.backups/` antes de tocar el hook versionado. + +## Qué no se hace + +No se fusiona `main` hasta que el ShellCheck de GitHub termine en verde. No se toca `git config`. diff --git a/lib/colors.sh b/lib/colors.sh index 00989e0..8b12022 100644 --- a/lib/colors.sh +++ b/lib/colors.sh @@ -1,4 +1,6 @@ #!/bin/bash +# Palette sourced by the launcher. The names are used from other files. +# shellcheck disable=SC2034 # Colores y estilos TxDefault="\e[0m" TxBold="\e[1m" TxUnderline="\e[2m" TCD="\e[0;0m" TCR="\e[0;31m" TCG="\e[0;32m" TCY="\e[1;33m" TCB="\e[0;34m" TCM="\e[0;35m" TCC="\e[0;36m" TCW="\e[0;37m" diff --git a/lib/hosts.sh b/lib/hosts.sh index 7060253..8f5b3c7 100644 --- a/lib/hosts.sh +++ b/lib/hosts.sh @@ -5,7 +5,6 @@ ETC_HOSTS=/etc/hosts add_host() { grep -q "$2" $ETC_HOSTS || sudo sh -c "echo '$1\t$2' >> $ETC_HOSTS"; } remove_host() { - local ip=$1 local proj=$2 if grep -q "$proj" $ETC_HOSTS; then echo "Removing $proj from $ETC_HOSTS" diff --git a/lib/menu.sh b/lib/menu.sh index 1d0f1a0..f822421 100644 --- a/lib/menu.sh +++ b/lib/menu.sh @@ -4,8 +4,6 @@ print_menu_items() { local type=$1 # "docker" or "online" - local keys=() - local display_lines=() # Get running containers efficiently local running_containers="" @@ -38,7 +36,7 @@ print_menu_items() { return fi - while [ $i -lt $total ]; do + while [ "$i" -lt "$total" ]; do # Item 1 local key1="${sorted_keys[$i]}" local desc1="" @@ -79,7 +77,7 @@ print_menu_items() { # Item 2 local str2="" - if [ $((i+1)) -lt $total ]; then + if [ $((i+1)) -lt "$total" ]; then local key2="${sorted_keys[$((i+1))]}" local desc2="" local stat2="" diff --git a/lib/utils.sh b/lib/utils.sh index 5e15984..8e3e0d7 100644 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -1,4 +1,6 @@ #!/bin/bash +# Colors are assigned in lib/colors.sh, which breakinglab.sh sources first. +# shellcheck disable=SC2154 print_date() { stat -c %y "$0"; } @@ -26,8 +28,7 @@ open_url() { wget -O - https://pkg.wslutiliti.es/public.key | sudo gpg --dearmor -o /usr/share/keyrings/wslu-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/wslu-archive-keyring.gpg] https://pkg.wslutiliti.es/debian $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/wslu.list sudo apt update -y - sudo apt install -y wslu - if [ $? -eq 0 ]; then + if sudo apt install -y wslu; then echo -e "$TCG wslu installed successfully $TCD" else echo -e "$TCR Failed to install wslu. Falling back to powershell $TCD" @@ -63,7 +64,7 @@ execute_hook() { docker_is_installed() { if [ -n "${DOCKER_INSTALLED_CACHE:-}" ]; then - return $DOCKER_INSTALLED_CACHE + return "$DOCKER_INSTALLED_CACHE" fi if command -v docker >/dev/null 2>&1; then echo -e "$TCG Docker command found $TCD" @@ -112,7 +113,8 @@ start_docker() { if is_wsl; then echo -e "$TCG Starting Docker Desktop (WSL) $TCD" local win_path="C:/Program Files/Docker/Docker/Docker Desktop.exe" - local wsl_path=$(wslpath -u "$win_path" 2>/dev/null) + local wsl_path + wsl_path=$(wslpath -u "$win_path" 2>/dev/null) if [ -z "$wsl_path" ] || [ ! -f "$wsl_path" ]; then echo -e "$TCR Docker Desktop not found at $win_path $TCD" echo "Please ensure Docker Desktop is installed and adjust the path if necessary." @@ -141,7 +143,11 @@ start_docker() { echo -e "$TCG Starting Docker service (Linux) $TCD" sudo systemctl start docker || sudo service docker start sleep 2 - docker_is_running && return 0 || { echo -e "$TCR Failed to start Docker service $TCD"; return 1; } + if docker_is_running; then + return 0 + fi + echo -e "$TCR Failed to start Docker service $TCD" + return 1 fi else echo -e "$TCR Docker is required for this operation. Exiting. $TCD" diff --git a/scripts/hooks/btslab_post.sh b/scripts/hooks/btslab_post.sh index b14b5d1..694adbf 100644 --- a/scripts/hooks/btslab_post.sh +++ b/scripts/hooks/btslab_post.sh @@ -1 +1,2 @@ +#!/usr/bin/env bash docker cp btslab/ btslab:/opt/lampp/htdocs diff --git a/scripts/hooks/btslab_pre.sh b/scripts/hooks/btslab_pre.sh index 21a9448..5db5e9b 100644 --- a/scripts/hooks/btslab_pre.sh +++ b/scripts/hooks/btslab_pre.sh @@ -1 +1,2 @@ +#!/usr/bin/env bash git clone https://github.com/CSPF-Founder/btslab diff --git a/scripts/hooks/damnvulnrest_post.sh b/scripts/hooks/damnvulnrest_post.sh index 288f37e..6630487 100644 --- a/scripts/hooks/damnvulnrest_post.sh +++ b/scripts/hooks/damnvulnrest_post.sh @@ -1 +1,4 @@ -cd Damn-Vulnerable-RESTaurant-API-Game && bash ./start_app.sh && cd .. +#!/usr/bin/env bash +cd Damn-Vulnerable-RESTaurant-API-Game || exit +bash ./start_app.sh || exit +cd .. || exit diff --git a/scripts/hooks/damnvulnrest_pre.sh b/scripts/hooks/damnvulnrest_pre.sh index 64a1c9e..bf545f8 100644 --- a/scripts/hooks/damnvulnrest_pre.sh +++ b/scripts/hooks/damnvulnrest_pre.sh @@ -1 +1,3 @@ -git clone https://github.com/theowni/Damn-Vulnerable-RESTaurant-API-Game.git && cd Damn-Vulnerable-RESTaurant-API-Game +#!/usr/bin/env bash +git clone https://github.com/theowni/Damn-Vulnerable-RESTaurant-API-Game.git || exit +cd Damn-Vulnerable-RESTaurant-API-Game || exit diff --git a/scripts/hooks/exploitcoil_post.sh b/scripts/hooks/exploitcoil_post.sh index e83c1ac..db188b0 100644 --- a/scripts/hooks/exploitcoil_post.sh +++ b/scripts/hooks/exploitcoil_post.sh @@ -1 +1,4 @@ -cd exploit.co.il-Docker && docker compose up -d && cd .. +#!/usr/bin/env bash +cd exploit.co.il-Docker || exit +docker compose up -d || exit +cd .. || exit diff --git a/scripts/hooks/exploitcoil_pre.sh b/scripts/hooks/exploitcoil_pre.sh index e200c84..20076f1 100644 --- a/scripts/hooks/exploitcoil_pre.sh +++ b/scripts/hooks/exploitcoil_pre.sh @@ -1 +1,3 @@ -git clone https://github.com/Cryoox/exploit.co.il-Docker.git && cd exploit.co.il-Docker +#!/usr/bin/env bash +git clone https://github.com/Cryoox/exploit.co.il-Docker.git || exit +cd exploit.co.il-Docker || exit diff --git a/scripts/hooks/jvl_post.sh b/scripts/hooks/jvl_post.sh index 5479a29..fae788b 100644 --- a/scripts/hooks/jvl_post.sh +++ b/scripts/hooks/jvl_post.sh @@ -1 +1,4 @@ -cd JavaVulnerableLab && docker-compose up -d && cd .. +#!/usr/bin/env bash +cd JavaVulnerableLab || exit +docker-compose up -d || exit +cd .. || exit diff --git a/scripts/hooks/jvl_pre.sh b/scripts/hooks/jvl_pre.sh index 22d2dee..e8d96bc 100644 --- a/scripts/hooks/jvl_pre.sh +++ b/scripts/hooks/jvl_pre.sh @@ -1 +1,3 @@ -git clone https://github.com/CSPF-Founder/JavaVulnerableLab.git && cd JavaVulnerableLab +#!/usr/bin/env bash +git clone https://github.com/CSPF-Founder/JavaVulnerableLab.git || exit +cd JavaVulnerableLab || exit diff --git a/scripts/hooks/mutillidae_post.sh b/scripts/hooks/mutillidae_post.sh index 765e8a8..e173424 100644 --- a/scripts/hooks/mutillidae_post.sh +++ b/scripts/hooks/mutillidae_post.sh @@ -1 +1,4 @@ -_name: database +#!/usr/bin/env bash +cd mutillidae-docker || exit +docker compose -f .build/docker-compose.yml up --build -d || exit +cd .. || exit diff --git a/scripts/hooks/mutillidae_pre.sh b/scripts/hooks/mutillidae_pre.sh index e5edefa..9771e19 100644 --- a/scripts/hooks/mutillidae_pre.sh +++ b/scripts/hooks/mutillidae_pre.sh @@ -1 +1,8 @@ -git clone https://github.com/webpwnized/mutillidae-docker.git && cd mutillidae-docker && sed -i 's +#!/usr/bin/env bash +if [[ ! -d mutillidae-docker ]]; then + git clone https://github.com/webpwnized/mutillidae-docker.git || exit +fi +cd mutillidae-docker || exit +sed -i 's|_name: database|_name: mutillidae-database|g' .build/docker-compose.yml +sed -i 's|_name: www|_name: mutillidae-www|g' .build/docker-compose.yml +sed -i 's|_name: directory|_name: mutillidae-directory|g' .build/docker-compose.yml diff --git a/scripts/hooks/nosqli_post.sh b/scripts/hooks/nosqli_post.sh index 52d329a..943e6eb 100644 --- a/scripts/hooks/nosqli_post.sh +++ b/scripts/hooks/nosqli_post.sh @@ -1 +1,4 @@ -cd nosqlilab && docker-compose up -d --build && cd .. +#!/usr/bin/env bash +cd nosqlilab || exit +docker-compose up -d --build || exit +cd .. || exit diff --git a/scripts/hooks/nosqli_pre.sh b/scripts/hooks/nosqli_pre.sh index c898ece..e329193 100644 --- a/scripts/hooks/nosqli_pre.sh +++ b/scripts/hooks/nosqli_pre.sh @@ -1 +1,6 @@ -git clone https://github.com/madamantis-leviathan/nosqlilab.git && cd nosqlilab && sed -i 's/^version: .*$/version: "3.7-3.9"/' docker-compose.yml && sed -i "/web:/at container_name: nosqli-web" docker-compose.yml && sed -i "s/^t//" docker-compose.yml +#!/usr/bin/env bash +git clone https://github.com/madamantis-leviathan/nosqlilab.git || exit +cd nosqlilab || exit +sed -i 's/^version: .*$/version: "3.7-3.9"/' docker-compose.yml +sed -i "/web:/at container_name: nosqli-web" docker-compose.yml +sed -i "s/^t//" docker-compose.yml diff --git a/scripts/hooks/oxninja_post.sh b/scripts/hooks/oxninja_post.sh index 6ba340c..68530e7 100644 --- a/scripts/hooks/oxninja_post.sh +++ b/scripts/hooks/oxninja_post.sh @@ -1 +1,4 @@ --\s*80\:\s*80 +#!/usr/bin/env bash +cd oxninja-sqlilab || exit +docker-compose up -d --build || exit +cd .. || exit diff --git a/scripts/hooks/oxninja_pre.sh b/scripts/hooks/oxninja_pre.sh index 2561336..aae30eb 100644 --- a/scripts/hooks/oxninja_pre.sh +++ b/scripts/hooks/oxninja_pre.sh @@ -1 +1,12 @@ -git clone https://github.com/OxNinja/SQLi-lab oxninja-sqlilab && cd oxninja-sqlilab && sed -i "/web:/at container_name: oxninja-web" docker-compose.yml && sed -i "s/^t//" docker-compose.yml && sed -i "s +#!/usr/bin/env bash +if [[ ! -d oxninja-sqlilab ]]; then + git clone https://github.com/OxNinja/SQLi-lab oxninja-sqlilab || exit +fi +cd oxninja-sqlilab || exit +if ! grep -q "container_name: oxninja-web" docker-compose.yml; then + sed -i "/web:/at container_name: oxninja-web" docker-compose.yml + sed -i "s/^t//" docker-compose.yml +fi +# shellcheck disable=SC1001 +sed -i "s|-\s*80\:\s*80|-\s*127.20.0.1\:\s*80\:\s*80|g" docker-compose.yml +sed -i "s/172.16.0/172.16.1/g" docker-compose.yml diff --git a/scripts/hooks/ssrflab_post.sh b/scripts/hooks/ssrflab_post.sh index 360250c..cf0436b 100644 --- a/scripts/hooks/ssrflab_post.sh +++ b/scripts/hooks/ssrflab_post.sh @@ -1 +1,4 @@ -cd SSRF-LAB && docker cp ./index.php ssrflab:/var/www/html && cd .. +#!/usr/bin/env bash +cd SSRF-LAB || exit +docker cp ./index.php ssrflab:/var/www/html || exit +cd .. || exit diff --git a/scripts/hooks/ssrflab_pre.sh b/scripts/hooks/ssrflab_pre.sh index 07632c0..49435a7 100644 --- a/scripts/hooks/ssrflab_pre.sh +++ b/scripts/hooks/ssrflab_pre.sh @@ -1 +1,3 @@ -git clone https://github.com/ph4nt0m-py/SSRF-LAB.git && cd SSRF-LAB +#!/usr/bin/env bash +git clone https://github.com/ph4nt0m-py/SSRF-LAB.git || exit +cd SSRF-LAB || exit diff --git a/scripts/hooks/vulnado_post.sh b/scripts/hooks/vulnado_post.sh index 7bf173c..3731096 100644 --- a/scripts/hooks/vulnado_post.sh +++ b/scripts/hooks/vulnado_post.sh @@ -1 +1,4 @@ -cd vulnado && sudo docker compose up -d && cd .. +#!/usr/bin/env bash +cd vulnado || exit +sudo docker compose up -d || exit +cd .. || exit diff --git a/scripts/hooks/vulnado_pre.sh b/scripts/hooks/vulnado_pre.sh index 1655a93..5c0647f 100644 --- a/scripts/hooks/vulnado_pre.sh +++ b/scripts/hooks/vulnado_pre.sh @@ -1 +1,3 @@ -git clone https://github.com/ScaleSec/vulnado && cd vulnado +#!/usr/bin/env bash +git clone https://github.com/ScaleSec/vulnado || exit +cd vulnado || exit diff --git a/scripts/hooks/web4pentester_post.sh b/scripts/hooks/web4pentester_post.sh index 01cce11..a81bbea 100644 --- a/scripts/hooks/web4pentester_post.sh +++ b/scripts/hooks/web4pentester_post.sh @@ -1 +1,2 @@ +#!/usr/bin/env bash sudo docker run --name web4pentester --label "com.docker.compose.project=BreakingLab" -h w4p -i -t --rm -p 127.18.0.1:80:80 tiizss/webforpentester:1.0 bash -c "service apache2 start && service mysql start && bash"