feat: session management with inventory, export, and AI analysis#71
Merged
feat: session management with inventory, export, and AI analysis#71
Conversation
Aguara v0.9.0+ moves NFKC normalization, tool exemptions, and scan profiles into the core engine. This delegates those responsibilities from oktsec to Aguara and simplifies the security pipeline. Changes: Engine (internal/engine/scanner.go): - Remove manual NFKC normalization (Aguara handles internally) - Remove golang.org/x/text/unicode/norm dependency - Add ScanContentWithTool() and ScanContentAsWithTool() methods that pass tool name to Aguara via WithToolName option, enabling built-in tool exemptions (TC-005 on Edit, MCPCFG_004 on WebFetch) Verdict (internal/verdict/verdict.go): - Refactor ApplyToolScopedOverrides into shared internal function - Add ApplyToolScopedOverridesPostAguara() that skips built-in exemptions (already applied by Aguara) while preserving ContentTools filtering, NLP_ exemption, and user overrides Pipeline (hooks + gateway): - Hooks handler: ScanContent -> ScanContentWithTool(ctx, content, ev.ToolName) - Gateway tool calls: ScanContent -> ScanContentWithTool(ctx, content, m.OriginalName) - Gateway response scan: same migration - All three switch to PostAguara variant for tool-scoped overrides Gateway API (internal/gateway/gateway.go): - NewGateway signature: variadic ...* audit.Store -> plain *audit.Store Code quality (/simplify): - Merge redundant agent collection loop in trace.go - Replace manual slice reverse with slices.Reverse - Replace manual byte reverse in avatar_test.go with slices.Reverse Fix: auditcheck OpenClaw host scanning - TestRunChecks_SecureConfig was flaky because it scanned real ~/.openclaw/openclaw.json from the host - Add openClawScanFunc hook (same pattern as mcpScanFunc) for test isolation
Aguara v0.9.0+ uses Aho-Corasick for pattern matching, which has a one-time automaton build on first scan. On CI runners this can push the integration test suite past the 120s timeout. Increase to 300s.
Phase 1 - Session Inventory:
- Add idx_audit_session index on session_id for query performance
- Add QuerySessions() with aggregated stats (events, agents, blocks,
quarantines, flags, duration, risk score) per session
- Add SessionSummary model and SessionTracer interface update
- New /dashboard/sessions page with table, filters (24h/7d/30d),
and summary stats (total sessions, threats, avg duration)
- Sessions nav link in sidebar
Phase 2 - Session Export:
- GET /dashboard/api/sessions/export?format=json&range=24h
- GET /dashboard/api/sessions/export?format=csv&range=24h
- CSV with headers, JSON array of SessionSummary objects
Phase 5 - AI Session Analysis:
- POST /dashboard/api/sessions/{id}/analyze endpoint
- Uses existing LLM Analyzer (Claude/OpenAI/webhook) synchronously
- Specialized prompt for session-level analysis: intent, threats,
anomalies, policy recommendations
- "Analyze with AI" button on session trace page with inline result
- Queue.Analyzer() getter for direct synchronous access
Code quality:
- Extract parseTS() as package-level function in audit store
(was duplicated as closure in trace.go)
The LLM queue was only created at startup. If configured via the dashboard UI, Test Connection and Analyze with AI would fail until restart. Now handleSaveLLM and handleToggleLLM call reloadLLMQueue() to create the queue in memory immediately after saving config.
Analyzer.Analyze() has its own security system prompt and expects structured JSON output. Session analysis needs a simple text prompt with a plain text response. Use direct Claude/OpenAI API calls reading provider config from cfg.LLM.
- Save AI analysis to reasoning_log (audit_entry_id='session-analysis') so it survives page refresh and serves as audit evidence - Load saved analysis on session trace page load - 2-column layout: timeline left, AI analysis right (sticky panel) - Falls back to single column when no analysis exists or on mobile - Re-analyze button replaces the saved analysis - Analysis stored with SHA-256 hash for integrity
- Add mdToHTML template function for server-side markdown rendering (bold, headers, lists, inline code) without external JS dependencies - Session trace: step headers wrap instead of clipping (flex-wrap) - Session trace: AI panel renders formatted HTML instead of raw markdown - Sessions table: fixed column widths, text-overflow ellipsis, right-aligned numeric columns, better timestamp truncation
…ner analysis - Remove "AI GENERATED" badge and "AI ANALYSIS" heading from trace panel - LLM prompt instructs no title/heading, starts with Objective directly - Sessions table: agents shown as pills instead of comma-separated text - Timestamps in monospace with better truncation - Add split template function for agent pill rendering
…rompt Sessions table: - Session name shown full (not truncated), with timestamp below - Search bar filters by session ID, agent, or status - Removed fixed table-layout for natural column sizing - Agent pills with better spacing Session trace: - AI analysis moved above timeline as full-width block - Removed 2-column layout (analysis is context, not a sidebar) AI prompt rewritten for enterprise SOC: - Risk Level (CRITICAL/HIGH/MEDIUM/LOW/CLEAN) as first line - Focus on WHAT TO DO, not description - Recommends suspension, restriction, escalation when warranted - "No action needed" for false positives with explanation - Actionable enough for a CISO to act without reading the timeline
Sessions table: - Session name shown in full (word-break, not truncated) - Timestamp + duration as subtitle below session name - Removed redundant Duration column (now in session cell) - 5 columns instead of 7 for cleaner proportions Session trace: - Restore 2-column layout (timeline left, AI analysis right) - Analysis panel sticky on scroll AI prompt rewritten for business audience: - No em dashes, no jargon (red-team, SOC, IOC) - Actions link to oktsec dashboard pages (suspend agent, review quarantine, add rule) so manager can act in one click - Markdown links [text](/dashboard/...) rendered as clickable hrefs - Only internal /dashboard/ links allowed for safety
…lacement Prompt improvements: - Timeline entries tagged [HUMAN] or [AGENT] so LLM correctly identifies who the threat actor is (human who injected, not agent who blocked) - Existing detection rules passed to prompt so LLM does not suggest adding rules for patterns already covered - Explicit instruction: suspend the sender of malicious content, not the agent that protected the system UI: - "Analyze with AI" button always visible next to CSV/SARIF/JSON exports - Shows "Re-analyze" when analysis exists, "Analyze with AI" when not
Sessions table: - 7 columns: Session, Date, Duration, Agents, Events, Threats, Risk - Date formatted as "Mar 19 16:57" instead of raw ISO timestamp - Session name truncated at 24 chars with tooltip for full name - Duration as separate column for sortability Session trace: - Removed Re-analyze from footer (only in top actions bar) - Top button shows "Analyze with AI" or "Re-analyze" based on state AI prompt: - No single hyphens as separators in sentences (use commas/periods)
Session trace: - Stats box uses flex-wrap so it does not clip on narrow viewports - Right column shows "Analyze with AI" CTA when no analysis exists - Analysis footer shows model name and timestamp for audit evidence - Model stored in reasoning_log.tool_use_id field Data layer: - QuerySessionAnalysis returns SessionAnalysisResult with Text, Model, Timestamp - SaveSessionAnalysis accepts model parameter
Layout: - Breakpoint adjusted to 1100px for 2-column layout AI prompt: - Explicit instruction: name after [HUMAN] is user account, name after [AGENT] is agent. Never suspend a name that only appears in [AGENT] entries. A name can appear in both roles. - "Suspend user X" must reference a [HUMAN] entry sender
Layout: - Grid columns 3fr/2fr (was 1fr/1fr) so timeline gets more space and stats box does not clip AI prompt: - Prepend explicit roster: "Human users: Gus (@guuuuus). AI agents: openclaw-main" before the timeline so the LLM cannot confuse roles - Instruction: "Only suspend names listed as Human users above"
New order: Agents, Session, Threats, Events, Risk, Duration, Date. Agents first for quick visual scan, threats prominent, metadata last.
Stats box: 4-column grid with borders (With Threats, Sessions, Total Events, Avg Duration) matching the mockup layout. Table columns reordered: Session, Agents, Threats, Events, Risk, Duration, Date. Added threat filter buttons (All / With threats / Clean) next to the search bar. Filters combine with text search.
- Active sidebar item is now "sessions" instead of "events" when viewing a session trace - Remove the empty "AI analysis not yet generated" placeholder box. The Analyze with AI button in the top actions bar is sufficient.
Stats box uses 4-column grid with vertical borders matching the sessions page layout. Reordered: Threats, Tool Calls, Duration, Started.
Inspired by NVIDIA NemoClaw's policy model.
Egress per-tool:
- New ToolRestrictions field on EgressPolicy maps tool names to
allowed domains. Empty list = no egress for that tool.
- ToolDomainAllowed() checks tool-specific restrictions before
falling back to general DomainAllowed()
- Prevents exfiltration via tool switching (e.g. using Bash to
reach a domain only WebFetch should access)
Integration presets:
- New Integrations field on EgressPolicy: ["slack", "github", etc.]
- 16 built-in presets with domain allowlists for common services:
Slack, GitHub, Telegram, Discord, Jira, Linear, Notion, Stripe,
OpenAI, Anthropic, Supabase, Firebase, npm, PyPI, Docker, HuggingFace
- ResolveIntegrationDomains() expands preset names to domain lists
- Preset domains merged with agent's explicit allowed_domains
Example config:
agents:
my-agent:
egress:
integrations: ["slack", "github"]
tool_restrictions:
WebFetch: ["arxiv.org", "api.github.com"]
Bash: [] # no egress
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Major feature PR: session management, Aguara v0.9.1 upgrade, and NemoClaw-inspired egress policies.
Session Management (Phases 1, 2, 5)
/dashboard/sessionspage with stats grid, search bar, threat filter (All/With threats/Clean)QuerySessions()aggregation,idx_audit_sessionindex/dashboard/api/sessions/exportEgress Per-Tool Restrictions (NemoClaw-inspired)
tool_restrictionson EgressPolicy: map tool names to allowed domainsToolDomainAllowed()checks tool-specific restrictionsIntegration Presets (NemoClaw-inspired)
integrations: ["slack", "github"]on agent egress config auto-loads domainsAguara v0.9.1 Upgrade
Files changed (26 files, +1220/-118)
Test plan
go test ./...all greengo build ./...clean