---
description: Cross-module integration verification. Check every dependency before committing.
globs: ["app/Domain/**", "database/migrations/**"]
---

# Integration Checks — Before Every Commit

## When Writing a Migration

- [ ] Column names match the exact names in `docs/rules/11-integration-contract.md`
- [ ] FK references point to tables that ALREADY EXIST (check migration order)
- [ ] CHECK constraint values exactly match the enum you'll write
- [ ] Composite unique constraints include `academy_id`
- [ ] No duplicate indexes (morphs and constrained() already create them)

## When Writing a Model

- [ ] `$fillable` lists EVERY column from migration (except id, timestamps, auto-fields)
- [ ] `$casts` match column types: bigint→'integer', jsonb→'array', date→'date', bool→'boolean'
- [ ] Enum casts use the correct enum class with matching values
- [ ] Relationships match FK direction (belongsTo where FK lives, hasMany on the other side)
- [ ] Traits applied: BelongsToAcademy, HasUuid, SoftDeletes, Auditable (as applicable)

## When Writing a Service

- [ ] Wrapped in DB::transaction
- [ ] Does NOT use auth(), request(), session()
- [ ] Dispatches events (does not send notifications directly)
- [ ] Validates business rules (state machine transitions, balance checks)
- [ ] Calls other services via constructor injection (not facades, not static)
- [ ] Updates ALL denormalized fields that this operation affects

## When Writing a Livewire Component

- [ ] mount() has $this->authorize() call
- [ ] rules() validation matches migration constraints character-for-character
- [ ] messages() has Arabic translations for every rule
- [ ] Query applies PermissionService::applyScope()
- [ ] try/catch around service calls with proper error handling
- [ ] Flash messages in Arabic
- [ ] Redirects to named routes

## When Writing a View

- [ ] No `href="#"` anywhere
- [ ] All links use `route()` helper
- [ ] All strings in `__()`
- [ ] All Tailwind uses logical properties (ms/me/ps/pe not ml/mr/pl/pr)
- [ ] Buttons/links wrapped in `@can()` for permission
- [ ] Loading states on all submit buttons
- [ ] Empty states for all lists

## Cross-Module Impact Checklist

When modifying enrollment:
- [ ] Group.current_count updated
- [ ] Attendance records generated/removed
- [ ] Invoice created (if fee > 0)
- [ ] Waitlist checked (if spot opened from cancellation)
- [ ] Participant status updated (registered → active on first enrollment)

When recording payment:
- [ ] Invoice.paid_amount updated
- [ ] Invoice.balance_due recalculated
- [ ] Invoice.status transitions if fully paid
- [ ] Double-entry transactions created
- [ ] Cash session updated (if cash)
- [ ] Wallet deducted (if wallet)
- [ ] Enrollment activated (if pending enrollment invoice now paid)

When cancelling session:
- [ ] Attendance records set to 'cancelled'
- [ ] Space reservation freed
- [ ] Affected people notified
- [ ] Session status set correctly

When changing participant status:
- [ ] Enrollments handled (frozen = pause, suspended = block new)
- [ ] Attendance expectations adjusted
- [ ] Financial impact handled (freeze stops billing)
- [ ] Notifications sent to guardian
