Appearance
Classroom Service API
Current Endpoints
GET /healthzGET /readyzGET /v1PUT /v1/classrooms/{classroomId}/snapshotGET /v1/classroomsPOST /v1/classroomsGET /v1/classrooms/{classroomId}PATCH /v1/classrooms/{classroomId}PATCH /v1/classrooms/{classroomId}/statusDELETE /v1/classrooms/{classroomId}GET /v1/classrooms/{classroomId}/delete-impactDELETE /v1/classrooms/{classroomId}/purgeGET /v1/classrooms/{classroomId}/membersPOST /v1/classrooms/{classroomId}/membersPUT /v1/classrooms/{classroomId}/members/{userId}DELETE /v1/classrooms/{classroomId}/members/{userId}GET /v1/classrooms/{classroomId}/studentsPOST /v1/classrooms/{classroomId}/studentsDELETE /v1/classrooms/{classroomId}/students/{studentId}POST /v1/classrooms/{classroomId}/joinGET /v1/classrooms/{classroomId}/progress
Native Classroom Foundation
Phase 8 classroom-service starts with classroom and classroom-member ownership. This is an internal /v1 foundation, not a public /api/classrooms* or /api/admin/classrooms* cutover.
Legacy evidence:
apps/api/src/modules/classrooms/classrooms.controller.ts:32-204maps legacy classroom list/detail/create/update/status/delete/join/student/progress routes.apps/api/src/modules/classrooms/classrooms.controller.ts:803-1430maps admin classroom list/create/update/detail/member/purge routes.apps/api/src/modules/app-data/app-data.classrooms-core.ts:38-520implements legacy classroom list/detail/create/update/status rules, teacher membership creation, manager checks, and response counters.apps/api/src/modules/app-data/app-data.classrooms-support.ts:50-150defines classroom manager, teacher-managed-classroom, reference, and membership assertions.apps/api/src/modules/app-data/app-data.public.ts:707-980implements delete impact, soft archive vs hard delete, purge, join, remove student, and student list behavior.apps/api/src/modules/app-data/app-data.progress-overview.ts:17-48implements classroom progress as a composition of classroom detail, student members, assignments, attempts, and weak topics.apps/api/prisma/schema.prisma:551-604definesClassroomandClassroomMemberwith uniquecode, uniquepublicSlug, unique(classroomId,userId), andACTIVE/ARCHIVEDstatus.packages/shared/src/index.ts:593-610andpackages/shared/src/index.ts:1160-1178define public slug, visibility, grade-level, and classroom input validation.apps/web/components/classroom/classroom-crud-client.tsx:168-336consumes/classrooms, status, delete-impact, delete, and admin purge.apps/web/app/join/class/[code]/join-class-link-client.tsx:30-39consumes/classrooms/{code}/join.
Native contract:
PUT /v1/classrooms/{classroomId}/snapshotupserts service-owned rows from legacy backfill, including timestamps, status, visibility, counters, and teacher/member data when supplied.GET /v1/classroomssupportsorganizationId,teacherId,studentId,status,visibility,q,page, andlimit;X-Actor-Id/X-Actor-Rolescopes non-admin reads.POST /v1/classroomscreates a classroom, generates a unique uppercase join code, and upserts the primary teacher as aTEACHERmember.GET /v1/classrooms/{classroomId}accepts id or code, preserving the legacy join-link lookup path.PATCH /v1/classrooms/{classroomId}preserves partial update rules for name, description, summary, cover image, visibility, public slug, featured flag, grade level, subject id, and teacher id.PATCH /v1/classrooms/{classroomId}/statussetsACTIVEorARCHIVED.DELETE /v1/classrooms/{classroomId}hard deletes only when there is no owned usage beyond the teacher membership; otherwise it archives and returns{deleted:false, archived:true}.GET /v1/classrooms/{classroomId}/delete-impactreturns service-owned counts immediately and zeroes deferred lesson/material/assignment/tuition counters until those slices are native.DELETE /v1/classrooms/{classroomId}/purgehard deletes the service-owned classroom and members for admin-only adapters.- Member routes preserve upsert by
(classroomId,userId), role updates, student join by id or code, student member listing, and primary-teacher reassignment when admin removes a teacher member. GET /v1/classrooms/{classroomId}/progressreturns the classroom, current student member rows, and zero assignment/weak-topic metrics until exam/analytics adapters provide native data.
Authorization model:
- Native service accepts
X-Actor-Id,X-Actor-Role, andX-Organization-Id;X-User-IdandX-User-Roleare accepted as fallbacks for gateway-injected headers. Gateway remains responsible for JWT verification and public route RBAC. ADMINmay manage any classroom in the requested organization scope.TEACHERmay manage classrooms whereteacherIdequals the actor or where the actor has aTEACHERclassroom member row.TEACHERcannot create or transfer a classroom to another teacher.STUDENTlist/detail access is membership-scoped and join may only add the actor as a student.PARENTcannot read or manage classroom-service foundation routes.
Envelope:
json
{
"success": true,
"data": {
"id": "class_local_math_6",
"name": "Toan 6",
"code": "A1B2C3",
"status": "ACTIVE",
"visibility": "PRIVATE",
"gradeLevel": 6,
"subjectId": "math",
"teacherId": "teacher_1",
"studentCount": 0,
"_count": {
"members": 1,
"lessons": 0,
"materials": 0,
"assignments": 0
}
},
"message": "OK"
}Database:
services/classroom-service/migrations/000002_classrooms.sqlcreatesclassroomsandclassroom_members.classrooms.organization_id,unit_id,subject_id,teacher_id, andcreated_by_idstore public ids from other services; classroom-service does not query other service databases.classrooms.codeis unique and stores the legacy uppercase join code.classrooms.public_sluguses a partial unique index so null slugs are allowed.classroom_membersenforces unique(classroom_id,user_id)and stores only user ids plus role.
Validation queries:
sql
SELECT id, legacy_id, organization_id, name, code, status, teacher_id
FROM classrooms
ORDER BY created_at DESC
LIMIT 20;
SELECT classroom_id, user_id, role, joined_at
FROM classroom_members
ORDER BY joined_at DESC
LIMIT 20;
SELECT c.id, c.code, count(m.id) AS member_count
FROM classrooms c
LEFT JOIN classroom_members m ON m.classroom_id = c.id
GROUP BY c.id, c.code
ORDER BY c.id;Rollback for this native slice:
- Keep
/api/classrooms*and/api/admin/classrooms*routed to legacy. - Disable gateway callers for
/v1/classrooms*. - Run
make test-classroom-route-guardafter route-table edits to prove public/admin classroom routes still stay legacy-proxied. - Keep lessons, materials, announcements, tuition, exam assignments, dashboard, leaderboard, and public catalog routes on legacy until their dedicated slices land.
- Drop classroom-service local
classroom_membersandclassroomstables with the migration down step if local test data must be reset.
Non-goals for P8-004:
- Public gateway adapter/cutover for
/api/classrooms*or/api/admin/classrooms*. - Lesson, material, video, announcement, tuition, notification, dashboard, leaderboard, exam, or exam-assignment ownership.
- Subject, teacher, organization, and student existence checks against other service databases.
- Full admin search hydration for teacher, organization, and subject names; gateway/user/school/question-bank adapters can hydrate later.
- Derived analytics, weak topics, attempt scores, and assignment completion.