# Active Context - Current Work Status ## Current Task: DNS SWITCHOVER COMPLETE + EMAIL NOTIFICATIONS ENABLED ✅ **MAD Lawsuit Website v2.0 - NOW LIVE AT MAIN DOMAIN**: - **v1.0 Status**: DECOMMISSIONED (containers stopped) - **v2.0 Status**: **LIVE AT https://mad-lawsuit.org** (Laravel + Inertia + Vue) - **Current Phase**: Phase 5 - DNS Switchover **COMPLETE** ✅ - **Status**: All systems operational at main domain 🎉 ### Latest Changes (December 19, 2025) **Phase 5.1 - DNS Switchover** ✅ COMPLETE: - **Old Domain**: v2.mad-lawsuit.org (preview) - **New Domain**: mad-lawsuit.org (production) - **Changes Made**: - Updated `.env`: Changed APP_URL and ASSET_URL to https://mad-lawsuit.org - Updated `docker-compose.yml`: Changed port from 8080 to 806 (matching v1) - Updated Caddyfile: Point mad-lawsuit.org → localhost:806 - Added redirects: v2.mad-lawsuit.org → mad-lawsuit.org - Stopped old v1.0 containers - **SSL Certificate**: Automatically issued by Caddy/Let's Encrypt - **Status**: Website fully accessible at https://mad-lawsuit.org ✅ **Phase 5.2 - Email Notifications to All Subscribers** ✅ COMPLETE: - **Previous**: Only sent test emails to chris@deafgain.org - **Now**: Sends to all active subscribers in database - **Implementation**: - Modified `app/Http/Controllers/Admin/DocketEntryController.php` - Queries all active subscribers: `Subscription::where('is_active', true)->get()` - Loops through each subscriber and sends personalized email - Each email includes unique unsubscribe token - Added detailed logging (success/failure tracking) - Handles individual failures gracefully - **Subscriber Count**: 27 active subscribers (28 total, 1 inactive) - **Status**: Deployed and ready to use ✅ **Phase 5.3 - iPad PDF Viewing Fix** ✅ COMPLETE: - **Issue**: iPad Safari couldn't scroll PDFs in modal viewer - **Solution**: Detect iOS devices and open PDFs in new tab (native Safari viewer) - **Implementation**: - Updated `resources/js/Pages/Home.vue` - Added iOS detection: `/iPad|iPhone|iPod/.test(navigator.userAgent)` - Desktop: Opens PDF in modal viewer - iOS/Mobile: Opens PDF in new tab - **Status**: Deployed and working perfectly ✅ ### Latest Enhancements (December 18, 2025) **Phase 4.1 - PDF Upload Fix** ✅ COMPLETE: - **Problem**: PDF uploads failing with "Permission denied" error - **Root Cause**: nginx temp directories had incorrect permissions (750 on parent `/var/lib/nginx`) - **Solution**: Updated Dockerfile to set parent directory to 755 - **Files Modified**: - `Dockerfile` - Added `chmod 755 /var/lib/nginx` command - Rebuilt container with proper permissions - **Status**: PDF uploads now working perfectly (tested with large files) **Phase 4.2 - Unsubscribe Confirmation Page** ✅ COMPLETE: - **Feature**: Two-step unsubscribe confirmation to prevent accidental unsubscribes - **Implementation**: - Created `resources/js/Pages/Unsubscribe.vue` with beautiful confirmation UI - Matches site styling (#6E6362 background, #6b9080 green buttons) - Shows user's email address - Two buttons: "Yes, Unsubscribe" (red) and "Cancel" (green) - Success/error feedback with appropriate icons - "Return to Home" button after completion - **Backend Changes**: - Added `showUnsubscribe()` method to `SubscriptionController` - Updated routes: `GET /unsubscribe/{token}` → confirmation page - Kept `POST /api/unsubscribe/{token}` for processing - Updated email template to use new route - **CSRF Fix**: Fixed token retrieval with proper TypeScript casting - **Status**: Fully deployed and working at https://v2.mad-lawsuit.org/unsubscribe/{token} **Phase 4.3 - Date Format Consistency** ✅ COMPLETE: - **Issue**: Subscriber page showing inconsistent date format - **Fix**: Updated `resources/js/Pages/Admin/Subscribers/Index.vue` - **Format**: Now shows American format (MM/DD/YYYY) matching home page and docket entries - **Implementation**: `new Date(subscriber.created_at).toLocaleDateString('en-US', { month: '2-digit', day: '2-digit', year: 'numeric' })` - **Status**: All dates now consistent across the application **Phase 4.4 - Remove Pagination from Docket Entries** ✅ COMPLETE: - **Change**: Admin docket entries page now shows all entries on one page (no pagination) - **Backend Changes**: - `app/Http/Controllers/Admin/DocketEntryController.php`: - Changed from `paginate(20)` to `get()` - Removed pagination data from response - **Frontend Changes**: - `resources/js/Pages/Admin/DocketEntries/Index.vue`: - Removed pagination interface and props - Removed pagination UI (Previous/Next buttons) - Shows total count: "X total entries" - **Rationale**: Simpler interface for managing all entries at once - **Status**: Deployed and working at https://v2.mad-lawsuit.org/admin/docket-entries ### Production URLs - **v1.0 (Current)**: https://mad-lawsuit.org - **v2.0 (Ready)**: https://v2.mad-lawsuit.org - **v2.0 Admin**: https://v2.mad-lawsuit.org/admin/login - **v2.0 Unsubscribe**: https://v2.mad-lawsuit.org/unsubscribe/{token} ### Admin Credentials - **Username**: eliza - **Password**: AXEoZWk2AMAD0naw - **Access**: Full CRUD operations on docket entries, documents, and subscribers ### v2.0 Phase 2 COMPLETED ✅ **Admin Dashboard - Fully Functional**: **Controllers Implemented**: - ✅ **AuthController** - Login/logout with session management - ✅ **DashboardController** - Statistics and recent entries - ✅ **DocketEntryController** - Full CRUD (7 resource methods, no pagination) - ✅ **DocumentController** - PDF upload/delete with UUID naming (working perfectly) - ✅ **SubscriberController** - List and deactivate subscribers **Vue Pages Created**: - ✅ **Admin/Login.vue** - Professional authentication page - ✅ **Admin/Dashboard.vue** - Statistics cards, quick actions, recent entries - ✅ **Admin/DocketEntries/Index.vue** - All entries on one page (no pagination) - ✅ **Admin/DocketEntries/Create.vue** - Form for new entries - ✅ **Admin/DocketEntries/Edit.vue** - Update existing entries - ✅ **Admin/DocketEntries/Show.vue** - View details + upload documents - ✅ **Admin/Subscribers/Index.vue** - Manage email subscribers (50 per page, American dates) - ✅ **Unsubscribe.vue** - Two-step confirmation page with matching styling **Features Implemented**: - ✅ Session-based authentication (separate from Breeze) - ✅ Full CRUD operations for docket entries - ✅ PDF document upload with validation (500MB max, PDF only) - **WORKING** - ✅ UUID-based file naming for security - ✅ File storage in `storage/app/public/documents` - ✅ Storage symlink configured (`php artisan storage:link`) - ✅ No pagination for docket entries (all on one page) - ✅ Pagination for subscribers (50 per page) - ✅ Soft delete for subscribers (deactivate) - ✅ Cascade delete for entries (removes documents) - ✅ Professional UI with Tailwind CSS - ✅ Form validation with error display - ✅ Success/error flash messages - ✅ Responsive design - ✅ Mobile PDF viewing optimized (opens in new tab on screens < 768px) - ✅ Unsubscribe confirmation page (prevents accidental unsubscribes) - ✅ Consistent American date format (MM/DD/YYYY) across all pages ### v2.0 Technology Stack **Backend**: - **Framework**: Laravel 12.43.1 (latest stable) - **PHP**: 8.3.28 - **Database**: PostgreSQL 16-alpine (production) - **ORM**: Eloquent (replacing Prisma) - **Auth**: Laravel Sanctum + Session - **API**: Inertia.js server-side **Frontend**: - **Framework**: Vue 3 + TypeScript - **Routing**: Inertia.js (SSR-like experience) - **Styling**: Tailwind CSS 3.x - **Build Tool**: Vite 7.x - **Components**: Vue SFC (Single File Components) **Production Environment**: - **Server**: 10.4.0.205 (dedicated server behind NAT) - **Docker**: Alpine Linux containers - **Web Server**: nginx 1.28.0 - **PHP**: PHP-FPM 8.3.28 - **Database**: PostgreSQL 16-alpine - **Reverse Proxy**: Caddy (with auto-SSL) ### v2.0 Progress Checklist **Phase 1 - Public Website** ✅ COMPLETE: - [x] Install PHP 8.3 and Composer locally - [x] Create Laravel 12 project - [x] Install Laravel Breeze with Vue + Inertia + TypeScript - [x] Resolve NPM dependency conflicts (Vite 7 compatibility) - [x] Install all NPM packages successfully - [x] Create database migrations (docket_entries, documents, subscriptions, admin_users) - [x] Create Eloquent models with relationships - [x] Run migrations successfully (SQLite) - [x] Create HomeController with Inertia - [x] Build Vue home page component matching v1.0 design - [x] Test locally with development servers (php artisan serve + npm run dev) - [x] Verify website rendering correctly - [x] Implement email subscription API - [x] Add document download functionality **Phase 2 - Admin Dashboard** ✅ COMPLETE: - [x] Build admin authentication (session-based) - [x] Create AdminUser model and migration - [x] Implement AuthController (login/logout) - [x] Create AdminAuth middleware - [x] Build Admin/Login.vue page - [x] Implement DashboardController with statistics - [x] Create Admin/Dashboard.vue page - [x] Implement DocketEntryController (all 7 CRUD methods) - [x] Create all DocketEntry Vue pages (Index, Create, Edit, Show) - [x] Implement DocumentController (store, destroy) - [x] Implement SubscriberController (index, destroy) - [x] Create Admin/Subscribers/Index.vue page - [x] Set up file storage for PDFs - [x] Configure storage symlink **Phase 3 - Data Migration** ✅ COMPLETE (100%): - [x] Export v1.0 production data (PostgreSQL dump) - [x] Copy PDF files from production (69 files, 158MB) - [x] Create V1DataMigrationSeeder (tested with sample data) - [x] Create Python parser script (parse_sql_to_seeder.py) - [x] Identify parser limitation (only captured 32/63 entries) - [x] Create improved parser v2 (parse_sql_to_seeder_v2.py) with multi-line support - [x] Generate complete PHP arrays (63 entries, 63 docs, 28 subs) - [x] Update seeder with all production data - [x] Run seeder to import ALL data - [x] Verify 100% data integrity in database (63/63/28) **Phase 4 - Production Deployment** ✅ COMPLETE (100%): - [x] Create Dockerfile and docker-compose.yml - [x] Build Docker image with PHP-FPM + nginx - [x] Fix PHP-FPM command issue (php-fpm8.3 → php-fpm) - [x] Deploy container to production server - [x] Configure Caddy reverse proxy - [x] Create production .env file - [x] Generate APP_KEY - [x] Fix AdminUser password double-hashing issue - [x] Update AdminSeeder with correct bcrypt hash - [x] Add TrustProxies middleware for HTTPS detection - [x] Match v1 background colors exactly - [x] Run migrations on production database - [x] Seed production database with v1 data - [x] Verify SSL certificate provisioning - [x] Test admin login (working perfectly) - [x] Test all functionality (all working) - [x] Visual design matches v1 exactly **Phase 4.1 - Post-Deployment Enhancements** ✅ COMPLETE (100%): - [x] Fix PDF upload permissions (nginx temp directories) - [x] Create unsubscribe confirmation page - [x] Fix CSRF token issue in unsubscribe page - [x] Update email template with new unsubscribe route - [x] Fix subscriber date format to American (MM/DD/YYYY) - [x] Remove pagination from docket entries admin page - [x] Deploy all enhancements to production - [x] Test all new features **Phase 5 - DNS Switchover** (PENDING USER DECISION): - [ ] Update DNS: mad-lawsuit.org → v2.mad-lawsuit.org - [ ] Monitor for 24-48 hours - [ ] Decommission v1 containers - [ ] Implement email notifications (future enhancement) ### v2.0 Design Specifications **Complete v1.0 documentation captured**: - ✅ Visual design (colors, typography, layout) - ✅ Component specifications (forms, cards, buttons) - ✅ Functional requirements (interactions, animations) - ✅ Data structures (63 entries, 63 PDFs, 28 subscribers) - ✅ Admin dashboard specs (complete CRUD operations) - ✅ Production data verified from live database - ✅ Exact color matching from v1 container **Reference Document**: `cline_docs/v1_design_specifications.md` (400+ lines) ### Next Steps (Optional Enhancements) **Future Improvements**: 1. **Email Notifications** - Configure SMTP for subscriber notifications 2. **Monitoring** - Set up application monitoring and alerts 3. **Backups** - Automated database and file backups 4. **Performance** - Redis caching for improved speed 5. **Analytics** - Track visitor statistics ### Data Migration Details **v1.0 Production Data**: - **Docket Entries**: 63 entries with dates, titles, summaries - **Documents**: 63 PDF files (UUID filenames) - **Subscriptions**: 28 email subscribers (27 active) - **Total Size**: 158MB of PDF files **Schema Mapping** (v1.0 → v2.0): - `docket_entries.id` → `docket_entries.id` - `docket_entries.date` → `docket_entries.date` - `docket_entries.title` → `docket_entries.title` - `docket_entries.summary` → `docket_entries.summary` - `docket_entries.notes` → `docket_entries.notes` - `docket_entries.createdAt` → `docket_entries.created_at` - `docket_entries.updatedAt` → `docket_entries.updated_at` - `documents.docketEntryId` → `documents.docket_entry_id` - `documents.storedFilename` → `documents.stored_filename` - `documents.originalFilename` → `documents.original_filename` - `documents.fileSize` → `documents.file_size` - `documents.mimeType` → `documents.mime_type` - `documents.displayOrder` → `documents.display_order` - `subscriptions.isActive` → `subscriptions.is_active` - `subscriptions.unsubscribeToken` → `subscriptions.unsubscribe_token` - `subscriptions.createdAt` → `subscriptions.created_at` ## Previous Task: v1.0 PRODUCTION SERVER MIGRATION COMPLETED ✅ **MAD Lawsuit Website Successfully Migrated to New Infrastructure**: - **Old Server**: chrishaulmark.com (DigitalOcean VPS - being decommissioned) - **New Server**: 10.4.0.205 (Dedicated server behind NAT) - **Status**: FULLY OPERATIONAL WITH ALL DATA MIGRATED ✅ - **v1.0 Tagged**: Git tag `v1.0` created and pushed to Gitea ### Migration Implementation Details **Infrastructure Changes**: 1. **Package Upgrades** ✅ COMPLETED - **Frontend**: React 18→19, Next.js 15→16, Tailwind 3→4 - **Backend**: Prisma 5→7, Express 4→5 - **All Dependencies**: Updated to latest stable versions - **Docker Images**: Rebuilt with new package versions 2. **Caddy Reverse Proxy Fix** ✅ COMPLETED - **Problem**: Docker DNS resolving container hostnames to wrong network IPs - **Impact**: Caddy timing out trying to reach containers - **Solution**: Updated Caddyfile to use direct IP addresses on caddy_network - **Frontend IP**: 172.18.0.6:806 (instead of hostname) - **Backend IP**: 172.18.0.5:901 (instead of hostname) - **File**: `/home/chaulmark/docker/caddy/config/Caddyfile` on server 3. **Data Migration** ✅ COMPLETED - **Database**: PostgreSQL data (47MB) migrated from old server - **PDF Files**: 158MB of court documents (69 files) migrated - **Redis Cache**: Cache data migrated - **Method**: Created tar archive, transferred via rsync, extracted on new server - **Location**: `/docker/websites/mad-lawsuit/` on 10.4.0.205 4. **SSL Certificates** ✅ COMPLETED - **Provider**: Let's Encrypt via Caddy - **Domains**: mad-lawsuit.org, files.mad-lawsuit.org, v2.mad-lawsuit.org - **Status**: Active and auto-renewing ### Final Production Architecture ``` ┌─────────────────────────────────────────────────────────┐ │ Caddy Reverse Proxy (10.4.0.205) │ │ │ │ mad-lawsuit.org → 172.18.0.6:806 (Frontend v1) │ │ files.mad-lawsuit.org → 172.18.0.5:901 (Backend v1) │ │ v2.mad-lawsuit.org → localhost:8080 (v2 LIVE) │ └─────────────────────────────────────────────────────────┘ │ ├─────────────────────────────┐ │ │ ┌──────▼──────┐ ┌──────▼──────┐ │ Frontend │ │ Backend │ │ Port 806 │──────────────│ Port 901 │ │ Next.js 16 │ API Calls │ Express 5 │ │ React 19 │ │ Prisma 7 │ └─────────────┘ └─────────────┘ │ ┌──────▼──────┐ │ PostgreSQL │ │ + Redis │ └─────────────┘ ``` ### Deployment Server Information **IMPORTANT**: All deployments now go to **10.4.0.205** (NOT chrishaulmark.com) **Server Details**: - **Hostname**: public-websites (internal: 10.4.0.205) - **External Access**: Via NAT through dedicated server - **SSH Access**: `ssh chaulmark@10.4.0.205` - **v1 Project**: `~/websites/mad-lawsuit.org/` - **v2 Project**: `~/websites/v2.mad-lawsuit.org/` - **Docker Volumes**: `/docker/websites/mad-lawsuit/` **v2 Deployment Commands**: ```bash # SSH to production server ssh chaulmark@10.4.0.205 # Navigate to v2 project cd ~/websites/v2.mad-lawsuit.org # Pull latest code git pull origin main # Build frontend assets inside container docker exec mad-lawsuit-v2 npm run build # For major changes, rebuild container docker compose down docker compose up -d --build # Check container status docker compose ps docker compose logs -f app # Run migrations docker exec mad-lawsuit-v2 php artisan migrate --force # Seed database docker exec mad-lawsuit-v2 php artisan db:seed --class=V1DataMigrationSeeder --force # Clear caches docker exec mad-lawsuit-v2 php artisan config:clear docker exec mad-lawsuit-v2 php artisan cache:clear docker exec mad-lawsuit-v2 php artisan route:clear ``` ### Verification ✅ - **v1 Website**: https://mad-lawsuit.org (HTTP/2 200 ✓) - **v1 Backend API**: https://files.mad-lawsuit.org (HTTP/2 200 ✓) - **v1 Database**: 63 docket entries with all historical data ✓ - **v1 PDF Files**: 69 court documents accessible ✓ - **v1 All Containers**: Running and healthy ✓ - **v2 Website**: https://v2.mad-lawsuit.org (HTTP/2 200 ✓) - **v2 Admin**: https://v2.mad-lawsuit.org/admin/login (Working ✓) - **v2 Database**: 63 entries, 63 documents, 27 subscribers ✓ - **v2 All Features**: Fully operational ✓ - **v2 PDF Upload**: Working perfectly ✓ - **v2 Unsubscribe**: Confirmation page working ✓ - **v2 Date Format**: Consistent American format ✓ - **v2 Pagination**: Removed from docket entries ✓ ## Current Status ### What's Working ✅ - **v1.0 Production**: Fully operational at https://mad-lawsuit.org - **v2.0 Production**: **FULLY OPERATIONAL** at https://v2.mad-lawsuit.org - **v2.0 Admin**: Login working, all CRUD operations functional - **v2.0 Database**: All data migrated and verified - **v2.0 Design**: Matches v1 exactly (colors, layout, functionality) - **v2.0 PDF Upload**: Working perfectly with proper permissions - **v2.0 Unsubscribe**: Two-step confirmation page prevents accidental unsubscribes - **v2.0 Date Format**: Consistent American format (MM/DD/YYYY) across all pages - **v2.0 Docket Entries**: All entries on one page (no pagination) - **SSL Certificates**: Active on all domains - **File Storage**: PDFs uploading and downloading correctly - **Authentication**: Admin login persists across rebuilds ### Ready for DNS Switchover 🎉 The v2.0 website is **production-ready** and can replace v1.0 at any time: - All features working - All data migrated - Visual design matches exactly - Admin dashboard fully functional - PDF upload working - Unsubscribe confirmation page active - Date formats consistent - Simplified admin interface (no pagination) - SSL certificates active - Performance tested ### Next Steps for User **Optional - DNS Switchover**: 1. Update DNS: Point mad-lawsuit.org to v2.mad-lawsuit.org 2. Monitor for 24-48 hours 3. Decommission v1 containers once stable 4. Consider future enhancements (email notifications, monitoring, etc.) ### Files Modified (Latest Session - December 18, 2025) **PDF Upload Fix**: - `Dockerfile` - Added `chmod 755 /var/lib/nginx` for proper permissions **Unsubscribe Feature**: - `resources/js/Pages/Unsubscribe.vue` - Created confirmation page - `app/Http/Controllers/SubscriptionController.php` - Added `showUnsubscribe()` method - `routes/web.php` - Added GET route for confirmation page - `resources/views/emails/new-docket-entry.blade.php` - Updated unsubscribe link **Date Format Fix**: - `resources/js/Pages/Admin/Subscribers/Index.vue` - American date format **Pagination Removal**: - `app/Http/Controllers/Admin/DocketEntryController.php` - Changed to `get()` from `paginate()` - `resources/js/Pages/Admin/DocketEntries/Index.vue` - Removed pagination UI ### Deployment Notes - **Phase 4.1 Complete**: All post-deployment enhancements operational - **DNS Ready**: v2.mad-lawsuit.org fully functional with all improvements - **SSL Active**: Let's Encrypt certificates auto-renewed - **Data Verified**: 100% migration success - **Design Verified**: Exact match to v1 - **Latest Commit**: b48b51ab (December 18, 2025) ## Investigation Process 1. **Phase 1**: Built public website matching v1.0 design ✅ 2. **Phase 2**: Implemented complete admin dashboard with CRUD ✅ 3. **Phase 3**: Exported production data and transferred PDF files, created seeders, imported all data ✅ 4. **Phase 4**: Deployed to production, fixed all issues, verified functionality ✅ 5. **Phase 4.1**: Post-deployment enhancements (PDF upload, unsubscribe, dates, pagination) ✅ The MAD lawsuit website v2.0 rebuild is **100% COMPLETE** with all enhancements and ready for production use! 🎉