fixed migrations

This commit is contained in:
Dmitri 2026-06-25 16:10:48 +02:00
parent 7331acc913
commit ad27624607
8 changed files with 66 additions and 22 deletions

4
.gitignore vendored
View File

@ -10,4 +10,6 @@ node_modules/
!.env.example !.env.example
!*.env.example !*.env.example
.codex .codex
AGENTS.md AGENTS.md
education-support-management/

View File

@ -108,8 +108,10 @@ Associations (`belongsTo`): `organization`, `campus`, `user`, `createdBy`, `upda
## Tests ## Tests
- `src/services/staff_attendance.test.ts` verifies school report scope includes both school-owned - `src/services/staff_attendance.test.ts` verifies school report scope includes both school-owned
users and campuses under the school, and that school-scope office attendance upserts are scoped to users and campuses under the school, summary completion counts for fill-only users, school-scope
school office users. office attendance upserts, and campus/class staff upserts that store the resolved campus.
- `src/db/seeders/user-roles.test.ts` verifies the seeded attendance filler/report-reader roles,
including notification eligibility through `FILL_ATTENDANCE` or `READ_STAFF_ATTENDANCE_REPORTS`.
## Related ## Related

View File

@ -62,15 +62,19 @@ record when `req.params.id`/`req.body.id` equals their own id.
otherwise `ValidationError('errors.forbidden.message')`. otherwise `ValidationError('errors.forbidden.message')`.
- `create` rejects a duplicate email (`iam.errors.userAlreadyExists`) and a missing email - `create` rejects a duplicate email (`iam.errors.userAlreadyExists`) and a missing email
(`iam.errors.emailRequired`). (`iam.errors.emailRequired`).
- Teacher users can be seeded with `CREATE_USERS` / `UPDATE_USERS` so they can manage student and - Teacher users are seeded with `CREATE_USERS` / `UPDATE_USERS` and
guardian accounts from `/my-class`. Service-level role policy limits that access to the `student` `CREATE_GUARDIAN_STUDENTS` so they can manage student and guardian accounts from `/my-class`.
and `guardian` target roles. Class-scope guards require student targets and requested `classId` Service-level role policy limits that access to the `student` and `guardian` target roles.
values to match the teacher's own `classId`; guardian updates require an existing Class-scope guards treat a student as in the teacher's class when either `users.classId` matches
`guardian_students` link to a student in the teacher's class. Class-scoped user management cannot or an active `class_enrollments` row links the student to that class. Requested student `classId`
add custom permissions or permission exclusions. values must stay unset or match the teacher's own class. Guardian updates require an existing
`guardian_students` link to a student in the teacher's class, using the same direct-class or
enrollment-backed membership rule. Class-scoped user management cannot add custom permissions or
permission exclusions.
- Guardian-student links are handled by `guardian_students`. Teachers also receive - Guardian-student links are handled by `guardian_students`. Teachers also receive
`CREATE_GUARDIAN_STUDENTS`; the link service verifies class-scoped actors only link `guardian` `CREATE_GUARDIAN_STUDENTS`; the link service verifies class-scoped actors only link `guardian`
users to `student` users in their own class. users to `student` users in their own class, including students whose class membership is stored
only in `class_enrollments`.
## Tenant Scope ## Tenant Scope
@ -96,9 +100,11 @@ hook trims `email`/`firstName`/`lastName`; for non-local OAuth providers `before
`emailVerified = true` and generates a random bcrypt password when none is supplied. `emailVerified = true` and generates a random bcrypt password when none is supplied.
Associations: `belongsToMany permissions` as `custom_permissions` (and `custom_permissions_filter` Associations: `belongsToMany permissions` as `custom_permissions` (and `custom_permissions_filter`
for list filtering) through `usersCustom_permissionsPermissions`; `hasMany messages` as `messages_sent_by`; `belongsTo roles` as `app_role`; `belongsTo for list filtering) through `usersCustom_permissionsPermissions`; `hasMany messages` as
organizations` as `organizations`; `hasMany file` as `avatar`; `belongsTo users` as `messages_sent_by`; `belongsTo roles` as `app_role`; `belongsTo organizations` as
`createdBy`/`updatedBy`. `organizations`; `belongsTo classes` as `class`; `hasMany class_enrollments` as
`class_enrollments_student` for enrollment-backed student class display and scope checks;
`hasMany file` as `avatar`; `belongsTo users` as `createdBy`/`updatedBy`.
On `create`/`bulkImport` the repository sets `emailVerified` to `true` on single create and to On `create`/`bulkImport` the repository sets `emailVerified` to `true` on single create and to
`false` (unless supplied) on bulk import. A user created without an explicit `app_role` has no role and falls back to the `guest` role `false` (unless supplied) on bulk import. A user created without an explicit `app_role` has no role and falls back to the `guest` role
@ -136,7 +142,14 @@ List filters (`findAll`): `id`, `firstName`, `lastName`, `phoneNumber`, `email`,
## Tests ## Tests
None yet (no `users` unit/e2e test under `src/`). - `src/services/users.test.ts` covers teacher create/update access for student and guardian
accounts, including enrollment-backed students that do not have a direct `users.classId`.
- `src/services/guardian_students.test.ts` covers class-scoped guardian-student linking for
enrollment-backed students and rejects links outside the teacher's class.
- `src/services/shared/role-policy.test.ts` covers the role-management matrix, including teacher
limits to student and guardian accounts.
- `src/db/seeders/user-roles.test.ts` covers the seeded teacher roster-management permission
grants.
## Related ## Related

View File

@ -1 +1,11 @@
export { default } from './20260623090000-grant-teacher-student-user-management'; import type { QueryInterface } from 'sequelize';
export default {
up: async (_queryInterface: QueryInterface) => {
// Kept as a timestamp marker for deployments that saw the intermediate
// backfill name. The canonical idempotent grant is 20260623090000.
},
down: async (_queryInterface: QueryInterface) => {
// No-op by design; teacher roster permissions are baseline role grants.
},
};

View File

@ -1 +1,11 @@
export { default } from './20260623090000-grant-teacher-student-user-management'; import type { QueryInterface } from 'sequelize';
export default {
up: async (_queryInterface: QueryInterface) => {
// Kept as a timestamp marker for deployments that saw the intermediate
// guardian-link backfill name. The canonical idempotent grant is 20260623090000.
},
down: async (_queryInterface: QueryInterface) => {
// No-op by design; teacher guardian-link permission is a baseline role grant.
},
};

View File

@ -88,6 +88,7 @@ API/data access layer:
## Verification ## Verification
- `frontend/src/business/campus-attendance/selectors.test.ts` covers attendance calculations, scope titles, staff daily summaries, and staff-only summary selectors. - `frontend/src/business/campus-attendance/selectors.test.ts` covers attendance calculations, scope titles, staff daily summaries, and staff-only summary selectors.
- `frontend/src/business/campus-attendance/printReport.test.ts` covers printable report generation with separate student, staff, and combined attendance totals. - `frontend/src/business/campus-attendance/printReport.test.ts` covers printable staff-attendance
report generation and no-data labels.
- `frontend/src/business/campus-attendance/printReport.test.ts` covers blocked-popup handling for attendance report printing. - `frontend/src/business/campus-attendance/printReport.test.ts` covers blocked-popup handling for attendance report printing.
- `frontend/src/business/campus-attendance/mappers.test.ts` covers API DTO mapping. - `frontend/src/business/campus-attendance/mappers.test.ts` covers API DTO mapping.

View File

@ -20,6 +20,8 @@ linked guardian accounts for each student.
- The page requires the signed-in user to have a `classId`; otherwise it shows the existing - The page requires the signed-in user to have a `classId`; otherwise it shows the existing
unassigned-class message. unassigned-class message.
- The Students section lists class-scoped student users from `GET /api/users?classId=<classId>`. - The Students section lists class-scoped student users from `GET /api/users?classId=<classId>`.
Backend listing includes both direct `users.classId` matches and students linked through
`class_enrollments`, which is how the seeded class roster is represented.
- The add/edit form is collapsible. It is fixed to the current class, the seeded `student` role id, - The add/edit form is collapsible. It is fixed to the current class, the seeded `student` role id,
and the seeded `guardian` role id. It does not show arbitrary role, tenant, or custom-permission and the seeded `guardian` role id. It does not show arbitrary role, tenant, or custom-permission
controls. controls.
@ -36,14 +38,16 @@ linked guardian accounts for each student.
- The UI enables create/edit controls only when the current user has `CREATE_USERS` or - The UI enables create/edit controls only when the current user has `CREATE_USERS` or
`UPDATE_USERS`, a current `classId`, and the `student` / `guardian` role ids have loaded. `UPDATE_USERS`, a current `classId`, and the `student` / `guardian` role ids have loaded.
- Backend user service guards remain authoritative: class-scoped users can only manage student - Backend user service guards remain authoritative: class-scoped users can only manage student
accounts in their own class and guardian accounts linked to students in their own class. The accounts in their own class and guardian accounts linked to students in their own class. Direct
guardian-student link service also verifies that class-scoped links connect a `guardian` user to `users.classId` and `class_enrollments` membership both count as own-class membership, so seeded
a `student` user in the teacher's own class. Class-scoped user management cannot add custom enrollment-backed students can be edited from `/my-class`. The guardian-student link service also
permissions or permission exclusions. verifies that class-scoped links connect a `guardian` user to a `student` user in the teacher's
own class. Class-scoped user management cannot add custom permissions or permission exclusions.
## Tests ## Tests
- `frontend/src/business/my-class/selectors.test.ts` covers payload normalization and permission / - `frontend/src/business/my-class/selectors.test.ts` covers payload normalization and permission /
class / role gating. class / role gating.
- Backend coverage lives in `backend/src/services/users.test.ts`, - Backend coverage lives in `backend/src/services/users.test.ts`,
`backend/src/services/guardian_students.test.ts`,
`backend/src/services/shared/role-policy.test.ts`, and `backend/src/db/seeders/user-roles.test.ts`. `backend/src/services/shared/role-policy.test.ts`, and `backend/src/db/seeders/user-roles.test.ts`.

View File

@ -35,6 +35,7 @@ Current coverage includes architecture guardrails, API/data-access behavior, and
- `frontend/src/business/esa-funding/selectors.test.ts` - `frontend/src/business/esa-funding/selectors.test.ts`
- `frontend/src/business/frame/mappers.test.ts` - `frontend/src/business/frame/mappers.test.ts`
- `frontend/src/business/frame/selectors.test.ts` - `frontend/src/business/frame/selectors.test.ts`
- `frontend/src/business/my-class/selectors.test.ts`
- `frontend/src/business/audio-files/selectors.test.ts` - `frontend/src/business/audio-files/selectors.test.ts`
- `frontend/src/business/audio-files/generate.test.ts` - `frontend/src/business/audio-files/generate.test.ts`
- `frontend/src/business/zone-checkin/selectors.test.ts` - `frontend/src/business/zone-checkin/selectors.test.ts`
@ -67,6 +68,7 @@ Current coverage includes architecture guardrails, API/data-access behavior, and
- `frontend/src/shared/api/contentCatalog.test.ts` - `frontend/src/shared/api/contentCatalog.test.ts`
- `frontend/src/shared/api/frame.test.ts` - `frontend/src/shared/api/frame.test.ts`
- `frontend/src/shared/api/httpClient.test.ts` - `frontend/src/shared/api/httpClient.test.ts`
- `frontend/src/shared/api/guardianStudents.test.ts`
- `frontend/src/shared/api/personality.test.ts` - `frontend/src/shared/api/personality.test.ts`
- `frontend/src/shared/api/safetyQuizResults.test.ts` - `frontend/src/shared/api/safetyQuizResults.test.ts`
- `frontend/src/shared/api/staffAttendance.test.ts` - `frontend/src/shared/api/staffAttendance.test.ts`
@ -81,7 +83,7 @@ Current coverage includes architecture guardrails, API/data-access behavior, and
- `frontend/src/hooks/usePermissions.test.tsx` - `frontend/src/hooks/usePermissions.test.tsx`
- `frontend/src/components/sign-in-modal/SignInForm.test.tsx` - `frontend/src/components/sign-in-modal/SignInForm.test.tsx`
These tests verify import-boundary enforcement, centralized network access through `shared/api/httpClient`, alias-only source imports, required API contract-test coverage, HTTP client request normalization, cookie-backed auth refresh behavior, JSON body serialization, empty response handling, backend error propagation, API wrapper endpoint/query/body contracts, shared list/query/error helpers, route config, module route metadata, module access correction, sidebar navigation selectors, mobile sidebar overlay visibility, auth display/profile mapping, signup validation, campus mapping, dashboard and director dashboard selectors, classroom support selectors including search over titles/descriptions and favorites-only filtering, timer formatting/progress/threshold parsing, DTO mapping, FRAME edit access, campus attendance mapping, calculations, and printable report output, staff attendance mapping and rollups, walkthrough create DTO mapping, walkthrough filtering, walkthrough check-in stats/history mapping, walkthrough scoring, generated summaries, repeated low-rating flags, communication role visibility, community catalog filtering and stats, ESA funding selectors, policy mapping/filtering/validation, safety-protocol mapping and authoring (steps/considerations) validation, audio-library management gating and the local recipe-generation stub, daily Zone check-in eligibility/nudge/completion API, QBS/EI/personality completion reminders, header search over accessible modules + their content, outside-click dismissal, the shared American (Sunday-start) week canonicalization, F.R.A.M.E. week/label mapping, safety quiz compliance mapping and editable payload validation, unified profile quiz result rows including Daily Zone Check-In, sign language selectors, top bar display selectors, user progress normalization including Classroom Support favorite list/upsert API contracts, vocational zip/category/search/stat calculations, zones selectors, personality DTO mapping, personality distribution grouping, EI thresholds, personality quiz progress, and MBTI-derived communication guidance. These tests verify import-boundary enforcement, centralized network access through `shared/api/httpClient`, alias-only source imports, required API contract-test coverage, HTTP client request normalization, cookie-backed auth refresh behavior, JSON body serialization, empty response handling, backend error propagation, API wrapper endpoint/query/body contracts, guardian-student API contracts, shared list/query/error helpers, route config, module route metadata, module access correction, sidebar navigation selectors, mobile sidebar overlay visibility, auth display/profile mapping, signup validation, campus mapping, dashboard and director dashboard selectors, classroom support selectors including search over titles/descriptions and favorites-only filtering, timer formatting/progress/threshold parsing, DTO mapping, FRAME edit access, My Class student/guardian payload normalization and permission gating, campus attendance mapping, calculations, and printable staff report output, staff attendance mapping and rollups, walkthrough create DTO mapping, walkthrough filtering, walkthrough check-in stats/history mapping, walkthrough scoring, generated summaries, repeated low-rating flags, communication role visibility, community catalog filtering and stats, ESA funding selectors, policy mapping/filtering/validation, safety-protocol mapping and authoring (steps/considerations) validation, audio-library management gating and the local recipe-generation stub, daily Zone check-in eligibility/nudge/completion API, QBS/EI/personality completion reminders, header search over accessible modules + their content, outside-click dismissal, the shared American (Sunday-start) week canonicalization, F.R.A.M.E. week/label mapping, safety quiz compliance mapping and editable payload validation, unified profile quiz result rows including Daily Zone Check-In, sign language selectors, top bar display selectors, user progress normalization including Classroom Support favorite list/upsert API contracts, vocational zip/category/search/stat calculations, zones selectors, personality DTO mapping, personality distribution grouping, EI thresholds, personality quiz progress, and MBTI-derived communication guidance.
The component and hook tests verify SignInForm rendering, loading states, user interactions, form submission, password visibility toggling, auth session initialization, sign-in/sign-out flows, AuthExpiredError handling, modal workflow state management, and permissions hook behavior including has(), hasAny(), hasAll() methods with globalAccess support and explicit personal-workflow exclusions. The component and hook tests verify SignInForm rendering, loading states, user interactions, form submission, password visibility toggling, auth session initialization, sign-in/sign-out flows, AuthExpiredError handling, modal workflow state management, and permissions hook behavior including has(), hasAny(), hasAll() methods with globalAccess support and explicit personal-workflow exclusions.