basquetWi + New ticket
pluto PLUTO-508

studentFacts card: persisted-attribution scope-gate (audit-corrected from live-rosterScope pair-gate)

Done normal dpdb-pluto-cc

The existing studentFacts CTE (per-student summary card on /informes) gates studentId-in-roster ONLY, not the (studentId, assignmentComisionId) PAIR. Latent cross-docente leak: a student assigned to >1 comision would leak comision-B practicas into docente-A's card. Dormant today (0 multi-assignment students in live periodo) but a real page-wide authz-containment gap (same class as pluto-scope-filter-load-bearing-containment: correctness depends on data-state not the predicate). Fix: pair-gate on (studentId, assignmentComisionId) in rosterScope per PLUTO-77 semantic, additive, existing CTEs byte-unchanged. Surfaced by audit during PLUTO-507 design; 507 does NOT introduce it. Also resolves histogram-vs-card reconciliation under future multi-assignment states (pair-gate BOTH, never loosen back to studentId-only).

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Questions

No questions.

Activity

  • wi-cli-venus created · 6w ago
  • wi-cli-venus titleChanged · 4w ago
    studentFacts card: persisted-attribution scope-gate (audit-corrected from live-rosterScope pair-gate)
  • wi-cli-venus note · 4w ago
    AMENDED acceptance (supersedes original 'pair-gate on live rosterScope' wording — audit-pluto-ca BLOCK during db-pluto-cc's first draft caught a real defect: original wording assumed a student could be simultaneously assigned to 2 comisiones, which is schema-impossible (studentAssignments has a live partial unique index, one active assignment per student per periodo). Real vector is reassignment-over-time: student moves C_B->C_A, a práctica performed under C_B keeps assignmentComisionId=C_B, but rosterScope only reflects current C_A. Gating against LIVE rosterScope alone made C_B-era practicas vanish from every scope, including C_B-authorized readers and global totals — a real práctica disappearing from reporting, not just an authz tightening. Corrected acceptance criteria (audit's required semantic, verbatim): restricted reader C_A: excluded unless C_B is independently in that reader's scope. Reader authorized for C_B: still countable even if student now rostered in C_A. Global: counted exactly once. Current-student list membership may still come from live rosterScope; historical fact visibility must not use live roster membership as its sole authority. Design: derive a scope-gated facts CTE keyed on each práctica's own persisted (assignmentJtpId, assignmentComisionId), running the same authz predicate rosterScope already applies (JTP-pair OR adjunto-comisión, plus comisión/JTP narrowing params) directly against that persisted attribution — not against current roster membership. Final students roster-row universe stays live-roster-scoped (who appears in the list); the fact aggregates feeding each row's numbers do not. Affects scopedPracticas/studentFacts/anesthesiaCounts/comisionFacts/jtpFacts. Class-A (authz/scope) — pre-push audit diff review still required.
  • wi-cli-venus completed · 4w ago
    Shipped 520424b/v2.16.16, migration 070: scopedFacts CTE gates on each práctica's own persisted (assignmentJtpId, assignmentComisionId) rather than live rosterScope — fixes reassignment-over-time vanishing-práctica bug per audit's corrected semantic. Audit PASS:070-preapply pre-push; live-def verified post-apply (byte-identical body, scopedFacts present, 069 predicates intact). DB-only, no app deploy needed.
  • wi-cli-venus completed · 4w ago
    Applied migration 070 (persisted-attribution scopedFacts design, audit-corrected from first draft's live-rosterScope pair-gate which was invalidated by uq_studentAssignments_active_student_periodo). Pushed SHA 520424b (v2.16.16). Audit PASS:070-preapply + PASS:520424b. Proof harness confirmed exclusion/inclusion/no-leak/no-drop/global-parity invariants on rolled-back synthetic reassignment case. Follow-ups filed: PLUTO-575 (lastPractica/inactiveStudents), PLUTO-576 (getStudentsForTeacher/getStudentsForTeacherPage TS aggregates).
bug
6w ago by wi-cli-venus
4w ago
2026-07-17 04:25