recipientGate evaluates outbound_policy against the message recipients (To+CC+BCC). open: never flagged. allowlist: flagged if any recipient is not in outbound_allowlist. domain: flagged if any recipient's domain != the agent's. Returns the first offending recipient for the audit row. This is the eg
(agent *identity.AgentIdentity, req outbound.SendRequest)
| 42 | // Returns the first offending recipient for the audit row. This is the egress |
| 43 | // firewall and the home of the trust-ramp (allowlist mode + review action). |
| 44 | func recipientGate(agent *identity.AgentIdentity, req outbound.SendRequest) (flagged bool, addr string) { |
| 45 | switch agent.OutboundPolicy { |
| 46 | case identity.OutboundPolicyAllowlist: |
| 47 | allow := make(map[string]struct{}, len(agent.OutboundAllowlist)) |
| 48 | for _, a := range agent.OutboundAllowlist { |
| 49 | allow[strings.ToLower(strings.TrimSpace(a))] = struct{}{} |
| 50 | } |
| 51 | for _, r := range allRecipients(req) { |
| 52 | if _, ok := allow[strings.ToLower(strings.TrimSpace(r))]; !ok { |
| 53 | return true, r |
| 54 | } |
| 55 | } |
| 56 | case identity.OutboundPolicyDomain: |
| 57 | for _, r := range allRecipients(req) { |
| 58 | if !strings.EqualFold(domainOf(r), agent.Domain) { |
| 59 | return true, r |
| 60 | } |
| 61 | } |
| 62 | } |
| 63 | return false, "" |
| 64 | } |
| 65 | |
| 66 | func allRecipients(req outbound.SendRequest) []string { |
| 67 | out := make([]string, 0, len(req.To)+len(req.CC)+len(req.BCC)) |