| name | mtp-student-phase-a-decisions | ||
|---|---|---|---|
| description | Resolved decisions for Student module Phase A (Exam-unblocker thin slice). Locked 2026-05-18. Drives the schema + service shape for the first Student build. | ||
| metadata |
|
Three architecturally significant decisions resolved after the six-cluster
Student study landed. These were the top three open questions in
inventory/student-replication-strategy.html. Update that page if these change.
NOT slim (15 columns). The medium shape covers identity + bio + address + parents
- contact + enrolment + status + audit. Slim was tempting for cleanliness but would force a churning rewrite when Phase B lands.
Approximate column inventory (refine during design step):
- Identity (10): StudentId, EnrolmentNo, FullName, DOB, Gender, Photo, MobileNo, Email, AadharNo, RegistrationNo
- Demographic (8): CategoryId, ReligionId, BloodGroupId, MotherTongueId, Nationality, MaritalStatus, IsPWD, IsForeignStudent
- Family (5): FatherName, MotherName, GuardianName, GuardianMobileNo, GuardianRelationId
- Address (8): PermanentAddress, CurrentAddress, CountryId, StateId, DistrictId, TalukaId, PinCode, IsHostelResident
- Enrolment (10): ProgramId, SpecializationId, AdmissionYearId, BatchYearId, SemesterId, SectionId, DivisionId, RollNumber, AdmissionQuotaId, AdmissionTypeId, AdmissionDate
- Status (5): Status, IsActive, IsBlocked, EligibilityStatus, BlockReason
- Audit (4): CreatedAt, CreatedByUserId, UpdatedAt, UpdatedByUserId
Total ~50 columns. Profile extras (hobbies, achievements, custom fields) defer to Phase B/C/D.
StudentExam is a Student-module-owned projection table that mirrors
(Student × Exam) state at registration time. Exam module reads only;
never writes.
Why Student owns it:
- Table name + columns are Student-state denormalisations
- Updates flow from Student state changes (program / section / semester promotion) into the projection
- Single write owner avoids ambiguity
Caveat: Exam-result-state fields currently on legacy STU_StudentExam
(DegreeCertificateState, ConvocationState) MUST split out into an
Exam-owned aggregate (exam.StudentExamResult or equivalent). Those
fields are post-result, Exam-side concerns; they don't belong on a
Student projection.
Sync mechanism: Student module emits domain events on enrolment / program /
section / semester changes; an internal StudentExamProjectionHandler
updates student.StudentExam rows. Marten event stream is the source of
truth; the table is the read model.
NOT one giant Student aggregate. NOT a per-feature explosion.
| Aggregate | Owns | Changes when |
|---|---|---|
StudentIdentity |
Bio, demographic, family, address, contact, photo | Rarely (admission + occasional address/contact update) |
StudentEnrolment |
Program, specialization, section, division, semester, roll, admission quota, status | Per semester / on promotion / on transfer |
StudentProfile |
Achievements, activities, hobbies, clubs, extension fields, mentor links | Continuously (Phase B-G concern) |
Shared StudentId (uuid). FK from Enrolment + Profile back to Identity.
Why three:
- Different change frequencies = different consistency boundaries
- Identity is mostly-immutable once admitted; Enrolment churns semester-by-semester
- Profile holds the extensibility surface (per-tenant fields, page 09); keeping it separate prevents Identity from bloating
- 180-parameter GNUMS SPs (
InsertFromEnrollment,UpdateFromEnrollment) conflated identity + enrolment + profile; splitting them reverses that - Each aggregate gets its own service + repository + event stream
Phase A delivers: StudentIdentity (medium shape above) + StudentEnrolment (slim slice — current-semester only) + StudentExam projection. StudentProfile fully defers to Phase B/D.
When working on Student-module code (Phase A or later):
- Use these three aggregates, not a unified
Student - Medium column count on
StudentIdentity; don't pre-collapse to slim - StudentExam writes go through Student module's services; Exam module
reads through a thin interface (
IStudentExamReaderor equivalent) - DegreeCertificateState / ConvocationState → Exam module, not Student
- Profile fields (extension fields, hobbies, achievements) deferred to Phase B+; do not pollute Phase A schema
[[gnums-conventions]] [[mtp-tenancy-model]] [[mtp-authz-model]]