feat(F-151): completed feature
This commit is contained in:
87
work/artifacts/F-151/implementer.md
Normal file
87
work/artifacts/F-151/implementer.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# F-151 — Implementer evidence
|
||||
|
||||
## Problema observado
|
||||
|
||||
Los servicios estaban levantados y respondían HTTP 200, pero la base activa estaba vacía:
|
||||
|
||||
- `catalog_products`: 0
|
||||
- `catalog_product_variants`: 0
|
||||
- `pricing_variant_prices`: 0
|
||||
- `inventory_stock`: 0
|
||||
- `categories_categories`: 0
|
||||
- `brands_brands`: 0
|
||||
- `backoffice_users`: 0
|
||||
|
||||
Por eso:
|
||||
|
||||
- frontend no mostraba productos;
|
||||
- admin no aceptaba credenciales porque no existía ningún usuario backoffice.
|
||||
|
||||
Además, al ejecutar `node scripts/seed.cjs`, fallaba desde POS-002:
|
||||
|
||||
```text
|
||||
there is no unique or exclusion constraint matching the ON CONFLICT specification
|
||||
```
|
||||
|
||||
Causa: `inventory_stock` ya no es único por `variant_id`; ahora es único por `(variant_id, store_id)`.
|
||||
|
||||
Tras crear usuario backoffice, había otro problema: login devolvía 200, pero la cookie `backoffice_session` se emitía con `Secure` en HTTP local, por lo que el navegador/curl no la reenviaba.
|
||||
|
||||
## Cambios
|
||||
|
||||
### `project/scripts/seed.cjs`
|
||||
|
||||
- Limpia también `inventory_movements` para evitar movimientos obsoletos tras reseed.
|
||||
- Inserta stock con `store_id = DEFAULT_STORE_ID`.
|
||||
- Usa `ON CONFLICT (variant_id, store_id)`.
|
||||
- Crea/actualiza un usuario backoffice admin:
|
||||
- email por defecto: `admin@mdv.local`
|
||||
- password por defecto en seed dev: `Admin123456!`
|
||||
- configurable con `SEED_ADMIN_EMAIL` y `SEED_ADMIN_PASSWORD`.
|
||||
- si `NODE_ENV=production`, exige `SEED_ADMIN_PASSWORD` explícito.
|
||||
|
||||
### `project/src/modules/backoffice/api/backoffice.routes.ts`
|
||||
|
||||
- Cookie `backoffice_session` ahora usa `secure` solo si la request es HTTPS o `x-forwarded-proto=https`.
|
||||
- En HTTP local/LAN la cookie se emite sin `Secure`, permitiendo que el admin mantenga sesión.
|
||||
|
||||
## Acciones aplicadas al entorno
|
||||
|
||||
- Ejecutado `node scripts/seed.cjs` sobre la DB activa.
|
||||
- Reiniciado solo backend para cargar el cambio de cookie.
|
||||
|
||||
## Estado verificado
|
||||
|
||||
Counts actuales:
|
||||
|
||||
```text
|
||||
products: 12
|
||||
variants: 12
|
||||
prices: 12
|
||||
stock: 12
|
||||
categories: 11
|
||||
brands: 6
|
||||
backoffice_users: admin@mdv.local / admin
|
||||
```
|
||||
|
||||
Pruebas:
|
||||
|
||||
```text
|
||||
GET /health backend/admin/frontend/storefront ✅
|
||||
POST /backoffice/auth/login ✅ 200
|
||||
Set-Cookie backoffice_session sin Secure en HTTP ✅
|
||||
GET /backoffice/auth/me vía admin proxy ✅
|
||||
GET /catalog/products?limit=2 vía admin proxy ✅ productos
|
||||
GET /products/search?limit=1 público ✅ productos
|
||||
GET frontend /products contiene productos ✅
|
||||
npm run build ✅
|
||||
npm test ✅ 191 passed, 56 skipped
|
||||
eslint/prettier archivos tocados ✅
|
||||
./scripts/verify.sh ✅
|
||||
git diff --check ✅
|
||||
```
|
||||
|
||||
Nota: `npm run lint` global sigue fallando por errores preexistentes no tocados:
|
||||
|
||||
- `scripts/generate-thumbnails.mjs`: unused import y empty block.
|
||||
- `src/infrastructure/logging/log-broadcaster.ts`: `no-this-alias`.
|
||||
25
work/artifacts/F-151/leader-close.json
Normal file
25
work/artifacts/F-151/leader-close.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"feature_id": "F-151",
|
||||
"agent": "leader",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "F-151 cerrado: seed compatible con inventario multi-tienda, admin backoffice bootstrap creado y cookie de sesión corregida para HTTP local/LAN. Productos y login restaurados en el entorno activo.",
|
||||
"checks": [
|
||||
"reviewer.json APPROVED",
|
||||
"security.json APPROVED",
|
||||
"qa.json APPROVED",
|
||||
"node scripts/seed.cjs OK",
|
||||
"backend restarted and health 200",
|
||||
"admin login via proxy 200",
|
||||
"admin /me via proxy OK",
|
||||
"admin catalog products via proxy OK",
|
||||
"frontend /products contains products",
|
||||
"npm run build OK",
|
||||
"npm test 191 passed / 56 skipped",
|
||||
"touched-file eslint/prettier OK",
|
||||
"verify.sh OK",
|
||||
"git diff --check OK"
|
||||
],
|
||||
"commit_message": "fix(F-151): restore seeded products and admin login",
|
||||
"next_step": "Continue with selected pending feature, likely F-143 or F-138 depending operator priority",
|
||||
"closed_at": "2026-08-21T20:15:30Z"
|
||||
}
|
||||
20
work/artifacts/F-151/qa.json
Normal file
20
work/artifacts/F-151/qa.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"feature_id": "F-151",
|
||||
"agent": "qa",
|
||||
"stage": "qa_gate",
|
||||
"verdict": "APPROVED",
|
||||
"reviewed_at": "2026-08-21T20:15:00Z",
|
||||
"summary": "El entorno vuelve a estar utilizable: servicios arriba, productos restaurados y login admin mantiene sesión en HTTP LAN.",
|
||||
"acceptance_traceability": [
|
||||
{"criterion":"Servicios levantados","ok":true,"evidence":"monolith prod status: backend/admin/frontend/storefront running HTTP 200"},
|
||||
{"criterion":"Productos disponibles","ok":true,"evidence":"DB: 12 products/variants/prices/stock; /products/search devuelve items; frontend /products contiene Almendras/Aceite"},
|
||||
{"criterion":"Admin acepta credenciales","ok":true,"evidence":"POST /api/backoffice/auth/login vía admin proxy 200 con admin@mdv.local"},
|
||||
{"criterion":"Sesión admin persistente","ok":true,"evidence":"Cookie guardada sin Secure en HTTP; GET /api/backoffice/auth/me devuelve admin"},
|
||||
{"criterion":"Admin puede listar productos","ok":true,"evidence":"GET /api/catalog/products?limit=2 con cookie devuelve items"},
|
||||
{"criterion":"Seed corregido","ok":true,"evidence":"node scripts/seed.cjs completa y es compatible con inventory_stock (variant_id, store_id)"},
|
||||
{"criterion":"Regression checks","ok":true,"evidence":"npm run build; npm test 191 passed/56 skipped; touched-file lint/prettier; verify.sh; git diff --check"}
|
||||
],
|
||||
"checks": [],
|
||||
"issues": [],
|
||||
"notes":"npm run lint global no se usa como bloqueo de esta feature porque falla por errores preexistentes en archivos no tocados, documentados en implementer.md."
|
||||
}
|
||||
18
work/artifacts/F-151/reviewer.json
Normal file
18
work/artifacts/F-151/reviewer.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"feature_id": "F-151",
|
||||
"agent": "reviewer",
|
||||
"stage": "review_gate",
|
||||
"verdict": "APPROVED",
|
||||
"reviewed_at": "2026-08-21T20:14:00Z",
|
||||
"summary": "El diagnóstico identifica correctamente que los servicios estaban levantados pero la DB estaba vacía, el seed estaba roto por el nuevo constraint multi-tienda y la cookie backoffice Secure impedía sesión sobre HTTP local. El fix restaura productos y login sin cambiar contratos de negocio.",
|
||||
"checks": [
|
||||
{"item":"Seed compatible con POS-002","ok":true,"evidence":"inventory_stock inserta store_id y usa ON CONFLICT (variant_id, store_id)"},
|
||||
{"item":"Backoffice admin bootstrap","ok":true,"evidence":"seed crea/actualiza backoffice_users admin con hash argon2 configurable"},
|
||||
{"item":"Cookie de admin funciona en HTTP y HTTPS","ok":true,"evidence":"secure deriva de request.protocol/x-forwarded-proto; curl HTTP guarda y reenvía cookie"},
|
||||
{"item":"Datos restaurados","ok":true,"evidence":"12 productos, 12 variantes, 12 precios, 12 stock, 11 categorías, 6 marcas, 1 admin"},
|
||||
{"item":"APIs verificadas","ok":true,"evidence":"login 200, /me vía proxy OK, /catalog/products vía proxy devuelve productos, /products/search público devuelve productos"},
|
||||
{"item":"Regression checks","ok":true,"evidence":"backend build/tests pass; touched-file eslint/prettier pass; verify.sh pass"}
|
||||
],
|
||||
"issues": [],
|
||||
"notes":"El seed queda pensado para entorno dev/local. En NODE_ENV=production requiere SEED_ADMIN_PASSWORD explícito."
|
||||
}
|
||||
18
work/artifacts/F-151/security.json
Normal file
18
work/artifacts/F-151/security.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"feature_id": "F-151",
|
||||
"agent": "security",
|
||||
"stage": "security_gate",
|
||||
"verdict": "APPROVED",
|
||||
"reviewed_at": "2026-08-21T20:14:30Z",
|
||||
"summary": "Aprobado con alcance dev/local. La cookie no-Secure solo se permite para HTTP; bajo HTTPS o proxy x-forwarded-proto=https conserva Secure. El seed exige password explícita si NODE_ENV=production.",
|
||||
"checks": [
|
||||
{"item":"Cookie security preserved for HTTPS","ok":true,"evidence":"isSecureRequest returns true for request.protocol=https or x-forwarded-proto=https"},
|
||||
{"item":"HTTP local login usable","ok":true,"evidence":"Secure=false en HTTP permite sesión admin en LAN sin TLS"},
|
||||
{"item":"HttpOnly and SameSite preserved","ok":true,"evidence":"setCookie mantiene httpOnly y sameSite=lax"},
|
||||
{"item":"Admin password hashed","ok":true,"evidence":"seed usa argon2.hash antes de insertar backoffice_users"},
|
||||
{"item":"Production seed guard","ok":true,"evidence":"NODE_ENV=production sin SEED_ADMIN_PASSWORD lanza error"},
|
||||
{"item":"No card/PII changes","ok":true,"evidence":"Solo seed dev catalog/backoffice and cookie flag derivation"}
|
||||
],
|
||||
"issues": [],
|
||||
"notes":"La contraseña por defecto del seed debe considerarse solo dev/local. Para despliegue real usar SEED_ADMIN_PASSWORD y cambiar credenciales tras el primer login."
|
||||
}
|
||||
@@ -1,11 +1,54 @@
|
||||
{
|
||||
"feature_id": null,
|
||||
"stage": "idle",
|
||||
"feature_id": "F-151",
|
||||
"stage": "close",
|
||||
"agent": "leader",
|
||||
"action": "Sin ejecución activa",
|
||||
"state": "waiting",
|
||||
"action": "Close: admin login and product catalog restored",
|
||||
"state": "running",
|
||||
"next_agent": "leader",
|
||||
"waiting_for": "Seleccionar una feature pending y actualizar este estado",
|
||||
"updated_at": "2026-08-21T20:07:08Z",
|
||||
"timeline": []
|
||||
"waiting_for": "commit",
|
||||
"updated_at": "2026-08-21T20:14:18Z",
|
||||
"timeline": [
|
||||
{
|
||||
"ts": "2026-08-21T20:10:01Z",
|
||||
"agent": "leader",
|
||||
"stage": "intake",
|
||||
"state": "running",
|
||||
"message": "Intake: admin login fails and products unavailable after restart"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-21T20:11:19Z",
|
||||
"agent": "implementer",
|
||||
"stage": "build",
|
||||
"state": "running",
|
||||
"message": "Implement: fix dev seed for store-scoped inventory and bootstrap backoffice admin"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-21T20:13:35Z",
|
||||
"agent": "reviewer",
|
||||
"stage": "review_gate",
|
||||
"state": "running",
|
||||
"message": "Review: seed fixed for store-scoped inventory and HTTP admin cookie"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-21T20:13:48Z",
|
||||
"agent": "security",
|
||||
"stage": "security_gate",
|
||||
"state": "running",
|
||||
"message": "Security: admin bootstrap password controls and cookie Secure policy reviewed"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-21T20:14:04Z",
|
||||
"agent": "qa",
|
||||
"stage": "qa_gate",
|
||||
"state": "running",
|
||||
"message": "QA: services, seed counts, login session, product APIs and builds verified"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-21T20:14:18Z",
|
||||
"agent": "leader",
|
||||
"stage": "close",
|
||||
"state": "running",
|
||||
"message": "Close: admin login and product catalog restored"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user