7.4 KiB
Phase 0 – Baseline + Decisions (Quick)
Goals
- Confirm we’ll keep one Jinja template with palette includes.
- Choose PDF engine flags and file layout.
Decisions
- PDF engine:
wkhtmltopdfviasubprocess(wrapper optional). - Page size: Letter (or A4 if you prefer).
- Output layout:
/data/output/<timestamp>/<config_slug>/report.pdf. - ZIP per run:
/data/output/reports_<timestamp>.zip.
Deliverables
- Short
DECISIONS.mdcapturing above. - “Current state” run that still only outputs HTML (for baseline timings).
Acceptance
- We can state in one sentence where PDFs will land and how they’re named.
Phase 1 – HTML → PDF Renderer (Additive)
Goals
- Convert your already-rendered HTML into a PDF file per scan config.
Tasks
-
Create
report_renderer.pywith:render_html(context) -> str(calls existing Jinja template)html_to_pdf(html, out_path, *, page="Letter", margin_mm=12, dpi=96) -> Path
-
Ensure local assets (e.g., logo) resolve without network.
-
Add
run_repo_scan()call: after HTML render, write PDF.
Deliverables
- One PDF per config alongside existing HTML.
Acceptance
- PDFs open cleanly (no missing fonts/boxes).
- Render time acceptable (<1–2s per average report on your host).
Phase 2 – Bundle + Manifest
Goals
- Zip all PDFs for a run and write an audit manifest.
Tasks
-
Create
report_bundler.pywith:collect_pdfs(run_dir) -> List[Path]write_manifest(run_info, per_config_stats, out_path) -> Pathmake_zip(files, out_zip) -> Path
-
Manifest fields (per file and rollup):
run_id, generated_at, timezone- Per config:
name, config_slug, total_hosts, ok_hosts, hosts_with_issues, pdf_path, pdf_sha256, duration_ms - Bundle:
zip_path, zip_size_bytes, pdf_count
-
Add SHA-256 hashing utility.
Deliverables
reports_<timestamp>.zipmanifest_<timestamp>.json
Acceptance
- ZIP opens; manifest accurately lists all PDFs with correct hashes.
Phase 3 – Email Output
Goals
- Email either the ZIP (preferred) or top-N PDFs when size overs threshold.
Tasks
-
Create
report_emailer.py:send_reports(summary, files, to, cc, subject, size_limit_mb)- Compose a concise plain-text body (global counts + path to ZIP).
- Size check: if ZIP > limit → attach top N “issue” PDFs, mention storage path for ZIP.
-
Configure SMTP from environment (no secrets in code).
Deliverables
- Successful email with attachments on a sample run.
Acceptance
- Emails received by
email_towith intended attachments. - Logs include message id / delivery status (if available).
Phase 4 – Unify Templates (Light/Dark via palette)
Goals
- One structural template; palette includes for dark/light.
Tasks
- Introduce
_palette_dark.j2/_palette_light.j2. - Replace hardcoded colors with palette tokens.
- Keep inline styles for email/PDF reliability.
- Ensure
reporting.dark_modedrives palette include.
Deliverables
- Single
report.html.j2+ two small palette partials.
Acceptance
- Dark/Light flips correctly; visual parity with previous separate templates.
Phase 5 – Config Flags & CLI ergonomics
Goals
- Make format and emailing behavior configurable per run.
Tasks
-
New config/env flags:
OUTPUT_HTML=true|falseOUTPUT_PDF=true|falseBUNDLE_ZIP=true|falseEMAIL_ENABLED=true|falseEMAIL_SIZE_LIMIT_MB=15
-
Optional CLI args override envs for ad-hoc runs.
Deliverables
- Documented flags in
READMEorDECISIONS.md.
Acceptance
- Toggling flags changes outputs without code edits.
Phase 6 – Logging Overhaul (Structured, Useful)
Goals
- Replace scattered prints with consistent, structured logs you can search.
Tasks
-
Adopt one logger (e.g.,
structlogorloggingwith JSON formatter). -
Standard fields on every log line:
run_id,config_name,config_slug,phase,duration_ms
-
Log events:
- Start/end per config, counts (ok/issues), output paths, sizes, hashes.
- PDF render timings and failures (with
exc_info=True). - Bundling: zip path/size; Email: recipients, attachment count, result.
-
Set sane defaults:
- Level INFO in prod, DEBUG when
DEBUG=1. - Rotate or daily-split logs; permissions via umask
0027.
- Level INFO in prod, DEBUG when
Deliverables
- Consistent logs; sample snippet documented in
LOGGING.md.
Acceptance
- You can answer “what happened to corp-wan at 03:05?” from logs alone.
Phase 7 – Docker & Dependencies
Goals
- Bake the toolchain into the image cleanly.
Tasks
apt-get install -y wkhtmltopdf fonts-dejavu-core- Keep pip deps minimal (Jinja2 already present).
- Health check: small mock HTML → PDF during build or startup test (optional).
Deliverables
- Rebuilt image; size acceptable.
Acceptance
- Container can render PDFs in a clean runtime (no missing libraries).
Phase 8 – Validation & Load Testing
Goals
- Confidence under multiple configs and larger reports.
Tasks
-
Run with N configs (e.g., 10–20) and capture:
- Total runtime, average PDF time, largest PDF size.
-
Edge tests:
- No targets → still produce a PDF with “No hosts”.
- All OK vs many Issues.
- Long hostnames and port lists (layout wrapping).
-
Verify email size behavior.
Deliverables
- Short
QA_NOTES.mdwith timings and observations.
Acceptance
- No crashes; PDFs legible; email strategy holds at size thresholds.
Phase 9 – Docs & Ops
Goals
- Make future you (or anyone) productive in 5 minutes.
Tasks
READMEupdates: flow diagram, flags, outputs.DECISIONS.mdfinalized.- Sample manifest + how to verify checksums.
- Runbook snippet: “How to re-send last run’s ZIP.”
Deliverables
- Docs committed and discoverable.
Acceptance
- You can hand this to a teammate and they’ll ship a report same day.
Phase 10 – Nice-to-Haves / Backlog
- “Issues-only” PDF variant (short brief for exec/IT).
- Per-config S3 upload (instead of email attachments).
- HTML preview endpoint for a single report (if you add a tiny web UI).
- Retention policy job: purge artifacts >30 days.
- Watermark/status banner for partial/incomplete scans.
- Per-run metrics export (Prometheus counters/gauges).
Global Punch List (copy/paste into your tracker)
- Phase 0: Lock decisions (page size, paths, file naming)
- Phase 1: Add renderer module and wire PDF creation in
run_repo_scan() - Phase 2: Add bundler + manifest (with SHA-256)
- Phase 3: Add email sender with size-aware attachment strategy
- Phase 4: Merge templates; add palette partials; test light/dark
- Phase 5: Add env/CLI flags for outputs & email
- Phase 6: Overhaul logging (structured, consistent fields, timings)
- Phase 7: Update Dockerfile (wkhtmltopdf, fonts), rebuild, smoke test
- Phase 8: Load test with multiple configs; capture timings; fix edge cases
- Phase 9: Update README/DECISIONS/LOGGING; add runbook snippet
- Phase 10: (Optional) Implement backlog items
Quick win(s) to start next session
- Pick Letter vs A4 and the exact output path format.
- Decide whether to keep writing HTML to disk (handy for debugging) or only in memory.
- Choose structlog vs stdlib logging + JSON (I can tailor either).
When you’re ready, we can start with Phase 1, and I’ll draft the exact renderer function signatures and logging fields so it slots right into your style.