Skip to main content

Overview

:::info Source Sourced from services/authoring-service/01-SERVICE_OVERVIEW.md in the documentation repo. :::

Companion: 03 authoring-service · 10 Authoring Tool Spec · 04 Event-Driven · 01 Enterprise Architecture


1. Mission Statement

The authoring-service is the single owner of the mutable course authoring workspace. It manages the full lifecycle of course drafts — from creation through AI-assisted block editing to the publish saga that hands off immutable content to the rest of the platform. It is classified as a Core Domain service and is the primary competitive differentiator of the Ghasi-edTech platform.

2. Bounded Context

AttributeValue
Context nameAuthoring
Domain classCore
Upstream contextsIdentity (authentication), Tenant (tenancy), Media (asset pipeline), AI Services (co-authoring)
Downstream contextsContent-Packaging (PlayPackage build), Catalog (course registration), Delivery (learner consumption)
Shared kernelCommon value objects (TenantId, UserId, I18nString, AIProvenance, Locale, MediaRef) from @ghasi/domain-primitives

3. Aggregate Roots

AggregateClusterConsistency boundary
CourseDraftModuleDraft → LessonDraft → Block[]Entire draft tree is a single transactional aggregate
CollaborationSessionparticipants, yDocUpdateLogPer-draft collaboration state

4. Service Responsibilities

┌─────────────────────────────────────────────────────────────────────┐
│ authoring-service │
│ │
│ ┌────────────┐ ┌────────────────┐ ┌───────────────────────────┐ │
│ │ CourseDraft│ │ Block Registry │ │ Course Publish Saga │ │
│ │ Lifecycle │ │ & Editor Logic │ │ (orchestrated, 5-step) │ │
│ └────────────┘ └────────────────┘ └───────────────────────────┘ │
│ ┌────────────┐ ┌────────────────┐ ┌───────────────────────────┐ │
│ │ AI │ │ SCORM Import │ │ Real-time Collaboration │ │
│ │ Co-Author │ │ Pipeline │ │ (Yjs, M4+) │ │
│ └────────────┘ └────────────────┘ └───────────────────────────┘ │
│ ┌────────────┐ ┌────────────────┐ ┌───────────────────────────┐ │
│ │ Review & │ │ GDPR Subject │ │ Sync Projection │ │
│ │ Approval │ │ Request Handler│ │ (offline authoring, S5) │ │
│ └────────────┘ └────────────────┘ └───────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘

4.1 Owns (read + write)

  • CourseDraft aggregate (modules, lessons, blocks)
  • Block ordering and structural integrity
  • Draft state machine (editing → in_review → approved → publishing → published_idle)
  • AI co-authoring flows (generate, improve, translate, quiz)
  • HITL acceptance/rejection of AI-generated blocks
  • Course Publish Saga orchestration
  • Collaboration sessions (Yjs state)
  • SCORM import pipeline
  • Block version history

4.2 Reads (via events/projections)

  • media.asset.ready.v1 — resolve media references in blocks
  • ai.completion.finished.v1 — attach AI completions to draft blocks
  • content.play_package.built.v1 — advance publish saga
  • catalog.course_version.published.v1 — advance publish saga
  • content.play_package.bundle.published.v1 — advance publish saga
  • gdpr.subject_request.received.v1 — anonymize/delete user data

4.3 Does NOT own

  • Immutable published course content (content-service)
  • Course catalog entry (catalog-service)
  • Media asset transcoding (media-service)
  • AI model execution (ai-gateway-service)
  • Learner progress or completion (progress-service)
  • Assessment quiz bank internals (assessment-service)

5. Technology Stack

LayerTechnology
RuntimeNode.js 22 LTS
FrameworkNestJS 11 (Clean/Hexagonal Architecture)
LanguageTypeScript 5.6+ (strict mode)
DatabasePostgreSQL 16 with RLS
Message brokerNATS JetStream
Real-timeWebSocket (ws) + Yjs protocol
ORMDrizzle ORM
ValidationZod
ObservabilityOpenTelemetry SDK
TestingVitest + Playwright (E2E) + Pact (contract)
ContainerDocker (distroless Node base)

6. Architecture Layers

┌─────────────── Presentation ─────────────────────────────────────┐
│ NestJS Controllers · WebSocket Gateway · SSE endpoints │
│ DTOs (Zod schemas) · OpenAPI decorators │
└──────────────────────────┬───────────────────────────────────────┘

┌─────────────── Application ──────────────────────────────────────┐
│ Use-Cases (commands + queries) · Saga Orchestrator │
│ Ports (interfaces) · Mappers · Application Events │
└──────────────────────────┬───────────────────────────────────────┘

┌─────────────── Domain (pure TS, zero deps) ──────────────────────┐
│ CourseDraft aggregate · Block discriminated union · VOs │
│ State machine · Invariant enforcement · Domain events │
└──────────────────────────┬───────────────────────────────────────┘

┌─────────────── Infrastructure ───────────────────────────────────┐
│ Postgres repos (Drizzle) · NATS publisher/subscriber │
│ Outbox relay · AI Gateway HTTP client · Media client │
│ Yjs persistence adapter · SCORM parser · Sync projector │
└──────────────────────────────────────────────────────────────────┘

7. Service Readiness Levels

MilestoneLevelCapabilities
M1L1CRUD drafts, block editor, basic AI co-author, publish saga v1
M2L3Full block registry (frozen F17), SCORM import v1, observability, contract tests
M4L4Live collaboration (Yjs), offline authoring, branching scenarios

8. Freeze Points

IDArtifactFrozen at
F17Block registry + BlockBase shapeM2 start
F15PlayPackage manifest schemaM1 start

9. Slice Assignments

SliceFeatures
S2Block editor + AI co-author + publish saga + SCORM import v1
S4Branching scenarios, SCORM 2004
S5Live collab (Yjs), offline authoring

10. Key Design Decisions

DecisionRationale
Single aggregate for entire draft treeBlock ordering invariants + tenant consistency require atomic writes; Yjs merge at aggregate level
Saga orchestrator (not choreography) for publish5-step publish with compensation requires explicit state machine; choreography would scatter the logic
AI blocks as first-class domain conceptHITL requirement means AI output must be tracked, reviewed, and audited at the domain level
Yjs in infrastructure layerDomain stays framework-free; Yjs is a persistence/sync concern, not a domain concern
Block discriminated union (not inheritance)TypeScript ADTs are more type-safe and serialization-friendly than class hierarchies

11. Dependency Diagram

┌──────────────┐
│ identity │
│ service │
└──────┬───────┘
│ JWT validation

┌──────────┐ ┌──────────────────────┐ ┌─────────────────┐
│ tenant │◄───│ authoring-service │───►│ ai-gateway │
│ service │ │ │ │ service │
└──────────┘ └──────────┬───────────┘ └─────────────────┘
│ │ │
┌──────────┘ │ └──────────┐
▼ ▼ ▼
┌─────────────┐ ┌──────────────┐ ┌──────────────────┐
│ content │ │ catalog │ │ media │
│ service │ │ service │ │ service │
└─────────────┘ └──────────────┘ └──────────────────┘
│ │
└────────┬────────┘

┌────────────┐
│ delivery │
│ service │
└────────────┘

All cross-service communication is via NATS JetStream events, except:

  • Tenant resolution: synchronous HTTP (1-hop, cached)
  • AI gateway requests: synchronous HTTP with SSE streaming