feat(ui): polish paper operations surface#193
Conversation
Reviewer's GuideAdds a dedicated, read-only paper operations surface in the research UI by introducing a new paper alerts API endpoint, wiring it into the frontend state/rendering, and styling a richer paper-ops panel, along with focused server tests for the new payload. Sequence diagram for loading paper health and alerts in the Ops viewsequenceDiagram
actor Operator
participant BrowserApp as Browser_AppJS
participant Server as Research_UI_Server
participant FS as FileSystem_paper_sessions
Operator->>BrowserApp: Open Ops view / refresh
BrowserApp->>BrowserApp: fetchAll(showNotice, silent)
BrowserApp->>Server: GET /api/paper-sessions-health
BrowserApp->>Server: GET /api/paper-sessions-alerts
BrowserApp->>Server: GET /api/broker-submissions-health
Server->>FS: build_paper_health_payload(project_root)
FS-->>Server: Read paper_sessions data
Server-->>BrowserApp: 200 JSON paperHealth
Server->>FS: build_paper_alerts_payload(project_root)
FS-->>Server: build_paper_sessions_alerts(paper_root)
Server-->>BrowserApp: 200 JSON paperAlerts
Server-->>BrowserApp: 200 JSON brokerHealth
BrowserApp->>BrowserApp: Update state.paperHealth
BrowserApp->>BrowserApp: Update state.paperAlerts
BrowserApp->>BrowserApp: renderOps()
BrowserApp->>BrowserApp: buildPaperMeta(health, alerts)
BrowserApp->>BrowserApp: buildPaperSummary(health, alerts)
BrowserApp->>BrowserApp: buildPaperPanel(health, alerts)
BrowserApp->>Operator: Updated Ops view with paper panel
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 2 security issues, and 1 other issue
Security issues:
- User controlled data in methods like
innerHTML,outerHTMLordocument.writeis an anti-pattern that can lead to XSS vulnerabilities (link) - User controlled data in a
elements.paperPanelBody.innerHTMLis an anti-pattern that can lead to XSS vulnerabilities (link)
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="test/test_research_ui_server.py" line_range="319-328" />
<code_context>
+ assert payload["alerts"] == []
+
+
+def test_build_paper_alerts_payload_summarizes_existing_alerts(tmp_path: Path):
+ paper_root = tmp_path / "outputs" / "paper_sessions"
+ _write_session(paper_root, "paper_001", "success")
+ _write_session(paper_root, "paper_002", "failed")
+
+ payload, status = research_ui_server.build_paper_alerts_payload(tmp_path)
+
+ assert status == 200
+ assert payload["status"] == "ok"
+ assert payload["available"] is True
+ assert payload["total_sessions"] == 2
+ assert payload["has_alerts"] is True
+ assert payload["alert_status"] == "critical"
+ assert payload["latest_success_session_id"] == "paper_001"
+ assert payload["latest_alert_session_id"] == "paper_002"
+ assert payload["latest_alert_code"] == "PAPER_SESSION_FAILED"
+ assert payload["alert_counts"]["critical"] == 1
+
+
</code_context>
<issue_to_address>
**issue (testing):** Add a test for the error path when alert summarization fails, ensuring the 500 status and error payload are exercised.
Currently we only verify the missing-root and successful-summarization paths. Since `build_paper_alerts_payload` catches exceptions from `research_ui_server.build_paper_sessions_alerts` and returns a 500 with `{"status": "error", "available": False, "root_dir": ..., "message": str(exc)}`, please add a test that monkeypatches `build_paper_sessions_alerts` to raise. That test should assert the 500 status and that the payload has `status == "error"`, `available is False`, and the expected `root_dir` so the error branch is covered.
</issue_to_address>
### Comment 2
<location path="research_ui/app.js" line_range="715" />
<code_context>
elements.paperPanelBody.innerHTML = buildPaperPanel(paperHealth, paperAlerts);
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-document-method):** User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern that can lead to XSS vulnerabilities
*Source: opengrep*
</issue_to_address>
### Comment 3
<location path="research_ui/app.js" line_range="715" />
<code_context>
elements.paperPanelBody.innerHTML = buildPaperPanel(paperHealth, paperAlerts);
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):** User controlled data in a `elements.paperPanelBody.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities
*Source: opengrep*
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| def test_build_paper_alerts_payload_summarizes_existing_alerts(tmp_path: Path): | ||
| paper_root = tmp_path / "outputs" / "paper_sessions" | ||
| _write_session(paper_root, "paper_001", "success") | ||
| _write_session(paper_root, "paper_002", "failed") | ||
|
|
||
| payload, status = research_ui_server.build_paper_alerts_payload(tmp_path) | ||
|
|
||
| assert status == 200 | ||
| assert payload["status"] == "ok" | ||
| assert payload["available"] is True |
There was a problem hiding this comment.
issue (testing): Add a test for the error path when alert summarization fails, ensuring the 500 status and error payload are exercised.
Currently we only verify the missing-root and successful-summarization paths. Since build_paper_alerts_payload catches exceptions from research_ui_server.build_paper_sessions_alerts and returns a 500 with {"status": "error", "available": False, "root_dir": ..., "message": str(exc)}, please add a test that monkeypatches build_paper_sessions_alerts to raise. That test should assert the 500 status and that the payload has status == "error", available is False, and the expected root_dir so the error branch is covered.
| elements.paperHealthMeta.textContent = buildPaperMeta(paperHealth); | ||
| elements.paperHealthMeta.textContent = buildPaperMeta(paperHealth, paperAlerts); | ||
| elements.paperSummary.textContent = buildPaperSummary(paperHealth, paperAlerts); | ||
| elements.paperPanelBody.innerHTML = buildPaperPanel(paperHealth, paperAlerts); |
There was a problem hiding this comment.
security (javascript.browser.security.insecure-document-method): User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities
Source: opengrep
| elements.paperHealthMeta.textContent = buildPaperMeta(paperHealth); | ||
| elements.paperHealthMeta.textContent = buildPaperMeta(paperHealth, paperAlerts); | ||
| elements.paperSummary.textContent = buildPaperSummary(paperHealth, paperAlerts); | ||
| elements.paperPanelBody.innerHTML = buildPaperPanel(paperHealth, paperAlerts); |
There was a problem hiding this comment.
security (javascript.browser.security.insecure-innerhtml): User controlled data in a elements.paperPanelBody.innerHTML is an anti-pattern that can lead to XSS vulnerabilities
Source: opengrep
Summary
This PR sharpens the local paper-operations surface in the research UI while keeping it fully read-only.
Changes included:
esearch_ui/server.py
Why
QuantLab already had strong paper-session artifacts and CLI inspection, but the local UI still treated paper ops as a small summary card.
At the current state of the repo, that underrepresented one of the most operator-facing parts of QuantLab. This slice makes paper ops easier to read at a glance without inventing controls or drifting away from the artifact-first design.
Scope
This PR does not:
It focuses only on improving read-only paper-session visibility and freshness signaling.
Validation
Validated with:
ode --check research_ui/app.js
Notes
Closes #80
Summary by Sourcery
Introduce a richer, read-only paper operations surface in the research UI powered by a new paper alerts API payload.
New Features:
Enhancements:
Tests: