Appearance
admin-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-023
Current implementation: services/admin-service.
Owns: feature maintenance state, admin compatibility read models, moderation workflows, operational dashboard projections, and temporary admin audit compatibility until audit-service route migration is explicit.
Must read:
docs/agents/handoff-phase-9-admin-foundation.md- legacy admin/support modules:
/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/admin/feature-maintenance.service.ts,/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/admin/operations.controller.ts,/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/admin/admin-dashboard.controller.ts,/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/admin/inbox.controller.ts,/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/support/support.service.ts,/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/common/feature-maintenance.guard.ts.
Legacy source evidence:
/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/admin/**/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/support/**/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/common/feature-maintenance.guard.ts- admin dashboard/read-model rows in
/Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/prisma/schema.prisma.
Writable files:
services/admin-service/**contracts/openapi/services/admin-service.yamldocs/api/admin-service.md
Orchestrator-owned files:
- audit-service storage migration, IAM credentials/profile/payment/wallet boundaries, gateway route cutovers, and shared deploy manifests unless delegated.
Delegated gateway verification scope:
- Only when the orchestrator assigns an admin route/live/browser proof subtask, this service agent may update non-default
deploy/gateway/routes.feature-maintenance-*.json,deploy/gateway/routes.admin-audit-*.json,deploy/gateway/routes.audit-admin-compat-*.json, matchingscripts/test/*admin*.shorscripts/test/feature-maintenance-*.sh,docs/qa/admin-*.md, and rootMakefiletest-feature-maintenance-*,test-admin-*, ortest-audit-admin-*targets. - Audit-service compatibility storage, IAM/profile/payment/wallet ownership, broad admin default routes, and frontend admin screens remain orchestrator-owned unless explicitly delegated. Public promotion still requires browser/runtime proof and rollback notes.
Initial tasks:
- Keep feature maintenance and admin audit foundation stable.
- Done: add a maintenance guard adapter slice.
GET /v1/feature-maintenance/guard/{key}lets gateway/BFF query native feature-maintenance state, preserve exact Vietnamese labels, and keep read-only AI classification job bypass behavior while default routes remain rollback-safe. - Done: add an admin operations/dashboard source-map slice before implementation.
GET /v1/admin/operations/source-mapmaps health to gateway/service health checks, queues/import jobs to the worker/import owner, outbox state to emitting owner projections, AI provider status to ai-classifier-service, wallet review summaries to wallet/payment owners, support queues to support/notification owners, identity/profile counts to IAM/profile APIs, and audit history to audit-service. - Done: expand the source-map contract for remaining legacy admin dashboard and operations parity areas before metric adapters are added. The map now includes organization roster/member counts, classroom/exam counts, attempt metrics, document totals/pending reviews, full queue depth projections, queue retry commands, and outbox clear commands with owner services/APIs named. It still does not execute commands or aggregate metric counts inside admin-service.
- Done: point DOCX import queue failures/depths at docx-import-service
GET /v1/admin/import/docx/queue-summary, and point DOCX Fast retry atPOST /v1/import/docx/docx-fast-jobs/{id}/reprocess. Admin-service may probe those owner routes through source snapshots, but must not readdocx_import_jobs, payload spools, Redis BullMQ keys, or import worker memory directly. Theimport.jobssource-map key points at docx-import-serviceGET /v1/import/docx/jobs. - Done: point AI classifier queue depth at ai-classifier-service
GET /v1/admin/ai-classifier/queue-summaryand AI retry atPOST /v1/ai-classifier/jobs/{id}/retry. Admin-service may probe those owner routes through source snapshots, but must not readclassification_jobsdirectly. - Done: point
organization.rosterat school-serviceGET /v1/admin/organizations/roster-summaryonce the owner API existed. Admin-service still only maps/probes owner APIs; it does not copy organization data or take IAM membership authority. - Done: point
learning.classroom-countsat classroom-serviceGET /v1/admin/classrooms/summaryonce the owner API existed. Admin-service still does not copy classroom roster state or own classroom metrics. - Done: point
learning.exam-countsat exam-serviceGET /v1/admin/exams/summaryonce the owner API existed. Admin-service still does not copy exam rows, access links, assignments, attempts, or analytics state. - Done: point
learning.attempt-metricsat attempt-serviceGET /v1/admin/attempts/summaryonce the owner API existed. Admin-service still does not copy attempt rows or own analytics rollups. - Done:
ai.providersnow has ai-classifier-service ownerGET /v1/ai/providers/status; admin-service source snapshots may probe that endpoint when configured, but provider settings and secrets stay AI-owned. - Done:
identity.countsnow names IAM ownerGET /v1/admin/identity/summaryand profile-service ownerGET /v1/admin/profiles/summary; admin-service must not synthesize these counts from its own storage or merge IAM/profile ownership. - Done:
support.queuesnow names notification-service owner APIGET /v1/admin/support/notification-summary, which summarizes support notification/event/delivery state only. Admin-service must not store support tickets, discover recipients, or synthesize support queue totals. - Done: add a service-local admin operations/dashboard source snapshot slice.
GET /v1/admin/operations/source-snapshotsuses the source-map keys as the required contract and probes only owner endpoints configured throughADMIN_OPERATIONS_SOURCE_TARGETS(key=url,key=url). Missing owner targets returnstatus=unconfigured; failing owner endpoints returnstatus=degradedorstatus=unavailable. It does not read legacy Prisma tables, BullMQ queues, or service databases directly, and it does not promote public admin dashboard/operations routes. - Done: configured owner snapshot probes use bounded parallelism (eight in flight) while preserving source-map order and each owner latency/status. A slow owner no longer serially delays every other configured probe.
- Done: the orchestrator-owned admin-web operations panel now reads those snapshot statuses only through the non-default Gateway rehearsal. It keeps fixture workflow rows as a fallback and never turns owner health/status into admin-service totals or dashboard aggregation.
- Define admin operations/dashboard read models without taking ownership from domain services: health, queues, outbox, imports, AI provider status, wallet review summaries, and support queues must come from owner APIs/projections.
- Add admin inbox/broadcast and support moderation slices in coordination with notification-service and audit-service; admin-service may coordinate the workflow but must not own notification delivery or compliance audit storage.
- Done: add explicit-recipient admin notification broadcast producer at
POST /v1/admin/notification-broadcasts. It requires a caller-suppliedclientRequestIdand concreterecipientIds, writes a local admin audit log, and best-effort emitsadmin.notification.broadcast.v1to notification-service withsourceEventId=admin:broadcast:{clientRequestId}. LegacyALL/ROLEStarget discovery remains pending until IAM/profile/gateway resolvers supply concrete recipients. - Done: add a first support ticket notification producer at
POST /v1/support/notification-events. It requires caller-suppliedticketId,clientRequestId, concreterecipientIds,title, andcontent, writes a local support audit log, and best-effort emitssupport.ticket.notification.v1to notification-service withsourceEventId=support:ticket:{ticketId}:notification:{clientRequestId},preferenceType=SUPPORT_TICKET,entity=SupportTicket, and legacy inbox types such asSUPPORT_TICKET_CREATED,SUPPORT_TICKET_REPLY, orSUPPORT_TICKET_STATUSsupplied throughtype. It does not store support tickets, discover admins/requesters, or write notification rows directly. - Done: add optional best-effort admin audit projection to audit-service.
AUDIT_SERVICE_URL/AUDIT_SERVICE_BASE_URLenables posting newly written admin audit logs to/v1/audit-eventswithsourceService=admin-service,sourceEventId=<admin audit log id>,category=ADMIN,severity=INFO,retentionPolicy=admin-operations, andcreatedAt -> occurredAt; projection failures do not block the current admin audit write path. - Coordinate with the existing
audit-servicefoundation before moving audit storage or public admin audit compatibility routes. - Teacher KYC review storage/list/detail/approve/reject is profile-service owned at
/v1/admin/users/kyc/teacher*; non-default gateway route rehearsal can route/api/admin/users/kyc/teacher*directly to profile-service. Admin-service may later add a public compatibility wrapper only after response parity, browser evidence, and wrapper ownership are explicit, and must not persist KYC document fields or hashes.
Acceptance:
- Admin-service does not own wallet ledger, payment rails, IAM credentials, or profile storage.
- Feature maintenance keys and Vietnamese labels are unchanged.
- Maintenance guard decisions preserve the read-only GET bypass for
/api/questions/ai-classify/jobs*onassessment.questionBankAiClassification. - Admin dashboards read from APIs/projections, not service DB joins.
/api/admin/operations/auditremains on the existing admin-service compatibility route until audit-service has browser/runtime proof, rollback evidence, and legacy response/backfill parity proof.make test-audit-admin-compat-routescovers the separate audit-service compatibility-preview route rehearsal; it does not promote the default route table.- Admin operations/dashboard source maps must list the owner API for every displayed count or command before code is added.
- Admin operations/dashboard source snapshots may report only configured owner endpoint health/status. They must not synthesize totals, queue counts, wallet review counts, or identity/profile counts from admin-service storage.
- Support/admin inbox flows emit notification and audit events through their owner-service APIs instead of writing those stores directly. The native admin broadcast and support notification slices are currently explicit-recipient only.
- Admin teacher KYC compatibility work delegates to profile-service owner APIs and never stores plaintext CCCD,
cccdNumberHash, or KYC document URLs in admin-service.
Verification:
GOTOOLCHAIN=go1.25.11 go test ./services/admin-service/...make test-feature-maintenance-routes test-admin-audit-routes test-admin-owner-source-routesmake test-admin-owner-source-browserfor the memory-only Admin Operations source-status candidate, including owner internal authentication and default legacy rollback; it is not dashboard parity or default-route proof.- Future dashboard/support/broadcast slices must add focused service tests, route guards for promoted paths, and browser/runtime evidence before default admin route cutover.