# Session 2026-06-07 (cont.) — Phase 8: digest email + web dashboard

## What's live
- **Daily digest email** to mholleran43@gmail.com — sent automatically after every scheduled scrape, contains top N ranked jobs (HTML + plain text via /usr/sbin/sendmail). Tracks `last_digest_at` per profile so the next email only shows truly new ingests
- **Web dashboard** at **https://genoa-entwuerfe.com/jobscraper/** behind HTTP Basic Auth (user `m3ac`, pass `eea8e111b2474ad680b77cd0`, stored at `/tmp/jobscraper_dashpass.txt` and the htpasswd file at `/home/m3ac/genoa-entwuerfe.com/jobscraper/auth/htpasswd`)
- Pages: queue (filter by status/score/keyword, mark interested/skip inline), job detail (full description, mark buttons), applications, schedules, sources
- 2 new MCP tools: `send_digest`, `set_digest_settings`. Total: **31 tools**

## How it works

```
06:00 UTC  ─ bi-manager-remote-daily fires ─┐
06:15 UTC  ─ bi-manager-columbus-daily      │
                                            ↓
                                       run_scheduled
                                            │
                       ┌────────────────────┼────────────────────┐
                       ▼                    ▼                    ▼
                 scrape per source      score_all_new       send_all_digests
                                                                  │
                                                                  ▼
                                            ┌─────────────────────────┐
                                            │ mholleran43@gmail.com   │
                                            │ "20 new · top 0.36"     │
                                            └─────────────────────────┘
                                            │
                                            └─→ dashboard link inside
                                                  https://.../jobscraper/
```

## Dashboard layout
- `/jobscraper/` — queue view, filter by status (new/interested/applied/...), min_score, contains-text
- `/jobscraper/jobs/<id>` — full job detail with mark buttons (new / interested / skip / applied / rejected / offer)
- `/jobscraper/applications` — application states, cancel-button on dry_run rows
- `/jobscraper/schedules` — last run summary per schedule
- `/jobscraper/sources` — throttle, config (secrets redacted), job count per source

## Apache layout (cPanel-friendly)
- `/etc/apache2/conf.d/userdata/std/2_4/m3ac/genoa-entwuerfe.com/jobscraper.conf` — proxy + basic-auth
- `/etc/apache2/conf.d/userdata/ssl/2_4/m3ac/genoa-entwuerfe.com/jobscraper.conf` — same for https
- Generated via `/scripts/ensure_vhost_includes --user=m3ac && systemctl reload httpd`
- Survives EasyApache rebuilds

## API surface split
- `/jobscraper/` *and* sub-paths → HTML dashboard (no FastAPI auth, Apache handles it)
- `/jobscraper/api/search`, `/jobscraper/api/jobs`, `/jobscraper/api/admin/*` → JSON (still gated by bearer token at FastAPI level for defense-in-depth)
- `/jobscraper/health` → 200 OK (no auth at API level either, but Apache still requires basic-auth)

## Verified live
- Test digest sent successfully: count=20, top_score=0.357, recipient=mholleran43@gmail.com
- Dashboard 401 unauth, 200 with auth
- Dashboard renders queue with 73 jobs filterable, top picks visible

## Open / next
- **Move on to the agent that applies for you** (per Michael's next directive):
  - Resume-tailoring (`resume.tailor(job_id)` — keep facts, reorder bullets)
  - Better cover letter LLM-generated against full job description (current is template fill-in)
  - Workday applier (per-tenant Playwright) since many BI Manager roles are on Workday
  - Generic Playwright applier with LLM form-fill for everything else
  - Wire `apply_url` follow → detect ATS → route to the right applier
- Real resume PDF still needed at `data/resumes/` (current is a 1-line stub)
- USAJobs key + Adzuna key still pending
