# CC Soccer D11 - Session Handoff
**Date:** May 23, 2026
**Branch:** `main`

---

## Current State

### 🎉 SITE IS LIVE at ccsoccer.com
Soft-launch mode (IP whitelist active). Board members beta testing.

### Code — All Servers In Sync
Local, TEST, and PROD all current on `main`. No pending deploys.

---

## Session Work — May 23, 2026

### Module Updates ✅ COMPLETE
- Drupal core 11.3.9 → 11.3.10 (security update) — deployed to TEST + PROD
- Better Exposed Filters 7.1.1 → 7.1.2 (had schema updates, ran updb) — deployed to TEST + PROD
- WebAuthn 2.0.0-rc7 → 2.1.0-beta1 — **deferred to this weekend** (needs careful auth testing)
- reCAPTCHA 8.x-3.5-rc1 — skipped (RC, not ready)

### Migration Welcome Email ✅ COMPLETE (previous session)
Bulk welcome email system fully built and tested. Queues email to all 1,729 active users. On TEST (non-production), only board members + beta_testers receive emails. On PROD (`site_instance = 'production'`), all users receive.

**To send on go-live day (on PROD):**
```bash
PATH=/opt/cpanel/ea-php83/root/usr/bin:$PATH /opt/cpanel/ea-php83/root/usr/bin/php vendor/drush/drush/drush.php -r web ccsoccer:migration-welcome
# Then let cron pick up the queue, or run manually:
PATH=/opt/cpanel/ea-php83/root/usr/bin:$PATH /opt/cpanel/ea-php83/root/usr/bin/php vendor/drush/drush/drush.php -r web queue:run ccsoccer_notification
```

**Key fixes applied this session:**
- Queue worker: when `sms_body === ''`, calls `sendEmail()` directly instead of `send()` (avoids SMS attempt + HTML stripping)
- Queue worker: removed `$result` logging block from email-only path (was causing PHP warnings for all 1729 items)
- `sendMigrationWelcome()`: fixed `- CC Soccer` → `- CCSoccer` in body
- `email.html.twig`: fixed `CC Soccer` → `CCSoccer` in footer
- `sendMigrationWelcome()`: hardcoded password reset URL to `https://ccsoccer.com/user/password` (was generating `http://default/user/password` in Drush CLI context)
- `sendMigrationWelcome()`: updated profile photo copy per Haley's feedback

**Logo:** Still shows broken in test email because Yahoo Mail proxy hits ccsoccer.com which is IP-whitelisted. URL is correct. Will work post-launch when whitelist is removed.

**Remaining "CC Soccer" in NotificationService:** Tournament deposit and jersey notification functions still say `CC Soccer` in subject/SMS body. Deferred — not migration welcome path.

### CAPTCHA / reCAPTCHA Fix ✅ (previous session)
Re-enabled modules, set persistence to "Always add a challenge", re-entered keys. Config committed and deployed.

### Pre-Launch Security Checklist ✅ COMPLETE (#9)
- ✅ `trusted_host_patterns` — set on both TEST and PROD `settings.local.php`
- ✅ `hash_salt` — set on PROD `settings.local.php`
- ✅ Devel — confirmed uninstalled on PROD; intentionally left on TEST for debugging
- ✅ HTTPS redirect + www → non-www redirect — confirmed in `web/.htaccess` on PROD

### Deploy Aliases Fixed ✅
`ccsDeploy` and `ccsProdDeploy` in `~/.bashrc` on server now include `composer install` after `git pull`. Previously composer was never running on deploys, meaning module updates weren't actually applied to the servers.

---

## Combined Pre-Launch Checklist

### Immediate / In Progress

1. **Andrew to verify** — Vanishing CAPTCHA: confirm stays visible after correct CAPTCHA + wrong password again.

2. ✅ DONE — Migration welcome email built, tested, URL fixed, copy updated, ready to send on go-live day.

3. ✅ DONE — Drupal core 11.3.10 security update + Better Exposed Filters 7.1.2 deployed to all servers (composer install confirmed running).

---

### Before Opening Whitelist to Public

4. ✅ DONE — Passkey + reCAPTCHA cross-device test (Caleb + Yong confirmed on live).

5. **Andrew** — Create real SLO Friendly 2026 season + tournament.

6. **Caleb** — Commerce checkout end-to-end with real card on prod (season registration path + jersey-only path).

7. **Andrew** — Geo/country blocking via Cloudflare (D7 used `ip_ban` + `ip2country` for reference).

8. **Caleb** — Remove IP whitelist from `web/.htaccess` on go-live day (both servers, skip-worktree protected).

9. **Andrew** — Delete `ccsoccer-d11-migrated-200users.sql` from repo root if present (contains real user data).

10. ✅ DONE — Pre-launch security checklist (trusted_host_patterns, hash_salt, Devel, HTTPS redirect).

11. **Caleb** — Security Metrics automated testing setup (create jersey test product; email them to determine scope).

12. **Caleb** — Configure cron on prod via cPanel, every 15–30 min.

---

### Mid-term

13. `test@ccsoccer.com` mailbox decision.

14. Andrew's local environment DB update.

15. `slofriendly` config role reference cleanup (Andrew).

16. **Caleb** — WebAuthn passkey update 2.0.0-rc7 → 2.1.0-beta1 (carefully, test auth flow after). **Do this weekend.**

17. Backup strategy verification (InMotion nightly + periodic off-server snapshot of `n6ac4b5_d11live`).

18. CSP headers in report-only mode (security assessment Finding #14).

---

### Post-Launch / First 72 Hours

19. ✅ DONE — Assign `permanent_override` role (Haley, Layne, Julie, Myk, Kyle).

20. ✅ DONE — Verify credit balances against D7.

21. ✅ DONE — Check credits/registrations after April 16 dump date.

22. Remove `beta_tester` role from all users.

23. `slofriendlysoccer.com` URL forward.

24. Archive/delete D7 waivers directory; eventually delete `ccsoccer_site_d7_archive/`.

25. Monitor login success rate, password reset volume, unhandled exceptions for first 72 hours.

26. Add Devel back to TEST.

---

### Development (Deferred)

27. Three-tier button methodology pass.

28. CSS consolidation — design tokens across ~33 CSS files.

29. Team handling refactor.

30. Profile picture migration — board decision pending.

31. EPL team names — Andrew.

32. Fix remaining `CC Soccer` → `CCSoccer` in tournament deposit + jersey notification subjects/SMS bodies in `NotificationService.php`.

---

## DB Quick Reference

### Production DB (live)
- DB: `n6ac4b5_d11live`
- User: `n6ac4b5_ccsoccer_user`
- Password: `vGL3KWO(K8C;`

### TEST DB
- DB: `n6ac4b5_d11test`
- User: `n6ac4b5_ccsoccer_user`
- Password: `vGL3KWO(K8C;`

### D7 archive DB
- DB: `n6ac4b5_ccsoccer`
- User: `n6ac4b5_ccsoccer_user`
- Password: `vGL3KWO(K8C;`

### Local D11 DB
- Admin: `admin` / `TJ4XxyYGCd`

---

## Server Directory Structure
```
/home/n6ac4b5/public_html/
  ccsoccer_site/            ← PRODUCTION (ccsoccer.com)
  ccsoccer_site_d7_archive/ ← D7 archive (old.ccsoccer.com, PHP 7.2)
  test_ccsoccer_site/       ← TEST (test.ccsoccer.com)
  slofriendly_redirect/     ← slofriendlysoccer.com redirect
```

---

## Email Architecture

### Pipeline
```
NotificationService / OrderCompleteSubscriber
  → Symfony Mailer pipeline
    → Inline CSS + Theme wrapper (email.html.twig)
    → URL to absolute + Wrap and convert
  → Google Workspace SMTP (TEST + prod)
  → Mailpit (local DDEV only)
```

### Key Files
- `web/modules/custom/ccsoccer/src/Service/NotificationService.php`
- `web/modules/custom/ccsoccer/src/Plugin/QueueWorker/NotificationQueueWorker.php`
- `web/modules/custom/ccsoccer/src/Commands/NotificationCommands.php`
- `web/themes/custom/ccsoccer_theme/templates/email/email.html.twig`

### Notification gating
- `site_instance = 'local'` → board members only (Mailpit catches all)
- `site_instance = 'test'` → board members + beta_testers only (real emails)
- `site_instance = 'production'` → all users

### Queue Worker — SMS suppression
When `sms_body === ''` (explicitly empty), `processItem()` calls `sendEmail()` directly, bypassing `send()` which would strip HTML for SMS. This is how migration welcome email avoids SMS.

### SMTP config (in settings.local.php, never in git)
- Host: `smtp.gmail.com`, Port: `465`, TLS: true
- User: `ccsoccer@ccsoccer.com`
- App password: `sqygkfykzwrziota`

### reCAPTCHA Keys
- Site key: `6LchguosAAAAC5kLFmKj0xCGdEWXNntLacANpVN`
- Secret key: `6LchguosAAAANBJ8ikcrZvYQMxs6-FM2YHbzPEl`

---

## Key Facts / Gotchas

### beta_tester role — do not delete from config/sync
Always `git checkout config/sync/user.role.beta_tester.yml` after `drush cex`.

### Google SMTP App Password
`sqygkfykzwrziota` — in `settings.local.php` on TEST and prod servers only.

### Symfony Mailer — User override
Do NOT enable the "User" override — replaces HTML with plain text.

### DB import fix for InMotion
```bash
gunzip -c dump.sql.gz | sed 's/DEFINER=[^*]*\*/\*/' | gzip > dump-clean.sql.gz
```

### Two-file CSS sync
- `web/modules/custom/ccsoccer/css/ccsoccer-base.css` (admin)
- `web/themes/custom/ccsoccer_theme/css/base.css` (public)

### composer install on servers
```bash
PATH=/opt/cpanel/ea-php83/root/usr/bin:$PATH /opt/cpanel/ea-php83/root/usr/bin/php /opt/cpanel/composer/bin/composer install --ignore-platform-req=ext-intl
```

### CAPTCHA admin path
`/admin/config/people/captcha` — must be logged in as `admin` user. Use private window to test.

### Migration welcome email — password reset URL
Hardcoded to `https://ccsoccer.com/user/password` in `sendMigrationWelcome()`. Drupal's `Url::fromRoute()` generates `http://default/` in Drush CLI context with no HTTP request.

---

## Server Quick Reference
```bash
# SSH in
ssh ccsoccer

# TEST deploy (includes composer install)
ccsDeploy && ccsCr

# PROD deploy (includes composer install)
ccsProdDeploy && ccsProdCr

# Full deploy with DB updates
ccsDeploy && ccsUpdb && ccsCim && ccsCr
ccsProdDeploy && ccsProdUpdb && ccsProdCim && ccsProdCr

# Drush full path (TEST/PROD)
PATH=/opt/cpanel/ea-php83/root/usr/bin:$PATH /opt/cpanel/ea-php83/root/usr/bin/php vendor/drush/drush/drush.php -r web [command]
```

## .htaccess — both servers
Not in git — protected via `git update-index --skip-worktree web/.htaccess`

## Git Workflow
- Always `git pull` before `git push`
- `main` is the primary branch
- `settings.local.php` is NOT in git
- Always `git checkout config/sync/user.role.beta_tester.yml` after `drush cex`
