Automated checks
Fromserver, with Node 24 and pnpm 9.15.4:
Live API and persistence
- Apply the certificate migration and build the backend. Confirm
dist/assets/certificatescontains the PDF and three fonts. Start the API, certificate worker and outbox worker with test configuration from Infisical. - Use two distinct learners. Complete a valid enrolled course as learner A.
Verify automatic generation produces one certificate and one outbox event;
the notification links to
/my-certificate?certificateId=.... - Call
POST /certificate/course/:courseId/issueas A. Expect 200 with metadata. Repeat it, including simultaneous HTTP requests and a queue job. Verify one database row, one issuance event, one ID/date and unchanged PDF SHA-256. - List with page/limit and course filters. Empty results must be valid. Get the certificate metadata; confirm no storage key or other learners’ records leak.
- Download with A’s JWT. Expect raw
application/pdf, attachment filename andprivate, no-store. Compare the downloaded SHA-256 with metadata. Repeat the download after changing A’s name/course title; bytes must remain unchanged. - Attempt list/get/download/issue without JWT, with expired JWT and as B. No unauthenticated access; B cannot fetch A’s metadata or PDF (404). Passing A’s user ID/name in the issuance body must never issue as A.
- Verify new issuance rejects incomplete/empty courses, pending/rejected/refunded enrollment, expired access and partial course access. Verify fully purchased sections and both supported completion paths can qualify.
- Test stale/foreign video/lesson IDs and a nearly complete rounded percentage. Neither may grant a certificate. Progress writes must reject another learner, another course’s content and unpurchased sections.
- Simulate Redis unavailability during final progress: saved progress survives; the explicit issue endpoint recovers after infrastructure is healthy. Retry a failed generation job and confirm no duplicate issuance.
- Simulate storage upload failure: no certificate/outbox record should commit. Restore storage and retry. Simulate unavailable/corrupted stored content: download returns 503 rather than a broken PDF or a silent regeneration.
- Simulate email failure after issuance: the PDF stays downloadable and the outbox retries. Repeated successful issuance requests must not create new emails.
- Verify migration up on the target schema and unique index enforcement using concurrent real database transactions. Back up before any rollback test; dropping the table does not remove objects from storage.
Visual acceptance
Generate reproducible reference, long-text and accented-name examples locally:server/tmp/certificate-previews by default. Render each generated
PDF with Poppler and open it in a browser PDF viewer: