# Admin Guide

This guide is for platform administrators to monitor, manage users, and maintain system health.

---

## Dashboard

Access admin panel at `https://api.yourdomain.com/admin` (or build a separate admin frontend). Key metrics:

- **Total Users**: Active and total
- **Active Sessions**: Count of connected WhatsApp numbers
- **Messages Sent (24h)**: Volume
- **Avg Delivery Rate**: Should be >95%
- **Banned Sessions**: Track numbers that got banned
- **Revenue (monthly)**: Stripe subscription income

Use Laravel Telescope (if installed) for request logs, queries, exceptions.

---

## User Management

### View Users

From CLI:
```bash
php artisan tinker
>>> App\Models\User::with('subscription', 'sessions')->get();
```

Or build admin page:

| User Info | Actions |
|-----------|---------|
| Email, name, plan | View profile |
| Messages used / limit | Edit quota |
| Active sessions count | Impersonate (login as) |
| Account created | Disable / Enable |

### Edit User

- Increase message limit (override plan) for specific users
- Reset monthly counter (if they hit limit mid-month)
- Add sessions manually (rare)
- Change plan (upgrade/downgrade)

**CLI commands**:

```bash
# Reset monthly usage
php artisan user:reset-usage user@example.com

# Grant extra messages
php artisan user:add-quota user@example.com 500

# Disable account
php artisan user:disable user@example.com --reason="spam violation"
```

### View All Campaigns

Filter by user, status, date range. See:
- Total recipients
- Delivery rate
- Any failures and error messages

Help identify problematic users sending spammy content.

---

## Session Monitoring

### Active Sessions

List all sessions with status:
- connected
- qr_ready
- disconnected
- banned

For disconnects, you may want to email the user prompting to reconnect.

### Ban Rate

Track how many numbers get banned. If rate > 2% per month, investigate sending patterns (maybe users are spamming). Consider adding stricter limits or warming guidance.

---

## Financials

### Revenue Dashboard

Connect to Stripe Dashboard directly or build a simple report:

```sql
SELECT
  DATE(created_at) as day,
  COUNT(*) as subscriptions,
  SUM(CASE WHEN stripe_price_id = 'price_pro' THEN 15 ELSE 49 END) as revenue
FROM subscriptions
WHERE status = 'active'
GROUP BY day;
```

### Churn

Users who canceled subscriptions. Reach out for feedback.

### Invoices

Export all successful payments for accounting.

---

## System Health

### API Response Times

Check Cloudflare analytics or use a monitoring service. Should be <200ms for endpoints.

### OpenWA Worker Health

On Mac mini, check PM2:

```bash
pm2 status
pm2 logs openwa-manager --lines 100
```

If many sessions are stuck in `creating` or `error`, restart manager: `pm2 restart openwa-manager`.

Check disk space: `df -h`. Sessions accumulate data; prune deleted sessions older than 30 days.

### Queue Backlog

Laravel Queues (database driver):

```bash
php artisan queue:monitor
# Or check DB: SELECT queue, COUNT(*) FROM jobs WHERE reserved_at IS NULL GROUP BY queue;
```

If backlog grows, consider:
- Increasing workers: `php artisan queue:work --daemon` (or use Supervisor)
- Moving to Redis queue (faster)

### Webhook Receipt

In Stripe Dashboard, monitor webhook delivery success. Any failures? Check endpoint availability.

In OpenWA, ensure webhook URL is correct. Use a tool like webhook.site to test.

---

## Security Audits

### Check for Suspicious Activity

- Users with unusually high message counts (maybe stolen credentials)
- Many sessions created from same IP
- Contact lists with thousands of numbers but tiny messages (data gathering?)

You can write Artisan commands to detect anomalies.

### Access Logs

If using Laravel Telescope, review recent login IPs, unusual endpoints.

Enforce 2FA for admin accounts.

---

## Backup & Disaster Recovery

### Database Backup

Automate daily backups:

```bash
# On VPS
mysqldump -u user -p database > /backups/db-$(date +%F).sql
# Encrypt and upload to S3/Backblaze
```

Test restore quarterly.

### Session Data Backup

The OpenWA session directories contain authentication cookies that allow sending messages. If the Mac mini dies, users lose their sessions and need to re-scan QR. That's acceptable for MVP.

For production, consider:
- Periodic tar of `/opt/openwa/sessions` to remote storage
- Or store session blobs in DB (future)

### Code Deployment

Use Git:
```bash
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Restart queue workers: supervisorctl restart all
```

---

## Handling Bans & Appeals

WhatsApp bans happen. When a session is marked `banned`:

1. User receives email: "Your WhatsApp number +852... has been banned. You'll need to use a different number."
2. Admin can see ban in Sessions list.
3. Optionally, send manual email with guidance on how to obtain a new number and re-onboard.

If a user appeals (claims false ban), you can do nothing - WhatsApp's decision is final from our side. They must use a new number.

---

## Rate Limiting & Abuse

If a user tries to send beyond their quota, API returns 429. Our system prevents them from creating campaigns exceeding limit. However, they could try to create many small campaigns. We total `messages_used_this_month` at user level, not per campaign. So as long as the sum doesn't exceed limit, they're okay.

If you notice a user repeatedly hitting limit, they might be abusing. Consider:
- Sending warning email
- Temporarily suspending their account
- Requiring manual review before sending more

### Edge Cases

- User upgrades mid-campaign: campaign continues and can exceed previous limit (since new limit is higher). That's fine.
- Recurring campaigns: ensure `messages_used_this_month` increments immediately when job dispatched, not on delivery. This prevents overspend if campaign scheduled for next month but counted now.

---

## Maintenance Windows

For backend updates:
1. Put up a maintenance page: `touch storage/framework/down`
2. Perform migration/updates
3. Clear caches, `php artisan up`

For frontend, Vercel handles zero-downtime deploys.

For OpenWA:
- Rolling restart of sessions one by one to avoid disruption
- Notify users of brief disconnection

---

## GDPR / Data Requests

Users may request their data or deletion.

### Export Data

```bash
php artisan user:export user@example.com --output=json
# This should create a JSON with: profile, contacts, campaigns, message logs
# (Implement command that compiles all data from DB into a file)
```

### Delete Account

```bash
php artisan user:delete user@example.com --confirm
```

This should:
- Delete all sessions (and instruct OpenWA to remove session directory)
- Delete contacts, campaigns, logs
- Anonymize emails in audit logs (if required)
- Cancel Stripe subscription
- Remove from mailing lists

Implement soft delete by default, but GDPR requires full deletion.

---

## Support Workflow

1. User submits issue via email/form
2. Acknowledge within 1 hour (auto-reply)
3. Investigate: check logs, API requests, campaign details
4. Respond with solution or status update within 24h
5. If bug, create issue in GitHub repo, assign severity

Common issues:
- "Cannot add WhatsApp number" → Check OpenWA manager status, session directory permissions.
- "Messages not sending" → Check session status, quota, recent bans.
- "QR not showing" → Increase timeout, ensure OpenWA can write to session dir.
- "Upgrade failed" → Check Stripe webhook logs, subscription status.

---

## Adding New Features

When building new features:

1. Update database migrations (keep them backward compatible when possible)
2. Add feature flags (config) to turn on/off for beta users
3. Document API changes in `docs/api-spec.md`
4. Update user guide and admin guide accordingly
5. Test with a few pilot users before rolling to all

---

## Scaling

When users grow:

### Database
- Read replicas for reporting queries
- Index tuning

### Backend
- Add more queue workers
- Move to Redis queue
- Consider splitting read/write APIs

### Frontend
- Vercel scales automatically
- Add CDN for static assets (already there)

### OpenWA Workers
- Deploy OpenWA on additional Mac minis (or Linux boxes)
- Modify manager to register as a "worker" with Laravel
- Sessions get distributed across workers
- Need load balancer? Or each worker pulls jobs from same queue with session affinity? Simpler: sessions stay on the worker they were created on. Create new sessions on least-loaded worker.

Implementation: add `worker_id` column to `wa_sessions`. When creating session, pick worker with fewest `status=connected` sessions.

Worker agent runs on each box:
- Keeps heartbeat
- Receives commands from Laravel via queue (create session, delete session)
- Exposes its own API (OpenWA) and health endpoint

---

## Metrics to Track (Long-term)

- Monthly Recurring Revenue (MRR)
- Customer Acquisition Cost (CAC)
- Lifetime Value (LTV)
- Churn Rate
- Session Ban Rate
- Average Messages per User per Month
- Support Ticket Volume / Resolution Time

Set up a simple Grafana dashboard if numbers get serious.

---

## Emergency Contacts

- **Stripe Support**: For payment issues
- **Cloudflare Support**: For tunnel problems
- **OpenWA GitHub Issues**: For engine bugs

---

## Regular Maintenance Tasks

**Daily**:
- Check error logs (Laravel, OpenWA)
- Monitor queue backlog

**Weekly**:
- Review banned sessions list
- Check Stripe disputes
- Backup verification

**Monthly**:
- Revenue reconciliation
- User growth report
- Clean up old session directories (deleted sessions >30 days)
- Review API rate limit usage

---

## Upgrading Dependencies

- Laravel updates: follow upgrade guide, test in staging first
- OpenWA updates: pull upstream, test with a few accounts before rolling out all sessions

---

That's it! You're ready to run the platform.