import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import type { EnrollmentErrorCode, EnrollmentFailure, EnrollmentResult, } from './enrollment.repository.js'; /** * Maps enrollment result unions onto the closed HTTP status set (design * docs/plans/2026-08-29-agent-enrollment-command-design.md §3.3, contract 5 * §4.2). Every refusal body carries the correlation id (contract 5 §4.3 * end-to-end traceability) alongside the enum code. `not_found` carries one * fixed message for every cause — missing agent and unauthorized caller are * indistinguishable on the wire (§3.2). */ const HTTP_STATUS: Record = { validation_failed: HttpStatus.BAD_REQUEST, authentication_failed: HttpStatus.UNAUTHORIZED, authorization_refused: HttpStatus.FORBIDDEN, not_found: HttpStatus.NOT_FOUND, conflict: HttpStatus.CONFLICT, precondition_failed: HttpStatus.UNPROCESSABLE_ENTITY, internal_fault: HttpStatus.INTERNAL_SERVER_ERROR, }; @Injectable() export class EnrollmentService { unwrap(result: EnrollmentResult): { ok: true; correlationId: string } & T { if (result.ok) return result; throw this.toException(result); } private toException(failure: EnrollmentFailure): HttpException { const status = HTTP_STATUS[failure.error]; return new HttpException( { statusCode: status, error: failure.error, message: failure.message, correlationId: failure.correlationId, }, status, ); } }