High-Level Summary
Automatically enroll new users in configured contact groups when they sign up. Introduce a ContactGroupEnrollmentPolicy API resource that defines which groups a contact is added to upon creation, replacing any manual process.
Motivation
When a new user signs up, they are not added to any contact groups. This means users miss product update emails and other communications unless someone manually adds them. Milo collects marketing communication consent at signup but does not act on it — the UserContactController creates the user's Contact and stops there.
This is the first instance of a "workflow" pattern in Milo: when a new user signs up, add them to these contact groups. Two groups should receive all new users:
- All Users (private) —
allusers-contact-group-4lqxdp: administrative list, not visible to users, no opt-out
- Email Newsletter (public) —
emailnewsletter-contact-group-3a3ar9: users can opt out from their account
Goals
- Automatically create
ContactGroupMembership records for new contacts based on declarative policy.
- Support both private groups (no opt-out) and public groups (user can opt out).
- Honor existing opt-outs: do not re-enroll a contact that has a
ContactGroupMembershipRemoval for the target group.
- Make the enrollment configuration operator-managed via a Kubernetes resource, not hardcoded.
Non-Goals
- This issue does not implement general workflow or automation infrastructure beyond enrollment on contact creation.
- This issue does not add consent-gating logic (e.g., only enroll if the user checked an opt-in box); consent is assumed to have been collected at signup.
- This issue does not change the opt-out mechanism (
ContactGroupMembershipRemoval) itself.
Proposed API
Introduce a new cluster-scoped resource, ContactGroupEnrollmentPolicy, in the notification.miloapis.com/v1alpha1 API group.
Resource Definition
apiVersion: notification.miloapis.com/v1alpha1
kind: ContactGroupEnrollmentPolicy
metadata:
name: new-user-all-users
spec:
# The contact group to enroll contacts into.
contactGroupRef:
name: allusers-contact-group-4lqxdp
# Trigger defines when enrollment happens.
trigger:
type: ContactCreated
# contactSelector filters which contacts this policy applies to.
# Omit to match all contacts.
contactSelector:
subjectKind: User # only enroll contacts linked to User resources
apiVersion: notification.miloapis.com/v1alpha1
kind: ContactGroupEnrollmentPolicy
metadata:
name: new-user-email-newsletter
spec:
contactGroupRef:
name: emailnewsletter-contact-group-3a3ar9
trigger:
type: ContactCreated
contactSelector:
subjectKind: User
Behavior
- When a
Contact that references a human user is created, the enrollment controller evaluates all ContactGroupEnrollmentPolicy resources.
- For each matching policy, the controller creates a
ContactGroupMembership linking the new contact to the target group.
Implementation Notes
- A new
ContactGroupEnrollmentController watches Contact and ContactGroupEnrollmentPolicy resources.
- The controller is idempotent — applying the same policy twice does not create duplicate memberships.
- Hooks into
UserContactController (internal/controllers/iam/usercontact_controller.go), which creates the Contact on user signup; enrollment fires after that.
High-Level Summary
Automatically enroll new users in configured contact groups when they sign up. Introduce a
ContactGroupEnrollmentPolicyAPI resource that defines which groups a contact is added to upon creation, replacing any manual process.Motivation
When a new user signs up, they are not added to any contact groups. This means users miss product update emails and other communications unless someone manually adds them. Milo collects marketing communication consent at signup but does not act on it — the
UserContactControllercreates the user'sContactand stops there.This is the first instance of a "workflow" pattern in Milo: when a new user signs up, add them to these contact groups. Two groups should receive all new users:
allusers-contact-group-4lqxdp: administrative list, not visible to users, no opt-outemailnewsletter-contact-group-3a3ar9: users can opt out from their accountGoals
ContactGroupMembershiprecords for new contacts based on declarative policy.ContactGroupMembershipRemovalfor the target group.Non-Goals
ContactGroupMembershipRemoval) itself.Proposed API
Introduce a new cluster-scoped resource,
ContactGroupEnrollmentPolicy, in thenotification.miloapis.com/v1alpha1API group.Resource Definition
Behavior
Contactthat references a human user is created, the enrollment controller evaluates allContactGroupEnrollmentPolicyresources.ContactGroupMembershiplinking the new contact to the target group.Implementation Notes
ContactGroupEnrollmentControllerwatchesContactandContactGroupEnrollmentPolicyresources.UserContactController(internal/controllers/iam/usercontact_controller.go), which creates theContacton user signup; enrollment fires after that.