06 — Stack tecnológico — RELE
1. Resumen
| Capa | Tecnología | Notas |
|---|
| Frontend | Angular (standalone components) | Puerto 4200 |
| Estilos | Tailwind CSS | Tokens en tailwind.config.js |
| Backend | NestJS | Prefijo global /api, puerto 3009 |
| ORM | Prisma | schema en apps/api/prisma |
| DB | Neon PostgreSQL | project sparkling-snow-59844541 |
| Auth | JWT (Bearer) | accessToken en login |
| Validación | class-validator + ValidationPipe | whitelist + transform |
| Repo | /Users/cristian/orca/rele-app/ | GitHub Criscode2022/rele-app |
2. Estructura monorepo app
rele-app/
├── package.json # scripts api / web
├── apps/
│ ├── api/ # NestJS
│ │ ├── prisma/
│ │ │ ├── schema.prisma
│ │ │ └── seed.ts
│ │ ├── src/
│ │ │ ├── auth/
│ │ │ ├── readings/
│ │ │ ├── prisma/
│ │ │ ├── app.module.ts
│ │ │ └── main.ts
│ │ └── package.json
│ └── web/ # Angular
│ ├── src/app/
│ │ ├── core/api.service.ts
│ │ └── pages/...
│ ├── tailwind.config.js
│ └── package.json
└── README.md
[DECISIÓN / D-P1-03]: apps independientes (npm install --prefix), sin workspaces npm que rompan Angular.
3. Frontend
| Aspecto | Detalle |
|---|
| Componentes | Standalone + templates inline |
| Routing | app.routes.ts |
| HTTP | HttpClient vía ApiService |
| Estado auth | localStorage keys rele_token, rele_user |
| API base | http://localhost:3009/api |
| Fonts | Google Fonts Sora + Nunito Sans en styles.css |
Rutas web
| Path | Página |
|---|
/ | HomePage |
/login | LoginPage |
/lecturas | ReadingsPage |
/lecturas/nueva | ReadingNewPage |
/lecturas/:id | ReadingDetailPage |
4. Backend
| Aspecto | Detalle |
|---|
| Prefijo | /api |
| CORS | origin: true, credentials |
| Puerto | process.env.PORT || 3009 |
| Módulos | AuthModule, ReadingsModule, PrismaModule |
Endpoints
| Método | Ruta | Auth | Rol |
|---|
| POST | /api/auth/login | No | — |
| GET | /api/readings | JWT | ambos |
| GET | /api/readings/stats/summary | JWT | ambos |
| GET | /api/readings/:id | JWT | scope |
| POST | /api/readings | JWT | RESIDENT |
| PATCH | /api/readings/:id/status | JWT | ADVISOR |
5. Base de datos
| Campo | Valor |
|---|
| Provider | PostgreSQL |
| Hosting | Neon serverless |
| Project | sparkling-snow-59844541 |
| URL | DATABASE_URL en .env (no commitear secretos) |
| Seed | prisma/seed.ts → 2 users, 1 home, 5 readings |
6. Auth JWT
| Pieza | Rol |
|---|
| Login | bcrypt compare + sign JWT |
| Payload | sub/userId, email, role |
| Guard | JwtAuthGuard en ReadingsController |
| Strategy | passport-jwt Bearer |
| Cliente | header Authorization: Bearer <token> |
7. Variables de entorno
| Variable | Servicio | Descripción |
|---|
DATABASE_URL | API | Connection string Neon |
JWT_SECRET | API | Firma de tokens |
PORT | API | Opcional, default 3009 |
Web: URL API fija en api.service.ts (localhost:3009) en v1.
8. Scripts habituales
cd /Users/cristian/orca/rele-app
npm install --prefix apps/api
npm install --prefix apps/web
npm --prefix apps/api run prisma:migrate
npm --prefix apps/api run prisma:seed
npm run api # :3009
npm run web # :4200
9. Decisiones técnicas
| Decisión | Razón |
|---|
| Puerto 3009 | Diversidad vs VOLTA 3008 / SURCO 3007 |
| Soft guards en Angular | Autoridad real en API; L2 simple |
| Create → SUBMITTED | Menos fricción que DRAFT+submit |
| Stats con kwhTotal | Dominio energía visible en strip |
| Templates inline | Velocidad daily; componentes autocontenidos |
| accessToken camelCase | Alineado a SURCO; evita snake_case mismatch |
10. Dependencias clave (orientativo)
| API | Web |
|---|
| @nestjs/* | @angular/* |
| @prisma/client | tailwindcss |
| passport-jwt | rxjs |
| bcrypt | — |
| class-validator | — |
11. Despliegue (recomendado, no obligatorio v1)
| Capa | Opción |
|---|
| API | Railway / Fly / Render |
| Web | Vercel / Netlify / static ng build |
| DB | Neon (ya) |
Documentar CORS y API URL de producción al desplegar.