* feat(notifications): add email notification preferences
Implement the email notification preferences PRD with org-level defaults
and personal opt-outs enforced at the email enqueue chokepoint.
- Add toggle map, profile.settings jsonb, and shouldSendEmail resolver
- Extend profile and organization update APIs with emailNotifications
- Pass preference context through all toggleable email send call sites
- Add Settings > Notifications page with personal and org admin sections
Co-authored-by: Rotimi Best <[email protected]>
* feat(notifications): group email toggles into course, cohort, and enrollment sections
Organize personal and org notification settings into scannable sections
so users can find course- or cohort-related emails quickly.
Co-authored-by: Rotimi Best <[email protected]>
* fix(notifications): use Exercise instead of Quiz in toggle copy
Co-authored-by: Rotimi Best <[email protected]>
* fix(notifications): only mark certification email sent when enqueued
Skip setMemberCertificationEmailSent when notification preferences or
missing Redis prevent the completion email from being queued, so the
email can still send if preferences change later.
Co-authored-by: Rotimi Best <[email protected]>
* fix(notifications): address PR review feedback
- Add EmailPreferenceLookupCache to avoid N+1 settings lookups in batch
processors and multi-recipient email enqueue paths
- Replace $effect store hydration in notifications settings with onMount
and explicit sync after save
- Remove thin api email-preferences re-export; import from db queries
- Hide tutor-only personal toggles (newStudent, newSubmission) for students
Co-authored-by: Rotimi Best <[email protected]>
* fix(notifications): hydrate toggles after store load and add profile settings migration
- One-time store hydration via onMount plus guarded effect when profile/org
load after mount, without clobbering in-progress edits
- Add drizzle migration for profile.settings jsonb column
Co-authored-by: Rotimi Best <[email protected]>
---------
* fix(email): make team org invites more transactional
Use org-branded sender and subject instead of the default
"Best from ClassroomIO" marketing identity. Include the inviter
name in the body, remove promotional emojis, and thread optional
subject overrides through the email job pipeline.
Co-authored-by: Rotimi Best <[email protected]>
* fix(email): escape invite fields and sanitize email headers
Address Greptile review: escape inviter/org/role values in the team
invite template, sanitize display names in buildEmailFromName, and
strip control characters from dynamic subjects.
Co-authored-by: Rotimi Best <[email protected]>
* fix(email): use RFC 5322 backslash escaping in display names
Co-authored-by: Rotimi Best <[email protected]>
* test(email): add vitest coverage for email header helpers
Cover escapeHtml, sanitizeEmailDisplayName, sanitizeEmailSubject, and
buildEmailFromName. Collapse repeated whitespace when stripping control
characters from header values.
Co-authored-by: Rotimi Best <[email protected]>
* fix(email): strip all ASCII control chars from email headers
Co-authored-by: Rotimi Best <[email protected]>
---------
Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: Rotimi Best <[email protected]>
Adds live-class session scheduling on lessons (join link, date/time,
timezone) with automatic 24h and 1h reminder emails plus a calendar
invite (.ics), a time-change notification with an updated invite, a
teacher-authored welcome email and session invite on enrollment, and a
"Notify students" quiz nudge.
LMS gets an upcoming live-sessions card and Join buttons, plus a
reusable live-session card component (3 states) in @cio/ui with a
Storybook story. The sidebar content tree now reflects sequential
progression locking like the content list, and the course-completion
confetti regression is fixed.
Org-based emails no longer reference ClassroomIO by name. Docs add
live-class, welcome-email, and course-progression guides, expand the
certificates guide (design, signatures, corrected labels), move
plan-required callouts to the top, flatten how-to-guides to the docs
root with redirects, and add screenshots. Includes an add-docs-image
skill.
New features:
- HLS video encoding/streaming (hls routes, hls-encoder) and a media
transcripts pipeline (transcripts route + media-transcript queries)
- AI assistant chat vs. run model: agent-course-generation worker/queue,
run-monitor pane, chat-changes card, content ask-ai bar
- Per-theme course-page previews across org landing-page themes (bold,
classic, corporate, editorial, etc.) with a shared course token/component set
- View-as-student mode and login-link / link-invite invite flows
Refactor:
- Extract packages/core consolidating config (env, storage, dashboard-url),
services and utils previously duplicated under apps/api/src/config
- Remove legacy agent service modules (chat-tools, chat-context,
context-window, document, fetch-url, lesson-content)
- Relax Cross-Origin-Resource-Policy to allow cross-origin media embedding
- Add format script to tenant-router so turbo run format covers it