Appearance
organization-service Agent Tasks
Agent workflow: follow README.md for Audit -> Investigate -> Code -> Test -> Fix; keep this pack's writable scope and verification commands authoritative.
Dispatch type: per-service
Dispatch ID: SVC-005
Current implementation: services/school-service.
Owns: organizations, units, tenant metadata, academic-year calendar/configuration, tenant resolve/validate, and membership compatibility read models only.
Must read:
docs/agents/handoff-phase-8-school-organization-foundation.md- legacy organization modules and Prisma
Organization*models.
Legacy source evidence:
/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/organizations/**/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/app-data/app-data.organizations.ts/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/tenant/**Organization,OrganizationUnit, andOrganizationMemberPrisma models in/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/prisma/schema.prisma
Writable files:
services/school-service/**contracts/openapi/services/school-service.yamldocs/api/school-service.md- organization-specific route example/test files when assigned.
Orchestrator-owned files:
- IAM membership canonicalization, default gateway route table, and shared deploy manifests unless explicitly delegated.
Delegated gateway verification scope:
- Only when the orchestrator assigns an organization route/live/browser proof subtask, this service agent may update non-default
deploy/gateway/routes.organizations-*.jsonexamples,scripts/test/organization-*.sh,docs/qa/organization-*.md, and rootMakefiletest-organization-*targets. - Permission-bearing membership write route rehearsal remains coordinated with
iam-serviceandapi-gateway; the default gateway route table and IAM membership contracts remain orchestrator-owned. Public promotion still requires browser/runtime proof and rollback notes.
Initial tasks:
- Use
services/school-serviceas the current implementation alias. Alias rename/removal is orchestrator-owned and not a service-agent decision. - Tenant validation workflow coverage now includes admin bypass, owner and ORG_ADMIN manager checks, active teacher/student member checks, manager-required denial for teachers, suspended-member denial, and non-member denial.
- Done: add a read-only admin roster summary owner API at
GET /v1/admin/organizations/roster-summary. It reports organization/unit counts and IAM-synchronized membership read-model rows for admin dashboard/source-map adapters without adding any membership write authority to school-service. - Done: define the versioned
student.roster.import.requested.v1boundary incontracts/events/README.md. IAM owns account and organization-membership writes; profile-service owns student display fields; classroom-service owns local classroom membership; school-service remains a membership read model. The public student-import route stays legacy-backed until cross-service live/browser/rollback evidence exists. - Done: academic-year lifecycle is organization-owned in
academic_yearswithDRAFT -> ACTIVE -> ARCHIVEDtransitions, one active year per organization, ISO calendar-date validation, and immutability after activation/archive.GET|POST /v1/organizations/{organizationId}/academic-yearsandPATCH /v1/organizations/{organizationId}/academic-years/{academicYearId}stay behind theADMIN-only, non-default candidate table. The isolated PostgreSQL proof verifies persistence after restart, and the isolated Admin browser candidate verifies list/draft/activate through Gateway; no other service stores academic years. - Remove split-brain with IAM: keep schools/centers/campuses/org-unit metadata here, and make permission-bearing organization membership writes IAM-owned or explicitly read-only/deprecated compatibility.
- Add a gateway target decision for
/api/organizations/:id/memberswrites only after an IAM-owned adapter exists. School-service member writes stay internal IAM read-model sync routes; ordinary callers return409 SCHOOL_MEMBERSHIP_NOT_AUTHORITATIVE. - Done:
iam_membership_boundary_test.goexplicitly proves ordinary member writes are rejected while IAM-marked sync writes return theiam-sync-read-modelresponse marker; the existing ordering/tombstone tests remain the read-model replay contract.
Acceptance:
- Permission-bearing organization membership writes are IAM-owned. Any school-service member write route is documented and tested as internal IAM read-model sync behavior; ordinary callers receive
409 SCHOOL_MEMBERSHIP_NOT_AUTHORITATIVE. - Organization membership remains outside profile-service.
- Tenant validation never reads another service DB.
- Gateway route rehearsals keep default routes legacy until parity evidence exists.
- School/organization metadata APIs cannot mutate IAM roles/permissions by side effect; membership policy changes go through IAM-owned contracts.
- Academic-year records, when implemented, are tenant-scoped organization metadata and must not be stored in classroom/course/exam databases.
Verification:
GOTOOLCHAIN=go1.25.11 go test ./services/school-service/...make test-organization-routesmake test-academic-year-routesmake test-academic-year-route-runtimemake test-academic-year-postgresmake test-academic-year-browser