Skip to content

feat(certification): R-7 Certification Engine + onboarding doc - #242

Open
Sainikhil-hub wants to merge 5 commits into
vicharanashala:mainfrom
Sainikhil-hub:certification-engine
Open

feat(certification): R-7 Certification Engine + onboarding doc#242
Sainikhil-hub wants to merge 5 commits into
vicharanashala:mainfrom
Sainikhil-hub:certification-engine

Conversation

@Sainikhil-hub

Copy link
Copy Markdown

Summary

Implements SRS R-7 (Certification Engine) end-to-end:

  • Backend: pure eligibility engine + MongoDB orchestrator with optimistic concurrency
  • API: POST /api/certification/review/:id (SUPERADMIN/ADMIN), GET /api/certifications
  • Auto-trigger: fires fire-and-forget at every addEvaluationReport site
  • Frontend: CertificationReviewPanel (admin queue) + CertificationHistoryCard (per-student)
  • Demo seed script: produces 2 review_needed + 1 active students for mentor demos
  • Onboarding doc: Ideas/ONBOARDING-Sainikhil.md (per project policy)

What changed (29 files in the feat commit,1 file in the docs commit)

  • backend/src/certification.ts — pure decideEligibility engine (81 lines)
  • backend/src/certificationRecords.ts — orchestration + optimistic concurrency (358 lines)
  • backend/src/competencyRequirements.ts + data/competencyRequirements.seed.json — registry (168 lines)
  • backend/src/routes/certification.ts — review + list endpoints (153 lines, NEW file)
  • backend/src/index.ts — route registration (2 lines)
  • backend/src/routes/evaluation.ts — 2 fire-and-forget triggers (7 lines)
  • backend/src/routes/students.ts — 1 fire-and-forget trigger (4 lines)
  • backend/src/db.tsCertification, CompetencyRequirement, MasteryLevel, CertificationStatus types + 7 DBStore accessors (134 lines)
  • backend/src/scripts/demo-cert.ts — demo seed (220 lines)
  • backend/src/modules/certification/ — future-Mongoose mirror + notification.service.ts
  • backend/src/__checks__/certification*.check.ts — runnable assert scripts (zero deps)
  • frontend/src/components/CertificationReviewPanel.tsx — admin queue (407 lines)
  • frontend/src/components/CertificationHistoryCard.tsx — per-student history (167 lines)
  • frontend/src/components/Layout.tsx — sidebar entry (4 lines)
  • frontend/src/components/PanelViews.tsx — panel routing (14 lines)

Test plan

  1. npm install && npm run lint — clean
  2. npx tsx backend/src/scripts/demo-cert.ts --reset → seeds 5 Class 4 students
  3. Login as superadmin@fln.org / Fln@2026
  4. Sidebar → Certification Reviews → see 2 review_needed rows
  5. Click Confirm on Sushma Khan → toast + status flips to active
  6. Click Revoke on Savita Ansari → modal asks reason → status flips to revoked
  7. curl race test: two parallel review POSTs → one succeeds, other gets 409

Onboarding

Per project policy: Ideas/ONBOARDING-Sainikhil.md includes all 6 required sections (What is FLN, FLN as a system, Current state, Gaps, Ideas, Your Contribution) and is ready for review.

Verification of gaps (live data)

/api/stats.certifiedCount = 63,276 (uses currentLevel >= 5 shortcut)
/api/certifications?status=active count = 2 (actual Certification rows)
→ documented as Gap 1 in the onboarding doc; the new engine doesn't fix this gap (out of scope for this PR) but the certification data is now the source of truth for the review workflow.

Notes

  • Cert rows live in MongoDB Atlas only — no data leaks via this PR (verified: 0 cert row matches in commit content)
  • Demo-cert seed script is the canonical way for reviewers to get review_needed certs for their own demos

…es split

- Add Certification/CompetencyRequirement types + DBStore accessors
  (getCertifications, getCertificationById, getCertificationByStudentClassLevel,
  addCertification, updateCertification, updateCertificationIfVersion,
  getCompetencyRequirements, getLatestConceptMastery)
- Seed competencyRequirements via getSeedCompetencyRequirements() loaded
  from data/competencyRequirements.seed.json
- New backend/src/routes/certification.ts:
  - POST /api/certification/review/:id  (SUPERADMIN/ADMIN, optimistic concurrency)
  - GET /api/certifications               (queue view = admins; per-student = any role with access)
- Register the route in backend/src/index.ts
- Fire-and-forget runCertificationEligibility() at every EvaluationReport
  creation site (routes/evaluation.ts x2, routes/students.ts x1)
- Frontend: 'Certification Reviews' sidebar entry (ADMIN/SUPERADMIN)
  in Layout.tsx, new 'certification_reviews' panel case in PanelViews.tsx
  mounting CertificationReviewPanel
- Tweak check fixtures / Mongoose stubs against post-remove-streak Student
… Engine (R-7)

Six-section structure per PR template:
1. What is FLN?
2. FLN as a system
3. Current state of the repo
4. Gaps observed (with file:line refs and impact analysis)
5. Ideas for the project (one per gap)
6. Your Contribution (the full Certification Engine work)

Gaps documented:
- stats.ts:28 still uses currentLevel >= 5 shortcut
- notification.service.ts:35 emails admins across all states
- certificationRecords.ts:24 in-memory lock won't survive restart/replicas
- demo-cert.ts:29 hard-coded to Class 4
- CertificationReviewPanel.tsx:62 race on role switch
- No test pinning cert shortcut vs engine agreement
… Engine (R-7)

Six-section structure per PR template:
1. What is FLN?
2. FLN as a system
3. Current state of the repo
4. Gaps observed (with file:line refs and impact analysis)
5. Ideas for the project (one per gap)
6. Your Contribution (the full Certification Engine work)

Gaps documented:
- stats.ts:28 still uses currentLevel >= 5 shortcut
- notification.service.ts:35 emails admins across all states
- certificationRecords.ts:24 in-memory lock won't survive restart/replicas
- demo-cert.ts:29 hard-coded to Class 4
- CertificationReviewPanel.tsx:62 race on role switch
- No test pinning cert shortcut vs engine agreement
@jgupta05072003-code

Copy link
Copy Markdown
Collaborator

Thank you for this, Sai Nikhil. This is a detailed and thoughtfully implemented contribution toward the R-7 Certification Engine.

A few things stood out positively during the review. The concurrency handling is not only mentioned in the PR description but is also properly implemented end to end. The optimistic concurrency flow, including the 409 conflict handling, is wired from the backend through to the frontend. The separation between the eligibility decision logic and the database/orchestration layer also makes the certification flow easier to understand, test, and maintain.

I also appreciate that the PR clearly mentions what is intentionally outside its current scope, particularly the existing currentLevel >= 5 statistics shortcut. Keeping that as a separate follow-up task makes the scope of this PR much clearer.

One point worth discussing further is the presence of two implementations of the eligibility engine: the live implementation in backend/src/certification.ts and the future Mongoose-oriented version under backend/src/modules/certification/. The manual validation script is a useful safeguard, but since we do not currently have CI configured to run it automatically, preventing drift still depends on someone remembering to run the check manually. We may want to decide whether this validation should be added to CI in the future, or whether the second implementation should wait until the Mongoose migration is actively being worked on.

Another important consideration is that the certification module is closely dependent on how the level progression logic is finalized and how student mastery is determined through the evaluation and report-generation flow. Since certification is ultimately based on the evidence produced by these systems, we should ensure that the certification criteria remain aligned with the final level logic, mastery calculations, and reporting methodology. Any future changes in these areas should be reflected consistently in the certification engine as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants