9장 승인 영수증으로 외부 행동을 통제한다
승인 버튼을 눌렀다는 불리언 하나는 부족하다. 무엇을 누가 언제 승인했는지, 그 뒤 내용이 바뀌었는지를 알아야 한다. BriefFlow의 영수증은 브리프 ID, 승인자, 산출물 SHA-256 해시, 승인·만료 시각을 갖는다.
const snapshot = JSON.stringify({ briefId: brief.id, status: brief.status, proposal });
const artifactHash = createHash('sha256').update(snapshot).digest('hex');
실행 직전에 현재 산출물로 해시를 다시 만든다. 다르면 ARTIFACT_CHANGED, 만료되면 RECEIPT_EXPIRED로 거절한다. dryRun은 승인 없이도 어떤 행동이 계획됐는지 보여 주지만 외부 시스템을 바꾸지 않는다.
큐에 넣을 때는 action type + brief ID + receipt ID로 멱등성 키를 만든다. 네트워크 재시도로 같은 메일이 두 번 발송되는 일을 막는 토대다. 실제 큐 저장소에는 이 키에 고유 제약을 둔다.