Cierre 21-jul: B4 con sync histórico verificado y B6 aplicado; horas, bitácora y Excel de avance al día
This commit is contained in:
@@ -846,6 +846,87 @@ Erika solicita un corte del avance de la Etapa 1. Johann se compromete a prepara
|
||||
|
||||
---
|
||||
|
||||
## 47 · Jul 19, 2026 · Gestión interna · demo del 18-jul no realizada; entorno local montado en la Mac
|
||||
|
||||
La **demo semanal planeada para el viernes 18-jul no ocurrió** (confirmado por Johann el 19-jul). Causa señalada: la validación del prototipo de la Etapa 0 sigue pendiente (quedó para el jue 23-jul) y eso ha retrasado el avance de la etapa. Los días 17–18 jul no registran trabajo en `../planeacion/Seguimiento-horas.csv`. La próxima demo queda apuntada al **viernes 24-jul** (cierre de Etapa 1), donde también conviene comunicar que la capa de escritura se entrega en dry-run (ver nota en `../planeacion/Agenda-semana-2026-07-20.md`).
|
||||
|
||||
El mismo 19-jul se montó el entorno local en la Mac: repo del cliente clonado en `balam-plataforma/` (convención de `../planeacion/Plan-Etapa1.md`), SDK .NET 10 instalado en usuario, token cargado en user-secrets, API corriendo (`/health` y `/api/bind/status` verificados, modo ReadOnly, 13/13 pruebas verdes) y frontend Angular servido. Se creó la agenda por día de la semana 20–24 jul (`../planeacion/Agenda-semana-2026-07-20.md`) y se actualizó el CSV de horas con los cortes del 16 y 19 jul.
|
||||
|
||||
---
|
||||
|
||||
## 48 · Jul 19, 2026 — noche · Desarrollo · B0+B1 completados (adelantados del lunes) + Scalar UI
|
||||
|
||||
Trabajo adelantado la noche del domingo siguiendo `../planeacion/Plan-Etapa1.md` al pie, con asistencia de IA (Claude Code). Tiempo real registrado en `../planeacion/Seguimiento-horas.csv` (~1.25 h de sesión — el plan estimaba 4–5.5 h manuales; el registro es de horas efectivamente trabajadas, conforme al contrato).
|
||||
|
||||
**B0 — Preparación local:** `docker-compose.yml` con Postgres 17 en puerto **5438** (5433–5437 ocupados por otros proyectos locales — difiere del 5433 que asume el plan en la otra máquina); cadena de conexión en `appsettings.Development.json`; `DesignTimeDbContextFactory`; referencia Infrastructure → Integrations.Bind; `dotnet-ef` 10.0.10.
|
||||
|
||||
**B1 — Fundación de datos:** entidades `Tenant`, `Client`, `Invoice` (modelo central: `Uuid` null ⇒ prefactura, `OpenBalance`, `CfdiPaymentTermRaw`, `PaidDetectedAtUtc`), `Quote`, `QuoteInvoiceLink` (ADR-003, con `JiraTicketKey` ADR-006), `InvoiceStatusChange` (ADR-004, fecha de detección), `WriteOperation` (pipeline Draft→DryRun→Confirmed, ADR-001); `TenantId` en `SyncCheckpoint`/`AuditLogEntry`; `BalamDbContext` → `IdentityDbContext` con llaves Guid; convenciones fechas BIND sin zona vs `*Utc` timestamptz y `decimal(18,2)`/`ExchangeRate(18,6)`; migración `Inicial` aplicada (16 tablas); `DbSeeder` idempotente verificado: tenant Balam (GUID fijo), 4 roles, 5 usuarios ficticios `*@balam.dev` (password en user-secrets `Seed:DefaultPassword`).
|
||||
|
||||
**Extra:** UI del OpenAPI con **Scalar** en `/scalar/v1` (solo Development). Estado verificado: API arriba con BD, 13/13 pruebas verdes, seed comprobado por consulta directa a Postgres. **Cambios sin commitear** en el repo del cliente — commit pendiente de Johann.
|
||||
|
||||
**Efecto en la agenda:** el lunes 20 queda libre para gestión + arrancar B2 (auth JWT + roles + bitácora) directamente.
|
||||
|
||||
---
|
||||
|
||||
## 49 · Jul 19, 2026 — noche · Desarrollo · B2 completado (adelantado del lunes): auth JWT + policies + bitácora
|
||||
|
||||
Continuación de la sesión nocturna asistida por IA (~0.5 h reales registradas en el CSV). Con esto el trabajo técnico planeado para el lunes 20 queda hecho; el lunes queda solo la gestión + arrancar B3 (sync de clientes).
|
||||
|
||||
**B2 conforme al plan:** `POST /api/auth/login` (Identity + JWT propio, sin `MapIdentityApi`, sin refresh en E1) y `GET /api/auth/me`; `Jwt:SigningKey` en user-secrets con fail-fast; policies nombradas (`PuedeVerCartera`, `PuedeDispararSync`, `PuedeVerBitacora`, `PuedeOperarEscritura`) con matriz provisional hasta la sesión del 22-jul; roles como constantes (`BalamRoles`); bitácora en dos piezas — `AuditMiddleware` (mutantes + 401/403) e `IAuditLogger` explícito — y `GET /api/audit` (Direccion/Administracion). Decisión aplicada del plan: **BD obligatoria con fail-fast**.
|
||||
|
||||
**Verificado end-to-end contra el API corriendo:** login fallido 401 (auditado una sola vez), login Finanzas 200 con token, `/me` 200, `/me` sin token 401, `/api/audit` con Finanzas 403 (auditado), con Dirección 200 mostrando toda la secuencia. 13/13 pruebas verdes.
|
||||
|
||||
Repo del cliente: 3 commits locales (`5631f55` Scalar, `6264ea3` B0+B1, `4617070` B2) — **push pendiente por decisión de Johann** (no se hace push sin su orden explícita).
|
||||
|
||||
---
|
||||
|
||||
## 50 · Jul 19, 2026 — noche · Desarrollo · B3 completado: sync de clientes CONTRA PRODUCCIÓN + hallazgo de datos
|
||||
|
||||
Cierre de la sesión nocturna (~0.5 h reales más). **Primer dato real de BIND viviendo en la plataforma:** 16 clientes sincronizados con detalle (días de crédito 0/30/45/60/90), checkpoint registrado y ciclo auditado en bitácora.
|
||||
|
||||
**Hallazgo de producción:** hay clientes con `LocationID`/`LoctaionID` **null** — caso que la validación del 6-jul no encontró. Se hicieron nullable todos los GUIDs de referencia de los modelos BIND (commit `fb0f066`); los IDs propios siguen no-nulos. Vale mencionarlo a Pedro junto con las 5 preguntas técnicas.
|
||||
|
||||
**B3 conforme al plan:** full-scan de lista + `SourceHash`, detalle solo nuevos/cambiados con tope por ciclo, normalización RFC/nombre, dedup por RFC exacto excluyendo genéricos — verificado en real: el único RFC repetido es `XEXX010101000` (2 clientes extranjeros) y quedó correctamente FUERA del dedup. Idempotencia comprobada: segundo run = 16 sin cambio, 1 sola petición. Consumo total del día: ~42 peticiones de 20,000.
|
||||
|
||||
`POST /api/sync/run` (Finanzas/Administración; Operaciones→403 verificado) y `GET /api/sync/status`. 13/13 pruebas verdes. Repo: **5 commits locales, push pendiente por decisión de Johann.**
|
||||
|
||||
**Estado de bloques al cierre del domingo: B0 ✅ · B1 ✅ · B2 ✅ · B3 ✅** — el lunes queda gestión + B4 (sync de facturas/cotizaciones + cartera, el bloque más grande) con margen de un día completo vs. el plan.
|
||||
|
||||
---
|
||||
|
||||
## 51 · Jul 21, 2026 · WhatsApp Erika ↔ Johann · estimación Jira→BIND comunicada (10 h) y alcance confirmado por Erika ⭐
|
||||
|
||||
Erika pidió en la mañana la estimación del cambio nuevo "para tenerla a la mano" antes de su sesión con directores. Secuencia clave:
|
||||
|
||||
1. **Johann comunicó: ~10 h de desarrollo, a confirmar el miércoles 22 en la sesión con Arturo** (primero cerrar reglas del flujo y validar la escritura de BIND). Quedó por escrito que "no estaba contemplado al inicio; es una mejora que surgió en el Discovery".
|
||||
2. Erika retó con la §1.4 de la propuesta ("¿no es esto lo de las cotizaciones?"). Aclaración que quedó asentada: **crear cotizaciones manualmente desde la plataforma SÍ está en el MVP** (capa de escritura); lo nuevo es que **los tickets de Jira las generen automáticamente**. Erika encontró ella misma la §1.3 donde Jira dice "Fuera de alcance" y lo confirmó con 👍. Erika lo valida internamente con los directores.
|
||||
3. Erika preguntó por 2 actividades vencidas en fechas del Excel (backend base y multi-tenant); Johann respondió "esas ya quedaron". Backend base ✅ real (B2); multi-tenant al ~80% — **hacer B6 (RLS real) de inmediato para que la afirmación quede cubierta.**
|
||||
4. **Nuevo compromiso:** compartir las horas semanalmente por Excel mientras Pedro habilita Jira, **con entregable + actividad + horas de cada etapa** (formato pedido por Erika, lunes de corte).
|
||||
|
||||
---
|
||||
|
||||
## 52 · Jul 21, 2026 — noche · Desarrollo · B4 completado: sync de facturas/cotizaciones + cartera por moneda + SYNC HISTÓRICO ⭐
|
||||
|
||||
Sesión nocturna asistida por IA (~1 h real registrada en el CSV). **La plataforma ya tiene la cartera completa de producción viviendo en Postgres.**
|
||||
|
||||
**B4 conforme al plan:** `InvoiceStatusMapper` como **función pura en Domain con 13 pruebas xUnit** (precedencia Cancelada→Pagada→Emitida→Vencida→Vigente; "hoy" en hora MX vía `MexicoTime`; la frontera Emitida/Vigente se ajusta en minutos si la sesión del 22 la cambia). `InvoiceSyncService` con ventana única (delta por `Date` + re-barrido de abiertas viejas, solape 1 día, cursor que solo avanza al completar la pasada) y `QuoteSyncService` con sonda del filtro `CreationDate` + fallback a full-scan. Detección de pagos ADR-004: transición → `InvoiceStatusChanges` con fecha de DETECCIÓN; **facturas nuevas NO generan transición** (el histórico fotografía, no detecta). Campo nuevo `DetailSyncedAtUtc` (migración `DetalleSyncPendiente`) para tope de detalle 50/ciclo + backfill B5. Endpoints: `GET /api/cartera` (por moneda, jamás suma monedas; primer uso de `PuedeVerCartera`), `GET /api/invoices|clients|quotes`. Normalización PPD/PUE desde la etiqueta larga de BIND.
|
||||
|
||||
**Sync histórico corrido y verificado esta noche (jamás en demo):** 1,494 facturas y 43 cotizaciones, **detalle 1,494/1,494 (0 pendientes)**, idempotencia comprobada (2ª pasada = 100% sinCambio), `InvoiceStatusChanges` = 0 (cero pagos falsos), 24.5 min, ~1,700 peticiones (~8.5% de cuota; cierre del día ~1,750 de 20,000). **Cartera verificada BD ↔ endpoint exacto:** MXN 17 abiertas $1,568,772.32 · USD 92 abiertas $320,379.06.
|
||||
|
||||
**Hallazgos de producción:** (1) el filtro `CreationDate` de Quotes SÍ funciona (pendiente §10 de VALIDACION-API resuelto de facto); (2) ⚠️ **las 1,374 facturas con método de pago traen PUE — ninguna PPD** (120 con el campo vacío). Todo el histórico se factura "pago en una sola exhibición" aunque cobran a crédito 30–90 días — preguntar a Arturo en la sesión del 22 (toca la regla PPD-default de la capa de escritura y el riesgo SAT que ellos mismos reportaron).
|
||||
|
||||
Commit `2e1ae82`. 26/26 pruebas verdes. **7 commits locales, push pendiente por decisión de Johann.**
|
||||
|
||||
---
|
||||
|
||||
## 53 · Jul 21, 2026 — noche · Desarrollo · B6: RLS real de Postgres (contractual) — código completo; verificación local pendiente de rol de app
|
||||
|
||||
Cierre de la sesión (~0.5 h real). **B6 conforme al plan:** `ITenantOwned` en las 8 entidades de negocio; `ICurrentTenantProvider` + `FixedTenantProvider` (ADR-005: tenant único); `TenantConnectionInterceptor` (`set_config('app.tenant_id',…)` en cada conexión, vías sync y async); filtros globales EF por entidad como segunda capa; migración `RlsPorTenant` a mano con `ENABLE/FORCE ROW LEVEL SECURITY` + política `tenant_isolation` (USING + WITH CHECK, fail-closed sin GUC) en las 8 tablas. Migración **aplicada** (catálogo confirma `relrowsecurity=t, relforcerowsecurity=t` en las 8); app end-to-end igual que antes (login, cartera, sync). Commit `fedb376`.
|
||||
|
||||
**⚠️ Verificación de aislamiento local INCOMPLETA:** la prueba psql devolvió filas sin GUC y con tenant ajeno porque `balam` (usuario bootstrap del contenedor) es **superuser con BYPASSRLS** — FORCE somete al *owner*, pero ningún candado somete a un superuser. El fix (pendiente de decisión de Johann, quedó en PENDIENTES): crear rol local `balam_app` (LOGIN, NOSUPERUSER, NOBYPASSRLS), transferirle la propiedad y apuntar la cadena de conexión de desarrollo a ese rol — replica cómo será Azure, donde el usuario de la app tampoco es superuser. Las políticas en sí son correctas; el hueco es del entorno local, no del código.
|
||||
|
||||
---
|
||||
|
||||
## Resumen ejecutivo del hilo (para contexto rápido)
|
||||
|
||||
### Datos duros confirmados por Balam
|
||||
|
||||
Reference in New Issue
Block a user