docs(specs): añadir spec del scaffold base-backend

Diseño aprobado para extraer un scaffold genérico (esqueleto mínimo +
config de Claude Code) a ~/code/ref/base-backend, usado como punto de
partida para futuros backends del mismo perfil arquitectónico.
This commit is contained in:
2026-05-06 09:50:11 +02:00
parent 5e77619d37
commit 3186b438c0

View File

@@ -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<E, D>` 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.