diff --git a/docs/superpowers/specs/2026-05-06-base-backend-scaffold-design.md b/docs/superpowers/specs/2026-05-06-base-backend-scaffold-design.md new file mode 100644 index 0000000..263fc14 --- /dev/null +++ b/docs/superpowers/specs/2026-05-06-base-backend-scaffold-design.md @@ -0,0 +1,225 @@ +# Diseño — Scaffold `base-backend` + +- **Fecha**: 2026-05-06 +- **Rama de origen**: `chore/claude-code-setup` (sf-sim) +- **Destino**: `~/code/ref/base-backend` (repo independiente, `git init`) +- **Autor**: Jorge + +## Contexto + +Sf-sim es un monorepo TypeScript ESM con varios microservicios DDD/Hexagonal sobre RabbitMQ + Postgres. Una vez estabilizada la configuración de Claude Code en la rama `chore/claude-code-setup` (commits `9a5308c`, `b67d53c`, `5e77619`), se quiere extraer un **scaffold genérico** que sirva de punto de partida para futuros backends del mismo perfil arquitectónico. + +El scaffold no debe arrastrar el dominio SIM (ICCID, NOS, Objenious) ni la infraestructura de mensajería/persistencia — solo el esqueleto del monorepo, el tooling y la configuración de agente. + +## Decisiones de diseño + +Ya validadas con el usuario antes de escribir este spec. + +| # | Decisión | Elegido | Alternativas descartadas | +|---|---|---|---| +| 1 | Alcance | **A — Esqueleto mínimo** | B (con shared genérico), C (stack completo con Docker/RabbitMQ/Postgres) | +| 2 | Documentación | **C — Híbrido** | A (genericizar todo), B (copiar tal cual) | +| 3 | `git init` + commit inicial | **Sí** | — | +| 4 | `amqplib` en `_template` | **Quitar** | Dejarla por si se usa después | +| 5 | Sección EVENTS-RABBITMQ del auditor | **Mantener** | Quitar | +| 6 | Carpeta `aplication` (typo) | **Pasar a `application`** | Mantener typo, dejarlo abierto | + +## Alcance + +### Lo que incluye `base-backend` + +``` +base-backend/ +├── .agents/ +│ └── skills/sf-backend-architecture/ # copia íntegra + nota inicial +├── .claude/ +│ ├── commands/ # /audit, /check, /md-lint +│ ├── rules/ +│ │ ├── code-style.md # genericizado +│ │ └── git-conventions.md # genericizado +│ ├── skills/ # symlink clean-ddd-hexagonal y demás +│ └── settings.local.json +├── packages/ +│ └── _template/ +│ ├── config/env/index.ts +│ ├── index.ts +│ ├── package.json # name "template", sin amqplib +│ ├── tsconfig.json +│ └── .env +├── docs/ +│ └── superpowers/specs/ # vacía, lista para nuevos specs +├── .editorconfig +├── .gitattributes +├── .gitignore +├── .yarnrc.yml +├── CLAUDE.md # genericizado +├── CONTRIBUTING.md # genericizado +├── README.md # nuevo +├── package.json # name "base-backend", workspaces +├── tsconfig.json +├── tsconfig.vitest.json +└── vitest.config.ts +``` + +### Lo que NO se copia + +- `deployment/` (Docker compose, Dockerfile.dev, migraciones). +- `imgs/` (diagrama `diagrama-rabbit.png`). +- `rabbitmq_plugins/`. +- Scripts `build.local.sh`, `run.local.sh`, `stop.local.sh`. +- `.understand-anything/` (knowledge graph generado para sf-sim). +- `skills-lock.json` (decisión: regenerar al instalar superpowers en el nuevo repo). +- `yarn.lock` (se regenera con `yarn install` al primer uso). +- Todos los packages de `packages/` excepto `_template/`. +- `docs/sim-api-documentation.html` y `docs/sim-objenious/*` (específicos). + +## Cambios sobre archivos copiados + +### 1. `package.json` (raíz) + +- `name`: `"sf-sim"` → `"base-backend"`. +- `description`: actualizar a "Monorepo backend TypeScript ESM con DDD/Hexagonal — base para servicios nuevos". +- `scripts`: mantener `dev`, `build`, `start`, `typecheck`, `lint`, `lint:fix`, `format`, `format:check`, `test`. +- **Quitar** script `migrate` y dependencia `@sf-alvar/db-migrate` (no hay migrations en el scaffold). +- Mantener `workspaces: ["packages/*"]`, `packageManager: "yarn@4.x"`. + +### 2. `CLAUDE.md` + +Reescritura completa. Mantiene la espina dorsal arquitectónica; quita lo específico de SIM. + +**Mantiene**: +- Sección "Comandos" con yarn dev/build/start/typecheck/lint/format/test/vitest run. +- ESM puro, imports `.js` aunque el archivo sea `.ts`, path aliases por servicio. +- Arquitectura: monorepo de microservicios DDD/Hexagonal con `domain/`, `application/`, `infrastructure/`, `config/`. +- `Result` para fallos esperables, `throw` para invariantes rotas. +- DI manual por constructor con objeto `args: { dep1, dep2 }`. Tipos apuntando al port, no al adapter. +- Skill `sf-backend-architecture` y referencias. +- `@.claude/rules/code-style.md` y `@.claude/rules/git-conventions.md`. + +**Quita**: +- Comandos relativos a Docker (`./build.local.sh`, `./run.local.sh`, `./stop.local.sh`). +- Comando `yarn migrate`. +- Bloque RabbitMQ (exchange, routing keys, retries, DLX, correlation_id, diagrama). +- Listado de packages (`sim-shared`, `sim-entrada-eventos`, `sim-consumidor-nos`, `sim-consumidor-objenious`, `sim-objenious-cron`). +- Mención al typo `aplication` (en `base-backend` será `application`). + +**Sustituye** la lista de packages por: +> `packages/_template/` — plantilla oficial para servicios nuevos. Cópiala, renómbrala y desarrolla desde ahí. + +### 3. `.claude/rules/code-style.md` + +Quita la sección "Excepciones de este repo" entera. El base no tiene los pasivos legacy de sf-sim: + +- No hay cobertura ~12%: la regla TDD + 70% aplica desde el día 1 (estricta para código nuevo). +- No existe `sim-objenious-cron`: no hay excepciones arquitectónicas que documentar. +- Carpeta `aplication`: deja de ser excepción porque pasamos a `application`. + +Resto del fichero se mantiene tal cual. + +### 4. `.claude/rules/git-conventions.md` + +Quita el bloque "Pull Requests" entero (Gitea self-hosted, reviewer Alvar San Martin, dominio `savefamilygps.com`). Sustituye por: + +```markdown +## Pull Requests + +Adapta este apartado al hosting y revisor de tu proyecto (GitHub, GitLab, Gitea, etc.). +``` + +Mantiene reglas de branches y conventional commits. + +### 5. `CONTRIBUTING.md` + +Barrido para quitar: +- Referencias a SIM, ICCID, RabbitMQ. +- Reviewer concreto y dominio de email. +- Comandos Docker locales. + +Mantiene reglas generales de contribución (commits, PRs, code style). + +### 6. `README.md` (nuevo) + +Breve. Explica: +- Qué es: monorepo backend TypeScript ESM con DDD/Hexagonal, yarn 4 workspaces. +- Cómo arrancar: `yarn install`, `yarn dev`. +- Cómo crear un servicio nuevo: copiar `packages/_template/`, renombrar. +- Dónde mirar: `CLAUDE.md`, `CONTRIBUTING.md`, skill `sf-backend-architecture`. + +### 7. `packages/_template/package.json` + +- `name`: `"sim-template"` → `"template"`. +- `description`: "Template de la estructura de archivos" → "Plantilla base para servicios del monorepo". +- **Quitar dependencias** `amqplib` y `@types/amqplib` (decisión 4). +- Path aliases (`imports`): mantener `#adapters/*`, `#domain/*`, `#ports/*`, `#tests/*`. **Añadir** `#application/*` (no estaba antes; refleja la corrección del typo en decisión 6). +- Resto se mantiene. + +### 8. `.agents/skills/sf-backend-architecture/SKILL.md` + +Añadir bloque al inicio (tras el frontmatter): + +> **Nota**: esta skill describe el estilo arquitectónico originado en el repo sf-sim (RabbitMQ + Postgres + DDD/Hexagonal + EDA). Los ejemplos están escritos contra ese dominio (SIM/ICCID/Objenious). Cuando la apliques en un repo distinto, **adapta los ejemplos** al dominio e infraestructura concretos — la arquitectura subyacente sigue valiendo. + +Las referencias en `references/` (HOUSE-STYLE, CODE-STYLE, ANTI-PATTERNS, AUDIT-CHECKLIST, EVENTS-RABBITMQ) se copian sin tocar. La sección EVENTS-RABBITMQ del checklist del auditor se mantiene (decisión 5): si en el futuro se añade RabbitMQ al `base-backend`, la sección está disponible. + +### 9. `.gitignore` + +Verificar que no arrastra patrones específicos de sf-sim. Si los hay (poco probable; suele ser estándar `node_modules/`, `dist/`, `.env`), eliminarlos. + +### 10. `tsconfig.json` (raíz) + +Limpiar `compilerOptions.paths`. En sf-sim contiene una entrada hardcoded: + +```json +"paths": { + "sim-consumidor-objenious": ["./packages/sim-consumidor-objenious/*"] +} +``` + +En `base-backend` esa entrada se elimina (deja `paths: {}` o se quita la clave entera). Resto del fichero se mantiene (`composite`, `module: nodenext`, `outDir: dist`, etc.). + +### 11. `tsconfig.vitest.json` y `vitest.config.ts` + +Se copian tal cual. Nota: `tsconfig.vitest.json` extiende `./tsconfig.app.json` que **no existe en sf-sim** (es un bug latente del repo origen). No se corrige aquí — corregirlo es responsabilidad de quien arranque el primer proyecto si llega a usar vitest a nivel raíz; mientras tanto los tests por package siguen funcionando como en sf-sim. + +### 12. `application` vs `aplication` + +Donde la documentación o el código mencione `aplication`, sustituir por `application`. Lugares conocidos: + +- `CLAUDE.md` — la mención al typo se elimina (no se sustituye, deja de ser relevante). +- `.agents/skills/sf-backend-architecture/SKILL.md` y referencias — buscar y sustituir. +- `.agents/skills/sf-backend-architecture/references/HOUSE-STYLE.md`. +- Comandos `/audit` y `/check` si lo mencionan. +- `packages/_template/` — añadir entrada `#application/*` en path aliases. + +El plan de implementación cerrará con un `grep -ri 'aplication' .` en el repo nuevo para garantizar que no queda ninguna mención. + +## Proceso de implementación (resumen) + +El plan detallado lo generará la skill `writing-plans` después de la aprobación de este spec. A alto nivel: + +1. Crear `~/code/ref/base-backend/` y subdirectorios. +2. Copiar archivos seleccionados de sf-sim. +3. Aplicar las modificaciones (puntos 1-10 de la sección anterior). +4. `git init` en `~/code/ref/base-backend`. +5. `yarn install` para regenerar `yarn.lock`. +6. Verificar que `yarn typecheck` y `yarn lint` pasan en el repo recién creado (típicamente vacío de errores en un scaffold). +7. Commit inicial: `chore: scaffold base-backend monorepo`. + +## Verificación de aceptación + +El scaffold se considera completo cuando: + +- [ ] `~/code/ref/base-backend` existe como repo git con commit inicial. +- [ ] `yarn install` desde la raíz se ejecuta sin errores. +- [ ] `yarn typecheck` pasa (puede no haber código en `_template/index.ts` más allá del placeholder). +- [ ] `yarn lint` pasa. +- [ ] No quedan referencias literales a "sim", "ICCID", "Objenious", "NOS", "RabbitMQ", "Postgres" en CLAUDE.md, CONTRIBUTING.md, README.md ni en `.claude/rules/*` (las menciones en las skills/referencias son intencionales por la nota añadida). +- [ ] No queda `aplication` como typo en ningún fichero del repo nuevo. +- [ ] Ejecutar `/audit` o `/check` desde Claude Code en `base-backend` carga sin errores y aplica al repo limpio. + +## Fuera de alcance + +- Crear servicios reales en `packages/`. El scaffold solo trae `_template`. +- Configurar CI (GitHub Actions, Gitea Actions, etc.). Lo decide quien arranque el primer proyecto. +- Migraciones de BBDD, Docker compose, scripts locales. Aplazado a una futura ampliación si se quiere una variante "stack completo". +- Push del scaffold a un remoto. El usuario lo decide cuando lo use.