Implementation PR Roadmap
This chapter breaks down the Registration system into small, reviewable pull requests. It complements the Implementation Plan with concrete PR scopes, dependencies, and acceptance criteria.
Guiding principles:
- Keep PRs tight and shippable behind feature flags.
- Prefer vertical slices that produce visible value.
- Add tests and docs incrementally with each PR.
Plan ↔ PR crosswalk (Registration workstream):
- Step 2 — Foundations (schema/backend): PR-2.x
- Step 3 — FCFS mode (admin + student): PR-3.x
- Step 4 — Preference-based mode (student + allocation): PR-4.x
- Step 5 — Roster maintenance: PR-5.x
- Scope: AR models
Registration::Campaign,Item,UserRegistration,Policyand additive migrations. - Migrations:
20251028000000_create_registration_campaigns.rb20251028000001_create_registration_items.rb20251028000002_create_registration_user_registrations.rb20251028000003_create_registration_policies.rb
- Refs: Models — Campaign, Item, UserRegistration, Policy
- Acceptance: Migrations run cleanly; models have correct associations and validations; no existing tables altered.
- Scope:
Registration::PolicyEnginewith two policy kinds. - Implementation:
Registration::PolicyEngine#evaluate_policies_for,Registration::Policy#evaluateforinstitutional_emailandprerequisite_campaignkinds. - Test doubles: Tests use doubles for checking roster membership in prerequisite campaigns.
- Refs: PolicyEngine, Policy#evaluate
- Acceptance: Policy engine evaluates ordered policies with short-circuit; tests pass with doubled roster data;
student_performancepolicy kind deferred to Step 11.
- Scope: Include
Registration::CampaignableinLectureandRegistration::RegisterableinTutorial. - Implementation:
Campaignable:has_many :registration_campaigns, as: :campaignableRegisterable:capacity,allocated_user_ids(raises NotImplementedError),materialize_allocation!(raises NotImplementedError)
- Refs: Campaignable, Registerable
- Acceptance: Tutorial includes Registerable; methods raise NotImplementedError when called; no functional changes to existing semester.
- Scope: Include
Registration::CampaignableinSeminarandRegistration::RegisterableinTalk. - Same pattern as PR-2.3 but for seminars.
- Refs: Same concerns, different models.
- Acceptance: Same as PR-2.3 for seminar context.
- Scope: Teacher/editor UI for campaign lifecycle (draft → open → closed → processing → completed).
- Controllers:
Registration::CampaignsController(new/create/edit/update/show/destroy). - Actions:
open(validates policies, updates status to :open),close(background job triggers status → :closed),reopen(reverts to :open if allocation not started). - Freezing: Campaign-level attributes freeze on lifecycle transitions (
allocation_mode,registration_opens_atafter draft; policies freeze on open). - UI: Turbo Frames for inline editing; flash messages for validation errors and freeze violations; feature flag
registration_campaigns_enabled; disabled fields for frozen attributes. - Refs: Campaign lifecycle & freezing, State diagram
- Acceptance: Teachers can create draft campaigns, add policies, open campaigns (with policy validation); campaigns cannot be deleted when open/processing; freezing rules enforced with clear error messages; frozen fields disabled in UI; feature flag gates UI.
- Scope: Manage registerable items within a campaign.
- Controllers:
Registration::ItemsController(nested routes under campaigns). - Freezing: Items cannot be removed when
status != :draft(prevents invalidating existing registrations); adding items always allowed. - UI: Turbo Frames for inline item addition/removal; capacity editing; delete button disabled for items when campaign is open.
- Refs: Item model, Freezing rules
- Acceptance: Teachers can add items anytime; items cannot be removed if campaign is open or has registrations for that item; capacity edits validated.
- Scope: Student registration for single-item campaigns (e.g., one tutorial per lecture).
- Controllers:
Registration::UserRegistrationsController(create/destroy). - Logic: FCFS mode with capacity checks; policy evaluation on create.
- Freezing: Item capacity can increase anytime; can decrease only if
new_capacity >= confirmed_count(prevents revoking confirmed spots). - UI: Registration button; Turbo Stream updates for immediate feedback; capacity editing validates against confirmed count.
- Refs: FCFS mode, Freezing rules
- Acceptance: Students can register for open campaigns; capacity enforced; policy violations shown with error messages; confirmed status set immediately; capacity decrease blocked if it would revoke spots.
- Scope: Extend PR-3.3 for multi-item campaigns (e.g., tutorial selection from multiple options).
- Controllers: Extend
Registration::UserRegistrationsControllerto handle item selection. - UI: Item selection dropdown; Turbo Stream for dynamic item list updates.
- Refs: Multi-item campaigns
- Acceptance: Students can select from available items; capacity per item enforced; switching items updates previous registration.
- Scope: UI for students to rank items by preference.
- Controllers: Extend
Registration::UserRegistrationsControllerwithupdate_preferencesaction. - UI: Drag-and-drop ranking interface; persisted as JSONB array in
preferencescolumn. - Refs: Preference mode
- Acceptance: Students can rank items; preferences saved; cannot submit incomplete rankings.
- Scope: Implement minimal roster persistence for
materialize_allocation!. - Models: Add
source_campaign_idtotutorial_membershipsjoin table. - Concerns: Implement
Roster::Rosterablewithallocated_user_ids,materialize_allocation!,roster_entries,mark_campaign_source!. - Implementation in Tutorial: Override
allocated_user_idsto delegate toroster_user_ids; implementmaterialize_allocation!usingreplace_roster!pattern. - Refs: Rosterable concern, Tutorial implementation
- Acceptance: Tutorial implements Rosterable methods;
materialize_allocation!replaces roster entries tagged with campaign;allocated_user_idsreturns current roster user IDs.
- Scope: Wire solver and finalize end-to-end.
- Services:
Registration::Allocation::Solver(delegates to CP-SAT or placeholder greedy),Registration::FinalizationGuard. - Controllers:
Registration::AllocationController(trigger/retry/finalize actions). - Background:
AllocationJobruns solver and updates UserRegistration statuses via Turbo Streams. - Logic: On finalize, call
FinalizationGuard#check!, thenmaterialize_allocation!for each confirmed user. - Freezing: Item capacity freezes once
status == :completed(results published); can be adjusted freely duringdraft,open,closedstates. - Refs: Solver, Finalization, Freezing rules
- Acceptance: Teachers can trigger allocation; results streamed to UI; finalize materializes rosters; capacity changes blocked after completion; unconfirmed users stay in limbo; confirmed users added to rosters via
materialize_allocation!.
- Scope: Post-allocation roster management.
- Controllers:
Roster::MaintenanceController(move/add/remove actions). - UI: Roster Overview with candidates panel (unassigned users from completed campaign); Detail view for individual roster with capacity checks.
- Refs: Roster maintenance
- Acceptance: Teachers can move students between rosters; capacity enforced; candidates panel lists unassigned users; manual add/remove actions work.
- Scope: Tutors can view rosters for their assigned groups.
- Abilities: Update CanCanCan to allow read-only roster access for tutors.
- UI: Tutors see Detail view without edit actions.
- Refs: Abilities
- Acceptance: Tutors can view rosters for their tutorials; cannot edit; exams do not show candidates panel.
- Scope: Add students to rosters manually.
- Controllers: Extend
Roster::MaintenanceControllerwithadd_studentaction. - UI: "Add student" button on Overview; search input for arbitrary student addition.
- Refs: Manual operations
- Acceptance: Teachers can add students from candidates or search; capacity enforced; duplicate prevention.
- Scope: Background job to verify roster consistency.
- Job:
AllocatedAssignedMatchJobcomparesItem#assigned_userswithRegisterable#allocated_user_ids. - Monitoring: Logs mismatches for admin review.
- Refs: Integrity invariants
- Acceptance: Job runs nightly; reports mismatches; no auto-fix (manual review required).
- Scope: Create
assessment_assessments,assessment_tasks,assessment_participations,assessment_task_points. - Migrations:
20251105000000_create_assessment_assessments.rb20251105000001_create_assessment_tasks.rb20251105000002_create_assessment_participations.rb20251105000003_create_assessment_task_points.rb
- Refs: Assessment models
- Acceptance: Migrations run; models have correct associations; no existing tables altered.
- Scope: Create
grade_schemesandgrade_scheme_thresholds. - Migrations:
20251105000004_create_grade_schemes.rb20251105000005_create_grade_scheme_thresholds.rb
- Refs: GradeScheme models
- Acceptance: Migrations run; models have correct validations; percentage-based thresholds supported.
- Scope: Background migration to create Assessment for each Assignment.
- Migration: Iterates existing Assignments; creates corresponding
Assessment::Assessmentwithassessable_type: "Assignment". - Refs: Assessment formalization
- Acceptance: All assignments have linked assessments; no data loss; migration idempotent.
- Scope: CRUD for assessments and participations.
- Controllers:
Assessment::AssessmentsController,Assessment::ParticipationsController(read-only for now). - UI: Index/show views for assessments; participation list per assessment.
- Refs: Assessment controllers
- Acceptance: Teachers can view assessments and participations; no grading UI yet; feature flag gates access.
- Scope:
Assessment::GradingServicefor saving points and grades. - Implementation: Fanout pattern creates Participation and TaskPoints per student (or team).
- Refs: GradingService
- Acceptance: Service creates participations and task points; handles team grading; validates point ranges.
- Scope: Grading interface for entering points.
- Controllers:
Assessment::GradingController(new/create/update). - UI: Grid view with students × tasks; inline editing; Turbo Frames for updates.
- Refs: Grading UI mockup
- Acceptance: Teachers can enter points; service called on save; results preview shown; feature flag gates UI.
- Scope: Toggle result visibility for students.
- Controllers: Extend
Assessment::AssessmentsControllerwithpublish_resultsandunpublish_resultsactions. - UI: Toggle button on assessment show page.
- Refs: Publication workflow
- Acceptance: Teachers can publish/unpublish results; students see results only when published.
- Scope: Create Achievement as assessable for non-graded participation.
- Model:
Achievementwithvalue_type(boolean/numeric/percentage). - Refs: Achievement model
- Acceptance: Achievement model exists; can be linked to assessments; value_type validated.
- Scope: UI for teachers to mark achievements.
- Controllers: Extend
Assessment::ParticipationsControllerwith achievement marking actions. - UI: Checkbox/numeric input for marking; student list view.
- Refs: Participation tracking
- Acceptance: Teachers can mark achievements; students see progress; feature flag gates UI.
- Scope: Student dashboard with widgets for registrations, grades, deadlines.
- Controllers:
Dashboards::StudentControllerwith widget partials. - Widgets: "My Registrations", "Recent Grades", "Upcoming Deadlines".
- Refs: Student dashboard mockup
- Acceptance: Students see dashboard; widgets show data from new tables; exam eligibility widget hidden (added in Step 13).
- Scope: Teacher dashboard with widgets for campaigns, rosters, grading.
- Controllers:
Dashboards::TeacherControllerwith widget partials. - Widgets: "Open Campaigns", "Roster Management", "Grading Queue".
- Refs: Teacher dashboard mockup
- Acceptance: Teachers see dashboard; widgets show actionable items; certification widget hidden (added in Step 13).
- Scope: Create
student_performance_records,student_performance_rules,student_performance_achievements,student_performance_certifications. - Migrations:
20251120000000_create_student_performance_records.rb20251120000001_create_student_performance_rules.rb20251120000002_create_student_performance_achievements.rb20251120000003_create_student_performance_certifications.rb
- Refs: Student Performance models
- Acceptance: Migrations run; models have correct associations; unique constraints on certifications.
- Scope:
StudentPerformance::ComputationServiceto aggregate performance data. - Implementation: Reads from
assessment_participationsandassessment_task_points; writes tostudent_performance_records. - Refs: ComputationService
- Acceptance: Service computes points and achievements; upserts Records; handles missing data gracefully.
- Scope:
StudentPerformance::Evaluatorto generate certification proposals. - Implementation: Reads Records and Rules; returns proposed status (passed/failed) per student.
- Refs: Evaluator
- Acceptance: Evaluator generates proposals; does NOT create Certifications; used for bulk UI only.
- Scope:
StudentPerformance::RecordsControllerfor viewing performance data. - Controllers: Index/show actions for Records.
- UI: Table view with points, achievements, computed_at timestamp.
- Refs: RecordsController
- Acceptance: Teachers can view Records; no decision-making UI; feature flag gates access.
- Scope:
StudentPerformance::CertificationsControllerfor teacher certification. - Controllers: Index (dashboard), create (bulk), update (override), bulk_accept.
- UI: Certification dashboard with proposals; bulk accept/reject; manual override with notes.
- Refs: CertificationsController
- Acceptance: Teachers can review proposals; bulk accept; override with manual status; remediation workflow for stale certifications.
- Scope:
StudentPerformance::EvaluatorControllerfor proposal generation. - Controllers:
bulk_proposals,preview_rule_change,single_proposal. - UI: Modal for rule change preview showing diff of affected students.
- Refs: EvaluatorController
- Acceptance: Teachers can generate proposals; preview rule changes; does NOT create Certifications automatically.
- Scope: Create
Exammodel with concerns. - Concerns:
Registration::Campaignable,Registration::Registerable,Roster::Rosterable,Assessment::Assessable. - Implementation:
materialize_allocation!delegates toreplace_roster!;allocated_user_idsreturns roster user IDs. - Refs: Exam model
- Acceptance: Exam includes all concerns; methods implemented; no functional changes to existing exams.
- Scope: Add
student_performancepolicy kind toRegistration::PolicyEngine. - Implementation:
Registration::Policy#eval_student_performancechecksStudentPerformance::Certification.find_by(...).status. - Phase awareness: Returns different errors for registration (missing/pending) vs finalization (failed).
- Refs: Policy evaluation
- Acceptance: Policy checks Certification table; phase-aware logic; tests use Certification doubles.
- Scope: Add certification completeness checks to campaign lifecycle.
- Controllers: Update
Registration::CampaignsController#opento check for missing/pending certifications; block if incomplete. - Update
Registration::AllocationController#finalizeto check for missing/pending; auto-reject failed certifications. - Refs: Pre-flight validation
- Acceptance: Campaigns cannot open without complete certifications; finalization blocked if pending; failed certifications auto-rejected.
- Scope: Exam registration with student_performance policy.
- Controllers: Extend
Registration::UserRegistrationsControllerfor exam context. - UI: Registration button with eligibility status display.
- Refs: Exam registration flow
- Acceptance: Students can register for exams; policy blocks ineligible users; clear error messages; feature flag gates UI.
- Scope: Apply grading schemes to exam results.
- Service:
GradeScheme::Applierto map points to grades. - Controllers:
GradeScheme::SchemesController(preview/apply). - Refs: GradeScheme applier
- Acceptance: Teachers can apply schemes; preview grade distribution; grades saved to participations.
- Scope: Add student performance and exam registration widgets.
- Widgets: "Exam Eligibility Status", "Performance Overview".
- Refs: Student dashboard complete
- Acceptance: Students see eligibility status; performance summary; links to certification details.
- Scope: Add certification and exam management widgets.
- Widgets: "Certification Pending List", "Eligibility Summary".
- Refs: Teacher dashboard complete
- Acceptance: Teachers see pending certifications; summary of eligible students; links to remediation UI.
- Scope: Create integrity jobs for student performance.
- Jobs:
PerformanceRecordUpdateJob(recompute Records after grading),CertificationStaleCheckJob(flag stale certifications),AllocatedAssignedMatchJob(verify roster consistency). - Refs: Background jobs
- Acceptance: Jobs run on schedule; log issues; no auto-fix for critical data.
- Scope: Admin UI for monitoring data integrity.
- Controllers:
Admin::IntegrityControllerwith dashboard views. - Widgets: Pending certifications, stale certifications, roster mismatches.
- Refs: Monitoring
- Acceptance: Admins see integrity metrics; drill-down to affected records; export reports.