DataTalksClub / DataTalksClub/website
Preserve cohort score breakdowns, leaderboards, privacy, and complaints
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Parent epic: #5. Downstream certificate/graduate consumer: #58. Final management parity: #59. Production-like rehearsal: #60.
PM disposition
GROOMED / P0 / DEPENDENCY-BLOCKED. Do not dispatch engineering.
This issue preserves the adopted cohort scoring aggregation, leaderboard, pseudonymous visibility, score-breakdown, and complaint behavior after the Course → Cohort and homework/project service migrations. It also supplies one exact, PII-free completion/eligibility result to #58. It does not redesign homework or project scoring, issue certificates, export PII, send email, inspect protected data, or execute a production migration.
Normative authority
_docs/PROCESS.md04 — Enrollment/certificates, preserved learner behavior, Studio coverage, migration checks06 — Studio/admin API registry, authorization, revisions, operations, and audit07 — learner privacy, retention, high-risk grading repair, cache, and redaction09 — course migration, score reconciliation, and rollback10 — Course/Cohort and management verification- resolved owner decisions #23 and #28
- accepted copied-source characterization/provenance baseline #30
Adopted inputs; no second scoring algorithm
#55 owns the authoritative homework-submission component result and #56 owns the authoritative project-submission component result, passed result, volunteer-review disposition, and project/review lifecycle. #57 consumes those accepted results; it never recalculates answers, rubric responses, peer-review points, FAQ/learning-in-public points, caps, or pass/fail independently.
For one accepted Cohort and Enrollment:
homework_totalis the sum of the accepted #55Submission.total_scorevalues belonging to that exact Cohort/Enrollment;project_totalis the sum of the accepted #56ProjectSubmission.total_scorevalues belonging to that exact Cohort/Enrollment wherevolunteer_review_onlyis false;total_score = homework_total + project_total; missing component rows contribute zero, while an unknown, malformed, stale, duplicated, quarantined, or cross-Cohort component blocks the result rather than being guessed or moved;passed_project_countcounts accepted #56 non-volunteer project submissions whose accepted result ispassed=true; andeligible = passed_project_count >= Cohort.min_projects_to_pass. The threshold must be positive. Total points, rank, complaint state, visibility, certificate presence, and volunteer-only reviews do not independently create graduate/certificate eligibility.
The accepted #55/#56 rules for disable_learning_in_public determine their component totals. Toggling that preference does not edit a #57 total directly: it uses the owning #55/#56 services and then produces a new #57 result/recomputation revision.
Exact score, completion, and ranking result
The shared courses query/service returns one immutable, PII-free CohortCompletionResult per Enrollment with exactly:
- schema version and stable
result_key; - Course UUID, Cohort UUID, Enrollment UUID, and retained Enrollment ordering identity;
- activated Cohort score revision;
homework_total,project_total, andtotal_score;passed_project_count, positiverequired_project_count, and booleaneligible;- ordered #55/#56 component-result fingerprint and scoring/settings fingerprint; and
- reconciliation disposition plus calculated timestamp as metadata, neither of which changes the logical result identity.
result_key is deterministic over the schema version, exact Course/Cohort/Enrollment identities, accepted ordered component-result identities, and the score/completion settings revision. Exact replay returns the same key and values. Any component, threshold, scope, or schema change produces a different result key and a new Cohort score revision. A stale, unactivated, quarantined, or foreign result cannot authorize a downstream action.
Leaderboard recomputation ranks every Enrollment in the Cohort, including zero-score and display_on_leaderboard=false records, by total_score descending and retained Enrollment database identity ascending. Positions are sequential 1..N; equal totals do not share a position. Migrated rows retain the source ordering identity accepted by #244, and new rows use the same final Enrollment identity order—never username, email, display name, insertion order from an unordered query, or a random tie break.
A recomputation stages one complete cohort revision and activates totals, positions, completion results, projection version, and cache-invalidation intent atomically. Readers see either the prior complete revision or the new complete revision, never mixed enrollment rows. Exact command replay returns the original operation/result; changed replay conflicts. Concurrent component mutation or settings drift makes the candidate stale and leaves the prior revision active. Long/full-cohort work is a durable bounded operation with progress, per-row safe errors, cancellation before activation, crash/resume fencing, and no request-thread bulk loop.
Preserved learner and public behavior
The final route identity comes from accepted #53/#244. Under the canonical Cohort base, preserve the leaderboard collection, one retained-Enrollment score breakdown, and authenticated complaint form; preserve every reviewed legacy alias/API route through the accepted compatibility boundary.
Visibility is exact and Cohort-specific:
display_nameremains the generated pseudonymous leaderboard label; it is not replaced by account email/name or an editorial Person;display_on_leaderboard=falseexcludes the Enrollment from public leaderboard collections and public YAML/data listings but does not remove it from scoring/ranking, change its stored position, or copy the choice to a sibling Cohort;- the adopted direct score-breakdown route remains pseudonymous, public, noindex, and zero-TTL/no-store, including for an unlisted Enrollment;
display_public_profilealone controls whether the characterized public profile relationship is shown; - the signed-in owner may see their own unlisted status and preferences without being inserted into a public cached collection; and
- a preference change invalidates only the affected Cohort projection. Anonymous/public output contains no email, account name, certificate name/destination, complaint text, learner-submission free text, private profile value, or cross-Cohort state.
This is preservation, not an intentional visibility change. If the accepted #244 characterization contradicts any route-level disposition above, engineering stops and returns both issues to PM; it does not silently tighten or broaden access.
Collection ordering, pagination, breakdown equations/component links, empty/unranked states, current-learner navigation, cache refresh, and configured public-profile behavior remain characterized. Reads are side-effect free and never create an Enrollment, score result, complaint, or profile relation.
Complaint lifecycle and repair boundary
A signed-in learner may create a complaint against one score-breakdown record in the resolved Cohort. Input is one exact issue type (learning_in_public, homework, project, or other) plus trimmed escaped plain-text description of 1–2,000 characters. Scope is resolved before record lookup. Anonymous, foreign-Cohort, malformed, oversized, or unavailable targets fail safely without exposing learner/account identity.
The adopted lifecycle is exactly open → resolved. Separate reports remain separate records; only an exact idempotent API replay returns the original record. There is no learner withdrawal, reopen state, deletion, or inline score mutation. Repeated resolve is allowed only as exact replay; otherwise it conflicts. Resolution requires current revision, the #52 complaint-resolution capability, a bounded reason, an explicit outcome (no_change, corrected, duplicate, or invalid), and redacted audit. corrected also records the already-completed #55/#56 repair operation/result identity; if repair fails or remains pending, the complaint stays open. Complaint resolution itself never changes a component score or #57 total.
Complaint descriptions/evidence are private learner/authorized-operator data. Public pages and exports show no complaint existence or text. Studio/admin API apply authorized Cohort scope before lookup, mask learner identity by default, and audit only safe actor/principal reference, complaint/Cohort/Enrollment UUIDs, outcome, reason code/digest, revision, request/correlation/idempotency IDs, and timestamps—not the description, evidence, email, display/profile/certificate value, submission/review content, or repair payload.
Shared management interfaces
Register at least these exact capabilities through the accepted #52 policy:
courses.leaderboard.view;courses.leaderboard.recompute;courses.completion_result.view;courses.leaderboard_complaint.view; andcourses.leaderboard_complaint.resolve.
Studio and /api/v1/admin/ use the same courses query/command services for leaderboard/result inspection, recomputation operation creation/status, complaint list/detail, and resolution. Admin resources use UUIDs; mutations require revision/If-Match, Idempotency-Key, allowlisted bodies, generic scope-first errors, and the accepted #28/#52 confirmation/reauthentication/audit behavior where grading repair or bulk activation is high risk. No adapter, compatibility view, signal, task, or Django-admin action writes score/position/complaint state directly.
The public/learner compatibility schemas remain source-characterized. #57 does not add PII to them or turn the token-protected graduates endpoint into the target export; #58 consumes the result below through #245's masked/export boundary.
Exact handoff to #58
#58 consumes the current activated CohortCompletionResult, not a fresh adapter-side query and not certificate presence. Certificate first issue and graduate selection must verify the exact Course/Cohort/Enrollment, schema version, result_key, activated Cohort score revision, component/settings fingerprint, passed_project_count, required_project_count, and eligible=true.
#58 snapshots the accepted result_key as its eligibility evidence. A stale/foreign/quarantined result or eligible=false denies issue. A later #55/#56/#57 result change does not silently revoke, replace, or rewrite an issued certificate; any exceptional follow-up uses #58's explicit lifecycle. Graduate selection uses current accepted results and #245 authorization/masking/export controls. This handoff contains no email, real name, certificate name/destination, template, sender, preference, delivery, or provider state.
Migration, reconciliation, and evidence identity
Repository verification uses deterministic synthetic fixtures only. #60 owns any authorized protected production-like rehearsal and cutover.
The engineer handoff freezes and records:
- full base/head SHAs and change-selective graph/plan/report digests;
- adopted source pin
98a235283904b4ef9ad29e196298540756cf1bcc, #30 copied-file manifest digest, and integration-patch-ledger digest; - exact prerequisite merge SHAs, migration leaves, and schema/migration-plan fingerprint;
- #51/#53 Course/Cohort/route/legacy-alias fingerprint and #244 Enrollment identity/visibility/preservation fingerprint;
- #52 capability/policy/registry/OpenAPI fingerprint;
- #55 homework-result schema plus characterized-fixture checksum and #56 project/result/pass/volunteer schema plus characterized-fixture checksum;
CohortCompletionResultschema/result-key policy, leaderboard projection/order/cache schema, and complaint lifecycle/reason/audit schema versions; and- #58 consumer-schema fingerprint current at dispatch.
Synthetic preflight/dry-run/apply/exact replay/reverse/forward reports source/target Cohort and Enrollment counts, component/result cardinalities, hidden/visible/profile combinations, total/position/tie/eligibility matrices, complaint state/outcome counts, legacy-ID→target mapping cardinalities, transformed/rejected/quarantined rows, and safe non-PII checksums. It preserves source totals, sequential positions, complaint ownership/state/timestamps, display preferences, and sibling-Cohort isolation. Unknown mapping, duplicate logical component/result, cross-Cohort relation, invalid threshold, unsupported complaint state, or unexplained score/rank/eligibility drift fails closed and leaves the prior revision active. Reports contain no reversible learner identifier, display name, complaint text, profile/certificate value, or production data.
Dependencies and readiness
Accepted baseline inputs are #23, #28, #30, and #31.
Engineering hard-depends on accepted and integrated:
- #52 — exact Course/Cohort authorization, assignment, object/field policy, management registry, and audit boundary;
- #53 — final Cohort lifecycle plus canonical/legacy route and alias identity;
- #244 — final cohort-isolated Enrollment identity, display/visibility/preferences, learner history/dashboard routes, and preservation/migration mapping;
- #55 — accepted homework component/scoring/reconciliation result; and
- #56 — accepted project/review component, volunteer disposition, pass/fail, and reconciliation result.
#224/#51 are transitive through #53/#244. #32/#33/#40/#288 are transitive through #52/#244. #230/#231/#234/#242/#243/#247/#248 are transitive through #244/#56. Broad parent #54 is a coordination epic, not a dependency. Open dependency state still blocks an interface; a local candidate or partial current-main model does not imply acceptance.
#58 consumes the accepted completion result and is downstream. #59 completes later broad management parity and #60 consumes migration/compatibility evidence for protected rehearsal; neither blocks this bounded source contract. #64 remains the shared legal-rights/tombstone boundary and is not reimplemented here.
Readiness remains GROOMED / DEPENDENCY-BLOCKED. After all five hard inputs are accepted and integrated on one green current-main base, PM must revalidate the frozen identities above and #58's consumer schema before an isolated engineer lane starts. Any prerequisite, schema, migration, capability, visibility, source-pin, or consumer drift returns #57 to PM.
Acceptance criteria
- The service consumes only accepted #55/#56 component results and reproduces exact homework/project/total score, passed-project count, positive threshold, and eligibility semantics without a second scoring/pass algorithm.
-
CohortCompletionResulthas the exact PII-free schema and deterministic result identity; exact replay is stable, changed/stale/foreign/quarantined input fails safely, and #58 can validate it without querying component tables directly. - Complete cohort recomputation is idempotent, concurrency-safe, durable when long, atomically activated, crash/resume safe, and never exposes mixed total/rank/result/cache revisions.
- Every Enrollment is ranked by total descending then retained Enrollment identity ascending with sequential positions; zero, hidden, equal-score, new, migrated, and sibling-Cohort cases preserve exact deterministic behavior.
- Display-name, leaderboard visibility, public-profile, owner-unlisted, breakdown, public YAML/data, cache, noindex/no-store, and sibling-Cohort behavior match the exact preserved contract without PII exposure.
- Complaints enforce the exact four issue types, bounded safe input, open→resolved terminal lifecycle, separate-report/exact-replay behavior, repair separation, resolution outcome/reason/revision, authorization, redaction, and audit.
- Studio/admin API/public compatibility adapters have service, capability, scope, revision, idempotency, operation, result/error, audit, OpenAPI, and cache-invalidation parity; no adapter writes domain state directly.
- Synthetic migration/reconciliation preserves mappings, totals, rank order, visibility, complaints, eligibility, timestamps, and checksums; all named corruption/drift cases fail closed with no outbound work, while protected rehearsal remains #60.
- Focused model/service/migration/API/security/concurrency/adoption tests plus graph-selected full verification pass on one frozen candidate; the independent tester inspects every required desktop/mobile screenshot before PM acceptance.
Required verification scenarios
- Zero/one/many homework and project components; volunteer-only project; passed/not-passed/boundary threshold; learning-in-public enabled/disabled; exact replay; changed component/settings; stale and cross-Cohort result.
- Equal totals, zero totals, null legacy position, hidden/unhidden, profile linked/unlinked, migrated/new Enrollment ordering, sibling Cohorts, concurrent score writes, worker crash before/after staging, stale activation, cancellation, cache/projection consistency.
- Anonymous, owner, another learner, unlisted Enrollment, configured public profile, direct breakdown, unknown/foreign IDs, public HTML/YAML/data, private Studio/API, warmed-cache canaries, and proof that reads create no state.
- Complaint valid/invalid issue type, empty/2,000/over-limit/Unicode/control input, separate duplicate reports, exact/changed replay, unauthorized/cross-Cohort target, resolve outcomes, missing/pending/completed repair reference, repeated resolve/reopen/delete denial, stale revision, concurrent resolution, and audit/log/export canaries.
- Studio/admin API allowed/denied/masked actors, stale
If-Match, idempotency conflict, bulk limit/partial result, operation progress/cancel/result, service parity, private/no-store/noindex, CSRF/Bearer separation, OpenAPI/registry coverage, and no direct model mutation. - Source-characterized and synthetic migration dry-run/apply twice/reverse/forward with missing/duplicate/cross-Cohort component, invalid threshold, unsupported complaint state, mapping drift, checksum drift, and all outbound Datamailer/Relay/SES/provider paths patched to fail if called.
- #58 contract test accepts only the current exact eligible result, rejects ineligible/stale/foreign/quarantined/schema-drifted results, snapshots the result key, and proves later score change has no implicit certificate mutation.
Independent browser evidence
Using synthetic .invalid fixtures at approximately 1440×900 and 390×844, the separate tester captures and reads:
- populated, tied-score, and empty leaderboard states with deterministic order/pagination/current-learner navigation;
- visible and unlisted owner preference states before/after save plus public collection/YAML absence for the unlisted record;
- pseudonymous score breakdown with component equations, configured public-profile link, no-profile state, and direct foreign-Cohort safe denial;
- complaint create validation/success and terminal resolved state;
- authorized and denied/masked Studio complaint list/detail/resolution; and
- recomputation preview/confirmation/progress/success, stale/conflict/failure states, and unchanged prior revision before activation.
Include keyboard-only operation, visible focus/status/error announcement, 44 CSS px targets, 200% zoom and 320 CSS px reflow, reduced motion, and supported JavaScript-disabled form/confirmation/error paths. Every screenshot must show the intended page rather than a debug/404/broken layout and contain no real or unnecessary synthetic learner identity, complaint text, profile/certificate value, credential, provider, or production data.
Explicit non-goals
- No homework answer/rubric/peer/vote scoring formula, project pass algorithm, Course/Cohort/Enrollment identity, registration/enrollment conversion, profile schema, certificate lifecycle, generic masked export infrastructure, notification, template, sender, preference, delivery, Relay/Datamailer/provider, or production migration behavior.
- No cross-Cohort leaderboard, shared position, score normalization, tied rank, new completion rule, complaint withdrawal/reopen/deletion, inline complaint score edit, new public identity field, learner-work disclosure, or intentional visibility change.
- No production/protected data or credentials, PII export, live migration/import, email/network side effect, deployment, workflow dispatch, commit, merge, or push during PM/engineering/tester gates.
Lifecycle
After prerequisites integrate, one engineer leaves an uncommitted frozen candidate and complete versioned verification report. A separate tester recomputes the plan, verifies every criterion, and captures/inspects the required screenshots. PM then performs product acceptance. Only after both gates pass may the engineer create a focused Closes #57 commit; the orchestrator locally merges with --no-ff, pushes, and on-call alone observes terminal CI.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Do not start implementation: the issue is explicitly dependency-blocked and says not to dispatch engineering. First read _docs/PROCESS.md and the linked specs 04, 06, 07, 09, and 10, then review prerequisites #52, #53, #55, #56, and #244; work is done only when the shared courses services, atomic cohort revisions, privacy and complaint behavior, and exact #58 handoff are verified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- api, backend, database, security, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 18/100