Champion Portal Development Phase 1
Estimated Effort: 8–12 weeks
Focus: Auth, Profile, Directory, Regional structure, DashboardRelated Documents:
- ../README.md — Champion Portal overview
- ../development/DATA-ARCHITECTURE.md — Data ownership
- ../development/DECISIONS.md — Resolved decisions
- ../features/HOMEPAGE-DASHBOARD.md — Dashboard spec
Phase 1 establishes the foundation for the Champion Portal. Champions will be able to:
This phase delivers the core identity and discovery features that make Champions feel part of a community from day one.
Phase 1 is divided into 5 sub-phases that can be implemented incrementally. Each sub-phase is a standalone prompt for an implementation agent.
| Sub-Phase | Name | Prompt | Est. Time |
|---|---|---|---|
| 1.1 | Database & Models | “Implement Phase 1.1” | 1–2 days |
| 1.2 | Email Authentication | “Implement Phase 1.2” | 1–2 days |
| 1.3 | SSO Authentication | “Implement Phase 1.3” | 1–2 days |
| 1.4 | Profile & Directory | “Implement Phase 1.4” | 2–3 days |
| 1.5 | Dashboard & Admin | “Implement Phase 1.5” | 2–3 days |
Goal: Create all database tables and models for Champion Portal foundations.
Status: ✅ COMPLETE (December 5, 2025)
Deliverables:
cp_champions table migration (all profile fields, verification_status enum)cp_profile_changes table migration (changelog for CRM export)
crm_data_changes table. See Affinaquest Import - UNIFIED_DATA_SYNC.mddistricts and regions tableszip_codes table with city/state lookupCp::Champion model with validations, Devise auth, associationsCp::ProfileChange model for CRM export trackingrails champion_portal:seed_geographic_dataImplementation Notes:
first_name, pref_first_name, college_last_name, last_nameMigrations Created:
20251204200000_create_champion_portal_foundation_tables.rb20251205194414_change_districts_csv_name_index_to_composite.rbDeployment: After deploying migrations, run seed task on staging/production:
heroku run rails champion_portal:seed_geographic_data --app alumni-lookup-staging
Acceptance Test:
# In rails console:
champion = Cp::Champion.create!(first_name: "Test", last_name: "User", email: "test@example.com", password: "password123")
champion.verification_status # => "unverified"
ZipCode.find_by(zip: "37027").district.name # => "Nashville"
ZipCode.find_by(zip: "37027").district.region.name # => "Southeast"
Goal: Champions can sign up with email, verify, and log in.
Status: ✅ COMPLETE (December 5, 2025)
Deliverables:
Cp::RegistrationsController — create account (name + email + zip code)Cp::ConfirmationsController — email verification with password settingCp::SessionsController — login/logoutCp::PasswordsController — forgot/reset passwordCp::DashboardController — authenticated landing pageCp::BaseController — feature flag checking, layoutCp::ChampionMailer — custom Devise mailer for champion subdomaindropdown_controller.js, mobile_menu_controller.jsTest Coverage (53 tests, 119 assertions):
test/controllers/cp/registrations_controller_test.rb (4 tests)test/controllers/cp/sessions_controller_test.rb (5 tests)test/controllers/cp/dashboard_controller_test.rb (4 tests)test/controllers/cp/confirmations_controller_test.rb (8 tests)test/controllers/cp/passwords_controller_test.rb (8 tests)test/models/cp/champion_test.rb (14 tests)test/mailers/cp/champion_mailer_test.rb (10 tests)Note: SSO buttons deferred to Phase 1.3 due to Devise multi-model OmniAuth path prefix conflict.
Files Created:
app/controllers/cp/base_controller.rbapp/controllers/cp/registrations_controller.rbapp/controllers/cp/sessions_controller.rbapp/controllers/cp/confirmations_controller.rbapp/controllers/cp/passwords_controller.rbapp/controllers/cp/dashboard_controller.rbapp/mailers/cp/champion_mailer.rbapp/views/cp/registrations/new.html.erbapp/views/cp/sessions/new.html.erbapp/views/cp/confirmations/show.html.erbapp/views/cp/confirmations/new.html.erbapp/views/cp/passwords/new.html.erbapp/views/cp/passwords/edit.html.erbapp/views/cp/dashboard/show.html.erbapp/views/layouts/champions.html.erbapp/views/layouts/champions/_header.html.erbapp/views/layouts/champions/_footer.html.erbapp/views/layouts/champions/_mobile_nav.html.erbapp/views/cp/champion_mailer/*.html.erb and .text.erbapp/javascript/controllers/dropdown_controller.jsapp/javascript/controllers/mobile_menu_controller.jstest/controllers/cp/*_controller_test.rbtest/models/cp/champion_test.rbtest/mailers/cp/champion_mailer_test.rbRoutes Added:
/signup → registrations#new/create/login → sessions#new/create/logout → sessions#destroy/confirm → confirmations#show/create/password/new → passwords#new/create/edit/update/dashboard → dashboard#showAcceptance Test:
champions.local.test/signup → enter name + email → submitGoal: Champions can sign up/log in with Google (Apple/Facebook deferred to future enhancement).
Status: ✅ COMPLETE (December 8, 2025)
Deliverables:
Cp::OmniauthCallbacksController)/profile/complete)google_uid column on cp_champions (existing from Phase 1.1)Implementation Notes:
/auth path prefix to work with multiple Devise modelsdevise_scope blocks for proper Devise mappingemail_verified status (email confirmed by provider)/profile/complete after loginGOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET env varsFiles Created:
app/controllers/cp/omniauth_callbacks_controller.rbapp/controllers/cp/profile_controller.rbapp/views/cp/profile/show.html.erbapp/views/cp/profile/edit.html.erbapp/views/cp/profile/complete.html.erbtest/controllers/cp/omniauth_callbacks_controller_test.rbtest/controllers/cp/profile_controller_test.rbFiles Modified:
config/initializers/devise.rb — Added path_prefix: '/auth' to Google OAuth configconfig/initializers/omniauth.rb — Added OmniAuth.config.path_prefix = '/auth'config/routes.rb — OmniAuth callbacks inside devise_scope blocksapp/views/cp/sessions/new.html.erb — Google button at topapp/views/cp/registrations/new.html.erb — Google button at topRoutes Added:
GET/POST /auth/google_oauth2/callback → cp/omniauth_callbacks#google_oauth2GET /auth/failure → cp/omniauth_callbacks#failureGET /profile → cp/profile#showGET /profile/edit → cp/profile#editPATCH /profile → cp/profile#updateGET /profile/complete → cp/profile#completePATCH /profile/complete → cp/profile#save_completeAcceptance Test:
champions.bualum.dev:3000/login → see “Sign in with Google” at topGoal: Champions can complete profiles and search for other Champions.
Deliverables:
Profile Completion Wizard:
Affinity Selection (Step 4 & Profile Edit):
cp_affinities table migration (champion_id, affinity_code, timestamps)Cp::Affinity model with associationsaffinity_selector_controller.js pattern or create cp_affinity_selector_controller.js/api/affinities or new)Profile Edit Page:
Directory:
Cp::DirectoryController with searchExport Infrastructure:
crm_data_changes table)Key UX Decisions:
Acceptance Test:
Goal: Champions see personalized dashboard; Staff can verify Champions.
Deliverables:
Cp::DashboardControllerAcceptance Test:
| Question | Decision | Source |
|---|---|---|
| What is the onboarding flow? | Progressive Account Creation (name + email first) | DECISIONS.md §2.1 |
| Is BUID required at signup? | No — Optional + Two-tier verification | DECISIONS.md §2.2 |
| What is the account data model? | Single cp_champions table with verification_status enum |
DECISIONS.md §2.3 |
| Which SSO providers? | Google, Apple, Facebook | DECISIONS.md §2.12 |
| How is location captured? | ZIP-first — ZIP → city/state/district/region | DECISIONS.md §2.10 |
| How are photos handled? | Separate: cp_champions.photo for Champion Portal |
DECISIONS.md §2.9 |
| Mobile or desktop first? | Mobile-first | DECISIONS.md §2.5 |
| Table naming convention? | cp_ prefix for Champion Portal tables |
DECISIONS.md §2.6 |
| Question | Decision | Notes |
|---|---|---|
| How should ZIP → District mapping be seeded? | CSV import — Seed from zip_district_region.csv |
Rake task: rails champion_portal:seed_geographic_data |
| What districts/regions exist initially? | 820 districts, 7 regions, with 8 highlighted | See data details below |
| How should verification queue be organized in Lookup? | New page in Lookup Portal — /admin/champion_verifications |
Future consideration: Unified admin portal at admin.bualum.co (see BACKLOG.md) |
| Password requirements? | 8+ characters, at least 1 letter and 1 number | Balanced security/friction |
| Session duration? | 7 days default, 30 days with “Remember me” | Mobile-friendly with security option |
Geographic Data (Imported December 5, 2025):
| Question | Who Decides | Impact |
|---|---|---|
| Pilot group composition | Engagement Team | Which Champions get first access |
| Verification turnaround SLA | Engagement Team | User messaging about wait time |
| Profile fields required vs optional | Product/Engagement | Onboarding friction |
| Champion role quiz — required or optional? | Product | Onboarding flow |
| Area | Deliverables |
|---|---|
| Authentication | Email signup, password reset, email verification, Google/Apple/Facebook SSO |
| Account model | cp_champions table with verification status enum |
| Profile | Personal info, contact info, employment, affinities, photo upload |
| Privacy controls | Per-field visibility settings |
| Location | ZIP-based city/district/region assignment |
| Directory | Search by name, city, grad year, college, major, industry |
| Dashboard | Welcome, role display, quick actions, regional events (placeholder), regional posts (placeholder) |
| Admin: Verification | Engagement Team can search alumni, link BUID to Champion account |
| Regional structure | Districts and regions tables, ZIP mapping |
| Feature | Phase |
|---|---|
| Event submission/calendar | Phase 2 |
| Story submission | Phase 2 |
| Mentorship matching | Phase 2 |
| Discussion boards | Phase 3 |
| Direct messaging | Phase 4 |
| Visit mode | Phase 5 |
| Map view | Phase 5 |
| Reporting dashboards | Phase 6 |
| Criterion | Validation |
|---|---|
| Champion can sign up with email | End-to-end test passes |
| Champion can sign up with Google SSO | End-to-end test passes |
| Champion can sign up with Apple SSO | End-to-end test passes |
| Champion can sign up with Facebook SSO | End-to-end test passes |
| Email verification flow works | User receives email, clicks link, can set password |
| Password reset works | User can request and complete reset |
| Email Verified user can edit own profile | Access control enforced |
| Email Verified user cannot see directory | Access control enforced |
| Champion Verified user can browse directory | Directory search returns results |
| Champion Verified user appears in directory | Searchable by name, city, etc. |
| ZIP code → city/district/region assignment works | Auto-populated on profile |
| Profile changes are logged | crm_data_changes records created (unified CRM sync) |
| Staff can verify Champions in Lookup Portal | Verification queue functional |
| Staff can search alumni and link BUID | BUID linking works |
| Dashboard displays for logged-in Champion | Personalized greeting, role, region |
| Metric | Target |
|---|---|
| Signup completion rate (email verified) | >80% |
| Profile completion rate | >70% |
| Time from signup to Champion Verified | <1 business day |
| Directory searches per pilot user | 2+ during pilot |
| Model | Test Cases |
|---|---|
Cp::Champion |
Valid factory, validation errors, verification status transitions, associations |
Cp::Champion |
ZIP → city/state/district/region lookup |
Cp::Champion |
Photo attachment (ActiveStorage) |
Cp::ProfileChange |
Auto-creates on attribute changes |
Cp::ProfileChange |
Tracks field_name, old_value, new_value, changed_by |
| Controller | Test Cases |
|---|---|
Cp::RegistrationsController |
Create account with valid data, reject invalid email, reject duplicate email |
Cp::RegistrationsController |
SSO callback creates account, links existing account |
Cp::SessionsController |
Login with password, login with SSO, logout |
Cp::SessionsController |
Reject unverified users, reject invalid credentials |
Cp::ChampionsController |
Email Verified can edit own profile, cannot edit others |
Cp::ChampionsController |
Champion Verified can view own profile |
Cp::DirectoryController |
Champion Verified can search, Email Verified cannot |
Cp::DirectoryController |
Search by name, city, grad year, college, industry |
Cp::DashboardController |
Returns dashboard for logged-in Champion |
Admin::VerificationsController |
Staff can view queue, search alumni, link BUID |
| Feature | Test Cases |
|---|---|
| Email signup flow | Complete journey: signup → email → verify → set password → profile |
| Google SSO flow | Click Google → authorize → account created → profile completion |
| Apple SSO flow | Click Apple → authorize → account created → profile completion |
| Facebook SSO flow | Click Facebook → authorize → account created → profile completion |
| Password reset | Request reset → email → click link → new password → login |
| Directory search | Log in as Champion Verified → search by name → view profile |
| Verification workflow | Staff logs into Lookup → verification queue → search alumni → link BUID |
| Scenario | Expected Behavior |
|---|---|
| Unverified user tries to log in | Rejected with “verify your email” message |
| Email Verified user visits directory | Redirected with “verification pending” message |
| Email Verified user edits own profile | Allowed |
| Champion Verified user visits directory | Allowed |
| Non-staff user visits verification queue | Rejected (403) |
| Data | Test Cases |
|---|---|
| Unique, valid format, required | |
| ZIP code | Valid 5-digit format, exists in database/lookup |
| Password | Meets complexity requirements |
| Profile fields | Required fields enforced, optional fields nullable |
After completing Phase 1, update the following documents:
| Document | Changes |
|---|---|
| ../README.md | Mark Phase 1 as complete, update prerequisites |
| ../development/DATA-ARCHITECTURE.md | Finalize cp_champions schema, add actual column list |
| ../development/DECISIONS.md | Record any new decisions made during implementation |
| ../STAKEHOLDER-OVERVIEW.md | Update pilot status |
| ../../features/CHAMPION_PORTAL.md | Create implemented feature doc (move from planning) |
| Document | Purpose |
|---|---|
docs/features/CHAMPION_PORTAL.md |
Document implemented functionality |
docs/development/CHAMPION_VERIFICATION_WORKFLOW.md |
Staff workflow guide |
| Champion Portal user guide (for pilots) | End-user documentation |
| Fixture | Purpose |
|---|---|
cp_champions.yml |
Test champions in various verification states |
districts.yml |
Test districts (Nashville, etc.) |
regions.yml |
Test regions (Southeast, etc.) |
zip_codes.yml |
Test ZIP codes mapped to districts |
For detailed specifications on each feature area, see: