ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: fred <[email protected]>
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
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<EnrollmentErrorCode, HttpStatus> = {
|
|
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<T>(result: EnrollmentResult<T>): { 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,
|
|
);
|
|
}
|
|
}
|