import { randomUUID } from "node:crypto"; import { inject } from "@codemation/core"; import { QueryHandler } from "../bus/QueryHandler"; import { HandlesQuery } from "../../infrastructure/di/HandlesQueryRegistry"; import { ApplicationRequestError } from "../ApplicationRequestError"; import { ApplicationTokens } from "../../applicationTokens"; import type { IWorkflowAuditEmitter } from "../../audit/IAuditEmitter"; import type { CredentialStore } from "../../domain/credentials/CredentialServices"; import { CredentialRuntimeMaterialService } from "../../domain/credentials/CredentialRuntimeMaterialService"; import { GetCredentialMaterialQuery, type CredentialMaterialDto } from "./GetCredentialMaterialQuery"; @HandlesQuery.for(GetCredentialMaterialQuery) export class GetCredentialMaterialQueryHandler extends QueryHandler { constructor( @inject(ApplicationTokens.CredentialStore) private readonly credentialStore: CredentialStore, @inject(CredentialRuntimeMaterialService) private readonly credentialRuntimeMaterialService: CredentialRuntimeMaterialService, @inject(ApplicationTokens.WorkflowAuditEmitter) private readonly auditEmitter: IWorkflowAuditEmitter, ) { super(); } async execute(query: GetCredentialMaterialQuery): Promise { const { displayName } = query; const instances = await this.credentialStore.listInstances(); const instance = instances.find((i) => i.displayName === displayName); if (!instance) { throw new ApplicationRequestError(404, "Credential not found"); } if (instance.setupStatus !== "ready") { throw new ApplicationRequestError(409, "Credential is not ready"); } let material: Awaited>; try { material = await this.credentialRuntimeMaterialService.compose(instance); } catch (error) { await this.auditEmitter .emit({ id: randomUUID(), occurredAt: new Date().toISOString(), actor: { userId: "system" }, action: "credential.material.read", resource: { type: "credential", id: instance.instanceId }, outcome: "failure", workflowId: "__credential_access__", }) .catch(() => {}); throw error; } await this.auditEmitter.emit({ id: randomUUID(), occurredAt: new Date().toISOString(), actor: { userId: "system" }, action: "credential.material.read", resource: { type: "credential", id: instance.instanceId }, outcome: "success", workflowId: "__credential_access__", }); return { instanceId: instance.instanceId, typeId: instance.typeId, material }; } }