// Journey: login with TOTP MFA — enroll → login (mfa_required) → login/mfa → /me // // Endpoints: // POST /api/v1/auth/register/confirm path (via registerAndConfirm) // POST /api/v1/members/me/totp/enroll-start + enroll-confirm // POST /api/v1/auth/login // POST /api/v1/auth/login/mfa // GET /api/v1/members/me import { get, checkEnvelope } from '../lib/http.js'; import { registerAndConfirm, loginExpectMFA, loginMfaConfirm } from '../lib/auth.js'; import { enrollTOTP } from '../lib/member.js'; import { generateTOTP } from '../lib/totp.js'; export const options = { vus: 1, iterations: 1, thresholds: { checks: ['rate==1.0'] }, }; export default function () { const { identity, tokens } = registerAndConfirm(); const bearer = { Authorization: `Bearer ${tokens.access_token}` }; const { otpauthUrl } = enrollTOTP(bearer); const mfa = loginExpectMFA({ email: identity.email, password: identity.password, }); const totpCode = generateTOTP(otpauthUrl); const session = loginMfaConfirm({ challengeId: mfa.mfa_challenge_id, code: totpCode, }); if (!session.access_token) { throw new Error('login/mfa journey: missing access_token'); } const me = checkEnvelope( get('/api/v1/members/me', { Authorization: `Bearer ${session.access_token}` }), 'GET /members/me (after login/mfa)', ).data; if (me.uid !== session.uid) { throw new Error('login/mfa journey: uid mismatch'); } }