alumni_lookup

Phase 10: Connections

Canonical sources: Portal philosophy, posture, and language live in /docs/planning/champion-portal/source/README.md.
Use these sources (including CHRIST_CENTERED__IDENTITY_STATEMENT.md) when writing specs or user-facing copy. Prefer quoting/paraphrasing over inventing new language.

Status: ✅ Complete (February 2026) Estimated Effort: 6-8 weeks Prerequisites: Phase 5 Complete, Phase 8 Complete (Notifications & Digests)

Completion Summary

All 6 sub-phases delivered. The Connections system fully replaces the old Contacts and open-messaging systems.

Key deliverables:

Tests: 3197 runs, 8143 assertions, 0 failures, 0 errors

Deferred: 7 items moved to BACKLOG.md (see bottom of this file)

Related Documents:


Sub-Phase Progress

Sub-Phase Name Status
10.1 Data Model & Connection Settings ✅ Complete
10.2 Connection Request Flow ✅ Complete
10.3 Connections & Messaging Transformation ✅ Complete
10.4 Directory & Profile Integration ✅ Complete
10.5 Contacts Migration & Cleanup ✅ Complete
10.6 Admin Connection Metrics ✅ Complete

Table of Contents

  1. Overview
  2. Why This Phase Exists
  3. Goals
  4. Non-Goals
  5. Key Design Decisions
  6. Terminology
  7. Data Model
  8. Sub-Phases
  9. Migration Strategy
  10. Definition of Success
  11. Testing Requirements
  12. Documentation Updates

1. Overview

Phase 10 introduces the Connections system — a relationship-first communication model that replaces the current open messaging and contacts systems. Instead of anyone being able to message anyone, Champions must first request a Connection, and communication begins only after the request is accepted.

Core Thesis

“Help alumni find people 5 steps ahead or 5 steps behind them, and make it easy to start a real conversation.”

The Champion Portal exists to remind alumni they belong to a greater community and to drive meaningful connection. Phase 10 operationalizes this by giving Champions a structured, low-pressure way to reach out — with clear expectations, respectful rate limits, and tools that make the first message feel natural.

What This Phase Delivers

Feature Description
Connection Requests Structured request flow: select a person, pick a reason, write an initial message
Connection Settings Per-champion preferences: what types of requests to accept, rate limits, pause mode
Two-Tab Inbox “Requests” (incoming + outgoing) and “Connections” (active conversations) replace Messages
Directory Filters Filter by connection type; show “open to” indicators on cards and profiles
Contacts → Connections Migration Mutual contacts become Connections; one-way contacts removed; “Add to Contacts” removed
Admin Metrics Connection stats, super-connector identification, request/acceptance rates

What Changes from Today

Today After Phase 10
Anyone can message anyone (privacy permitting) Must have an accepted Connection to message
“Add to Contacts” (one-way) with mutual detection Removed — replaced by Connection system
Messages nav item Connections nav item (with Requests + Connections tabs)
No structured reason for reaching out Connection type required (Say Hi, Career Advice, etc.)
No rate limiting on messages Daily cap for requestors (10/day), daily cap for requestees (10/day default, configurable)
Support threads mixed in Messages UI Support threads remain separate (unchanged)

2. Why This Phase Exists

The Insight

The #1 thing we hear from alumni and students: “I want to connect with other alumni who can speak into my life, or that I can speak into.” This is especially true for:

The Problem with Today’s System

  1. Open messaging feels transactional — No structure around why you’re reaching out
  2. “Add to Contacts” is confusing — Users don’t understand the value; one-way contacts feel incomplete
  3. No indication of willingness — Can’t tell if someone is open to being contacted, or what they’d want to talk about
  4. No rate protection — Popular alumni could be overwhelmed; no guardrails

The Connection Model

Connections solve these by:

  1. Requiring intent — You must select a reason (Career Advice, Networking, etc.)
  2. Requiring consent — The requestee must accept before conversation can happen
  3. Protecting availability — Daily caps and pause mode prevent overload
  4. Signaling openness — Profile and Directory show what types of connections someone welcomes

3. Goals

  1. Lower the barrier to meaningful outreach — Make it easy and natural to request a connection
  2. Protect Champions from overload — Rate limits, pause mode, ignore option
  3. Replace confusion with clarity — Remove Contacts; one system (Connections) for relationships
  4. Integrate seamlessly into existing UX — Directory, Profiles, and Messaging evolve rather than being replaced
  5. Maintain support infrastructure — Staff support threads are untouched
  6. Provide institutional insight — Admin metrics to identify super-connectors and measure program health

4. Non-Goals

Not Doing Why
Full CRM / relationship management Too much bloat; keep it simple
Conversational scripts / guided prompts Will be a Career Center resource (Phase 7), not part of Connections
Notes / next-steps tracker on connections Keep lightweight; backlog if demand emerges
Connection expiration / inactivity rules Connections persist forever; backlog inactive status detection
Proactive outbound match suggestions (“You should reach out to X”) Requestee-side push suggestions add complexity; existing Alumni Like Me recommendations are retained and unchanged
Delayed/queued sends when cap is hit Just show a “try again tomorrow” message; iterate later
Group connections / group threads 1:1 only for now
Real-time messaging (WebSocket) Separate backlog item

5. Key Design Decisions

D1: Connections Replace Both Messaging and Contacts

The current “Add to Contacts” feature is being removed. The existing messaging system evolves into the Connections system. The key change: you need an accepted Connection to message someone (except for support threads).

Rationale: Contacts was confusing and low-value. Open messaging lacked structure. Connections combine the relationship aspect of Contacts with the communication channel of Messages, with added intent and consent.

D2: Connection Types Are Requestee-Advertised, Requestor-Selected

Champions configure which types of connections they’re open to. When requesting a connection, the requestor selects from the types the requestee has enabled. The four types:

Type Description
Say Hi / Reconnect Casual — catching up, reconnecting with a fellow Bruin
Career Advice / Professional Development Seeking or offering career guidance
Networking / Job Seeking Professional networking, job leads, industry connections
Community Connection Getting involved locally, finding community. Scoped: only available between members of shared communities

D3: The Request IS the First Message

A Connection Request includes: the requestor, the requestee, the selected connection type, and a freeform initial message. When the request is accepted, a message thread is created with the initial message as the first message. This makes the transition from request to conversation seamless.

D4: Ignore Is Silent

When a requestee ignores a request, the requestor is not notified. The request simply remains in the requestor’s “Sent Requests” as pending. Ignored requests are hidden from the requestee’s inbox by default, with an option to view and reconsider them.

D5: Daily Caps for Both Requestors and Requestees

When a requestor hits their cap: “You’ve reached your daily limit. Come back tomorrow!” When a requestee’s cap is full: “This person has reached their daily cap of incoming connections, try again tomorrow.”

D6: Breaking a Connection Is Not Blocking

Either party can disconnect. This archives the thread and requires a new request to reconnect. It does not block the other person. Blocking (separate feature) does break connections.

D7: All Membership Types Participate Equally

Alumni, Almost Alumni, and Faculty/Staff can all send and receive connection requests. The only opt-out is per-champion: a setting to not receive requests from Almost Alumni.

D8: Existing Mutual Contacts Become Connections

During migration, all mutual ChampionContact records become Connection records. One-way contacts are removed. The “Add to Contacts” feature is removed entirely.

D9: Support Threads Are Separate

The existing staff support thread system (Cp::SupportThreadMailer, support message types) is completely untouched by this phase. Support threads remain accessible from Help/Settings.


6. Terminology

Term Definition
Connection An accepted relationship between two Champions that enables messaging
Connection Request A structured ask to connect, including type and initial message
Requestor The Champion initiating the connection request
Requestee The Champion receiving the connection request
Connection Type The reason for connecting (Say Hi, Career Advice, Networking, Community)
Pause Mode Temporarily stop receiving new connection requests (with optional end date)

Terminology we are NOT using: mentor, mentee, mentorship, contact, friend


7. Data Model

New Tables

cp_connection_requests

Column Type Notes
id bigint PK
requestor_id bigint FK → cp_champions, NOT NULL
requestee_id bigint FK → cp_champions, NOT NULL
connection_type string One of: say_hi, career_advice, networking, community_connection
message text Initial message (required, freeform)
status integer Enum: pending (0), accepted (1), ignored (2), cancelled (3)
responded_at datetime When accepted/ignored (nullable)
created_at datetime  
updated_at datetime  

Indexes:

Validations:

cp_connections

Column Type Notes
id bigint PK
champion_a_id bigint FK → cp_champions, NOT NULL (lower ID)
champion_b_id bigint FK → cp_champions, NOT NULL (higher ID)
connection_request_id bigint FK → cp_connection_requests (nullable — null for migrated contacts)
message_thread_id bigint FK → cp_message_threads, NOT NULL
connection_type string From the original request (nullable for migrated)
connected_at datetime NOT NULL
disconnected_at datetime Nullable — set when either party disconnects
disconnected_by_id bigint FK → cp_champions (nullable)
created_at datetime  
updated_at datetime  

Indexes:

Design note: champion_a_id always holds the lower of the two IDs to ensure uniqueness without needing both orderings. Query helpers will abstract this away.

Modified Tables

cp_champions — New Columns

Column Type Notes
connection_preferences jsonb Default: { "open_to": ["say_hi", "career_advice", "networking", "community_connection"], "daily_cap": 10, "accept_almost_alumni": true }
connections_paused_until datetime Nullable — when set and in the future, requests are blocked
connection_count integer Default: 0 — counter cache for active connections
pending_requests_count integer Default: 0 — counter cache for pending incoming requests

Note: unread_messages_count column stays as-is — messaging infra unchanged.

cp_message_threads — New Column

Column Type Notes
thread_type string Default: "connection" — values: "connection", "support"

This distinguishes champion-to-champion connection threads from support threads in queries.

Tables to Remove (Phase 10.5)

Table Disposition
cp_champion_contacts Migrated to cp_connections, then dropped

Tables Unchanged

Table Notes
cp_message_threads Evolves with thread_type column; otherwise unchanged
cp_messages Completely unchanged
cp_message_thread_participants Completely unchanged
cp_message_reactions Completely unchanged

8. Sub-Phases

Sub-Phase 10.1: Data Model & Connection Settings

Goal: Create the data model and settings UI so Champions can configure their connection preferences.

Deliverables

Profile Wizard: New “Connections” Step

Add a new Connections step to the Profile Wizard to ensure every champion configures their connection preferences during onboarding. This also serves as the introduction to the Connections system.

Wizard step changes:

Updated STEPS constant:

# BEFORE:
STEPS = %w[help_find_you confirm_education location champion_role profession photo bio affinities join_communities].freeze

# AFTER:
STEPS = %w[help_find_you confirm_education location profession connections photo bio affinities join_communities].freeze

Updated progress indicator steps:

# BEFORE (8 visual steps):
# Education, Location, Champion Role, Profession, Photo, Bio, Affinities, Communities

# AFTER (8 visual steps):
# Education, Location, Profession, Connections, Photo, Bio, Affinities, Communities

Icon for Connections step: :link or :user_plus (TBD based on available Heroicons)

Connections wizard step content (_step_connections.html.erb):

  1. Intro copy: Brief, warm explanation of how Connections work — “Other Bruins can request to connect with you based on shared interests. You decide who you’re open to hearing from.”
  2. Connection Types (checkboxes, all checked by default):
    • “Say Hi / Reconnect”
    • “Career Advice / Professional Development”
    • “Networking / Job Seeking”
    • “Community Connection”
  3. Daily Request Limit: Dropdown: 3, 5, 10 (default), 15, 20, Unlimited
  4. Almost Alumni: Checkbox: “Accept requests from current students” (default checked)
  5. Notification preferences for connections (optional — can defer to existing notification settings if too much for one step):
    • Email frequency for connection requests: Immediate / Daily Digest / Weekly Digest
    • Or: link to “You can customize notifications in Settings later”

Note: Pause Mode is intentionally omitted from the wizard — it’s an advanced setting available in Settings for existing users.

Implementation requirements:

Connection Settings UI Details

The Connection Preferences section replaces the current “Messaging Privacy” section in Settings. It should include:

  1. Connection Types (checkboxes, all checked by default):
    • “Say Hi / Reconnect”
    • “Career Advice / Professional Development”
    • “Networking / Job Seeking”
    • “Community Connection”
    • If none are checked → effectively “not accepting requests” (Connect button hidden/disabled)
  2. Daily Request Limit:
    • Number input or dropdown: 3, 5, 10 (default), 15, 20, Unlimited
    • Helper text: “Maximum new connection requests you’ll receive each day”
  3. Almost Alumni:
    • Checkbox: “Accept requests from current students (Almost Alumni)” — default checked
    • Helper text: “Uncheck to only receive requests from Belmont graduates”
  4. Pause Mode:
    • Toggle: “Pause all incoming connection requests”
    • When toggled on: optional date picker for “Resume on” (or leave blank for indefinite)
    • When paused: show a banner at the top of the Connections page reminding the champion
    • Helper text: “You won’t receive new requests while paused. Existing connections are unaffected.”

Sub-Phase 10.2: Connection Request Flow

Goal: Enable Champions to send, receive, accept, ignore, and cancel connection requests.

Deliverables


Sub-Phase 10.3: Connections & Messaging Transformation

Goal: Transform the Messages UI into the Connections UI with two tabs, and gate messaging behind accepted connections.

Deliverables


Sub-Phase 10.4: Directory & Profile Integration

Goal: Surface connection availability in the Directory and on Profile pages.

Deliverables


Sub-Phase 10.5: Contacts Migration & Cleanup

Goal: Migrate existing data, remove the Contacts system, and update all references.

Deliverables


Sub-Phase 10.6: Admin Connection Metrics

Goal: Give staff visibility into Connection program health and identify super-connectors.

Deliverables


9. Migration Strategy

Phase Ordering

The sub-phases must be implemented roughly in order (10.1 → 10.2 → 10.3 → 10.4 → 10.5 → 10.6), but some parallelism is possible:

Data Migration Plan

  1. Before removing anything: Create the new tables and models (10.1)
  2. Build the new system alongside the old (10.2, 10.3, 10.4)
  3. Migrate data and remove old system (10.5)
    • Rake task: bin/rake connections:migrate_contacts
    • Creates Connection + thread for each mutual contact pair
    • Deletes one-way contacts
    • Run on staging first, verify, then production
  4. Post-migration: Drop the old table in a follow-up migration

Existing Message Threads

The user has very few (if any) existing message threads. Strategy:


10. Definition of Success

Metric Target
Champions with at least 1 connection type enabled > 80% of active Champions
Connection requests sent in first month > 50
Request acceptance rate > 60%
“Add to Contacts” references remaining in codebase 0
Average time from request to acceptance < 72 hours
Champions who send 3+ messages in a connection thread > 40% of those who connect

11. Testing Requirements

Per Sub-Phase

Each sub-phase must include tests for all new:

Critical Test Scenarios

Scenario Sub-Phase
Can’t request yourself 10.2
Can’t request someone you’ve blocked / who blocked you 10.2
Can’t request if already connected 10.2
Can’t request if pending request exists 10.2
Requestor daily cap enforced (10/day) 10.2
Requestee daily cap enforced (configurable) 10.2
Can’t request when requestee is paused 10.2
Can’t request a type the requestee doesn’t accept 10.2
community_connection type requires shared community membership 10.2
Accept creates Connection + Thread + first message 10.2/10.3
Ignore is silent (requestor still sees “pending”) 10.2
Disconnect archives thread, requires re-request 10.3
Can’t send message without active connection (except support) 10.3
Directory filters show only open-to-connect Champions 10.4
Mutual contacts become Connections in migration 10.5
One-way contacts are removed 10.5
Privacy settings updated correctly 10.5
Admin stats are accurate 10.6

12. Documentation Updates

When Phase 10 is complete, update:


Backlog (Deferred from Phase 10)

Items explicitly deferred for future consideration:

Item Reason Potential Phase
Conversational scripts / guides Will live in Career Center as downloadable PDF resources Phase 7 (Career Center)
Notes / next-steps tracker per connection Avoid CRM bloat; revisit if demand emerges Backlog
Connection expiration / inactivity detection Connections persist forever for now Backlog
Proactive outbound match suggestions (“You should reach out to X”) Requestee-side push suggestions add complexity; existing Alumni Like Me recommendations are retained Backlog
Delayed/queued sends when cap is hit Simple “try again tomorrow” for now Backlog
Connection-based recommendation algorithm changes Current AlumniLikeMeService factors already work well Backlog
Group connections / multi-party threads 1:1 only for now Backlog