fix(api): use admin app URL for teacher auto-enroll email links (#771)

* fix(api): use admin app URL for teacher auto-enroll links

Teacher payment-request emails now build course and grant-access URLs
with getAppBaseUrl() instead of getDashboardBaseUrl(org), so links
point at app.classroomio.com rather than a custom or tenant domain.

Document the teacher vs student email link rule in AGENTS.md.

Co-authored-by: Rotimi Best <[email protected]>

* docs: surface email link URL rules where emails are wired

Document getAppBaseUrl vs getDashboardBaseUrl in dashboard-url.ts,
packages/email/README.md, enqueueTransactionalEmail JSDoc, and AGENTS.md
so staff vs learner hosts are discoverable when building email links.

Co-authored-by: Rotimi Best <[email protected]>

---------

Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: Rotimi Best <[email protected]>
This commit is contained in:
Rotimi Best
2026-07-19 13:50:12 +01:00
committed by GitHub
co-authored by Rotimi Best Cursor Agent
parent e09b3caa8a
commit 0f23453f91
5 changed files with 67 additions and 12 deletions
@@ -5,7 +5,7 @@ import { getCourseWithOrgData } from '@cio/db/queries/course';
import { buildEmailFromName, buildEmailBranding } from '@cio/email';
import { enqueueTransactionalEmail } from '@api/services/jobs';
import { trackServerEvent, SERVER_EVENTS } from '@cio/analytics';
import { getDashboardBaseUrl } from '@cio/core/config/dashboard-url';
import { getAppBaseUrl } from '@cio/core/config/dashboard-url';
export interface PaymentRequestData {
courseId: string;
@@ -48,14 +48,9 @@ export async function createPaymentRequest(data: PaymentRequestData) {
const teacherEmail = teacherResult[0].email;
const dashboardOrg = {
siteName: course.orgSiteName,
customDomain: course.orgCustomDomain,
isCustomDomainVerified: course.orgIsCustomDomainVerified
};
const dashboardBaseUrl = getDashboardBaseUrl(dashboardOrg);
const courseUrl = `${dashboardBaseUrl}/courses/${data.courseId}`;
const autoEnrollUrl = `${dashboardBaseUrl}/courses/${data.courseId}/people?grantAccess=${encodeURIComponent(data.studentEmail)}`;
const appBaseUrl = getAppBaseUrl();
const courseUrl = `${appBaseUrl}/courses/${data.courseId}`;
const autoEnrollUrl = `${appBaseUrl}/courses/${data.courseId}/people?grantAccess=${encodeURIComponent(data.studentEmail)}`;
try {
await enqueueTransactionalEmail('teacherStudentBuyRequest', {