| PLUTO-112 |
pluto |
Live 500 on /informes — fn_getInformesBundle returns porAnestesia (and likely sibling array keys) undefined for sparse/zero-row scope; client .map crashes. PLUTO-97 regression. Fix fn to COALESCE every array key to [] + client null-guard. PTD must GET /informes for the failing scope, not log-tail. |
backlog |
urgent |
db-pluto-cc |
2026-06-14 05:24 |
| PLUTO-69 |
pluto |
Access regression: students who previously logged in are now blocked (agujero negro / blocked-user landing) - PROD, real users |
inProgress |
urgent |
coder-pluto-cc |
2026-06-12 17:29 |
| PLUTO-149 |
pluto |
SECURITY: isActive=false students NOT blocked — auth/callback + render path lack isActive gate; disabled+roled user with live session loads app |
backlog |
high |
coder-pluto-cc |
2026-06-19 19:31 |
| PLUTO-116 |
pluto |
Real-time error tee: appEvents AFTER-INSERT pg_notify trigger on Pluto Supabase (error→PM DM, warn stays in digest). GATED on nw-venus's exact spec (channel name, WHEN-clause, payload — byte-identical channel+payload across 3 apps; host listener LISTENs + DMs PM). Pluto level vocab = error|warn|info (NO fatal) so WHEN-clause = level='error'. Pre-apply audit review per DDL discipline. Additive/reversible. Do NOT start until spec lands + 112 done. |
backlog |
high |
db-pluto-cc |
2026-06-14 05:31 |
| PLUTO-102 |
pluto |
D8 Tier-1: collapse fan-out-vs-pool on 4 hot pages (admin/usuarios:97 8-wide, a-solucionar:37 6-wide, practicas:188/249, alumnos/[id]:86) via bundle-RPC/CTE per PLUTO-97 ↳#98 |
backlog |
high |
db-pluto-cc |
2026-06-14 03:20 |
| PLUTO-40 |
pluto |
Mobile-first refactor (Elazar all-app directive): audit + base-up redesign of layouts/nav/forms/touch-targets/breakpoints |
backlog |
high |
coder-pluto-cc |
2026-06-12 01:29 |
| PLUTO-147 |
pluto |
Disable never-logged-in students (year-end) so they drop from reports + regular screens |
backlog |
normal |
— |
2026-06-19 19:25 |
| PLUTO-146 |
pluto |
DB connection scaling: verify Supavisor txn-pooler + query-shape pass (pre-scale) |
backlog |
normal |
— |
2026-06-19 17:16 |
| PLUTO-145 |
pluto |
Per-agent git worktree / path-scoped add for coder-pluto + db-pluto on venus (end shared-checkout git-add-all race) |
blocked |
normal |
nw-venus-cc |
2026-06-16 17:24 |
| PLUTO-136 |
pluto |
PLUTO-133 follow-up (Elazar 5b, sequenced AFTER the main toast sweep ships): should-be-required / data-integrity candidates needing a verify pass then fix — (1) periodo date-range fechaFin<=fechaInicio unvalidated client+server; (2) practica rejection comentario not required; (3) destructive activo toggles (periodo/comision) no confirm dialog → toggle-off cascades; (4) admin create-user with no role → primaryRoleId NULL → blank-redirect login. Verify each path first (2nd-sweep agent guessed some), then fix. Do NOT start until PLUTO-133 main sweep is shipped. |
backlog |
normal |
— |
2026-06-15 16:33 |
| PLUTO-132 |
pluto |
feat(soporte): copy mars soporte into pluto |
deferred |
normal |
— |
2026-06-15 07:32 |
| PLUTO-129 |
pluto |
Hardening: roster-add forms allow adding a fraud-table membership into a NON-current/closed period — isPeriodoValid checks only deletedAt IS NULL, not isCurrent. Affects BOTH the new docente-detail add-form (PLUTO-128) AND the already-shipped list-page dialog (docentes/page.tsx) — PARITY, not a 128 regression. If cross-period roster-add is NOT an intended workflow (pre-stage future / correct past period), gate both forms on isCurrent. PENDING Elazar's intent call (is cross-period add a feature?). Surfaced by audit on PLUTO-128 pre-push review. |
backlog |
normal |
— |
2026-06-14 07:11 |
| PLUTO-126 |
pluto |
Email retry/failure backstop gap (pre-existing, exposed by PLUTO-38 cron-drop): after dropping the dead drain-email-outbox cron, Pluto has NO email retry and NO failure alert. A failed send (SMTP timeout) strands the row 'pending' forever — no retry, no operator alert (the alert-after-5-attempts only ever fired from the now-dead drain, which never functioned anyway). Invisible today (0 pending). Live happy-path = Next.js after()-hook send. Restore options: (a) pg_net+pg_cron */5 GATED drain (sanctioned path; vercel.json CANNOT host sub-daily cron — fails the whole build); (b) external scheduler; (c) minimum cheap win = alert-on-strand observability (appEvents warn when a row sits pending > N min). Disposition: reliability vs cron-cost — Elazar's call. Not urgent. |
backlog |
normal |
db-pluto-cc |
2026-06-14 06:50 |
| PLUTO-121 |
pluto |
KPI-rework /informes (gathering inputs, do NOT implement yet): teacher-scoped report quality pass. Inputs so far: (a) wrap bare CohortAndProcedureCards grid (teacher-report.tsx:818) in titled ReportSection; (b) Moda operador/asistente cards mislabeled (modal per-student count, not most-frequent person) + redundant beside Promedio -> cut or relabel; (c) EPI RE-WEIGHT: Puia wants MORE epidemiology on pluto+venus -> KEEP/EXPAND porSexo/porProvincia/etc (REVERSES earlier generic-remove rec; do NOT cut epi buckets). Grounding: judge on ACTUAL teacher-scoped values via audit-venus KPI->source-view map + db-pluto value pull, NOT admin-proxy shape. Awaiting full KPI->view map (~20-30min from audit-venus) + Elazar per-item rulings before WI splits into coder/db work. |
backlog |
normal |
— |
2026-06-14 06:25 |
| PLUTO-119 |
pluto |
Code sweep: retire stale eventType-based appEvents queries (pre-migration schema paths still running, 35-37ms × 112-257 calls/day). Surfaced in PLUTO-115 EXPLAIN. Find + update to the current level/category/action schema. Coder sweep. |
backlog |
normal |
— |
2026-06-14 05:55 |
| PLUTO-117 |
pluto |
Harden getInformesBundle fn-output↔consumer contract (durable fix beyond the 112 runtime guard). Root lesson: Pluto's fn emits UNTYPED jsonb (jsonb_build_object) that TS only CASTS — a key rename (porLookup vs porAnestesia) compiles clean and crashes at runtime. A bare 'as' cast gives FALSE confidence (compiles while runtime JSON lacks the key). Fix: zod-parse (or equivalent runtime validate) the RPC return at the queries.ts:3897 boundary so fn↔consumer key drift fails LOUDLY at the boundary with a clear error, not a deep .map crash. Contrast venus: its reshapes build typed objects in TS code, so key drop fails COMPILE — Pluto's SQL-built JSON can't be compile-checked that way, hence runtime validation. |
backlog |
normal |
— |
2026-06-14 05:33 |
| PLUTO-101 |
pluto |
D8 views+indexes (db lane): a-solucionar 6-scan view, academic-hierarchy + practicas team-stats/hierarchy views; verify 8d index candidates (deletedAt partial, periodoId, assignment*Id, comisionId/jtpId/adjuntoId, appEvents.createdAt, authId) vs actual index inventory ↳#98 |
backlog |
normal |
— |
2026-06-14 03:20 |
| PLUTO-99 |
pluto |
D8 Tier-2: compute-in-Node over DB rows (cron practicas-kpi-report:277/330/146/208, legacy-export-actions:68-88, hierarchy-utils:22-74/team-stats) -> SQL GROUP BY/ORDER BY ↳#98 |
backlog |
normal |
— |
2026-06-14 03:20 |
| PLUTO-98 |
pluto |
PLUTO D8 compute-placement remediation (self-scan) |
backlog |
normal |
— |
2026-06-14 03:20 |
| PLUTO-82 |
pluto |
Historial de cambios rows appear duplicated (~4x) on practica change history; investigate root cause (view join fan-out / archive double-write / query) and fix at source - data should not be stored 4x |
backlog |
normal |
— |
2026-06-13 08:14 |
| PLUTO-81 |
pluto |
PLUTO-77 v1 LOW followup: comision-day secondary list capped at limit-200 first-page (no cursor pagination); add cursor paging if an ayudante's assisted-comision roster exceeds 200 |
backlog |
normal |
— |
2026-06-13 07:40 |
| PLUTO-78 |
pluto |
Duplicate practicas: operador + asistente each create the SAME clinical event picking each other as counterpart -> 2 mirror practica rows for 1 real práctica. Need duplicate-detection + canonical-record rule (natural key candidates: fecha+comision+paciente/tratamiento+the operador/asistente pair). Design WITH Elazar; covers (a) prevent new dupes at create, (b) reconcile existing dupes in prod. Cross-team lessons-learned for mars/venus. |
backlog |
normal |
— |
2026-06-13 05:59 |
| PLUTO-73 |
pluto |
conform appEvents to fleet SSOT (categoryId FK, promoted cols, append-only+GUC, appEventRelays sidecar, retention guard, logger, views) |
blocked |
normal |
— |
2026-06-13 02:32 |
| PLUTO-68 |
pluto |
/practicas/nueva form: lay fields side-by-side to save vertical space (currently stacked one-below-the-other) |
inProgress |
normal |
coder-pluto-cc |
2026-06-12 17:24 |
| PLUTO-61 |
pluto |
Stop writing dot-stripped gmail form to users.email (commons Email-Norm violation, cosmetic) |
backlog |
normal |
— |
2026-06-12 06:34 |
| PLUTO-53 |
pluto |
404: /notificaciones dead route — UI link points to nonexistent page (active Jun 3+9) |
backlog |
normal |
— |
2026-06-12 05:50 |
| PLUTO-46 |
pluto |
Vercel log-drain setup: Elazar greenlit (2026-06-12) true 24h+ runtime-log retention (currently logs are point-in-time only via Vercel MCP). Scope: pick drain destination (log service/endpoint), configure Vercel log-drain, implementer is infra (nw-whey/nw-venus) not coder. PM owes Elazar the concrete scoped plan before dispatch. |
backlog |
normal |
— |
2026-06-12 03:35 |
| PLUTO-44 |
pluto |
Defense-in-depth: render-path requireCapForAction throw should render graceful acceso-denegado, not 500 + admin error-email storm (generic error-boundary / convert render-path cap checks to redirect variant). Surfaced by PLUTO-43 (dead-fetch was the trigger; this guards the class). |
backlog |
normal |
— |
2026-06-12 01:54 |
| PLUTO-42 |
pluto |
/practicas mobile card is read-only: teachers cannot change practica estado/grade from a phone — handleChangeEstado control is desktop-table-only; add it to the md:hidden mobile card |
backlog |
normal |
— |
2026-06-12 01:44 |
| #602 |
pluto |
Prácticas rectificar + bidirectional comment/email-notification workflow (port/adapt from Mars) |
blocked |
normal |
evolutiva-pm-cc-w |
2026-06-01 22:02 |
| #490 |
pluto |
Plan: paciente DNI + HC central store — autocomplete, dedup warning, estadísticas |
blocked |
normal |
— |
2026-05-25 02:04 |
| #58 |
pluto |
CR 39: Crear una sección interna accesible para usuarios autenticados con manual de uso, SOP operativos y ayudas de carga/revisión. Debe poder crec |
blocked |
normal |
— |
2026-05-18 10:06 |
| #133 |
pluto |
/administrar/comisiones spreadsheet grid — Stage 4 editable comisión/day rows por período |
blocked |
normal |
— |
2026-05-18 10:06 |
| #61 |
pluto |
CR 42: 3 docentes reales sin asignación a comisión: gonzalo.oviedo, lorena.salomone, cirugia1 (@odontologia.uba.ar). Necesitan ser asignados a comi |
blocked |
normal |
— |
2026-05-17 20:47 |
| PLUTO-148 |
pluto |
appEvents off-schema categories: 'toast' (53) + 'admin' (3) not in valid category list; logging hygiene |
backlog |
low |
— |
2026-06-19 19:29 |
| PLUTO-139 |
pluto |
DB-health sweep follow-ups (from PLUTO-138, non-urgent): (1) verify practicas.idx_practicas_editlocked query path — drop if genuinely cold; (2) confirm userAuditLogLegacy table is retired → archival candidate (table+idx); (3) FK-usage audit: of 64 advisor-flagged unindexed FKs, identify which appear in live WHERE/JOIN (hot) vs audit/write-path (createdBy/deletedBy/archivedBy — leave cold), index only the hot ones via migration w/ archive-context. Don't index/drop blindly — query-path verify first. |
backlog |
low |
coder-pluto-cc |
2026-06-16 02:39 |
| PLUTO-125 |
pluto |
Advisory (low pri): enable auth_leaked_password_protection (HaveIBeenPwned check) in Supabase auth — currently disabled. Low value for Pluto (allowlist-only, no open signup) but a free defense-in-depth toggle. From PLUTO-123 security sweep. |
backlog |
low |
— |
2026-06-14 06:44 |
| PLUTO-120 |
pluto |
Phase-2 demo cleanup (BLOCKED on demo-row purge): strip the now-unneeded demo filters/labels/tab once Elazar purges demo rows. These are PROTECTIVE while rows exist — removing earlier leaks demo data into real reports. Sites: admin/page.tsx:11 (@demo pendingUsers filter), informes/page.tsx:117-121 + practicas/page.tsx:139-142 ('Demo ' comision filter), admin-user-detail.tsx:68/127 + audit-log.tsx:122 (isDemo/demo_seed label map), complication-rate/dificultad-distribution/procedure-type cards '(no demo)' text, admin/usuarios 'Usuarios demo' tab. Coupled to PLUTO-118 phase-1 + the row purge. |
backlog |
low |
— |
2026-06-14 06:00 |
| PLUTO-113 |
pluto |
Dead-code removal: softDeletePeriodo + softDeleteComision (admin-actions.ts:443/534) are exports with ZERO callers; live paths are removePeriodo/removeComision. Remove the dead exports. |
backlog |
low |
— |
2026-06-14 05:25 |
| PLUTO-111 |
pluto |
Observability: log /api/image 401/403 auth-denials to appEvents (category auth/authz, level info) so denial-storms are diagnosable; route currently logs only proxy-failures, not the gate denials |
backlog |
low |
coder-pluto-cc |
2026-06-14 05:18 |
| PLUTO-103 |
pluto |
Hygiene: vPracticaParticipantFacts counts demo-practica-by-real-student in scoped teacher stats (pre-existing, surfaced during PLUTO-97 gate-A) |
backlog |
low |
— |
2026-06-14 03:30 |
| PLUTO-100 |
pluto |
D8 Tier-3: batch sequential per-row write loops (personas-actions:378/388 role add/remove) into set-based INSERT VALUES / UPDATE WHERE id=ANY ↳#98 |
backlog |
low |
— |
2026-06-14 03:20 |
| PLUTO-91 |
pluto |
PLUTO-89 fast-follow hardening: multi-pieza dup-guard is order-sensitive ('11,12' vs '12,11' evades tier-1 because piezas keep insertion order). Canonicalize the pieza set for the dedup KEY only (sorted), preserving as-entered display/storage order. Needs functional index or normalized key column |
backlog |
low |
— |
2026-06-13 10:57 |
| PLUTO-85 |
pluto |
public/formulario-practica.pdf rides unrelated commits — byte re-touch (identical size, no content change) re-touches in the push window, not present in pre-push git status. Recurring since PLUTO-77, again on PLUTO-84. Find what regenerates it (build step / file watcher) and either .gitignore it or normalize so it stops riding unrelated commits. Harmless but persistent noise. |
backlog |
low |
— |
2026-06-13 09:29 |
| PLUTO-67 |
pluto |
fn_detectRateSpike cadence: every-2min cron is 91% of DB-time (frequency-driven, ~7.6s/day absolute) - weigh fraud-detection latency vs cost |
backlog |
low |
— |
2026-06-12 07:53 |
| PLUTO-66 |
pluto |
log-toast ingest: no server-side rate limit (anon-flood appEvents amplification) |
backlog |
low |
— |
2026-06-12 07:26 |
| PLUTO-65 |
pluto |
PLUTO-34 contract step: DROP flat columns on 7 archive tables after jsonb expand verified in prod (irreversible) |
backlog |
low |
— |
2026-06-12 07:12 |
| PLUTO-60 |
pluto |
Retire residual /login?error=no-profile UI path |
backlog |
low |
— |
2026-06-12 06:26 |
| PLUTO-59 |
pluto |
Convenience VIEW joining clientError.digest -> serverError.detail (full message+stack) for client-error diagnosis |
backlog |
low |
— |
2026-06-12 06:17 |
| PLUTO-58 |
pluto |
Table convergence: drop server page-size oddball 15 (->[10,25,50,100] fleet baseline); later adopt Mars-style column-config API over Pluto server stack |
backlog |
low |
— |
2026-06-12 06:09 |
| PLUTO-57 |
pluto |
UX: pre-filter practica list-row links by viewer scope so out-of-scope rows aren't clickable (avoids working-as-designed scope-deny on /practicas/[id]) |
backlog |
low |
— |
2026-06-12 06:08 |
| PLUTO-51 |
pluto |
Proxy viewport tooling: chrome-devtools-mcp (CDP) for Pluto needs an auth path — Pluto is OAuth-only |
backlog |
low |
— |
2026-06-12 04:21 |
| PLUTO-45 |
pluto |
KPI weekly-cron staleness alert: last-success-timestamp check that pages if no kpiCronReport appEvent in >8 days. Weekly crons (0 9 * * 1) can fail silently for ~7d before anyone notices (PLUTO-39 showed how easily a weekly gap reads as 'dead'). Defensive observability add, NOT a bugfix. Touches email/alert path → audit pre-push. |
backlog |
low |
— |
2026-06-12 03:17 |
| PLUTO-41 |
pluto |
Migrate all touch primitives (Button/Select/Input) to uniform pointer-coarse:min-h-11 for 44px touch targets — replaces the 3-way convention (Button h-11 sm:h-9 / Select flat h-11 / Input sm:-gated); keys on input modality not viewport so a narrowed desktop window stays 36px. Ref Venus impl. Do AFTER PLUTO-40 lands. |
backlog |
low |
— |
2026-06-12 01:39 |
| PLUTO-36 |
pluto |
Pluto P3: canonicalizeEmail JS/DB parity edge — JS lastIndexOf('@') vs DB SPLIT_PART first-'@'; diverge only on malformed multi-@ input (dedup-parity, not dot-strip). Align the @-split semantics. |
backlog |
low |
— |
2026-06-10 13:16 |
| PLUTO-32 |
pluto |
Pluto P3 residual: bulkInviteUsers welcome-email loop bypasses the /send-email HTTP rate limiter (PLUTO-20) — uncapped in-process sends on bulk invite. Decide cap (e.g. 100/batch or inter-send delay) vs accept (admin-initiated, low-freq, in-process-mail-undroppable per PLUTO-20 design). From audit round-1. |
backlog |
low |
— |
2026-06-10 06:37 |
| PLUTO-31 |
pluto |
Pluto P3: cold audit FK cols (createdBy/updatedBy) unindexed — defer to post-go-live advisor run |
backlog |
low |
— |
2026-06-10 05:12 |
| PLUTO-30 |
pluto |
Pluto P3: periodos.isCurrent no uniqueness constraint — two isCurrent=true rows possible |
backlog |
low |
— |
2026-06-10 05:12 |
| PLUTO-29 |
pluto |
Pluto P3: vPracticas* views don't filter isDemo — demo inflates grader stats (fix at vPracticas base) |
backlog |
low |
— |
2026-06-10 05:12 |
| PLUTO-28 |
pluto |
Pluto P3: denyAccess UUID-in-URL + deny-vs-404 — practica-existence probe |
backlog |
low |
— |
2026-06-10 05:12 |
| PLUTO-27 |
pluto |
Pluto P3: getCurrentPeriodoId + getComisionesForCurrentPeriodo no auth guard — comision enumeration |
backlog |
low |
— |
2026-06-10 05:12 |
| #119 |
pluto |
User contact profile split — userProfile 1:1 table para campos opcionales |
blocked |
low |
— |
2026-05-18 08:48 |
| #372 |
pluto |
DEFERRED: extract userDocumentoReview workflow table from users.documento* cols if documento approval flow grows. Workflow entity with natural FK, not generic profile split. Counter to WI#119 verdict. |
backlog |
someday |
— |
2026-05-15 07:20 |
| #100 |
pluto |
Análisis estadístico — rol researcher dedicado + acceso a datos anonimizados |
backlog |
someday |
— |
2026-05-01 01:56 |