v1.6.28 — Scheduled report-only jobs, compliance audit log, and documentation update
- Scheduled jobs can now run in report-only mode (skip scan, email latest DB results) - Compliance audit log records all significant admin actions in an immutable DB table - VERSION bumped to 1.6.28; CHANGELOG [Unreleased] sealed as [1.6.28] — 2026-05-28 - Both manuals updated: CPR-only mode, OCR language, file redaction, related documents, date-range token scoping, report-only jobs, audit log tab, two new FAQ entries - TODO.md updated with all completed tasks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
744813f4ac
commit
26c45165b9
12 files changed
+211
-19
No files matched your search
@@ -196,6 +196,17 @@ Allows reviewing results from any past scan session without running a new scan.
|
||||
- **Auto-email after manual scan** — `_maybe_send_auto_email()` in `routes/scan.py` is called from the `_run()` thread immediately after `run_scan()` returns. Reads `smtp_cfg.get("auto_email_manual")` from `smtp.json`; no-ops if the flag is false, no flagged items, or no recipients. Same Graph-first → SMTP-fallback pattern as the scheduler. Toggle: **Settings → Email report → Email report after manual scan** (`#st-smtpAutoEmail`), saved by `stSmtpSave()` in `scheduler.js`.
|
||||
- **Gmail vs Google Workspace detection** — auth error handlers check whether the SMTP username ends in `@gmail.com` / `@googlemail.com`. If not, the account is treated as Google Workspace (custom domain) and the error message points to the Workspace admin console rather than the user's personal security settings.
|
||||
|
||||
## Scheduler — scan_scheduler.py + routes/scheduler.py + static/js/scheduler.js
|
||||
|
||||
- **Job config keys** — `id`, `name`, `enabled`, `frequency` (daily/weekly/monthly), `day_of_week`, `day_of_month`, `hour`, `minute`, `profile_id`, `auto_email`, `auto_retention`, `retention_years`, `fiscal_year_end`, `report_only`. Stored in `~/.gdprscanner/schedule.json`. Auto-migrates old single-job format; assigns UUIDs to legacy entries without one.
|
||||
- **`_execute_scan(job_id)`** — the core execution method. Acquires a per-job lock (`_running_jobs` set), records a DB run via `db.begin_schedule_run()`, then either takes the report-only path (see below) or runs the full scan pipeline (M365 → file → Google), then emails and applies retention if configured. The DB run is finalised in a `finally` block so status/counts are always recorded.
|
||||
- **Report-only path** — when `report_only=True`, `_execute_scan` short-circuits before the M365 auth check. It populates `_m.flagged_items` from `db.get_session_items()` if the in-memory list is empty, then calls `_send_email_report(job_cfg)` and returns. Does NOT acquire the scan lock; does NOT require M365 auth. Fails with `RuntimeError("No scan results available")` if both in-memory state and the DB are empty, which the outer `except` handler records as a failed run.
|
||||
- **`_send_email_report(job_cfg)`** — builds Excel via `_m._build_excel_bytes()`, loads SMTP config, tries Graph first (if `state.connector` is authenticated), falls back to SMTP. Adjusts the email body text based on `job_cfg.get("report_only")`: "Scan completed" vs "Report on latest scan results".
|
||||
- **`_m.flagged_items` and `state.flagged_items` are the same object** — `gdpr_scanner.py` assigns `_state.flagged_items = flagged_items` at startup, so both names reference the same list. In-place updates (`flagged_items[:] = ...`) in the scheduler propagate to routes and vice versa.
|
||||
- **`scheduler_started` / `scheduler_done` SSE events** — broadcast at start and end of every job (including report-only). `scheduler_done` carries `flagged`, `scanned`, `emailed`, and `job_name`. Do not confuse with `scan_done` (M365) — they are separate event types.
|
||||
- **UI — job card badge** — `schedRenderJobs()` in `scheduler.js` adds a blue "Report only" (`m365_sched_report_only`) badge to the job name when `j.report_only` is true.
|
||||
- **UI — `schedToggleReportOnly()`** — dims the Profile row (`#schedProfileRow` opacity 0.4), shows/hides `#schedReportOnlyHint`, and forces `#schedAutoEmail` checked. Called from the checkbox `onchange` handler and at the start of `schedAddJob()` / `schedEditJob()`.
|
||||
|
||||
## Global gotchas
|
||||
|
||||
- **Pattern matching in Python** — when using `str.replace()` to patch JS/HTML, whitespace and quote style must match exactly. Use `in` check first and print if not found.
|
||||
|
||||
Reference in new issue
Block a user