fix(mail): validate recipient exists before sending (#886)

Add validateRecipient() to check that mail recipients correspond to
existing agents before sending. This prevents mail from being stored
with invalid assignees that won't match inbox queries.

The validation queries agent beads and checks if any match the
recipient identity. The only special case is "overseer" which is the
human operator and doesn't have an agent bead.

Tests create a temporary isolated beads database with test agents
to validate both success and failure cases. Tests are skipped if
bd CLI is not available (e.g., in CI).

Fixes gt-0y8qa

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
aleiby
2026-01-24 21:46:09 -08:00
committed by GitHub
parent 2fb787c7a2
commit 4e4824a6c6
2 changed files with 133 additions and 0 deletions

View File

@@ -566,11 +566,39 @@ func (r *Router) sendToGroup(msg *Message) error {
return nil
}
// validateRecipient checks that the recipient identity corresponds to an existing agent.
// Returns an error if the recipient is invalid or doesn't exist.
func (r *Router) validateRecipient(identity string) error {
// Overseer is the human operator, not an agent bead
if identity == "overseer" {
return nil
}
// Query all agents and check if any match this identity
agents, err := r.queryAgents("")
if err != nil {
return fmt.Errorf("failed to query agents: %w", err)
}
for _, agent := range agents {
if agentBeadToAddress(agent) == identity {
return nil // Found matching agent
}
}
return fmt.Errorf("no agent found")
}
// sendToSingle sends a message to a single recipient.
func (r *Router) sendToSingle(msg *Message) error {
// Convert addresses to beads identities
toIdentity := AddressToIdentity(msg.To)
// Validate recipient exists
if err := r.validateRecipient(toIdentity); err != nil {
return fmt.Errorf("invalid recipient %q: %w", msg.To, err)
}
// Build labels for from/thread/reply-to/cc
var labels []string
labels = append(labels, "from:"+msg.From)