Appearance
Service Boundaries
Phase: Service boundaries for staged implementation Status: active; native foundations follow these boundaries and public/default cutovers remain proof-gated.
Boundary Rules
- A service owns its database, migrations, SQL queries, events, and domain invariants.
- A service may expose read APIs for other services, but consumers must not join across databases.
- Shared libraries may contain request IDs, auth context structs, OpenAPI helpers, error envelope helpers, and generated clients. They must not contain domain write logic.
- Legacy source remains a read-only reference. Copying behavior requires an evidence note in the implementing task.
- New source goes under
go-platform/only.
API Gateway
Owns:
- Public
/api/*route compatibility. - Legacy proxy routing.
- Native service routing.
- Auth token extraction and basic JWT compatibility.
- Request/correlation ID propagation.
- CORS and body limits matching legacy defaults.
- SSE pass-through.
- Public health and metrics compatibility.
Does not own:
- Domain writes.
- Per-service database migrations.
- AI/provider credentials beyond route-level policy.
- Business rules hidden inside gateway adapters.
BFF Service
Owns:
- Frontend-specific screen aggregation and response shaping for gateway-approved web/admin routes.
- Source-service status snapshots and route metadata for frontend shells.
- Read-only composition over owner service APIs.
Current state:
services/bff-servicefoundation exists for native admin overview, admin operations summary, teacher dashboard, teacher operations summary, and role-based frontend shell metadata.- It has no primary business database and does not read service databases.
- Public
/api/admin/overview,/api/dashboard/teacher, and frontend shell routes remain legacy/gateway controlled until route-table rehearsal and browser evidence exist.
Does not own:
- Domain writes or canonical state.
- IAM credentials, profile, wallet, payment, billing, usage, question, exam, import, search, audit, notification, or admin source data.
- Auth policy beyond trusting gateway-derived actor headers on native tests.
Canonical Service Naming
Some Go services already existed before the July 2026 responsibility refresh. The canonical product boundary is binding; the current implementation name is kept when renaming would break route tables, deploy manifests, or historical handoffs.
| Canonical boundary | Current implementation | Rename status |
|---|---|---|
organization-service | school-service | Alias until a dedicated rename task is approved. |
question-service | question-bank-service | Alias; service owns the question bank. |
file-service | document-service | Alias; service owns files/media/teaching documents. |
import-service | docx-import-service | Alias for DOCX/PDF/import workflow foundation. |
formula-docx-service | go-formula-docx runtime behind docx-import-service | Runtime split is internal for now. |
ai-service | ai-classifier-service | Current slice covers AI classification/provider work. |
user-service | deprecated compatibility scaffold | Do not add new ownership here; identity/profile work routes to iam-service and profile-service. |
audit-service | services/audit-service foundation; admin audit route still in admin-service | Compliance ledger split started; public route cutover is separate. |
IAM Service
Owns:
- Account identity and credential state.
- Local register/login/refresh/logout/session revocation.
- Refresh-token persistence and rotation.
- JWT/JWKS compatibility metadata.
- Roles, permissions, account-role assignment, permission checks.
- Organization memberships and invitations when used for access control.
- Login/security audit records.
Depends on:
profile-servicefor display/profile hydration.school-service/organization-servicefor organization metadata when needed.
Must preserve:
- Bearer token and
hoctapaz.accessTokencookie compatibility at gateway. - Access token
type=access. - Refresh token
type=refreshandjti.
Does not own:
- Avatar, DOB, educational profile, learning progress.
- Subscription, AZ Credits, wallet ledger, payment provider state.
Profile Service
Owns:
- Base educational profile read/write after identity creation.
- Avatar/display name, phone, date of birth, gender.
- Student, teacher, parent, and staff profile details.
- Public profile views and internal full profile views.
- Parent-student display/read models only when they are profile metadata.
Does not own:
- Login credentials, password verification, token issuance, session revocation.
- Role and permission source of truth.
- Organization membership policy.
- Subscription, wallet, payment, usage quota.
Organization Service (school-service current implementation)
Owns:
- Organizations.
- Organization units.
- Tenant metadata and tenant validation.
- IAM-synchronized organization-member read models, including sync ordering and tombstone state required to project a member directory locally.
- School-scoped roster metadata when imported from roster flows, without becoming the access-control membership authority.
Must preserve:
X-Organization-Idbehavior.- Admin bypass rules only through explicit policy, not implicit DB access.
Does not own:
- Authoritative organization membership writes, membership policy, invitations, roles, or permissions. Those remain
iam-serviceresponsibilities. - A second source of truth for a member relationship.
school-serviceaccepts trusted IAM synchronization only and must reject ordinary member writes.
Classroom Service
Owns:
- Classroom records.
- Classroom members.
- Announcements.
- Lessons created inside classrooms.
- Classroom materials and tuition records.
Phase 8 start:
- P8-004 implements only classroom records and classroom members.
- Lesson, material, announcement, tuition, dashboard, leaderboard, and exam-assignment behavior remains legacy-proxied until later slices.
- Organization, unit, subject, teacher, creator, and student identifiers are stored as public ids; validation and hydration stay behind gateway adapters and owning services.
Depends on:
school-servicefor tenant and membership checks.document-servicefor media/document references.exam-servicefor exam assignment references.
Course Service
Owns:
- Course catalog records.
- Sections, lessons, materials.
- Enrollment and progress.
- Course quizzes as references to exam/question contracts.
Phase 8 start:
- P8-005 implements course records, sections, lessons, material metadata, enrollments, lesson/video progress, material views, and public course projections.
- Question links, quizzes, mastery, recommendation, reports, wallet purchase, and file streaming remain legacy-proxied until later adapters.
- Organization, subject, topic, instructor, creator, student, media, uploader, question, exam, and wallet identifiers are stored as public ids; validation and hydration stay behind gateway adapters and owning services.
Does not own:
- Question canonical content.
- Exam attempt grading.
File Service (document-service current implementation)
Owns:
- Media asset metadata.
- S3/MinIO object key policy.
- Presigned upload compatibility.
- Teaching documents, purchases, shares, and content serving.
Must preserve:
- Existing object keys where migrated.
- Formula/image variant serving used by import and question editor.
- MIME and size policy compatibility until a product change is approved.
Import Service (docx-import-service current implementation)
Owns:
- DOCX Fast jobs.
- OCR document conversion jobs.
- MathType -> Word Equation conversion jobs.
- Import review draft state.
- Import question segments and processing events.
- Import SSE event stream.
Depends on:
document-servicefor object reads/writes and media metadata.question-bank-servicefor approval into questions.exam-servicefor approval into draft exams/templates.ai-classifier-serviceonly through explicit classification API/event contracts.
Must preserve:
docx-fast,mathtype-equation,ocr-documentsource values.- Vietnamese labels such as
Import Đề Thi Nhanh (VIP),MathType -> Word Equation, andOCR Tài Liệu. - Manual question-type overrides from review/editor saves.
- Warning, timing, media, formula, table, and source-location fields.
Formula DOCX Service
Owns:
- CPU/runtime-heavy DOCX, OMML, MathType/OLE/MTEF, formula and table parsing when separated from import orchestration.
- Parser latency, warning, and corpus metrics.
- Deterministic conversion outputs that import-service can store/review.
Current state:
- Implemented as
go-formula-docxruntime behinddocx-import-service. - Do not expose it directly to frontend.
Does not own:
- Import approval, question persistence, exam creation, quota charging.
AI Service (ai-classifier-service current implementation)
Owns:
- AI classify job creation/status/events/cancel/apply workflow.
- AI provider settings.
- AI provider usage events.
- Question solution history if generated by AI.
Depends on:
question-bank-servicefor applying classification or solution output.admin-servicefor feature maintenance state if centralized there.
Must preserve:
- Read-only GET bypass behavior for feature maintenance where legacy allowed it.
- SSE snapshot/heartbeat/job update semantics.
Does not own:
- Usage entitlement, credit debits, subscription state, or payment reconciliation.
Question Service (question-bank-service current implementation)
Owns:
- Questions.
- Question versions.
- Question options.
- Question type definitions.
- Folders, groups, tags.
- Difficulty and taxonomy references unless centralized later.
Must preserve:
- Existing question types:
SINGLE_CHOICE,MULTIPLE_CHOICE,TRUE_FALSE,TRUE_FALSE_GROUP,SHORT_ANSWER,SHORT_NUMERIC_ANSWER,ESSAY. - Rich content JSON compatibility.
- Scoring rule semantics.
- Archive-vs-hard-delete behavior until explicitly changed.
Exam Service
Owns:
- Exam folders.
- Exam blueprints and generation runs.
- Exam paper templates and sections.
- Exam authoring, scheduling, assignments, access links.
- Exam question snapshots at publish time.
Depends on:
question-bank-servicefor source question reads before snapshot.classroom-servicefor classroom assignment validation.
Must preserve:
- Draft-only edit rule.
- Publish snapshot refresh rule.
- Access password hash behavior.
Native snapshot boundary:
exam-servicestores exam question snapshots as its own persisted state.- Callers must provide hydrated question payloads through service APIs;
exam-servicemust not join the question-bank database. - Snapshot payloads preserve content JSON, options, sub-items, answer keys, scoring rules, media/formula refs, option order, and section/order metadata for later attempt snapshots.
Attempt Service
Owns:
- Attempt creation.
- Attempt question snapshots.
- Answer saves.
- Optimistic answer versioning.
- Submission and grading.
- Attempt events and result visibility.
Depends on:
exam-servicefor published exam snapshot/start policy.
Must preserve:
- Student-only start rule.
- Online/open/assigned/link access checks.
- Attempt snapshots independent from later question edits.
clientVersionvsserverVersionconflict semantics.
Notification Service
Owns:
- Notifications.
- Notification preferences.
- Notification event fanout and delivery state.
- In-app delivery state for already-resolved recipients.
Consumes:
- Exam published/assigned/submitted events.
- Import completed/failed events.
- Admin or support ticket events if retained.
Does not own:
- User search, role broadcast resolution, or parent/student relationship lookup. These come from iam/profile/school-service adapters.
- Admin audit logs. Those belong to admin-service.
- Support ticket storage. That stays legacy-proxied until an admin/support slice owns it.
- Email/SMS provider delivery in P9-001.
Analytics Service
Owns:
- Read models for dashboard, weak topics, progress, mastery, and result analytics.
- Event-derived aggregates.
- Attempt-result projections ingested from already-hydrated attempt/event payloads.
- Service-local analytics/audit event capture that is not admin audit history.
Does not own:
- Canonical exam, attempt, course, or question state.
- Parent-child relationships or user profile hydration.
- Classroom membership validation.
- Notification unread rows used in full parent progress.
Billing Service
Owns:
- Subscription plans and prices.
- Billing cycles, invoices, subscription status.
- Plan entitlements as commercial policy.
Does not own:
- Payment provider webhook ingestion.
- Wallet ledger or AZ Credit debits.
- Login, profile, course, question, exam, or import state.
Current state:
services/billing-servicefoundation exists for plan catalog, plan prices, subscriptions, invoices, payment-outcome activation, cancellation, and entitlement snapshots.- Public
/api/wallet, package, subscription, and payment routes remain legacy-proxied until payment events, wallet credit grants, usage entitlement sync, gateway adapters, and browser/runtime parity are proven.
Wallet Service
Owns:
- Wallet balances.
- Immutable AZ Credit ledger.
- Credit grants, debits, refunds, and adjustment audit trail.
Does not own:
- Subscription plan lifecycle.
- Provider payment webhook reconciliation.
- Feature quota policy beyond balance checks.
Current state:
services/wallet-servicefoundation exists for wallet ensure/read, immutable ledger entries, debit/credit/adjustment idempotency, and service-owned Postgres storage.- Existing wallet/AZ Credit public behavior remains legacy-proxied until top-up/withdrawal/admin-review state machines, payment outcome consumers, gateway adapters, and browser/runtime parity are proven.
Usage Service (entitlement-service alias)
Owns:
- Feature gates and plan entitlement checks.
- Usage counters and quota periods.
- Monthly resets and idempotent consume/check APIs.
Does not own:
- Money movement, wallet ledger, or payment provider state.
- AI/import execution or parser state.
Current state:
services/usage-servicefoundation exists for entitlement materialization, feature gates, usage counters, quota periods, limit overrides, check/consume decisions, and service-owned Postgres storage.usage-serviceis the canonical service name;entitlement-serviceis an allowed planning alias only. Early services must not implement quota locally except through a documented temporary compatibility adapter.
Payment Service
Owns:
- Payment orders.
- Provider transactions.
- Webhooks, idempotency, reconciliation.
Does not own:
- Subscription activation rules except by emitting successful payment events.
- Wallet balance as source of truth.
Current state:
services/payment-servicefoundation exists for payment orders, provider webhook evidence, provider transactions, reconciliation, and idempotent replay handling.- Provider webhook and payment routes remain legacy-proxied until SePay auth verification, payment event publishing, billing/wallet consumers, gateway adapters, and browser/runtime parity are proven.
Search Service
Owns:
- Search indexes and sync checkpoints.
- Full-text/vector-style query APIs over copied/indexed data.
Does not own:
- Canonical course/question/exam/document state.
Current state:
services/search-servicefoundation exists for read-only/rebuildable index projections, generic search filters, and source sync checkpoints. Public routes remain legacy-proxied until owner-service backfill/event pipelines and gateway adapters are proven./api/public/catalog*is currently mapped to course-service, not search-service. Copied course index rows can support discovery, but public catalog route compatibility stays with the owner mapping until a separate route cutover explicitly selects search-service with legacy evidence.
Audit Service
Owns:
- Compliance-grade append-only audit and security event history.
- Source-service event idempotency, retention policy metadata, legal hold metadata, and query filters for compliance review.
Current state:
services/audit-servicefoundation exists for native/v1/audit-eventsand/v1/security-events. It is an internal event sink only.admin-servicestill owns the public admin audit compatibility foundation forGET /api/admin/operations/audit; future migration must preserve legacy action/entity keys, newest-first ordering, and labels.
Does not own:
- Domain decisions, source writes, feature maintenance, or admin dashboards.
- IAM credentials, session policy, or permission checks.
- Public
/api/admin/operations/audituntil gateway cutover evidence exists.
Admin Service
Owns:
- Feature maintenance registry state and public active-feature payloads.
- Admin audit logs.
- Admin dashboard and operational controls in later slices.
- Support/admin workflow storage only after an explicit audited task.
Consumes:
- Audit events emitted by other native services or gateway adapters.
- Operational projections produced by service-specific APIs/events.
Does not own:
- Wallet/AZ Credit ledger or payment rails in P9-003.
- User credentials, profile, KYC storage, or tenant membership.
- Queue retry, AI provider settings, support tickets, or admin dashboard aggregation in the feature-maintenance/audit foundation slice.
Must preserve:
- Exact feature maintenance keys and Vietnamese labels from the legacy shared registry.
- Public status payload
{ items, activeFeatureKeys, generatedAt }. - Read-only AI classification job GET bypass during maintenance.
- Audit action/entity keys so the existing Vietnamese admin operation labels keep working through adapters.
- CSV/XLSX classroom report export in P9-002.