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:
@@ -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.
|
||||||
Reference in New Issue
Block a user