Appearance
Handoff: SVC-005-iam-membership-school-sync-proof organization-service IAM membership and school sync proof
Scope
- Service/area:
organization-serviceimplemented byservices/school-service - Task ID:
SVC-005-iam-membership-school-sync-proof - Dispatch ID:
SVC-005 - Task pack:
docs/agents/service-tasks/organization-service.md - Accepted first-slice handoff:
docs/agents/handoffs/SVC-005-student-roster-import-boundary.md - Goal: prove IAM-owned membership writes and school-service read-model sync before member-write route promotion.
- Non-goals: moving canonical membership writes into school-service, default gateway promotion, student roster import cutover, live data migration, or changes to legacy source under
/Users/velikho/Desktop/WORKING/HOCTAPAZ/.
Docs Read
docs/architecture/service-responsibility-matrix.mddocs/architecture/legacy-api-map.mddocs/agents/service-agent-manifest.jsondocs/agents/service-agent-proof-ledger.jsondocs/agents/service-agent-closeout-ledger.jsondocs/agents/service-agent-execution-queue.jsondocs/agents/service-agent-next-slice-queue.jsondocs/agents/service-agent-next-slice-closeout-ledger.jsondocs/agents/service-agent-next-slice-spawn-packets.mddocs/agents/service-agent-accepted-handoffs.mddocs/agents/agent-handoff-format.mddocs/agents/service-tasks/organization-service.mddocs/agents/handoffs/SVC-005-student-roster-import-boundary.mddocs/agents/handoff-phase-8-organization-membership-write-route-rehearsal.mddocs/api/school-service.mddocs/api/iam-service.mddocs/qa/organization-iam-membership-school-sync-proof.md
Legacy Evidence Read
/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/**/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/prisma/schema.prisma
Legacy source was read-only evidence only. No file under /Users/velikho/Desktop/WORKING/HOCTAPAZ/ was changed.
Files Changed
services/school-service/internal/http/iam_membership_boundary_test.godocs/agents/handoffs/SVC-005-iam-membership-school-sync-proof.mddocs/qa/organization-iam-membership-school-sync-proof.mddocs/agents/service-agent-next-slice-closeout-ledger.jsondocs/agents/service-agent-next-slice-closeout-ledger.mddocs/agents/service-agent-accepted-handoffs.mddocs/agents/service-tasks/organization-service.mddocs/api/school-service.mddocs/index.mddocs/.vitepress/config.tsdocs/qa/service-agent-goal-completion-audit.mddocs/qa/service-agent-readiness-smoke.md
No IAM canonical write code, default route table, or shared deployment manifest was changed in this service-owned proof slice.
Behavior Implemented
- Added a focused school-service HTTP contract test proving ordinary member writes return
SCHOOL_MEMBERSHIP_NOT_AUTHORITATIVE. - Proved an IAM-marked member sync returns the read-model source header and persists the sync response through the school-service route.
- Preserved existing stale replay, tombstone, patch ordering, replayed delete, and last-owner read-model behavior.
- Confirmed IAM publisher/outbox tests emit membership events and deliver them to school-service via the internal marker and ordering headers.
- Confirmed organization member-write gateway rehearsals route add/remove to IAM while default organization routes remain legacy-backed.
Required evidence covered:
- IAM membership write authority proof
- school-service read-model sync proof
- member-write route rollback notes
Tests And Verification
Command:
GOTOOLCHAIN=go1.25.11 go test ./services/school-service/...Result: passed, including the new HTTP boundary test and existing sync ordering/tombstone/last-owner tests.
Command:
make test-organization-routesResult: passed. Default organization routes remain legacy; read rehearsals target school-service and member-write rehearsals target IAM.
Command:
GOTOOLCHAIN=go1.25.11 go test ./services/iam-service/internal/schoolsync -count=1Result: passed. Add/remove event mapping, sync headers, role projection, retries, permanent failures, and unrelated-event filtering are covered.
Command:
GOTOOLCHAIN=go1.25.11 go test ./services/iam-service/internal/usecase -run 'TestIAMPublishesOrganizationMembershipSyncEvents|TestIAMMembershipOutboxRetriesAfterPublisherFailure' -count=1Result: passed. IAM membership event authority and outbox retry behavior are covered.
Command:
ruby -e 'require "yaml"; ARGV.each { |path| YAML.load_file(path) }' services/school-service/api/openapi.yaml contracts/openapi/services/school-service.yamlResult: passed; service and contract OpenAPI files parsed.
Command:
diff -u services/school-service/api/openapi.yaml contracts/openapi/services/school-service.yamlResult: passed; service and contract OpenAPI files match.
Command:
docker compose -f deploy/docker-compose.yml config --quietResult: passed; IAM/school-service runtime wiring remains valid.
Route State
- Route/default state: member-write route promotion blocked until IAM write authority and school read-model sync proof exist
- IAM is the canonical permission-bearing membership writer.
- School-service accepts member mutations only as IAM-marked read-model sync and returns
409 SCHOOL_MEMBERSHIP_NOT_AUTHORITATIVEfor ordinary callers. - Non-default organization member-write route examples target IAM; default
deploy/gateway/routes.jsonremains untouched and legacy-backed. - Rollback: use
GATEWAY_ROUTE_TABLE=deploy/gateway/routes.json, disable public member-write candidates, keep IAM outbox delivery pending/retry-safe, and runmake test-organization-routes.
Data Notes
- Tables touched: none in this proof run.
- Migrations: none.
- Validation report: not applicable because no live data was migrated.
Risks / Blockers
SVC-003IAM production-like cutover dependency remains open.- Public member-write browser/runtime proof and rollback-after-candidate review are not present.
- Student roster import still requires IAM account/membership, profile, and classroom handoff contracts.
- School-service remains a read-model owner, not permission authority; the service and organization row remain
not-complete.
Next Step
- Continue with the next non-gated service slice while keeping SVC-005 member writes non-default, or prepare the production-like IAM dependency evidence required by
SVC-003before any organization member-write promotion.