stage-22: cockpit reflects the live adapter + all six feeds
The Worker Mesh Classifier badge was hardcoded "psyc-v4" — it kept claiming the old model even after the v5 swap, making it look like nothing had changed. Now derived dynamically from the inference server's reported adapter via inference.adapter_name(); shows the real version (psyc-v5) or "rules" when the server is down, so it can't go stale on the next swap. Also refreshed the cases page intro/help text to name all six feeds (URLhaus, CISA KEV, Feodo, ThreatFox, MalwareBazaar, OTX) instead of the original three. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -77,7 +77,12 @@ def case_journey(request: Request, case_id: str) -> HTMLResponse:
|
||||
if isinstance(result, Err):
|
||||
raise HTTPException(status_code=404, detail=result.reason)
|
||||
beats = journey_view.build_journey(result.value)
|
||||
return TEMPLATES.TemplateResponse(request, "journey.html", {"case": result.value, "beats": beats})
|
||||
model_label = inference.adapter_name() or "rules"
|
||||
return TEMPLATES.TemplateResponse(
|
||||
request,
|
||||
"journey.html",
|
||||
{"case": result.value, "beats": beats, "model_label": model_label},
|
||||
)
|
||||
|
||||
|
||||
@app.get("/ledger", response_class=HTMLResponse)
|
||||
|
||||
@@ -34,6 +34,15 @@ def server_adapter(timeout: float = 2.0) -> Optional[str]:
|
||||
return None
|
||||
|
||||
|
||||
def adapter_name(timeout: float = 2.0) -> Optional[str]:
|
||||
"""Short name of the live adapter, e.g. 'psyc-v5' from '/data/adapters/psyc-v5/final'."""
|
||||
path = server_adapter(timeout=timeout)
|
||||
if not path:
|
||||
return None
|
||||
parts = [p for p in path.split("/") if p and p != "final"]
|
||||
return parts[-1] if parts else None
|
||||
|
||||
|
||||
def model_severity(case: Case, timeout: float = 15.0) -> Optional[str]:
|
||||
"""Ask the live model to classify case severity. None if the server is down."""
|
||||
payload = {
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<h1>Case Queue</h1>
|
||||
<span class="count">{{ total }} case{{ '' if total == 1 else 's' }}</span>
|
||||
</div>
|
||||
<p class="page-intro">Every threat case psyc is tracking — ingested from URLhaus, CISA KEV, and Feodo Tracker, then classified by severity and TLP. The live queue of what the platform currently knows about; click any case to follow it through the pipeline.</p>
|
||||
<p class="page-intro">Every threat case psyc is tracking — ingested from URLhaus, CISA KEV, Feodo Tracker, ThreatFox, MalwareBazaar, and AlienVault OTX, then classified by severity and TLP. The live queue of what the platform currently knows about; click any case to follow it through the pipeline.</p>
|
||||
<details class="page-help">
|
||||
<summary>how to use this view</summary>
|
||||
<div class="help-body">
|
||||
<p><b>How to use.</b> Scan the severity and TLP badges to triage; click any case ID to open its full record and Worker Mesh journey. Run <code>psyc fetch-all</code> to pull fresh cases from the feeds.</p>
|
||||
<p><b>What you're seeing.</b> Each row is one normalized Case object — ingested by Scoutline from URLhaus, CISA KEV, or Feodo Tracker, then rated by Classifyline.</p>
|
||||
<p><b>What you're seeing.</b> Each row is one normalized Case object — ingested by Scoutline from any of six feeds (URLhaus, CISA KEV, Feodo Tracker, ThreatFox, MalwareBazaar, OTX), then rated by Classifyline.</p>
|
||||
<p><b>Why it matters.</b> A defender needs one place that answers "what is happening right now" before deciding what to act on — this queue is that place.</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
{% set rule_sev = case.classification.severity.value if case.classification.severity else '' %}
|
||||
{% set agrees = b.model_answer == rule_sev %}
|
||||
<p class="bot-model {{ 'model-agree' if agrees else 'model-differ' }}">
|
||||
<span class="model-chip">⬡ psyc-v4 · live model</span>
|
||||
<span class="model-chip">⬡ {{ model_label }} · live model</span>
|
||||
severity: <strong>{{ b.model_answer | upper }}</strong>
|
||||
{% if agrees %}<span class="model-verdict">✓ agrees with the rule</span>
|
||||
{% else %}<span class="model-verdict">✗ differs — rule said {{ rule_sev | upper }}</span>{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user