Drafted coverage tickets for the missing HTTP e2e flows. Not yet in the sprint — pending review/approval before being added.
These run in the existing real-stack harness: the real Express app driven over HTTP (supertest) against real MySQL 8 + real Redis 7 (Testcontainers, nothing internal mocked). Only external network boundaries are mocked (Didit, email/validation providers, S3/Bunny). No worker process runs in tests, so anything asynchronous (emails, certificate PDFs, bulk/onboarding jobs) is asserted at the enqueue / PENDING boundary.
Current coverage: only the V-Learning member slice (assignments, planner, lesson progress/gating, certificate read/download) plus health/auth-gate/404. Every other route group below has zero e2e.
Acceptance Criteria convention (all e2e tickets): coverage % is not the yardstick for journey tests. Each ticket's AC is: the listed flows/cases pass end-to-end through HTTP against the real-stack harness; only external boundaries mocked; new tests live in tests/integration/ and self-skip without Docker; all tests pass.
Real-stack HTTP e2e coverage for /api/v1/auth/* and session management, broken into small, independently reviewable tickets under one epic. Shared conventions (apply to every child ticket): real Express app over supertest against real MySQL 8 + Redis 7 (Testcontainers); only external boundaries mocked (email/validation providers); async work asserted at the enqueue boundary (no worker runs); tests live in tests/integration/ and self-skip without Docker.
Child tickets
Issue Type: Task
Epic: Auth & sessions
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-auth-core
Test Root: tests/integration/
Description
Real-stack HTTP coverage for the core entry journey only: register → verify email → login → refresh → logout. Recovery, OTP, session listing, and rate limits are out of scope here (separate child tickets). Email/validation providers are mocked at the boundary; the activation email is asserted as enqueued, not sent.
Files / Scope
tests/integration/http/auth/coreLifecycleHttp.integration.test.ts
Test Cases
POST /auth/register
status=Pending, email_verified=false, kyc_verified=false; one activation-email job is enqueued.DISABLE_EMAIL_VERIFICATION=true → user created already Active + email_verified=true, and no activation email is enqueued.GET /auth/verify-email?token=
Active, email_verified=true, token cleared; redirects to the frontend with verified=true.verified=false and an error message.POST /auth/login
Active user + correct password → 200; returns an access token and a refresh token; a session row is created.Pending user → 200 with status: "pending" and no token issued.Suspended / Terminated user → 401 with the corresponding message.POST /auth/refresh
POST /auth/logout
POST /auth/logout-all
Acceptance Criteria
All listed cases pass end-to-end through HTTP against the real-stack harness (Testcontainers MySQL + Redis); only external boundaries (email/validation providers) mocked; the activation email is asserted at the enqueue boundary. Tests self-skip without Docker. All tests pass.
Issue Type: Task
Epic: Auth & sessions
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-auth-recovery
Test Root: tests/integration/
Description
Real-stack HTTP coverage for password recovery and resend-verification. Email providers mocked; the reset/activation emails are asserted as enqueued, and the reset token is checked in Redis. Throttle behavior is covered separately in the Auth rate limiting ticket.
Files / Scope
tests/integration/http/auth/recoveryHttp.integration.test.ts
Test Cases
POST /auth/forget-password
POST /auth/reset-password
POST /auth/resend-email-verification
Active user → 200 generic message; nothing enqueued (no-op).Acceptance Criteria
All listed cases pass end-to-end through HTTP against the real-stack harness (Testcontainers MySQL + Redis); email providers mocked; reset/activation emails asserted at the enqueue boundary and the reset token asserted in Redis. Tests self-skip without Docker. All tests pass.
Issue Type: Task
Epic: Auth & sessions
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-auth-otp
Test Root: tests/integration/
Description
Real-stack HTTP coverage for the passwordless OTP login flow. Email provider mocked; the OTP is asserted in Redis and the email asserted as enqueued/sent at the boundary. The 3-attempt lockout is covered in the Auth rate limiting ticket.
Files / Scope
tests/integration/http/auth/otpLoginHttp.integration.test.ts
Test Cases
POST /auth/send-login-otp
Active user → 200; a 6-digit OTP is stored in Redis with a 10-minute TTL and an OTP email is enqueued.Active user (Pending/Suspended) → 200 with success:false and the login-status message; no OTP stored (controller stays 200 to avoid enumeration).POST /auth/login-with-otp
Acceptance Criteria
All listed cases pass end-to-end through HTTP against the real-stack harness (Testcontainers MySQL + Redis); email provider mocked; OTP asserted in Redis. Tests self-skip without Docker. All tests pass.
Issue Type: Task
Epic: Auth & sessions
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-auth-sessions
Test Root: tests/integration/
Description
Real-stack HTTP coverage for the authenticated session-listing/revocation endpoints and the in-session password change.
Files / Scope
tests/integration/http/auth/sessionsHttp.integration.test.ts
Test Cases
GET /auth/sessions
DELETE /auth/sessions/:sessionId
PUT /auth/update-password
Acceptance Criteria
All listed cases pass end-to-end through HTTP against the real-stack harness (Testcontainers MySQL + Redis). Tests self-skip without Docker. All tests pass.
Issue Type: Task
Epic: Auth & sessions
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-auth-rate-limits
Test Root: tests/integration/
Description
Real-stack HTTP coverage for the application-level (Redis-backed) auth rate limits. Note: the HTTP per-IP express-rate-limit middleware is currently commented out in app.ts, so there is no per-route IP throttle to test today — scope is the two enforced in-app limits below.
Files / Scope
tests/integration/http/auth/rateLimitsHttp.integration.test.ts
Test Cases
resend-email-verification throttle (1 per 5 minutes per user)
activation_email_rate:<userId>).OTP 3-attempt lockout
(Note)
app.ts. If it is re-enabled, add per-route cases here (e.g. burst on /auth/login, /auth/register → 429).Acceptance Criteria
All listed cases pass end-to-end through HTTP against the real-stack harness (Testcontainers MySQL + Redis); Redis-backed limits asserted via the relevant keys/attempt counters. Tests self-skip without Docker. All tests pass.
Issue Type: Task
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-kyc
Test Root: tests/integration/
Description
Real-stack coverage for /api/v1/kyc/* and the KYC access gate in verifyToken. Didit provider mocked; the webhook is exercised with a genuine HMAC x-signature over the raw body using a known DIDIT_WEBHOOK_SECRET.
Files / Scope
tests/integration/http/kycHttp.integration.test.ts
Test Cases
kycVerified:true; required + already verified short-circuit; required + unverified returns latest verification status (incl. max_declined).not_started/in_progress returns same URL; declined-at-max-retries → blocked; creates a new session (Didit mocked).approved flips kyc_verified=true; declined sets rejection reason; unknown session handled.x-service-key → 401; valid approved flips kyc_verified./kyc/status, /auth/refresh, admin) bypasses; after approval webhook the gated route passes.Acceptance Criteria
All listed flows pass through HTTP against the real-stack harness; Didit mocked, webhook signature real. Self-skips without Docker. All tests pass.
Issue Type: Task
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-admin-users
Test Root: tests/integration/
Description
Real-stack coverage for admin auth, the requireAdmin/requireRole gates, and the /api/v1/admin/users/* management surface — including the moderation journey and the BR-243 manual inconsistency path.
Files / Scope
tests/integration/http/adminUsersHttp.integration.test.ts
Test Cases
User token on admin route → 403; admin success.status, kycVerified, country, search), soft-deleted exclusion, sort.PUT /users/:id updates fields; setting kycVerified and status independently (documents the BR-243 manual Pending + kyc_verified=true path).Active; invalid status → 400; cannot modify own account.Admin_Removed), cannot delete self, child referrals reassigned.Failed → Pending, kyc_verified reset to false).Acceptance Criteria
All listed flows pass through HTTP against the real-stack harness; bulk/email jobs asserted at the enqueue boundary. Self-skips without Docker. All tests pass.
Issue Type: Task
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-member-exam
Test Root: tests/integration/
Description
Extends the existing V-Learning member e2e to the untested member surface: the full exam-to-certificate journey, planner edits, module browsing, and notes. Certificate generation asserts at the PENDING/enqueue boundary (no cert worker runs in tests).
Files / Scope
tests/integration/http/memberExamHttp.integration.test.ts (and extend vlearningHttp.integration.test.ts)
Test Cases
GET /modules/:id/exam; POST .../exam/start creates an attempt; cannot start when ineligible (lessons incomplete / max attempts / cooldown); active-attempt returns the in-flight attempt.POST /exam-attempts/:id/answer saves; submit scores → pass enqueues a PENDING certificate, fail does not; results reflect the score.violation records and (at threshold) auto-finalizes; abandon → abandoned; timed-out attempt → timed_out.PATCH /planner/:id, DELETE /planner/:id.GET /modules, /modules/:id, /current-lesson, lesson notes get/save, resource download, active categories.Acceptance Criteria
All listed flows pass through HTTP against the real-stack harness; cert/email async asserted at the enqueue boundary. Self-skips without Docker. All tests pass.
Issue Type: Task
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-members-account
Test Root: tests/integration/
Description
Real-stack coverage for /api/v1/users/* — profile, the referral cycle/stats, public lookups, and account cancellation — including the referral registration journey.
Files / Scope
tests/integration/http/membersAccountHttp.integration.test.ts
Test Cases
referral/:code (valid / invalid / referral-rule errors); invitation/:code (valid / invalid / expired).referral-cycle list + pagination; CSV export; referrals/stats active-vs-pending counts.referral-cycle/stats reflect the new member; level-up eligibility flips when the circle is full + verified.Self_Removed, sessions revoked, subsequent login blocked.Acceptance Criteria
All listed flows pass through HTTP against the real-stack harness. Self-skips without Docker. All tests pass.
Issue Type: Task
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-content
Test Root: tests/integration/
Description
Real-stack coverage of the publish lifecycle for news, posts, and events across the admin (requireAdminOrPublisher) and public surfaces, plus event registration. (No capacity/sanitization assertions — those aren't implemented.)
Files / Scope
tests/integration/http/contentHttp.integration.test.ts
Test Cases
GET → publish → present in public list + get-by-id → unpublish → gone; update; delete; role gate (User → 403); validation → 400.GET /events/:id/registrations.register → my-registrations shows it → registration-status → unregister; duplicate registration handled.Acceptance Criteria
All listed flows pass through HTTP against the real-stack harness. Self-skips without Docker. All tests pass.
Issue Type: Task
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-platform
Test Root: tests/integration/
Description
Real-stack coverage for the remaining admin/platform surfaces. Storage (S3/Bunny) and email providers mocked at the boundary; bulk/onboarding jobs asserted at the enqueue boundary.
Files / Scope
tests/integration/http/platformHttp.integration.test.ts
Test Cases
GET; admin create / get-by-key / update / delete / bulk-update; a toggled setting (e.g. KYC-required, registration-disabled) is reflected by the consuming route.upload single + multiple (multer), with the latin1→UTF-8 filename normalization applied to a non-ASCII name; delete; get-url; auth/role gates.upload (validation of good/bad rows) → start → status → retry-email / retry-failed → history / batch details (bulk email enqueued; no worker)./webhook/postmark (+ the two other provider webhooks) update the email-notification record; invalid payload/signature rejected.Acceptance Criteria
All listed flows pass through HTTP against the real-stack harness; storage/email mocked, jobs asserted at enqueue. Self-skips without Docker. All tests pass.
Issue Type: Task
Area: API Integration Tests (HTTP e2e)
Branch: cov/COV-XXX-e2e-admin-vlearning
Test Root: tests/integration/
Description
Real-stack coverage for the admin V-Learning authoring surface (modules, lessons, exams/questions, categories, announcements, assignments, results). Prerequisite: the admin vLearningController eagerly loads ESM file-type and is currently stubbed out of the e2e harness; this ticket must first make that import test-loadable (lazy/dynamic import or a vitest-compatible shim) so the controller can be driven over HTTP.
Files / Scope
tests/integration/http/adminVlearningHttp.integration.test.ts
Test Cases
requireAdmin gate.Acceptance Criteria
The file-type import is made test-loadable; all listed flows pass through HTTP against the real-stack harness (storage mocked). Self-skips without Docker. All tests pass.