RejectInboundReviewCore drops a held INBOUND message (status pending_review → review_rejected; it stays hidden from the agent, raw payload retained for forensics) and fires email.review_rejected. Compare-and-set semantics as in ApproveInboundReviewCore.
(ctx context.Context, userID, reason string, msg *identity.ReviewMessageMeta)
| 281 | // forensics) and fires email.review_rejected. Compare-and-set semantics as in |
| 282 | // ApproveInboundReviewCore. |
| 283 | func (a *API) RejectInboundReviewCore(ctx context.Context, userID, reason string, msg *identity.ReviewMessageMeta) *OutboundError { |
| 284 | if err := a.store.RejectInboundReview(ctx, msg.ID, msg.AgentID, userID, reason); err != nil { |
| 285 | if errors.Is(err, identity.ErrNotPendingReview) { |
| 286 | return &OutboundError{http.StatusConflict, "message_not_pending", "message is not pending review"} |
| 287 | } |
| 288 | log.Printf("[api] reject inbound review %s: %v", msg.ID, err) |
| 289 | return &OutboundError{http.StatusInternalServerError, "internal_error", "failed to reject message"} |
| 290 | } |
| 291 | log.Printf("[mail:%s] dir=inbound type=%s status=%s agent=%s rejected_by=user:%s reason=%q", |
| 292 | msg.ID, msg.Type, identity.MessageStatusReviewRejected, msg.AgentID, userID, reason) |
| 293 | a.publishRejected(ctx, a.buildInboundRejectedEvent(msg, a.reviewOwnerID(ctx, msg.AgentID, userID), userID, reason), msg.ID) |
| 294 | return nil |
| 295 | } |