// Shared "launch/view a student's disposable Lab" logic. Phase 5B extracted this out of // server.js's original POST /api/environment/launch route body so the new entitlement-gated // self-paced launch route (selfpaced-routes.js) can reuse the EXACT same Provisioner call and // response shape instead of a second copy — the underlying disposable-Lab mechanism (Phase // 2A-4.1) is completely unchanged either way, only who's allowed to reach it differs. async function publicEnvView(provisioner, env) { if (!env) return { status: 'none' }; const view = { status: env.status }; if (env.status === 'running') { let token = env.routing_token && env.routing_token !== '[redacted]' ? env.routing_token : null; if (!token) { const { status, body } = await provisioner.getToken(env.environment_id); if (status === 200) token = body.routing_token; } if (token) view.launch_path = `/lab/${token}/`; } if (env.status === 'error') view.error_reason = 'Lab failed to start. You can try launching again.'; return view; } async function launchEnvironmentForStudent(provisioner, studentId) { const existing = await provisioner.listForStudent(studentId); const active = existing.body?.find((e) => ['requested', 'provisioning', 'running', 'resetting'].includes(e.status)); if (active) return { status: 200, body: await publicEnvView(provisioner, active) }; const { status, body } = await provisioner.provision(studentId); if (status === 409) { const retry = await provisioner.listForStudent(studentId); return { status: 200, body: await publicEnvView(provisioner, retry.body?.[0]) }; } if (status === 503 && body?.code === 'CAPACITY_EXCEEDED') { return { status: 503, body: { error: 'capacity_exceeded', message: 'Lab capacity is temporarily full. Try again shortly.' } }; } if (status !== 201) return { status: 502, body: { error: 'provision_failed', message: body?.error } }; return { status: 200, body: await publicEnvView(provisioner, { environment_id: body.environment_id, status: body.status, routing_token: body.routing_token }) }; } module.exports = { publicEnvView, launchEnvironmentForStudent };