# Developer B — Catalog, Content & Assessment Definition

**Scope:** the `catalog` database. Everything that *defines* what can be learned: the curriculum
trees, courses, content items + media pipeline, supplementary resources, the question bank,
exam/quiz definitions, the content approval workflow, and platform configuration for SRS and
AI features and target-exam templates.
**Depends on Track A for:** entitlement checks (`SubscriptionService::isEntitled`), RBAC
middleware, audit base model, response envelope.
**Serves Track C (learning runtime) and Track D (dashboards/campaigns) via `CatalogService`.**

Legend: `DEPS:` = hard dependency (must be DONE). `DEPS⚡:` = contract-only.

---

## PHASE 0 — Catalog Foundations

### T-B-01 · Catalog base model + connection lock
- `BaseCatalogModel` extends A's `BaseDomainModel` with `$connection = 'catalog'` enforced;
  catalog models live in `app/Models/Catalog/`.
- Migration folder `database/migrations/catalog/` seeded with empty baseline.
- **DEPS:** T-A-01
- **AC:** test asserts every model in `Models/Catalog` uses the catalog connection; migration
  folder runs clean on the catalog SQLite sim.

### T-B-02 · `CatalogService` interface (contract for C & D)
- `App\Services\Catalog\CatalogService` (interface) + facade binding:
  `contentItem(id)`, `courseTree(courseId)`, `questionsFor(assessmentId)`,
  `topicCoverage(courseId)`, `prebuiltMaps(subjectId)`, `sampleContent(courseId)`.
- Stub implementation in Phase 0 (returns empty) so C/D can compile against it; real
  implementation lands with T-B-05/T-B-08/T-B-09.
- **DEPS:** T-A-01, T-A-06
- **AC:** interface file + stub merged; C and D feature tests can inject it via mock;
  docblock states "implementors must never cross into other DB connections".

### T-B-03 · Catalog response DTOs + access-gate helper
- Standardized DTOs (CourseDto, ContentItemDto, AssessmentDto) mapping model→payload;
  each DTO carries `access: full | sample | locked` computed via
  `SubscriptionService::isEntitled` (DEPS⚡ T-A-13) — **samples ≈ 2 min preview**, locked =
  subscription/purchase required (message states what's needed).
- **DEPS:** T-A-05, DEPS⚡ T-A-13
- **AC:** DTO for unentitled user shows `access: sample` with preview fields only (no full
  transcript/URL); entitled user gets `full`; locked shows upgrade path; test per state.

---

**Phase 0 complete** — [x] T-B-01 · [x] T-B-02 · [x] T-B-03 — 2026-09-24 — merged `df7ef31` (branch `track-b/T-B-01-catalog-base-model`). GATE 1 passed.


## PHASE 1 — Curriculum & Course Structure

### T-B-04 · Curriculum organization (academic + professional trees)
- Tables: `boards` (status active/inactive/archived), `grades` (per board, ordering, age band),
  `subjects` (per grade within board; cross-subject links prerequisite/related),
  `chapters`, `topics` (importance high/med/low **required on every topic**; directional
  prerequisite links — enforce vs recommend), `categories`, `sub_categories` (professional;
  skill tags from single shared vocabulary, career-path suggestions).
- CRUD endpoints with board-scoping: same grade/subject name under different boards = distinct
  nodes; material mapped to one board never surfaces under another (test).
- Boards/grades/subjects with dependents → **archive, not delete**; archive stops new mapping,
  preserves history; delete only dependency-free (409 otherwise).
- Topic = unit of attachment for content/assessments/progress; node with no content = visible
  gap in coverage reports (never silent).
- Certification config per board (auto-issuance requirements; revocation reason-recorded with
  learner notification — event to D).
- **DEPS:** T-B-01
- **AC:** archive cascade rules (test: subject with content → 409 on delete, archive OK);
  prerequisite graph validation (cycle rejected 422); skill tag vocabulary enforced (unknown
  tag 422); importance required (422 missing); coverage-gap report lists empty topics (test).
- [x] T-B-04 — 2026-09-24 — merged `bc0a862` (branch `track-b/T-B-04-curriculum-trees`)

### T-B-05 · Course management (academic + professional)
- `courses`: type academic (placed under board→grade→subject) | professional (category→
  sub-category, outcomes, instructor, effort estimate, prerequisites recommend/enforce,
  certification alignment); **one structure placement, set at creation, nodes must be
  active**.
- `course_modules`/`course_units`: ordered; unit = unit of content & progress; progression
  rule (locked-in-order vs free-nav) — rule change never invalidates completed units.
- Status: draft / published / archived; **publish gated by readiness check** (content
  completeness per unit — incomplete course not published cleanly, 409 with gap list);
  archive (not delete) when enrollments exist; visibility vs availability are SEPARATE
  controls (visible-but-restricted, assignment-only).
- `course_assignments` (course↔group many-to-many; unassignment reviewed for in-progress
  impact), batch assessment schedules (assessment + time window + group; reschedule →
  re-notification event + prior-attempt handling).
- Learning paths (curated sequenced course sets; assignment to learner/group) — definitions
  here; runtime progress in C (T-C-11).
- **DEPS:** T-B-04
- **AC:** readiness gate blocks publish with explicit missing-unit list (test); academic
  course never surfaces in professional browse tree (test); assignment-only course hidden
  from public browse but enrollable by assigned group; archive preserves progress refs
  (test with C stub).

### T-B-06 · Content items + media pipeline
- `content_items` (generic): type (video_tutorial, podcast, article), status (draft/
  published/unpublished/archived/deleted), placement (course/unit, topic), prerequisite
  links, difficulty, completion estimate, media reference (object storage key S3/MinIO —
  metadata only in catalog).
- Upload pipeline: `POST /content/videos` → validation (format/quality/size, specific
  rejection reasons) → state uploaded → processing → playable; subtitles = timed text,
  multi-language; missing language coverage flagged (not silent) against supported set.
- **Versioning: append-only**; media replacement = new version preserving identity/placement;
  restore = recorded version event; learners always see latest; retention per platform policy.
- Podcasts: downloadable flag policy-gated (system settings from A, DEPS⚡ T-A-23).
- Assignment: targets must be active nodes; coverage view exposes per-node gaps; unassignment
  reviewed for learner impact (confirmation flag required).
- Delete blocked by dependency check (409); archive = default retirement.
- Effectiveness metrics (completion rate, drop-off curve, feedback score) — raw counters
  written by C via `CatalogService` counters, aggregated by D (analytics).
- **DEPS:** T-B-05
- **AC:** bad upload → 422 with format/size reason; item playable only after processing state
  (test with queued processing); version restore creates new version row (history intact);
  delete with active assignment → 409; subtitle language coverage report (test).

### T-B-07 · Resource library (PDFs, flashcards, mind maps, FAQs)
- `resources`: type (pdf, worksheet, solved_example, formula_sheet, case_study, research,
  infographic), per-video or per-subject, assignment to video/topic/subject, versioned
  (append-only, same rules as T-B-06).
- `flashcard_decks`/`flashcards` (front/back, image/audio, topic+difficulty; AI-generated =
  **draft until human review**; marked with source video; community library with moderation
  state), `mind_maps` (per topic; clickable nodes with content links; color-coded by
  importance), `faqs` (per-video; searchable; student-submitted → moderated;
  teacher-verified answers).
- Downloads governed by platform download policy (entitlement check via A, DEPS⚡ T-A-23).
- External links validated (resolve, correct target); broken links replaced/removed (job).
- **DEPS:** T-B-06
- **AC:** AI flashcard deck stays draft until reviewer approves (test); delete resource with
  references → 409; community deck moderation states (pending/approved/removed with reason);
  broken-link job flags N planted dead links (test); worksheet download for unentitled user
  → 403.

---

## PHASE 2 — Assessment Definition & Approval

### T-B-08 · Question bank + assessment definitions
- `questions`: stem/options/answer/explanation; type (MCQ, multi-select, fill-blank, T/F,
  numeric, short-answer, essay); difficulty; Bloom's level; topic/subject tags; source
  (manual | AI with source video); status draft→approved (duplicates flagged).
  **AI-generated questions are drafts — enter bank only after human review; rejected ones
  recorded and never enter.**
- `assessments`: format (practice, mock, full-length, sectional, timed, video-wise
  auto-generated); passing score (change applies to FUTURE attempts only — recorded outcomes
  never retrochanged); retake policy (allowance, limit, best/last score rule); adaptive
  config (difficulty floor/ceiling, calibration rule — opt-in); exam pattern (counts/marks/
  duration); status active/retired (attempts exist → retire, not delete, 409).
- Video-wise auto-generated quizzes from content (per video, DEPS T-B-06); content update →
  regeneration prompt (not silent overwrite).
- Past papers: per subject/year/exam, availability-conditional, batch-scoped access,
  memo where available.
- Grading config: objective instant; subjective → AI (rubric-based with rationale) →
  optional human review per config (deeper for high-stakes); override keeps AI's original
  grade (reason recorded). **Runtime attempt handling is Track C (T-C-05) — B owns the
  definition + grading config.**
- `CatalogService::questionsFor` real implementation.
- **DEPS:** T-B-04, T-B-06
- **AC:** AI question without approval not returnable in bank queries (test); exam with
  attempts → delete 409, retire OK; passing-score change: prior attempt scores untouched
  (test); multi-select grading config validated (full-marks rule documented); adaptive
  bounds enforced in config validation (422 floor>ceiling).

### T-B-09 · Content approval workflow + moderation
- `review_items`: content type, creator, status pending → in_review → approved | rejected |
  flagged; **content never auto-approved, never live until approved** (approval recorded:
  reviewer, time).
- Workflow variants per content type/risk (low vs high); reviewer assignment by
  subject/type/expertise; workload visible; reassignment recorded.
- Rejection = definitive with specific reasons + creator notification (event to D) +
  resubmission path; Flag = marker on pending OR live content, type-specific action,
  resolution mandatory (never left open).
- Community content (flashcards, forums, Q&A — forums/Q&A records in engagement/D) →
  intake: `POST /moderation/reports` (review → action/dismiss reason noted → close).
- Age-appropriate filter: age group (grade/band) × content age rating; **enforced gate,
  not bypassable**; mis-rated items corrected + recorded.
- Queue endpoint: filter type/subject/creator/status; bulk approve = per-item records.
- Version history shared with T-B-06 (compare, restore previewed before commit).
- **DEPS:** T-B-06, T-B-07
- **AC:** draft content unreachable by learner endpoints until approved (test: 404/403 per
  access state); rejection without reasons → 422; flag on live content triggers its
  type-specific action; age gate: over-age content hidden for young learner (test);
  queue aging metric (for D dashboard, event emitted).

### T-B-10 · SRS platform configuration
- `srs_schedule_config`: intervals (1d/3d/1w/2w/1m) + floor/cap; per-grade-band overrides.
- `ebbinghaus_params`: retention-curve parameters — **must decay monotonically, invalid
  combos rejected (422)**; preview endpoint renders curve from same model.
- `recall_adjustment_rules`: success extension factor, failure reset (e.g. to 1d),
  consecutive-success bonus, rating map (Too Easy/Good/Hard → exactly one next interval,
  no compounding), caps (max extension, min reset).
- `srs_eligibility`: flashcard sets, quiz questions, videos, concept-reinforcement mappings
  (**no orphan concepts**); non-eligible content never enters SRS.
- Resurfacing rules (interval, trigger on-error/on-schedule/both, error-weighting never
  below floor, per-question cap), video revision reminders (cap, skip-if-rewatched).
- `mastery_model`: level thresholds from recall rate (**no manual override**), confidence-
  rating config, retention prediction (at-risk threshold), graduation (criteria, archive,
  re-entry, periodic re-check).
- Config changes apply to **newly scheduled reviews only** (C's runtime honors this,
  DEPS⚡ T-C-08).
- **DEPS:** T-B-07
- **AC:** non-monotonic Ebbinghaus params → 422; rating map completeness validated
  (every rating → exactly one interval); grade-band override > global (test);
  eligibility: non-eligible flashcard set excluded from C's due-queue (test via contract).

### T-B-11 · Target-exam templates + AI feature configuration
- `exam_types`: kind (school/board/competitive/professional), status active/disabled
  (**disable-only if active students**; duplicate created as draft; name conflict 422).
- `exam_templates`: sections, question types, total marks (sections sum ≤ total, 422);
  **versioned — active-in-use never edited in place** (new version on edit; archived =
  read-only).
- `topic_mappings`: per exam type, importance (default chain: topic → subject default →
  global medium); mapping change on live type = versioned; bulk import with row-level
  reject report.
- `prediction_config`: algorithm+params per exam type (override > global; rollback exact;
  in-use versions not deleted), data inputs (freshness, min data points), confidence
  intervals (**zero-width rejected**), update frequency, accuracy calibration (drift →
  alert event).
- `study_plan_generation_config`: inputs (exam date, level, gaps), coverage rule, gap-first
  rule, horizon (full vs rolling weekly), task templates (learn-before-practice ordering —
  violations never generated), revision cycles (clamped ≥ SRS minimum; high importance
  never deprioritized below low), milestone triggers (fire once per student per plan;
  parent notification respects prefs), adherence (late = slipped; at-risk threshold).
- AI feature configs (tutor/mentor/planner/companion/score-prediction) from super-admin
  module 28: question limits per plan, escalation rules (student-requested always succeeds,
  low-confidence threshold, handoff context auto-generated, async-ticket fallback),
  mentor personas per grade band, EI thresholds, planner (Pomodoro, distraction-free —
  suppressed notifications queued, allowed interruptions), companion (mood, burnout,
  break rules 5/10/20, counselor triggers).
- **DEPS:** T-B-08, T-B-10
- **AC:** active exam type with students → delete 422, disable OK; template edit creates
  v2 (v1 frozen); prediction with insufficient data → "not shown, prompt to practice"
  (contract with C); config changes non-retroactive (test).

---

## PHASE 3 — Catalog Administration

### T-B-12 · Catalog coverage, gaps & retirement jobs
- Coverage reports: per board/subject node — topics without content, topics without
  assessments, content without approval, questions without topic tag (visible gaps, never
  silent).
- Retirement: content update → dependent quiz regeneration prompt; retired course flag
  (history preserved); external-link validation job (T-B-07); orphan resource detection.
- `CatalogService` final implementations (`topicCoverage`, `prebuiltMaps`, `sampleContent`).
- **DEPS:** T-B-05, T-B-08, T-B-09
- **AC:** coverage report matches planted gap fixture (test); retirement job flags quizzes
  attached to replaced media (test); sample content respects 2-min preview bound (test).

### T-B-13 · Catalog seeding & fixtures
- Seeded board/grade/subject trees (1 board, 2 grades, 3 subjects, chapters/topics with
  importance + prerequisites), 2 courses (1 academic, 1 professional) with units,
  10 content items (mixed states/versions), 20 questions (mixed types/sources), 2
  assessments (1 timed, 1 adaptive), 1 flashcard deck, 1 SRS config set, 1 exam type +
  template + prediction config.
- **DEPS:** T-B-12
- **AC:** seed command idempotent (`artisan catalog:seed` runs twice cleanly); fixtures
  used by C and D integration tests (documented in each track's test bootstrap).

---

## Phase Gates (Track B)
- **Gate 1 (end Phase 0):** C & D can compile against `CatalogService` stub; catalog DB green.
- **Gate 2 (end Phase 1):** a super admin can build board→topic, publish a course, upload +
  version content, attach resources — all through approval workflow.
- **Gate 3 (end Phase 2):** question bank + adaptive exam + SRS config + target-exam template
  E2E-configurable; approval gate enforced on every content path.
- **Gate 4 (end Phase 3):** fixtures live; C can run a full learning session against seeded catalog.

## Contract Stub Obligations (Track B must ship)
- `CatalogService` (real impl by Gate 2/3), DTOs with access states, approval status
  transitions as events (`ContentApproved`, `CoursePublished`), SRS config reader
  interface for C (`SrsConfigService`), AI config reader for C (`AiConfigService`).
