# Phase 5 Execution Plan: Modular Student Lifecycle Extraction


# Islamic Sunday School Alignment Update

Phase 5 student lifecycle now treats Sunday School as **Islamic Sunday School**.

`SchoolCore\Students` owns neutral student identity, guardians, households, enrollment, assignment, status transitions, promotion, and audit.

`IslamicSundaySchool\Students` may extend student profiles with:

```text
masjid family/community profile
Qur'an level
Arabic level
Islamic studies track
halaqa/group
memorization progress summary
recitation placement
volunteer/family participation flags
sensitive imam/admin notes, only with strict authorization
```

Do not store these fields in the core student model. Core should remain reusable for any school system.

---
## 1. Purpose

Phase 5 extracts student lifecycle behavior into a reusable `SchoolCore` module that can support any school system while allowing Islamic Sunday School-specific student profile behavior through extension tables, policies, and domain services.

The student lifecycle module must own the invariant parts of student management:

- student identity
- student profile
- guardian relationships
- family/household relationships
- enrollment
- class/group assignment
- student identifiers
- status transitions
- promotion
- transfer
- withdrawal/archive
- student search/read models
- audit logging
- cross-school isolation
- authorization boundaries

Islamic Sunday School may customize:

- masjid family/community profile fields
- Qur'an, Arabic, Islamic studies, halaqa, and masjid-family fields
- Islamic Sunday School class grouping
- Qur'an/Islamic studies curriculum level
- family/masjid/community relationship labels
- Islamic Sunday School promotion rules
- imam/admin notes, if allowed by policy
- ministry participation flags

Islamic Sunday School must not define the global student model. It extends it. That distinction matters unless the plan is to make every school system pretend it is a Islamic Sunday School wearing a fake mustache.

---

## 2. Required Dependency Direction

Student lifecycle must follow the modular platform boundary:

```text
App\Domain\IslamicIslamicSundaySchool\Students
        ↓ depends on
App\Domain\SchoolCore\Students
        ↓ depends on
App\Domain\SchoolCore\Shared
```

Forbidden dependencies:

```text
SchoolCore\Students -> IslamicSundaySchool\*
SchoolCore\Students -> Http\Request
SchoolCore\Students -> auth()
SchoolCore\Students -> controller classes
SchoolCore\Students -> Islamic Sunday School vocabulary
SchoolCore\Students -> direct unscoped school queries
```

Allowed dependencies:

```text
IslamicSundaySchool\Students -> SchoolCore\Students contracts
Http\Controllers -> student lifecycle contracts
Jobs -> student lifecycle contracts
Student services -> SchoolContext
Student services -> shared audit/transaction contracts
Student services -> enrollment/promotion policy contracts
```

---

## 3. Target Namespace Structure

Create the student lifecycle module under `SchoolCore`:

```text
app/
  Domain/
    SchoolCore/
      Students/
        Contracts/
          StudentServiceContract.php
          StudentProfileServiceContract.php
          StudentIdentifierGeneratorContract.php
          GuardianServiceContract.php
          HouseholdServiceContract.php
          EnrollmentServiceContract.php
          AssignmentServiceContract.php
          PromotionServiceContract.php
          PromotionPolicyContract.php
          StudentLifecycleAuditLoggerContract.php
          StudentReadServiceContract.php
        DTO/
          CreateStudentData.php
          UpdateStudentData.php
          StudentProfileData.php
          CreateGuardianData.php
          UpdateGuardianData.php
          LinkGuardianData.php
          HouseholdData.php
          EnrollmentData.php
          AssignmentData.php
          PromotionData.php
          StudentStatusTransitionData.php
          StudentSearchQuery.php
        Enums/
          StudentStatus.php
          GuardianRelationshipType.php
          EnrollmentStatus.php
          AssignmentStatus.php
          PromotionResult.php
          StudentAuditAction.php
        Exceptions/
          StudentException.php
          StudentNotFoundException.php
          StudentIdentifierCollisionException.php
          InvalidStudentStatusTransitionException.php
          UnauthorizedStudentAccessException.php
          EnrollmentException.php
          GuardianException.php
          PromotionException.php
        Services/
          StudentService.php
          StudentProfileService.php
          StudentIdentifierService.php
          GuardianService.php
          HouseholdService.php
          EnrollmentService.php
          AssignmentService.php
          PromotionService.php
          StudentLifecycleAuditLogger.php
          StudentReadService.php
        Policies/
          DefaultPromotionPolicy.php
          DefaultStudentIdentifierGenerator.php
          DefaultEnrollmentPolicy.php
        Repositories/
          StudentRepository.php
          GuardianRepository.php
          HouseholdRepository.php
          EnrollmentRepository.php
          AssignmentRepository.php
          StudentReadRepository.php
        Support/
          StudentTransactionRunner.php
          StudentIdentifier.php
          StudentLifecycleStateMachine.php
          StudentSearchNormalizer.php
```

Islamic Sunday School-specific student lifecycle behavior goes here:

```text
app/
  Domain/
    IslamicSundaySchool/
      Students/
        DTO/
          IslamicSundaySchoolStudentProfileData.php
        Policies/
          IslamicSundaySchoolPromotionPolicy.php
          IslamicSundaySchoolEnrollmentPolicy.php
          IslamicSundaySchoolStudentIdentifierGenerator.php
        Services/
          IslamicSundaySchoolStudentProfileService.php
          IslamicSundaySchoolFamilyProfileService.php
        Reports/
          IslamicSundaySchoolStudentReportBuilder.php
        Providers/
          IslamicSundaySchoolStudentServiceProvider.php
```

---

## 4. Core Design Rules

### 4.1 Student services must require `SchoolContext`

Every public student lifecycle service method must receive `SchoolContext`.

Example:

```php
public function createStudent(
    SchoolContext $context,
    CreateStudentData $data
): StudentResult;
```

A student operation without `SchoolContext` is invalid. A student operation with loose school scoping is how platforms become accidental data-sharing programs.

### 4.2 Core student model must stay school-neutral

Core may contain:

```text
name
date_of_birth
gender, optional
contact fields, if applicable
status
school_id
external_id, optional
student_identifier
profile photo reference
metadata, constrained
```

Core must not contain Islamic Sunday School-only fields like:

```text
quran_level_id
arabic_level_id
masjid/community_membership_status
ministry_group
islamic_studies_track_id
religious/community_notes
favorite_surah
```

Those belong in `IslamicSundaySchool` extension profile storage.

### 4.3 Student identifiers must be race-safe

Current-style identifier generation using `max(id) + 1` is forbidden.

Required strategy:

```text
1. Create student row inside transaction.
2. Generate identifier from actual persisted ID or sequence.
3. Save identifier.
4. Enforce unique constraint.
5. Retry on collision if policy permits.
```

A generated identifier without a database unique constraint is just a polite suggestion.

### 4.4 Controllers must not orchestrate lifecycle rules

Controllers may:

```text
- validate request
- authorize route
- build DTO
- call service contract
- return resource
```

Controllers may not:

```text
- generate student IDs
- create guardians directly during student creation
- assign classes directly
- decide promotion eligibility
- mutate status transitions directly
- write Islamic Sunday School profile fields into core student table
```

### 4.5 Lifecycle transitions must be explicit

Student status changes must pass through a state machine or transition service.

Example statuses:

```text
prospective
active
inactive
withdrawn
graduated
archived
transferred
```

Forbidden:

```php
$student->status = $request->status;
$student->save();
```

That is not lifecycle management. That is letting HTTP edit reality with a crayon.

---

## 5. Core Contracts

### 5.1 `StudentServiceContract`

```php
namespace App\Domain\SchoolCore\Students\Contracts;

use App\Domain\SchoolCore\Shared\Context\SchoolContext;
use App\Domain\SchoolCore\Students\DTO\CreateStudentData;
use App\Domain\SchoolCore\Students\DTO\UpdateStudentData;
use App\Domain\SchoolCore\Students\DTO\StudentStatusTransitionData;

interface StudentServiceContract
{
    public function createStudent(SchoolContext $context, CreateStudentData $data): StudentResult;

    public function updateStudent(SchoolContext $context, int $studentId, UpdateStudentData $data): StudentResult;

    public function transitionStatus(
        SchoolContext $context,
        int $studentId,
        StudentStatusTransitionData $data
    ): StudentResult;

    public function getStudent(SchoolContext $context, int $studentId): StudentView;
}
```

### 5.2 `StudentIdentifierGeneratorContract`

```php
namespace App\Domain\SchoolCore\Students\Contracts;

use App\Domain\SchoolCore\Shared\Context\SchoolContext;

interface StudentIdentifierGeneratorContract
{
    public function generateForPersistedStudent(
        SchoolContext $context,
        StudentView $student
    ): StudentIdentifier;
}
```

### 5.3 `GuardianServiceContract`

```php
namespace App\Domain\SchoolCore\Students\Contracts;

use App\Domain\SchoolCore\Shared\Context\SchoolContext;
use App\Domain\SchoolCore\Students\DTO\CreateGuardianData;
use App\Domain\SchoolCore\Students\DTO\LinkGuardianData;

interface GuardianServiceContract
{
    public function createGuardian(SchoolContext $context, CreateGuardianData $data): GuardianResult;

    public function linkGuardianToStudent(
        SchoolContext $context,
        LinkGuardianData $data
    ): GuardianLinkResult;

    public function unlinkGuardianFromStudent(
        SchoolContext $context,
        int $studentId,
        int $guardianId,
        string $reason
    ): GuardianLinkResult;
}
```

### 5.4 `HouseholdServiceContract`

```php
namespace App\Domain\SchoolCore\Students\Contracts;

use App\Domain\SchoolCore\Shared\Context\SchoolContext;
use App\Domain\SchoolCore\Students\DTO\HouseholdData;

interface HouseholdServiceContract
{
    public function createHousehold(SchoolContext $context, HouseholdData $data): HouseholdResult;

    public function addStudentToHousehold(
        SchoolContext $context,
        int $householdId,
        int $studentId
    ): HouseholdResult;

    public function addGuardianToHousehold(
        SchoolContext $context,
        int $householdId,
        int $guardianId
    ): HouseholdResult;
}
```

### 5.5 `EnrollmentServiceContract`

```php
namespace App\Domain\SchoolCore\Students\Contracts;

use App\Domain\SchoolCore\Shared\Context\SchoolContext;
use App\Domain\SchoolCore\Students\DTO\EnrollmentData;

interface EnrollmentServiceContract
{
    public function enrollStudent(SchoolContext $context, EnrollmentData $data): EnrollmentResult;

    public function withdrawStudent(SchoolContext $context, int $studentId, string $reason): EnrollmentResult;

    public function transferStudent(SchoolContext $context, int $studentId, EnrollmentData $data): EnrollmentResult;
}
```

### 5.6 `AssignmentServiceContract`

```php
namespace App\Domain\SchoolCore\Students\Contracts;

use App\Domain\SchoolCore\Shared\Context\SchoolContext;
use App\Domain\SchoolCore\Students\DTO\AssignmentData;

interface AssignmentServiceContract
{
    public function assignStudent(SchoolContext $context, AssignmentData $data): AssignmentResult;

    public function unassignStudent(SchoolContext $context, int $assignmentId, string $reason): AssignmentResult;
}
```

### 5.7 `PromotionServiceContract`

```php
namespace App\Domain\SchoolCore\Students\Contracts;

use App\Domain\SchoolCore\Shared\Context\SchoolContext;
use App\Domain\SchoolCore\Students\DTO\PromotionData;

interface PromotionServiceContract
{
    public function evaluatePromotion(SchoolContext $context, int $studentId): PromotionEvaluationResult;

    public function promoteStudent(SchoolContext $context, PromotionData $data): PromotionResult;

    public function bulkPromote(SchoolContext $context, BulkPromotionData $data): BulkPromotionResult;
}
```

### 5.8 `PromotionPolicyContract`

```php
namespace App\Domain\SchoolCore\Students\Contracts;

use App\Domain\SchoolCore\Shared\Context\SchoolContext;

interface PromotionPolicyContract
{
    public function evaluate(
        SchoolContext $context,
        StudentView $student,
        EnrollmentView $enrollment
    ): PromotionEvaluationResult;
}
```

Islamic Sunday School may bind this to a Islamic Sunday School-specific policy.

---

## 6. DTO Requirements

Do not pass raw request arrays into student services.

### 6.1 `CreateStudentData`

Fields:

```text
first_name
middle_name, nullable
last_name
preferred_name, nullable
date_of_birth, nullable
gender, nullable
primary_language, nullable
photo_file, nullable
external_id, nullable
initial_status
guardians, nullable array
household_id, nullable
enrollment, nullable
profile_metadata, nullable
extension_profile, nullable
idempotency_key, nullable
```

### 6.2 `UpdateStudentData`

Fields:

```text
first_name, nullable
middle_name, nullable
last_name, nullable
preferred_name, nullable
date_of_birth, nullable
gender, nullable
primary_language, nullable
photo_file, nullable
profile_metadata, nullable
update_reason
```

`update_reason` should be required for sensitive profile changes if policy requires it.

### 6.3 `CreateGuardianData`

Fields:

```text
first_name
last_name
email, nullable
phone, nullable
relationship_type, nullable
address, nullable
emergency_contact, bool
pickup_authorized, bool
metadata, nullable
```

### 6.4 `LinkGuardianData`

Fields:

```text
student_id
guardian_id
relationship_type
emergency_contact
pickup_authorized
financial_responsibility, nullable bool
academic_contact, nullable bool
notes, nullable
```

### 6.5 `EnrollmentData`

Fields:

```text
student_id
academic_year_id
term_id, nullable
grade_level_id, nullable
program_id, nullable
class_group_id, nullable
enrollment_date
status
reason, nullable
metadata, nullable
```

### 6.6 `PromotionData`

Fields:

```text
student_id
from_academic_year_id
to_academic_year_id
from_level_id, nullable
to_level_id, nullable
from_group_id, nullable
to_group_id, nullable
effective_date
reason
override_policy, bool
override_reason, nullable
```

---

## 7. Student Identity and Identifier Strategy

### 7.1 Identifier requirements

Student identifiers must be:

```text
school-scoped
unique per school
generated through contract
race-safe
auditable
replaceable by policy
not dependent on max(id) + 1
```

### 7.2 Recommended default algorithm

```text
1. Insert student without public identifier.
2. Use persisted student ID and school prefix to generate identifier.
3. Save identifier.
4. Enforce unique(school_id, student_identifier).
5. Retry on collision if necessary.
```

Example format:

```text
SCH-0000123
```

Islamic Sunday School may override with:

```text
SS-2026-000123
```

But it must use the same contract and uniqueness rules.

### 7.3 Tests

```text
- creates unique identifier
- two concurrent student creations do not collide
- identifier is unique per school
- same identifier can exist in different schools only if policy permits and DB constraint supports it
- collision retry works
```

---

## 8. Student Profile Extension Strategy

### 8.1 Core profile

Core profile is school-neutral.

Suggested tables or model concepts:

```text
students
student_profiles
guardians
households
student_guardian
enrollments
student_assignments
student_audit_logs
```

### 8.2 Islamic Sunday School profile

Islamic Sunday School-specific profile belongs outside core.

Possible table:

```text
islamic_sunday_school_student_profiles
```

Suggested fields:

```text
school_id
student_id
masjid/community_family_id, nullable
quran_level_id, nullable
arabic_level_id, nullable
ministry_group_id, nullable
bible_curriculum_level_id, nullable
religious/community_notes, nullable with strict authorization
metadata, nullable
created_at
updated_at
```

Rules:

```text
- every extension profile row must include school_id
- extension profile must reference a core student
- extension profile access must be policy-controlled
- sensitive fields require explicit authorization
```

### 8.3 Profile composition

Read models may compose core + extension:

```text
Core StudentView
  + IslamicSundaySchoolStudentProfileView
  = IslamicSundaySchoolStudentView
```

Core must not know about `IslamicSundaySchoolStudentView`.

---

## 9. Guardian and Household Model

### 9.1 Guardian rules

Guardians are reusable people records connected to students.

A guardian may be linked to:

```text
one student
multiple siblings
multiple households, if policy allows
financial responsibility
academic contact
emergency contact
pickup authorization
```

### 9.2 Required relationship metadata

```text
relationship_type
is_primary
emergency_contact
pickup_authorized
financial_responsibility
academic_contact
effective_from
effective_to, nullable
notes, nullable
```

### 9.3 Authorization concerns

Guardian/student access must be scoped by:

```text
school_id
relationship
role
custody/contact rules, if applicable
sensitive data policy
```

Do not assume every guardian can see every student field. Family data gets legally spicy very quickly, because apparently humans turned family structure into a distributed permissions problem.

---

## 10. Enrollment and Assignment Model

### 10.1 Enrollment

Enrollment answers:

```text
Is this student part of this school/program/year/term?
```

Core fields:

```text
school_id
student_id
academic_year_id
term_id, nullable
program_id, nullable
grade_level_id, nullable
status
enrolled_at
withdrawn_at, nullable
reason, nullable
metadata
```

### 10.2 Assignment

Assignment answers:

```text
Where is this student placed?
```

Examples:

```text
class
group
section
homeroom
cohort
session group
volunteer/program group extension
```

Core should use neutral terms:

```text
assignment_type
assignable_type
assignable_id
effective_from
effective_to
status
```

Islamic Sunday School can map class/ministry labels through extension configuration.

### 10.3 Assignment rules

```text
- no active duplicate assignment for same student/type/period unless policy allows
- assignment must belong to same school
- assignment must fit enrollment period
- assignment changes require audit log
```

---

## 11. Promotion and Progression

### 11.1 Core promotion concept

Promotion is a transition from one enrollment/level/group context to another.

Core must support:

```text
grade promotion
level promotion
group movement
program completion
graduation
retention
manual override
```

### 11.2 Policy-driven promotion

Promotion decision belongs to `PromotionPolicyContract`.

Default policy may use:

```text
academic year completion
current level
attendance threshold, optional
academic completion status, optional
manual review flag
```

Islamic Sunday School policy may use:

```text
Qur'an/Islamic studies curriculum completion
age group
Islamic Sunday School attendance
teacher recommendation
program readiness
```

But the core only sees policy result, not Islamic Sunday School-specific rules.

### 11.3 Promotion audit

Every promotion must log:

```text
from state
to state
actor
policy result
override flag
override reason
effective date
```

---

## 12. Transaction Strategy

### 12.1 Student creation

Required transaction:

```text
BEGIN
  create student
  generate student identifier
  save identifier
  create profile
  create or link guardians, if included
  create or link household, if included
  create enrollment, if included
  create extension profile through extension hook, if provided
  write audit log
COMMIT
```

### 12.2 Student update

Required transaction:

```text
BEGIN
  lock student
  capture before state
  validate transition/update policy
  update core profile
  update extension profile through extension service, if applicable
  write before/after audit log
COMMIT
```

### 12.3 Enrollment change

Required transaction:

```text
BEGIN
  lock student
  lock active enrollment rows
  close or update previous enrollment
  create new enrollment
  update assignments if needed
  write audit log
COMMIT
```

### 12.4 Promotion

Required transaction:

```text
BEGIN
  lock student
  lock current enrollment
  evaluate or confirm promotion result
  close old enrollment/assignment
  create new enrollment/assignment
  write audit log
COMMIT
```

---

## 13. Audit Logging Requirements

Every student lifecycle mutation must create an audit event.

Required audit fields:

```text
school_id
academic_year_id, nullable
term_id, nullable
actor_user_id
actor_role_snapshot
action
entity_type
entity_id
before_json, nullable
after_json, nullable
reason, nullable
request_id
ip_address, nullable
user_agent, nullable
idempotency_key, nullable
created_at
```

Required actions:

```text
student.created
student.updated
student.status_changed
student.archived
student.transferred
guardian.created
guardian.updated
guardian.linked
guardian.unlinked
household.created
household.updated
student.enrolled
student.withdrawn
student.assigned
student.unassigned
student.promoted
student.retained
student.graduated
student.extension_profile.updated
```

Audit logs are append-only.

---

## 14. Authorization Requirements

Minimum actions:

```text
student.view
student.create
student.update
student.archive
student.transfer
student.sensitive.view
guardian.view
guardian.create
guardian.update
guardian.link
guardian.unlink
household.view
household.manage
enrollment.view
enrollment.manage
assignment.view
assignment.manage
promotion.evaluate
promotion.execute
student.report.view
```

Every student endpoint must have tests for:

```text
unauthenticated
wrong school
wrong role
wrong owner/family
authorized admin
authorized staff
authorized teacher within assignment scope
authorized guardian for own student, if allowed
```

Sensitive Islamic Sunday School extension fields need separate permissions.

Example:

```text
student.islamic_sunday_school_profile.view
student.religious/community_notes.view
student.religious/community_notes.update
```

---

## 15. Idempotency Requirements

Student creation should support idempotency because duplicate form submissions create duplicate children, which is less charming in databases than in sitcoms.

Minimum implementation:

```text
idempotency_key
actor_user_id
school_id
operation
payload_hash
result_entity_type
result_entity_id
created_at
expires_at
```

Apply first to:

```text
student creation
guardian creation
enrollment creation
bulk promotion
```

Behavior:

```text
- same key + same operation + same payload returns original result
- same key + same operation + different payload fails
- missing key allowed for legacy clients during transition
```

---

## 16. Migration Strategy

### 16.1 Use vertical slices

Recommended order:

```text
1. Student identifier generation
2. Student creation orchestration
3. Guardian linking
4. Enrollment creation/update
5. Assignment service
6. Student status transitions
7. Promotion service
8. Islamic Sunday School profile extension
9. Student read models and reports
```

Why this order:

```text
- identifier generation has a known race bug
- creation is the root lifecycle flow
- guardians/enrollment are part of creation but can be extracted behind services
- promotion builds on enrollment/assignment
- reports should consume stable read models last
```

### 16.2 Compatibility layer

Existing controllers may remain temporarily, but must delegate to new contracts.

Example:

```text
StudentController
  -> CreateStudentRequest
  -> SchoolContext
  -> CreateStudentData
  -> StudentServiceContract::createStudent()
  -> StudentResource
```

Legacy service methods should become wrappers or be deprecated.

### 16.3 Deprecation rule

Every legacy student lifecycle method must be labeled as one of:

```text
canonical
adapter
deprecated
remove
```

No unlabeled duplicate student creation, guardian linking, assignment, enrollment, or promotion logic.

---

## 17. First Implementation Slice: Race-Safe Student Identifier

### Objective

Replace unsafe student identifier generation.

### Tasks

```text
STU-001. Create Students module scaffold.
STU-002. Create StudentIdentifierGeneratorContract.
STU-003. Implement DefaultStudentIdentifierGenerator.
STU-004. Add unique constraint on school_id + student_identifier.
STU-005. Update student creation flow to generate identifier after insert.
STU-006. Add collision retry behavior.
STU-007. Add concurrency tests.
```

### Required tests

```text
- creates student identifier after insert
- two concurrent student creations do not receive same identifier
- unique constraint prevents duplicate identifier
- identifier is scoped by school
- collision retry works
```

### Done when

```text
- no active creation path uses max(id) + 1
- identifier generation is contract-based
- concurrent creation test passes
```

---

## 18. Second Implementation Slice: Student Creation Service

### Objective

Move student creation orchestration into modular core service.

### Tasks

```text
STU-008. Create StudentServiceContract.
STU-009. Create CreateStudentData.
STU-010. Implement StudentService::createStudent().
STU-011. Add StudentTransactionRunner.
STU-012. Add student.created audit event.
STU-013. Update StudentController to delegate.
STU-014. Preserve response compatibility.
```

### Required tests

```text
- creates basic student
- creates student with guardian link
- creates student with enrollment
- rejects cross-school enrollment context
- writes audit log
- returns compatible API response
- supports idempotency key
```

### Done when

```text
- controller no longer orchestrates student creation
- student creation is transactional
- identifier generation happens through contract
```

---

## 19. Third Implementation Slice: Guardian and Household Services

### Objective

Extract guardian and household behavior into modular services.

### Tasks

```text
STU-015. Create GuardianServiceContract.
STU-016. Create HouseholdServiceContract.
STU-017. Create CreateGuardianData and LinkGuardianData.
STU-018. Implement guardian create/link/unlink.
STU-019. Implement household create/link.
STU-020. Add guardian/household audit events.
STU-021. Update student creation to use GuardianService.
```

### Required tests

```text
- creates guardian
- links guardian to student
- prevents cross-school guardian link
- prevents duplicate active guardian relationship if policy disallows
- unlink requires reason
- guardian link creates audit log
```

### Done when

```text
- guardian/student links are service-owned
- household behavior is not embedded in StudentController
```

---

## 20. Fourth Implementation Slice: Enrollment Service

### Objective

Move enrollment and withdrawal behavior into modular service.

### Tasks

```text
STU-022. Create EnrollmentServiceContract.
STU-023. Create EnrollmentData.
STU-024. Implement enrollStudent().
STU-025. Implement withdrawStudent().
STU-026. Add enrollment audit events.
STU-027. Add school/year/term validation.
```

### Required tests

```text
- enrolls student into academic year
- enrolls student into term if provided
- rejects academic year from another school
- prevents duplicate active enrollment if policy disallows
- withdrawal requires reason
- writes audit log
```

### Done when

```text
- enrollment rules are centralized
- student creation delegates enrollment to EnrollmentService
```

---

## 21. Fifth Implementation Slice: Assignment Service

### Objective

Move class/group assignment into modular service.

### Tasks

```text
STU-028. Create AssignmentServiceContract.
STU-029. Create AssignmentData.
STU-030. Implement assignStudent().
STU-031. Implement unassignStudent().
STU-032. Add assignment audit events.
STU-033. Add assignment conflict checks.
```

### Required tests

```text
- assigns student to class/group
- rejects assignment from another school
- rejects duplicate active assignment if policy disallows
- unassign requires reason
- writes audit log
```

### Done when

```text
- assignments are service-owned
- Islamic Sunday School class/group behavior can map through extension configuration
```

---

## 22. Sixth Implementation Slice: Status Transition Service

### Objective

Make student lifecycle state transitions explicit.

### Tasks

```text
STU-034. Create StudentLifecycleStateMachine.
STU-035. Create StudentStatusTransitionData.
STU-036. Implement transitionStatus().
STU-037. Add status_changed audit event.
STU-038. Replace direct status updates.
```

### Required tests

```text
- active can become withdrawn with reason
- withdrawn cannot become graduated unless policy allows
- archived student cannot be updated without special permission
- invalid transition fails
- status transition writes before/after audit
```

### Done when

```text
- no active controller directly assigns student status
- invalid transitions are blocked centrally
```

---

## 23. Seventh Implementation Slice: Promotion Service

### Objective

Move promotion behavior into policy-driven modular service.

### Tasks

```text
STU-039. Create PromotionServiceContract.
STU-040. Create PromotionPolicyContract.
STU-041. Implement DefaultPromotionPolicy.
STU-042. Implement promoteStudent().
STU-043. Implement bulkPromote().
STU-044. Add student.promoted/student.retained audit events.
STU-045. Add IslamicSundaySchoolPromotionPolicy binding.
```

### Required tests

```text
- evaluates promotion
- promotes eligible student
- retains ineligible student
- override requires reason
- cross-school promotion fails
- bulk promotion returns row-level results
- Islamic Sunday School policy can change eligibility without core changes
```

### Done when

```text
- promotion rules are policy-driven
- core does not contain Islamic Sunday School promotion logic
```

---

## 24. Eighth Implementation Slice: Islamic Sunday School Profile Extension

### Objective

Move Islamic Sunday School-only student fields into extension layer.

### Tasks

```text
STU-046. Create IslamicSundaySchoolStudentProfileData.
STU-047. Create IslamicSundaySchoolStudentProfileService.
STU-048. Create extension profile table/model if needed.
STU-049. Add policy checks for sensitive fields.
STU-050. Compose IslamicSundaySchoolStudentView from core StudentView + extension profile.
STU-051. Update Islamic Sunday School endpoints to use extension service.
```

### Required tests

```text
- creates Islamic Sunday School profile for student
- rejects profile for student from another school
- sensitive field requires permission
- core StudentService does not import IslamicSundaySchool profile classes
- IslamicSundaySchoolStudentView composes core + extension data
```

### Done when

```text
- Islamic Sunday School-only fields are not required by core student creation
- Islamic Sunday School profile behavior lives outside SchoolCore
```

---

## 25. Student Read Models and Reports

Reports must consume student read models, not re-implement lifecycle logic.

### Tasks

```text
STU-052. Create StudentReadServiceContract.
STU-053. Create StudentReadRepository.
STU-054. Create student search query DTO.
STU-055. Add school context to every query.
STU-056. Add core student summary read model.
STU-057. Add Islamic Sunday School student summary extension read model.
```

### Required tests

```text
- student list excludes other schools
- guardian sees only allowed student fields
- teacher sees only assigned students if policy says so
- archived students excluded by default
- Islamic Sunday School report fields do not appear in core report
```

---

## 26. Database and Schema Requirements

### 26.1 Required indexes

Add or verify:

```text
students.school_id indexed
students.student_identifier indexed
students.status indexed
students.created_at indexed

guardians.school_id indexed
guardians.email indexed, nullable
guardians.phone indexed, nullable

student_guardian.school_id indexed
student_guardian.student_id indexed
student_guardian.guardian_id indexed
student_guardian.relationship_type indexed

households.school_id indexed

enrollments.school_id indexed
enrollments.student_id indexed
enrollments.academic_year_id indexed
enrollments.term_id indexed, nullable
enrollments.status indexed

student_assignments.school_id indexed
student_assignments.student_id indexed
student_assignments.assignment_type indexed
student_assignments.assignable_type/assignable_id indexed
student_assignments.status indexed

student_audit_logs.school_id indexed
student_audit_logs.actor_user_id indexed
student_audit_logs.entity_type/entity_id indexed
student_audit_logs.created_at indexed
```

### 26.2 Required unique constraints

Recommended:

```text
unique(students.school_id, students.student_identifier)
unique(enrollments.school_id, student_id, academic_year_id, term_id, status) where status is active, if DB supports partial indexes
unique(student_assignments.school_id, student_id, assignment_type, assignable_type, assignable_id, effective_from) where status is active, if policy requires uniqueness
```

### 26.3 Migration caution

Do not immediately flatten or rename legacy student fields. Add service/repository adapters first. Student data tends to be referenced by half the app, several reports, and someone’s exported spreadsheet from 2017 that has somehow become sacred scripture.

---

## 27. FormRequest Requirements

Create or update:

```text
CreateStudentRequest
UpdateStudentRequest
StudentStatusTransitionRequest
CreateGuardianRequest
LinkGuardianRequest
CreateHouseholdRequest
EnrollmentRequest
AssignmentRequest
PromotionRequest
BulkPromotionRequest
IslamicSundaySchoolStudentProfileRequest
StudentSearchRequest
```

Each FormRequest must define:

```text
authorize()
rules()
messages(), if needed
toDTO(), optional but recommended
```

Controllers should use:

```php
$data = $request->toDTO();
```

Not raw request merging.

---

## 28. Service Provider Bindings

Create:

```php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Domain\SchoolCore\Students\Contracts\StudentServiceContract;
use App\Domain\SchoolCore\Students\Services\StudentService;

final class SchoolCoreStudentServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(StudentServiceContract::class, StudentService::class);
        $this->app->bind(StudentProfileServiceContract::class, StudentProfileService::class);
        $this->app->bind(StudentIdentifierGeneratorContract::class, DefaultStudentIdentifierGenerator::class);
        $this->app->bind(GuardianServiceContract::class, GuardianService::class);
        $this->app->bind(HouseholdServiceContract::class, HouseholdService::class);
        $this->app->bind(EnrollmentServiceContract::class, EnrollmentService::class);
        $this->app->bind(AssignmentServiceContract::class, AssignmentService::class);
        $this->app->bind(PromotionServiceContract::class, PromotionService::class);
        $this->app->bind(PromotionPolicyContract::class, DefaultPromotionPolicy::class);
        $this->app->bind(StudentLifecycleAuditLoggerContract::class, StudentLifecycleAuditLogger::class);
        $this->app->bind(StudentReadServiceContract::class, StudentReadService::class);
    }
}
```

Islamic Sunday School may override policy/extension bindings in its own provider.

---

## 29. Architecture Tests

Add tests that fail if student lifecycle boundaries are violated.

Required assertions:

```text
SchoolCore\Students must not depend on Domain\IslamicIslamicSundaySchool
SchoolCore\Students must not depend on Illuminate\Http\Request
SchoolCore\Students services must not call auth()
SchoolCore\Students services must not call request()
Controllers must not instantiate student concrete services directly
StudentController must not generate identifiers directly
Core student contracts must not contain Islamic Sunday School vocabulary
Student creation must go through StudentServiceContract
Promotion must go through PromotionServiceContract
```

Optional static checks:

```text
No max(id) + 1 identifier generation
No direct student status assignment in controllers
No Sunday/masjid/community/ministry/baptism vocabulary inside SchoolCore\Students contracts
No guardian/student relationship mutation outside GuardianService
No enrollment mutation outside EnrollmentService
```

---

## 30. Rollout Plan

### Step 1: Add student lifecycle module scaffolding

```text
- create namespaces
- create contracts
- create DTOs
- create provider
- bind default implementations
```

### Step 2: Add regression tests around current student creation

```text
- basic student creation
- student with guardian
- student with class/group assignment
- duplicate school ID race scenario
- student list/read response compatibility
```

### Step 3: Fix identifier generation

```text
- remove max(id) + 1
- generate after insert
- add unique constraint
- add concurrency tests
```

### Step 4: Extract student creation service

```text
- move orchestration into StudentService
- keep controller compatibility
```

### Step 5: Extract guardian/household services

```text
- centralize family relationships
- prevent cross-school linking
```

### Step 6: Extract enrollment and assignment services

```text
- centralize placement and school-year behavior
```

### Step 7: Add status transition and promotion services

```text
- explicit lifecycle transitions
- policy-driven promotion
```

### Step 8: Add Islamic Sunday School extension profile

```text
- remove Islamic Sunday School-specific assumptions from core
- compose extension read models
```

### Step 9: Add architecture tests and deprecation labels

```text
- enforce boundaries
- mark legacy methods
```

---

## 31. Implementation Tickets

## STU-001: Create student lifecycle module scaffold

### Description

Create the `SchoolCore\Students` namespace and initial contracts, DTO folders, service folders, enum folders, exception folders, and provider.

### Acceptance Criteria

```text
- Namespace exists.
- Service provider is registered.
- Empty contracts compile.
- No controller behavior changes yet.
```

---

## STU-002: Replace unsafe student identifier generation

### Description

Replace pre-insert `max(id) + 1` identifier generation with contract-based, race-safe generation.

### Acceptance Criteria

```text
- Identifier is generated after student insert.
- Unique constraint exists.
- Collision retry exists.
- Concurrency test passes.
- No active path uses max(id) + 1.
```

---

## STU-003: Extract StudentService create flow

### Description

Move student creation orchestration into `StudentService`.

### Acceptance Criteria

```text
- Uses SchoolContext.
- Uses transaction.
- Creates audit log.
- Supports guardian/enrollment delegation.
- Controller delegates only.
- Existing response shape remains compatible.
```

---

## STU-004: Extract GuardianService and HouseholdService

### Description

Move guardian and household relationship management into modular services.

### Acceptance Criteria

```text
- Guardian creation is service-owned.
- Guardian linking is service-owned.
- Cross-school links fail.
- Unlink requires reason.
- Audit logs are written.
```

---

## STU-005: Extract EnrollmentService

### Description

Move enrollment and withdrawal behavior into modular service.

### Acceptance Criteria

```text
- Enrollment is school/year scoped.
- Duplicate active enrollment is prevented where policy disallows.
- Withdrawal requires reason.
- Audit logs are written.
```

---

## STU-006: Extract AssignmentService

### Description

Move class/group assignment behavior into modular service.

### Acceptance Criteria

```text
- Assignments are school-scoped.
- Assignment conflicts are detected.
- Unassignment requires reason.
- Audit logs are written.
```

---

## STU-007: Add StudentLifecycleStateMachine

### Description

Centralize student status transition rules.

### Acceptance Criteria

```text
- Invalid transitions fail.
- Direct controller status mutation is removed.
- Status changes require reason where policy requires.
- Before/after audit is written.
```

---

## STU-008: Extract PromotionService

### Description

Move promotion behavior into policy-driven modular service.

### Acceptance Criteria

```text
- Promotion evaluation uses PromotionPolicyContract.
- Bulk promotion returns row-level results.
- Override requires reason.
- Islamic Sunday School can override policy without changing core.
```

---

## STU-009: Add Islamic Sunday School student profile extension

### Description

Move Islamic Sunday School-only student fields into extension layer.

### Acceptance Criteria

```text
- Extension profile is school-scoped.
- Sensitive fields require explicit permission.
- Core student creation does not require Islamic Sunday School fields.
- SchoolCore does not import IslamicSundaySchool classes.
```

---

## STU-010: Add student lifecycle architecture tests

### Description

Enforce student module boundaries in CI.

### Acceptance Criteria

```text
- SchoolCore\Students cannot import IslamicSundaySchool.
- Student services cannot call auth() or request().
- Core contracts contain no Islamic Sunday School vocabulary.
- StudentController does not generate identifiers.
- CI fails on boundary violation.
```

---

## 32. Definition of Done for Phase 5

Phase 5 is done when:

```text
- Student lifecycle core contracts exist.
- Student identifier generation is race-safe.
- Student creation uses StudentService.
- Guardian behavior uses GuardianService.
- Household behavior uses HouseholdService.
- Enrollment behavior uses EnrollmentService.
- Assignment behavior uses AssignmentService.
- Student status transitions are centralized.
- Promotion is policy-driven.
- Islamic Sunday School profile behavior lives outside SchoolCore.
- Student services require SchoolContext.
- Cross-school student/guardian/enrollment access is blocked by tests.
- Architecture tests prevent SchoolCore from depending on IslamicSundaySchool.
- Legacy student lifecycle methods are labeled canonical, adapter, deprecated, or remove.
```

---

## 33. Non-Goals

Do not include in Phase 5:

```text
- full student UI redesign
- full admissions system
- parent portal redesign
- external SIS integration
- biometric/student ID card printing
- full medical record system
- full masjid/community affiliation CRM
```

Those may happen later. Phase 5 is about making the student lifecycle reliable, reusable, school-scoped, and extensible.

---

## 34. Main Risks

### Risk: duplicate student identifiers

Mitigation:

```text
- generate after insert
- unique constraint
- collision retry
- concurrency tests
```

### Risk: Islamic Sunday School fields pollute core

Mitigation:

```text
- extension profile table/service
- architecture tests
- vocabulary review
```

### Risk: guardian privacy leakage

Mitigation:

```text
- relationship-aware authorization
- sensitive field policies
- guardian-specific read models
```

### Risk: enrollment/assignment drift

Mitigation:

```text
- centralized enrollment and assignment services
- unique constraints where appropriate
- audit logs
```

### Risk: behavior break during extraction

Mitigation:

```text
- snapshot current responses
- controller adapters
- vertical slices
```

---

## 35. Immediate Next Work Queue

Start here:

```text
1. STU-001 Create student lifecycle module scaffold
2. STU-002 Replace unsafe student identifier generation
3. STU-003 Extract StudentService create flow
4. STU-004 Extract GuardianService and HouseholdService
5. STU-005 Extract EnrollmentService
6. STU-006 Extract AssignmentService
7. STU-007 Add StudentLifecycleStateMachine
8. STU-008 Extract PromotionService
9. STU-009 Add Islamic Sunday School student profile extension
10. STU-010 Add student lifecycle architecture tests
```

Do not start with reports or cosmetic model renaming. Fix identity, creation, relationships, enrollment, and promotion first. Reports can wait their turn like everyone else in the bureaucracy.
