Bug #2945
Session Remark Reports + compulsory Resolution: All-Remarks list & Customer Support Audit (claimed vs actual)
Description
Context
Builds on the existing Session Status Remark feature (support execs add a remark to a FAILED session; it auto-cascades across the same user's failed sessions within a rolling 2-hour chain). This adds a compulsory resolution verdict at add-time and two reporting surfaces so supervisors can review whether remarks were justified.
Scope
Compulsory resolution on Add-remark
POST /api/v1/reporting/session-remarks now requires resolution = RESOLVED | UNRESOLVED (the exec's own call: did the action resolve the user's issue?).
Stored on every row of the cascade batch (new resolution column on session_status_remarks, CHECK RESOLVED/UNRESOLVED).
Missing/invalid → 400 "resolution is required and must be 'RESOLVED' or 'UNRESOLVED'."
Report — All Remarks (GET /api/v1/reporting/session-remark-reports/remarks)
Paginated list of every remark (newest first) with session GUID, user, author, applied-via (MANUAL/CASCADE), resolution, group id — user-friendly for analysis.
Filters: from, to, userId, appliedVia, search (remark text / session GUID).
Report — Customer Support Audit (GET /api/v1/reporting/session-remark-reports/audit)
One row per remark group (per add-operation / cascade batch).
Shows the failed run window (chainStart→chainEnd, failedSessionCount, cascadeCount).
Cross-checks CLAIMED vs ACTUAL:
Claimed = what the exec entered (claimedResolution).
Actual = did the same user get a successful session (COMPLETED, energy>0) within 2 hours of the failed run (verdict / resolved, with resolvedSessionGuid + minutesToResolve).
auditResult = MATCH / MISMATCH / UNKNOWN. MISMATCH (e.g. "marked Resolved but no success within 2h") is the review target.
Summary (over the whole filtered set): resolution rate, resolved/unresolved, match/mismatch counts, total failed sessions remarked, resolution window (2h).
Filters: from, to, userId.
Access — new dedicated permission reporting.session-remark-audit.view; on existing tenants auto-granted to holders of reporting.session-remarks.view.
DB migrations (tenant schemas)
V0117 — seed permission reporting.session-remark-audit.view (+ provisioning via GetTenantPermissions()).
V0118 — add resolution column to session_status_remarks (+ provisioning template). Existing rows stay NULL (shown as UNKNOWN in audit).
Acceptance criteria
Add-remark rejects when resolution is absent/invalid; accepts RESOLVED/UNRESOLVED and stores it on the whole batch.
All-Remarks list returns filtered, paginated remarks with session GUID + resolution.
Audit returns per-group claimed vs actual with correct MATCH/MISMATCH/UNKNOWN and accurate summary counts across the filtered set.
Only users with the new permission can access either report.
Pre-feature remarks (no resolution) appear as UNKNOWN and are excluded from match/mismatch counts.
Out of scope / notes
Resolution enum is RESOLVED/UNRESOLVED only (extendable later, e.g. PENDING/ESCALATED).
"Resolved" = success within 2h of the failed run end (matches the cascade window).