Files
jorgecuadros-platform/docs/BACKLOG.md
T
rmancinasandClaude Opus 5 3e12597204 docs: add BACKLOG.md, one list of everything outstanding
Open work was spread across six documents: PLAN's per-step status,
RESUME §6, two specs' collected open questions, and the "Not built"
sections of the two OCR docs. Nothing tracked the two live data defects
except a paragraph inside INSURANCE_FEATURES_SPEC, and nothing at all
recorded that master is 14 commits and 5 migrations past the last tag.

Compiled by reading those six, then checking each claim against the code
and the dev database rather than trusting the prose — which is how the
dead-table finding surfaced and how both insurance defects were confirmed
still open.

Leads with the ship blocker: SES_* is unset in Gitea while the pólizas
sweep defaults to enabled at 06:00, so deploying current master gives a
nightly sweep that fails every run. Set the secrets or disable the
schedule before cutting v1.0.7.

Findings not previously written down anywhere:

- policy_types still holds only AUTO/LICENCIAS/MULT and 5 policies still
  have a NULL policyTypeId; policyTypeId is still `String?` with Prisma's
  default SetNull, so the spec's recommended Restrict was never applied.
- EmailTemplate / EmailCampaign / EmailLog have zero references in
  apps/api/src or apps/web/src. Scaffolded for step 10's "email
  campaigns"; notificaciones shipped against email_notification_log
  instead. Either wire them or drop them.
- Customer.customerNumber does not exist, so recycling is not merely
  unbuilt but unstarted at the schema level.

Linked from PLAN.md and README so it is findable from either entry point.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 13:14:25 -07:00

11 KiB
Raw Blame History

Backlog — what is pending, missing, and not yet built

One place for work that is known-outstanding. Compiled 2026-08-02 from PLAN.md, RESUME.md, the four specs and the two OCR docs, then checked against the code and the dev database rather than trusted — several items in those documents had already been closed, and two defects they describe are still live.

This file is an index, not a replacement. Each item points at the document that carries the reasoning. Close an item there as well as here, or the two drift.

Verified against dev at compile time (re-run before trusting the numbers):

policy_types: AUTO, LICENCIAS, MULT
policies NULL policyTypeId: 5
policies pending liquidación: 226
customers: 1536
last tag: v1.0.6 (2026-08-02 02:06 UTC) — 14 commits, 5 migrations behind HEAD

0. Ship-blocked — read before the next deploy

Everything from the notificaciones arc is unreleased. v1.0.6 predates it. Five migrations are waiting:

20260801120000_ocr_batch_discarded
20260801130000_renewal_email_notifications
20260801200000_mass_email_notifications
20260802120000_renewal_notices_unified_log
20260802140000_app_settings

Plus three backup-pipeline fixes that have never reached prod (860d483, 567b033, 898cf48 — the last prod run went green through the whole chain and died on the final step wanting deploy/.env.prod).

⚠️ SES_* is unset in Gitea, and the renewal sweep is on by default

The variables are wired through both deploy workflows and the app stack, but the secrets were never set. The production image runs NODE_ENV=production, which disables the stdout dev fallback, so every send fails and logs FAILED.

The pólizas sweep defaults to enabled, 06:00 America/Tijuana. Deploying current master with SES still blank means a sweep that fails every single night, silently except for the log.

Before cutting v1.0.7: either set the Gitea secrets, or disable the pólizas schedule at /notificaciones → "Programación de envíos" first. See MASS_EMAIL_NOTIFICATIONS.md and DEPLOY_AND_MIGRATIONS.md.

Also outstanding on the deploy path: every pre-existing database still needs its one-time prisma migrate resolve --applied 0000_init.


1. Blocked on a decision from Jorge

Nothing here is a build problem. Each one makes the work either impossible or a guess.

# Question Blocks Source
1.1 What "garantías" refers to §2 liquidación's exclusion filter INSURANCE §2
1.2 What "Solicitud Atlas" is — application form or certificate §3 entirely INSURANCE §3
1.3 Carrier API direction: outbound quote/issue (ANA supports today) or inbound portfolio sync (no evidence either carrier offers it) whether §4 is buildable at all INSURANCE §4
1.4 CFE amount: the rounded barcode figure ($268, what is paid at the window) or the exact breakdown total ($268.88) the parser currently takes the barcode STATEMENT_OCR / RECEIPT §2
1.5 The Seguros USD bank's name, currency and details multi-bank is built; that account does not exist yet RECEIPT §3
1.6 Recycling triggers — exact "1 year inactive" / "cancelled" definitions, and whether recycling ever means true data purge §4 recycling RECEIPT §4
1.7 Notice body in Spanish or English Customer carries no language preference INSURANCE §1
1.8 How to model TRASPASOS PAYPAL — a clearing account, not a customer, carrying 7.03M MXN over 309 movements and therefore topping the adeudo worklist deliberately not special-cased in code RESUME §6
1.9 The 78 policyholders with no email — skip silently or produce a print worklist recommendation is the worklist INSURANCE §1

1.3 also needs the practical half: WSDL + credentials for server.anaseguros.com.mx/ananetws/service.asmx, whether a cartera download exists for an agent's own book, whether GMX daños has any machine interface at all, and whether one Grupo Valore credential spans both carriers. All four go in the same phone call — (55) 5480-4000.


2. Live data defects — open, and confirmed open today

2.1 policy_types is missing INCENDIO and M_EMPR, and 5 policies are orphaned

policyTypeId is String? with a plain relation, so Prisma's default is SetNull. The spec's recommended onDelete: Restrict was never applied. Five m_empr policies lost their ramo; four of them are pending liquidación and are invisible to every ramo-filtered query — including the pending report §2 is supposed to produce.

Fix alongside the liquidación work (3.1), since it distorts that feature's own report. Source: INSURANCE "Two defects found while verifying this spec".

2.2 ≤41 MULT second settlements were dropped in migration

MULT/INCENDIO carry two settlement slots and M EMPR carries four; Policy collapses to one. Spec recommends moving settlement onto PolicyPaymentInstallment rather than adding a second slot. Open sub-question: whether to backfill the lost rows.

2.3 Three dead tables

EmailTemplate, EmailCampaign and EmailLog exist in the schema with zero references anywhere in apps/api/src or apps/web/src. They were scaffolded for plan step 10's "email campaigns"; notificaciones shipped against email_notification_log instead. Either wire them or drop them — a schema that carries tables nothing writes teaches the next reader the wrong thing.


3. Spec'd, not built

# Item State Source
3.1 Liquidación batch workflow ~70% of the fields already wired end to end. 226 policies pending. Needs the ramo-parameterized pending report + POST /policies/liquidate-batch under a new policy:liquidate (MANAGER). Smallest remaining piece of step 12 INSURANCE §2
3.2 Certificate rendering The report half is buildable now off the same format: "letter" machinery as aviso-renovacion. Portal delivery waits on steps 8/9. Whole section waits on 1.2 INSURANCE §3
3.3 Carrier API integration Blocked on 1.3. ANA's SOAP service is real with a known operation list; GMX publishes nothing machine-readable and writes the larger half of this book INSURANCE §4
3.4 Customer-number recycling Not started. Customer.customerNumber does not exist in the schema. Backfill needs care: ~140 utilities rows and all insurance-only customers carry synthetic rownum_N/insrow_N placeholders, not real NUM ids. Last unbuilt piece of step 11 RECEIPT §4

Note 3.3 partly overlaps what POLICY_OCR.md already does — an OCR path that turns a carrier PDF into a Policy row covers some of what the API was wanted for, and unlike the API it is not waiting on a phone call.


4. Roadmap steps with no spec

# Item State
4.1 Step 8 — VPS provisioning Not started. Provider undecided (Hetzner vs DigitalOcean), size, Tailscale + MySQL replica. Pure ops; the design is settled. RESUME calls this the only genuinely blocking item left on the roadmap
4.2 Step 9 — sync worker Not built. Unblocked now that utility_dbo and the portal code are on disk, but depends on 4.1. Portal write points to poll: peticion_gas, PayPal payments, notifications_settings, verification_codes
4.3 Step 10 — reports / campaigns / admin Mostly done by other work. /reportes exists; "email campaigns" landed as /notificaciones against a different table (see 2.3)
4.4 Phase B sync in production Verified 32/32 against dev, never run from the /operaciones UI (the OpsService path) nor against a prod-shaped database

5. Gaps in features that already shipped

Each of these is a known, deliberate stopping point rather than a bug.

NotificacionesMASS_EMAIL_NOTIFICATIONS.md

  • No multi-replica lock on the servicios sweep (pólizas has one via scheduled_job_states). Safe only while the deployment stays single-replica.
  • No per-recipient preview of a sent body in the UI.
  • No SNS bounce/complaint webhook. providerMessageId is captured so one can be added.
  • No SKIPPED_NO_EMAIL worklist (see 1.9).

Policy OCRPOLICY_OCR.md

  • GMX only. The dispatcher is a [provider, pattern] table plus a parser map, so a second carrier is one function and two entries — but no other layout has been seen, and guessing produces a parser nobody can verify.
  • The recibo PDF is unread. The GMX certificate carries no premium at all; reading the separate receipt and pairing it to its certificate is what would let postPremium stop being a manual tick.
  • No versioning. A re-issued policy arrives as a new certificate with the same number and confirm updates the existing row. Nothing records that this is the 2027 issue of that policy.

Statement OCRSTATEMENT_OCR.md

  • CFE / CESPT / Telnor have no unit suite. They predate the gas/predial extension and were verified end to end against the 46-page corpus only. Close this if those parsers are ever touched.
  • No way to re-run a corrected parser over a stored batch, though the source PDFs are kept precisely so it is possible.
  • Handwritten folder numbers are deliberately not an input to matching (Tesseract read 405 as 205).

Bank — the concept→ramo classifier is won't-build, not pending. concepto is a payee name (0 of 22,354 match a category) and TABLA RAMODOS is a property-management expense chart, not the business-line split it was assumed to be. /banco intentionally has no category dimension. Recorded here only because bank_transactions.categoryId being null on every row otherwise reads as unfinished work.


6. Security / hygiene

  • The old repo's dbConnection.php has a plaintext MySQL password committed to git history. Not carried into this platform, but the credential is already exposed and has not been rotated. Rotate regardless of this repo.
  • The pre-migrate backup step sets NODE_TLS_REJECT_UNAUTHORIZED=0 because Portainer serves a self-signed certificate. Scoped to that one step; the real fix is replacing the certificate.

Source documents

Document What it carries
../PLAN.md build sequencing, locked decisions, per-step status
../RESUME.md session history and §6 open items
INSURANCE_FEATURES_SPEC.md §1 renewal emails (built), §2 liquidación, §3 certificate, §4 carrier APIs
RECEIPT_CAPTURE_SPEC.md §1 Editor (built), §2 OCR (built), §3 multi-bank (built), §4 recycling
MASS_EMAIL_NOTIFICATIONS.md mass email + schedules, as built
STATEMENT_OCR.md · POLICY_OCR.md the two OCR intakes, as built
DEPLOY_AND_MIGRATIONS.md release chain, galactus, known caveats