REFERENCE¶
Read this first for a non-trivial task. AGENTS.md and CLAUDE.md govern workflow; this file locates the relevant code and chapter. Read the task's chapter, then the smallest useful set of source files. For a new checkout, start with Getting Started.
1. System at a glance¶
SIS is a multi-tenant K-12 school system: a NestJS modular monolith, Prisma, and PostgreSQL. The API also serves an internal backoffice SPA; timetable generation calls a separate Python solver. Architecture explains ownership and request boundaries.
The handbook documents implemented behavior and durable engineering rules. Stories and approved designs inform changes, but do not prove that a route or behavior exists. Check the source before changing a contract; follow the root design gate for unexplored work.
2. Mental model¶
| Concept | Meaning | Read |
|---|---|---|
| Tenant | School boundary enforced by service predicates and database RLS; global/auth-private data has explicit exceptions. | 02 |
| Academic year | Additional boundary for annual records. A read-year selector does not authorize a write; each domain applies its lifecycle rules. | 05, 08 |
| Login identity and school User | Global credential versus school-local membership, grants, and established person type. A membership ends with its last bound person row. | 03 |
| Profile and view | Person identity selected for a session versus the optional role view that narrows its grants. | 03, 04 |
| Entity, scope, action | Resource key, field/sub-resource capability, and operation capability. Record policies additionally determine which rows are reachable. | 04 |
| Valid time | Placement, selection, roster, teaching, and timetable facts effective on a school-local date; forward metadata is not historical authority. | 14, 19 |
| Transaction and deferred effects | Database invariants commit atomically; external effects wait for the real outer commit. | 02, 16 |
| Domain response | Explicit DTO and visibility projection, rather than a raw Prisma record. | 05, 13 |
3. Request lifecycle¶
The application applies global origin/rate-limit controls. A protected resource composes JWT authentication, scope/action checks, field-write checks, role admission, and response filtering.
- Authentication establishes the school User, tenant, and active session view.
- Guards load effective permissions and assignment parameters. Guard-time tenant reads use their explicit GUC boundary.
TenantTransactionInterceptoropens the handler's tenant transaction, sets the tenant GUC, and publishes the transaction through CLS.- Validated controller inputs reach services; services enforce row visibility, write authority, and domain invariants through owner queries.
FieldFilterInterceptorprojects permitted scope groups where applicable. Flat and aggregate responses have explicit contracts.- The outer transaction commits before
PostCommitCoordinatordrains deferred jobs. Rollback discards them.
@NoTenantTx routes own explicit transaction phases. AllExceptionsFilter renders failures as { statusCode, code, messages, timestamp, path, field?, data? }; internal message parameters are not wire fields.
Entry points: main.ts, app.module.ts, ProtectedResource, tenant transaction interceptor, exception filter.
4. Module map¶
Paths below are under src/ unless explicitly rooted elsewhere. Modules expose their contracts through their barrels and Nest provider exports; not every module has a controller or uses the generic CRUD base.
| Area | Ownership | Chapter |
|---|---|---|
auth/, profile/, users/ |
Credentials, school/session selection, recovery, own profile, school User directory. | 03 |
invitations/ |
School-local onboarding, account compatibility, durable credential delivery. | 03, 08 |
permissions/ |
Catalogue, effective grants, assignment parameters, guards, policies, role assignment and presets. | 04 |
prisma/, post-commit/ |
Database clients, RLS classifications, ambient transaction routing, deferred effects. | 02 |
common/ |
Shared DTOs, errors, CRUD/import primitives, temporal and policy utilities. | 05, 06, 13 |
students/ |
Annual students, placements, selections, guardians, relationship projections, imports and documents. | 05, 07, 14 |
teachers/, staff/, referents/ |
Employee and family profiles, links, imports where supported, own-record and document access. | 03, 05, 07 |
school/, academic-years/, departments/ |
School configuration, year lifecycle, grades, departmental calendars and periods. | 08, 14 |
rooms/ |
Rooms, lunch shifts, room-type catalogue and imports. | 07, 17 |
curriculum/, evaluation-scales/, subject-levels/ |
Curriculum grid, selection windows, scales, levels, consistency rules. | 14, 21 |
homerooms/, subject-groups/ |
Classes, courses, rosters, combined classes, teaching assignments, eligibility and placement views. | 14 |
filters/ |
Authorized browsing options and structural contexts; option visibility is not write authority. | 14, 04 |
setup/, command-center/ |
Setup state machine, rollover, completeness/onboarding/selection worklists and next steps. | 08, 14 |
custom-fields/ |
Definition management, validation and response projection, subject to catalogue grants and the visibility flag. | 04, 05 |
files/ |
Blob validation/storage, file ownership, signed reads and cleanup. | 05 |
timetable-templates/, timetables/, root solver/ |
Generation inputs, manual schedule/version lifecycle, diagnostics, teacher commitments, solver integration. | 18 |
attendance/ |
Dated register, expected attendance, school/family views, justifications and follow-up loop. | 19 |
audit-log/ |
Transactional audit writes and localized, navigable read projections. | 20 |
grades/ |
Grade revision ledger, calculation evidence, corrections, withdrawal and aggregate reads. | 21 |
notifications/, mailer/ |
Private notification inbox, email/push transports, device registration and delivery callbacks. | 23, 24 |
communications/ |
Recipient authority, mailing groups, queued sends, delivery ledger and own inbox/archive. | 24 |
disciplinary-notes/ |
School notes, family delivery, acknowledgement and withdrawal. | 25 |
assignments/ |
Homework/tests, lesson summaries, attachments and school/family projections. | 26 |
reports/ |
Finite catalogue, private settings, durable report runs, frozen results and exports. | 27 |
report-cards/ |
Report-card templates and cycles, card values, frozen card documents, publication and the family read. | 28 |
conferences/ |
Parent–teacher conferences: status machine, appointment grid and its diff, availability by caller, the locked booking transaction, cancellation and the in-app cancellation notice. | 29 |
report-v2/ |
Live people reports: population registry, synchronous query engine, private saved configurations and exports. | 27 |
tenants/, curriculum-presets/, root backoffice/ |
Platform onboarding and catalogue administration. | 17 |
config/, logger/, health/ |
Environment validation, request logging, liveness/readiness. | 10 |
5. Cross-cutting invariants¶
- Tenant isolation: derive tenant identity from the authenticated context, never a payload. Use tenant predicates even with RLS. Classify models in
rls-coverage.ts; required-tenant models also belong intenanted-models.ts. Administrative bypasses need an explicit owner. 02 - Real commit boundary: nested service transactions join the ambient request transaction. Use named route budgets; do not flush external effects at an inner callback's return. Background or exempt flows own their GUC and commit boundaries. 02
- Grant and row authority: route admission, record reach, and response visibility are separate. Qualified role slices retain the parameters of the assignment supplying the grant; unrelated roles must not lend authority to one another. 04
- Policy composition: use
resolvePolicyWherefor resolved policies. Share owner queries and onePolicyEvaluationrather than nesting complete authorization graphs or synchronously calling an asynchronous predicate. 04 - Safe query composition: intersect tenant, year, visibility, and user filters with
AND; object spreading must not overwrite an existingOR. Sensitive filters require their own read check because IDs/counts also disclose information. 05 - School time: capture school-local date/time once per command. Resolve current, pending, and slot-level interval evidence with the appropriate temporal helper; do not authorize from forward-head columns. Preserve graph/row/day-lock ordering and CAS checks. 14, 19
- Participation: live operational populations use
participatingStudentWhere; dated register populations pairparticipationHistoryStatusWherewith interval evidence. Directory, rollover, and selection workflows have deliberately different status contracts. 14, 19 - Scheduling: lesson duration resolves
slotDuration ?? resolvedDuration ?? curriculum cascade. Templates are generation inputs. Non-timetable saves can request diagnostic review after commit; the header is not evidence of a violation. 18, 06 - Historical evidence: attendance snapshots, grade revisions, structural intervals, and audit events have different owners. Preserve each domain's immutable evidence rather than reconstructing history from mutable present-day rows. 19, 20, 21
- Errors and public docs: domain code throws
AppException(code, status, { params, data }); the backend renders bilingual messages. Controller and DTO JSDoc is public OpenAPI copy; backend mechanisms belong in services or inline comments. 06, 22 - Module contracts: consume exported services/queries by importing their provider module into the consuming module.
AppModuleregistration alone does not make providers available to consumers. 05 - Schema safety: read Migrations before migration work. Preserve raw SQL constraints, policies, triggers, and registries as well as the Prisma schema.
- Verification authorization: do not run builds, tests, lint, or other verification commands unless the user explicitly asks; root instructions govern execution.
6. File index — if touching X, open Y first¶
Paths are repository-relative. Directory entries identify the owner; open the relevant controller/service/query and DTO rather than reading the entire directory.
| Task | Open first | Chapter |
|---|---|---|
| Local setup or commands | package.json, .env.template, docker-compose.yml, prisma.config.ts |
00 |
| Add a field, scope, or endpoint | Owning dto/, controller/service/queries/swagger; src/common/constants/scope-fields.ts; prisma/seed/rbac-catalogue.ts |
11, 05 |
| Add a domain or shared concern | Owning module/barrel, src/app.module.ts, prisma/schema.prisma, src/common/constants/entity-keys.ts; root design gate |
16, 11 |
| Change tenant transactions or bypasses | src/prisma/prisma.service.ts, src/prisma/admin-prisma.service.ts, src/prisma/rls-coverage.ts, src/prisma/tenanted-models.ts; src/common/utils/tenant-guc.ts; tenant transaction interceptor |
02 |
| Defer external effects or change transaction budgets | src/post-commit/, src/common/interceptors/tenant-transaction.interceptor.ts, src/common/decorators/tenant-tx-budget.decorator.ts |
02, 16 |
| Login, school selection, profile/view switching | src/auth/auth.service.ts, src/auth/auth.controller.ts, src/auth/cookie-helper.service.ts, src/auth/utils/session-views.ts; src/common/utils/narrow-roles.ts |
03 |
| Shared identity, local account type, password recovery | src/auth/identity/, src/auth/password-reset/, src/config/jwt-lifetime.ts, prisma/schema.prisma |
03 |
| Invitation/account conflicts or delivery | src/invitations/invitations.service.ts, src/invitations/invitations.queries.ts, src/invitations/sender; person mutation/import callers |
03, 07, 08 |
| Own profile, canWrite, own documents | src/profile/, src/common/constants/self-editable-scopes.ts, src/common/services/base-tenanted-crud.service.ts; owning person controller/service |
04, 05 |
| Scope/action enforcement and assignment cache | src/permissions/guards/, src/permissions/interceptors/, src/permissions/permissions.service.ts, src/permissions/request-assignments.ts |
04 |
| Record policy or relationship queries | Owning *.policy.ts and *.policy.queries.ts; src/common/utils/entity-access-policy.ts, src/common/utils/policy-evaluation.ts; src/students/students.policy.queries.ts |
04 |
| Preset grants, role catalogue or reconciliation | prisma/seed/roles.ts, prisma/seed/rbac-catalogue.ts, prisma/seed/helpers/expected-preset-grants.ts; src/permissions/role-clone.ts, src/permissions/roles.controller.ts; tools/reconcile-preset-roles.ts |
04, 15 |
| Assign/revoke a management role | src/permissions/role-assignments.service.ts, src/permissions/role-assignments.queries.ts, src/permissions/role-assignments.mapper.ts, src/permissions/dto; invitation materialization |
04 |
| List search, pagination or sensitive filters | Owning list-query DTO and buildListArgsForX; src/common/utils/person-search-where.ts; src/permissions/private-data-access.ts |
05 |
| Custom fields or profile completeness | src/custom-fields/, src/common/constants/completion-required-fields.ts, src/command-center/completeness.service.ts, src/command-center/completeness.queries.ts |
04, 05, 08 |
| Student family/employee relationship flags | src/students/school-relationships.queries.ts, src/students/school-relationship-people.mapper.ts, src/students/students.service.ts |
05 |
| Guardians, links, shared identity document | src/students/guardians.service.ts, src/students/guardians.queries.ts, src/students/guardians.policy.ts, src/students/guardian-orphan-sweep.ts, src/students/dto/guardian.dto.ts |
05 |
| File upload, metadata, signed reads or cleanup | src/files/files.service.ts, src/files/storage/file-storage.port.ts; owning sub-resource's authority checks |
05 |
| Import, setup replacement or template columns | src/common/services/import-pipeline.ts, src/common/utils/import-file-parser.ts, src/common/utils/import-duplicate-checker.ts, src/common/utils/import-columns.ts; owning src/<domain>/constants/import-schema.ts and service |
07 |
| Setup step, rollover or next steps | src/setup/, src/academic-years/, src/command-center/next-steps/ |
08 |
| Department calendar and periods | src/departments/departments.service.ts, src/departments/department-periods.service.ts, src/departments/retro-calendar-guard.ts; src/common/utils/periods.ts |
08, 14 |
| Curriculum grid, hours, levels, scales or criteria | src/curriculum/curriculum-structure-sync.ts, src/curriculum/curriculum.validation.ts, src/curriculum/selection-consistency.ts; src/evaluation-scales/, src/subject-levels/ |
14, 21 |
| Selection windows or student curriculum selection | src/curriculum/selection-window.service.ts; src/students/curriculum-selection.service.ts, src/students/curriculum-selection-authority.ts, src/students/class-selection-sync.ts |
14 |
| Placement, exit/readmission or temporal boundary | src/students/student-placement.ts, src/students/student-placement.queries.ts, src/students/students.service.ts; src/common/temporal/ |
14, 19 |
| Homeroom/course CRUD, roster or eligibility | src/homerooms/, src/subject-groups/; their *-eligibility.ts classifiers; src/students/class-selection-sync.ts |
14 |
| Course-driven choices or homeroom cascade | src/subject-groups/course-roster-reconciliation.ts, src/subject-groups/course-roster-plan.ts, src/subject-groups/from-homeroom; src/homerooms/linked-course-cascade.ts, src/homerooms/explicit-belonging.ts |
14 |
| Tables, filters, assignable pickers or readiness counts | src/filters/; owning homeroom/course query helpers; src/command-center/selection-process.queries.ts, src/command-center/selection-process.service.ts |
14, 04 |
| Combined classes and dated shared membership | src/subject-groups/combined-classes/, src/common/temporal/enrolment-schedule-lock.ts; timetable course coverage |
14, 18 |
| Timetable lessons, breaks, activities or publication | src/timetables/timetables.service.ts, src/timetables/timetables.queries.ts, src/timetables/dto; dated lifecycle queries |
18 |
| Diagnostics or post-save review hints | src/timetables/timetables.diagnostics.ts, src/timetables/diagnostics-facts.queries.ts, src/timetables/diagnostics-cards.ts, src/timetables/timetable-review.queries.ts; src/common/utils/timetable-review-context.ts |
18, 06 |
| Lesson teachers, assistance or hour budgets | src/timetables/lesson-teachers.ts, src/timetables/lesson-teachers.queries.ts, src/timetables/lesson-assistance.service.ts, src/timetables/assistance-queries.ts, src/timetables/teacher-commitments.ts, src/timetables/teacher-budgets.queries.ts |
18 |
| Templates or automatic generation | src/timetable-templates/, src/timetables/generation/, solver/app/ |
18 |
| Attendance expected schedule, reads or taking | src/attendance/expected/, src/attendance/attendance-board.service.ts, src/attendance/attendance-planning.ts, src/attendance/attendance.service.ts |
19 |
| Attendance authorization or teacher day | src/attendance/attendance.policy.ts, src/attendance/attendance-access.service.ts, src/attendance/attendance-authority.ts, src/attendance/attendance-teacher.service.ts |
19, 04 |
| Family attendance, justifications, follow-ups | src/attendance/attendance-family.service.ts, src/attendance/attendance-justifications.service.ts, src/attendance/attendance-justifications.read.service.ts, src/attendance/attendance-loop.service.ts, src/attendance/attendance-notifier.service.ts |
19 |
| Audit event or presentation/navigation | src/audit-log/, especially structural vocabulary and presentation resolver; the producer's transaction |
20 |
| Grade recording, correction, history or aggregates | src/grades/grades.service.ts, src/grades/grades.visibility.ts, src/grades/grades.scale-snapshot.ts, src/grades/grades.scale-context.ts, src/grades/dto |
21 |
| Error code, translated label or frontend rendering | src/common/constants/error-codes.ts, src/common/constants/error-examples.ts, src/common/i18n/, src/common/filters/all-exceptions.filter.ts |
06, 22 |
| Notification kind, target, inbox or push registration | src/notifications/ registries, read service and push registration/sender; producer's post-commit seam |
23 |
| Automatic family milestones | src/command-center/notification-milestones.service.ts, src/command-center/notification-milestones.queries.ts, src/command-center/notification-milestones.config.ts |
23, 08 |
| Communication recipients, groups, send or delivery | src/communications/recipient-policy.ts, src/communications/recipient-policy.queries.ts, src/communications/mailing-groups, src/communications/communications.service.ts, src/communications/sender; src/mailer/resend/ |
24 |
| Communication inbox or receipt notification | src/communications/inbox/, src/communications/communications-notifications.service.ts, src/communications/communications-notifications.queries.ts |
24, 23 |
| Disciplinary notes, family ACK or withdrawal | src/disciplinary-notes/ service/policy/queries and notifier |
25 |
| Assignments, lesson summaries or attachments | src/assignments/, especially src/assignments/assignments-attachments.service.ts and owning school/family policies |
26 |
| Report catalogue, private settings or compatibility | src/reports/catalogue/, src/reports/saved/, src/reports/reports.access.ts, src/reports/catalogue/report.compatibility.ts |
27 |
| Report worker, frozen results, preview or export | src/reports/runs/, src/reports/export/, src/reports/reports.config.ts; source-domain src/<domain>/reporting/ or src/<domain>/reporting.queries.ts |
27 |
| Attendance report measures | src/attendance/reporting/, src/attendance/expected/expected-attendance.resolver.ts; src/reports/runs/report.source.ts |
27, 19 |
| Report-card templates, cycles, values, generation or family read | src/report-cards/: authority shared/report-cards.access.ts, structure structure/, status status/card-status.ts, versioned JSON shared/snapshots.ts, attendance attendance/ |
28, 19 |
| Parent–teacher conferences: grid, status, availability, booking or cancellation | src/conferences/: pure rules conference-grid.ts, conference-dates.ts, conference-status.ts, conference-availability.ts; locks and eligibility conferences.queries.ts; booking conferences-family.service.ts; cancellation conferences-bookings.service.ts |
29, 23 |
| Platform onboarding, reset or preset editor | src/tenants/, src/curriculum-presets/, backoffice/src/, src/permissions/role-assignments.queries.ts |
17 |
| Schema, migration or raw database invariant | prisma/schema.prisma, prisma/migrations/, src/prisma/rls-coverage.ts, test/db-constraints.e2e-spec.ts |
12 |
| Seed data or fixture drift | prisma/seed.ts, prisma/seed/, tools/reconcile-preset-roles.ts |
15 |
| Test design or mock boundary | Owning spec, src/common/testing/, test/helpers/, Jest config |
09 |
| Types and Prisma payloads | Owning query/include and interfaces/; shared DTO/data helpers |
13 |
| CI/deploy/environment | .github/workflows/, railway.toml, src/config/, src/main.ts |
10 |
| Refactor sizing or architectural boundary | Owning public barrel, providers, callers, transaction seams | 16 |
7. Glossary¶
| Term | Meaning |
|---|---|
| Referent | Login-capable parent/family profile, school-flat; student links supply year context and per-child write authority. |
| Guardian | Shared non-login caregiver profile with one identity document and separate per-student relationship/pickup/emergency facts. |
| Homeroom | Registration/form class with its own roster; courses have independent rosters. |
| Subject group / course | Teaching section for a curriculum subject and grade. An optional homeroom link supports the explicit roster cascade. |
| Combined class | Shared teaching unit across member courses; members retain course-level identity. |
| Curriculum grid | Subjects, tracks and option blocks with positive-hours cells for the grades where subjects are taught. |
| Study-plan projection | A student's selected curriculum/track/choices, mapped from the grid and dated selection; not a separate StudyPlan model. |
| Forward head | Terminal planned metadata used by a defined display/planning contract; never a substitute for dated authority. |
| Structural audit | Transaction-time account of a valid-time command, anchored to a stable domain identity. |
| Bootstrap year | Hidden sentinel used to anchor a provisioned employee administrator before school setup. |
| Aggregate response | Deliberately mapped response that bypasses ordinary scope-group stripping and must enforce its own constituent visibility. |
8. Chapter directory¶
| Chapter | Topic |
|---|---|
| 00 | Local setup and command entry points |
| 01 | Architecture and ownership |
| 02 | Tenant isolation and transactions |
| 03 | Authentication, profiles, recovery and onboarding |
| 04 | Permissions and record authority |
| 05 | Modules, DTOs, queries and files |
| 06 | Backend errors and localization |
| 07 | Imports and column metadata |
| 08 | Setup, rollover and operational readiness |
| 09 | Test design, mocks and fixtures |
| 10 | Configuration, CI and deployment |
| 11 | Implementation recipes |
| 12 | Schema and migration safety |
| 13 | Type boundaries and DTO contracts |
| 14 | Curriculum, classes, courses and temporal placement |
| 15 | Seed tiers, presets and fixtures |
| 16 | Change boundaries and maintainability |
| 17 | Platform backoffice and onboarding |
| 18 | Scheduling, diagnostics and generation |
| 19 | Register, expected attendance and family loop |
| 20 | Audit persistence and read presentation |
| 21 | Grade ledger and aggregate views |
| 22 | Client error handling |
| 23 | Notification inbox, email and push |
| 24 | Email communications and mailing groups |
| 25 | Disciplinary notes and acknowledgement |
| 26 | Assignments, lesson summaries and attachments |
| 27 | Reporting and export lifecycle |
| 28 | Report-card templates, cycles, generation and family read |
| 29 | Parent–teacher conferences: status, grid, availability, booking and cancellation |
9. Maintaining the handbook¶
Top-level numbered chapters and this reference are durable documentation. Describe implemented contracts, invariants, rationale, reusable procedures, and canonical source locations.
Update the owning section in place when behavior changes, remove obsolete claims, and reconcile related examples and links. Do not append a correction that leaves contradictory text above it. Do not add commit hashes, release dates, implementation/iteration diaries, test-run totals, unrun-check notices, rollout status, handoff checklists, pending work, or speculative plans.
Keep task history and execution evidence in the task conversation or its separately scoped artifacts. A durable compatibility rule may name a real persisted schema/API version and supported behavior; it must not become a release narrative. Workflow references to design artifacts belong in the root instructions, not in chapter authority chains.
This file remains a map: one concise task row and chapter pointer are usually enough. Explanations belong in their owning chapter; avoid copied inventories of grants, tables, error codes, or migrations that already have an authoritative registry in code.