Exact wire contract for every screen → endpoint. Base /api/v1; envelope per
00-shared/07 . All endpoints from src/modules/homework/homework.controller.ts;
business rules from homework.service.ts; attachments from files.controller.ts.
Guard: @UseGuards(JwtAuthGuard) (homework.controller.ts:19) — no RBAC metadata
(OQ-9). Tenant from JWT only; never in body (tenant is injected by
BaseRepository, base.repository.ts:24-29).
Aspect Contract
Base https://api.<domain>/api/v1
Headers Authorization: Bearer <accessToken>; x-request-id; Content-Type: application/json; multipart for /files/upload
Response {success, message:"OK", data, meta?, timestamp, requestId} (response-envelope.interceptor.ts:49-52)
Error {success:false, message, error:{code, details?}, timestamp, requestId} (http-exception.filter.ts:73-81)
Pagination homework/submissions are non-paginated arrays (no meta) — render all
Caching client list cache TTL 5 min; detail no cache (00-shared/06 §3.3 )
Offline reads cached; writes blocked (create/submit/grade) except attachment upload retry
Retry backoff on 5xx/network; no auto-retry on 429 (api tier 100/min)
Endpoint GET /api/v1/homework/class/:classId
Params classId (MongoId)
Success 200 data: [HomeworkDoc…] sorted dueDate desc (homework.repository.ts:20)
Source homework.controller.ts:25-27
Errors 404/400 invalid id (CastError → 400 VALIDATION_ERROR, http-exception.filter.ts:47-55); 5xx
Student variant client resolves own classId from profile (PLAN.md:67 endpoint missing — OQ-6)
Pagination none (full array)
HomeworkDoc shape (homework.schema.ts:8-35 + BaseSchema):
_id, tenantId, teacherId, classId, subjectId, title, description?, attachments[], assignedDate, dueDate, status: 'active'|'closed', createdAt, updatedAt, isDeleted…
Endpoint GET /api/v1/homework/:id
Success 200 data: HomeworkDoc
Errors 404 RESOURCE_NOT_FOUND "Homework not found." (homework.service.ts:47)
Endpoint POST /api/v1/homework (homework.controller.ts:22-24)
Body {teacherId, classId, subjectId, title, description?, attachments?: string[], dueDate} (homework.dto.ts:4-33; dueDate ISO date string)
Success 201 data: HomeworkDoc — server sets assignedDate: now, status: 'active' (homework.service.ts:30-32)
Side effect emits HomeworkCreated {homeworkId, classId} → in-app queue (homework.service.ts:34-41, event-queue-map.ts:22)
Errors 400 VALIDATION_ERROR (decorators: IsMongoId, IsString, IsDateString); 5xx
Endpoint PATCH /api/v1/homework/:id (homework.controller.ts:31-36)
Body any subset of {title, description, attachments, dueDate, status} (homework.dto.ts:35-58) — classId/subjectId/teacherId immutable
Success 200 data: HomeworkDoc ($set, version+1 via updateById, base.repository.ts:57-66)
Side effect emits HomeworkUpdated {homeworkId, changes[]} → in-app (homework.service.ts:59-67, event-queue-map.ts:23)
Errors 404 "Homework not found." (homework.service.ts:56-58); 400 invalid status enum value
Endpoint DELETE /api/v1/homework/:id (homework.controller.ts:37-39)
Success 200 {message:"OK"} — soft delete (homework.service.ts:70-81, base.repository.ts:68-74); submissions retained (no cascade)
Side effect emits HomeworkDeleted {homeworkId} → audit-write queue (event-queue-map.ts:26)
Errors 404 "Homework not found." (homework.service.ts:71-72)
Endpoint POST /api/v1/homework/:id/submit (homework.controller.ts:40-45)
Body {studentId, remarks?, attachments?: string[]} (submission.dto.ts:4-17)
Success 201 data: SubmissionDoc — server sets submittedAt: now, status: 'submitted' (homework.service.ts:93-98)
Side effect emits HomeworkSubmitted {homeworkId, studentId, submissionId} → in-app (homework.service.ts:99-110, event-queue-map.ts:24)
Errors 404 "Homework not found." (homework.service.ts:87); 409 DUPLICATE_RESOURCE "Already submitted." (homework.service.ts:92) + unique index (homework-submission.schema.ts:37-40); 400
Note No due-date enforcement — late accepted (OQ-1)
SubmissionDoc shape (homework-submission.schema.ts:8-32):
_id, tenantId, homeworkId, studentId, attachments[], remarks?, submittedAt, status: 'submitted'|'graded', gradedAt?, marks?
Endpoint GET /api/v1/homework/:id/submissions (homework.controller.ts:46-48)
Success 200 data: [SubmissionDoc…] insertion order (homework-submission.repository.ts:20-24)
Errors 400 invalid id; 5xx
Endpoint PATCH /api/v1/homework/:id/submissions/:submissionId/grade (homework.controller.ts:49-55)
Body {marks, remarks?} (submission.dto.ts:19-26) — marks has no validation decorator (OQ-4)
Success 200 data: SubmissionDoc — sets marks, remarks, status:'graded', gradedAt: now (homework.service.ts:127-134)
Side effect emits HomeworkGraded {homeworkId, submissionId, marks} → in-app (homework.service.ts:136-143, event-queue-map.ts:25)
Errors 404 "Submission not found." (homework.service.ts:126); 400
Regrade repeatable — overwrites + re-emits (OQ-2)
Upload POST /api/v1/files/upload multipart file field, @Permissions('file.upload') (files.controller.ts:29-41); returns FileRecord doc (file.schema.ts:8-43) incl. _id → put id in attachments[]
Download GET /api/v1/files/:id/download file.read → stream (files.controller.ts:55-64)
Meta GET /api/v1/files/:id file.read (files.controller.ts:49-53)
Delete DELETE /api/v1/files/:id file.delete (files.controller.ts:66-71) — not called by homework flows (attachment removal = homework PATCH replacing the array)
Limits none enforced server-side (size/mime) — client enforces (OQ-4/01)
Screen Loading Streaming Realtime
list AppSkeleton— (planned) WS topic; re-fetch on focus
detail skeleton — re-fetch on focus (grade may have landed)
create/edit button spinner — —
submit button spinner + per-file upload progress upload stream —
grade button spinner — —
Screen code UI
submit 409 DUPLICATE_RESOURCE "Already submitted" info state (not error)
any detail 404 RESOURCE_NOT_FOUND empty state "removed"
grade 404 back + refresh list
create/edit 400 VALIDATION_ERROR field-level errors
any 401 → refresh → fail sessionExpired
any 429 RATE_LIMITED countdown, no retry
any 5xx generic + requestId, retry
No optimistic mutations — create/submit/grade/delete are all server-confirmed
(side effects: events + notifications; 00-shared/07 §9 ).
Undo: only in-form attachment removal (local). Delete has confirm dialog, no undo
(soft-delete but no restore endpoint).
GET /api/v1/notifications, GET /notifications/unread-count,
PATCH /notifications/:id/read, PATCH /notifications/read-all
(notifications.controller.ts:21-47). Homework event types are routed
(event-queue-map.ts:22-25) but fail enum validation today (notification.schema.ts:7-12,
inapp.worker.ts:46-53) — OQ-8; badge counts homework activity once the enum is extended.