feat(console): named sessions — explicit, switchable active scan workspace - #61
Merged
Merged
Conversation
…space The final piece of the session/inventory split: make the active scan session a first-class, visible thing so the session-scoped tabs can never silently show two runs. - A session is an out* dir. GET /api/sessions lists every workspace (findings count, friendly name, active flag); POST /api/session opens an existing one or creates a fresh named one (out-<slug> + session.json), setting the OUT the read/scan endpoints use. - Header gains a session selector + "+ New"; switching hard-reloads so every tab repopulates from the chosen session, and a scan defaults its output dir to the active session. - open is guarded to an allowlist of discovered dirs (no path traversal); new slugifies the name. Agent-native parity: a read-only MCP `sessions` tool lists the same workspaces (an agent targets a session via the `out` param every tool already takes), and the MCP `retire` tool now exposes the `lb` selector the CLI/console gained, so an agent can disambiguate a finding live on two LBs. Full suite: 1206 passed, 15 skipped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… create-session gap
Adversarial review of the named-sessions feature (2 finders found nothing — traversal guard and
XSS escaping held):
- A summary.json/session.json that is valid JSON but NOT an object (null / 42 / a list) made
{}.update(loaded) raise TypeError/ValueError, uncaught — 500-ing all of /api/sessions and the MCP
`sessions` tool over ONE damaged file. New shared `sessions.read_meta` returns {} for a missing,
unparseable, OR non-object sidecar; both surfaces use it.
- Agent-native parity gap: the console's 'New session' writes a friendly session.json name, but no
MCP tool could create a named session — an agent could read the name it can't set. New WRITES_OUT
`session_new` tool creates out-<slug> + session.json via the SAME shared helper the console now
uses (`sessions.create_session` / `slugify`), so the slug rules and metadata shape can't drift.
Full suite: 1209 passed, 15 skipped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
henleda
force-pushed
the
feat-console-sessions
branch
from
August 19, 2026 01:57
272653a to
705ab75
Compare
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.
Stacked on #60 (
feat-session-inventory) → which is stacked on #59. Merge order: #59 → #60 → this. It retargets to main as each parent lands.The final piece of the session/inventory split (PR 2). PR #60 separated per-session scan artifacts from the global live-band-aid inventory; this makes the active session a first-class, visible thing so the session-scoped tabs can never silently show two runs.
What it adds
out*dir.GET /api/sessionslists every workspace (findings count, friendly name, active flag).POST /api/sessionopens an existing one or creates a fresh new named one (out-<slug>+ asession.jsonholding the display name + created-at), setting theOUTthe read/scan endpoints use.openonly accepts a dir the discovery lists (no path traversal);newslugifies the name and won't clobber an existingsession.json.Agent-native parity
The console's session switcher is a new user capability, so an agent gets equivalents via MCP:
sessionstool lists the same workspaces (an agent targets a session by passing itsoutto any tool);retiretool now exposes thelbselector the CLI--lb/ console gained in feat(inventory): split scan sessions from a global live-band-aid inventory #60, so an agent can disambiguate a finding live on two LBs.Verification
test_console_sessions.py(list/open/new/traversal-guard/slug) +test_mcp.pyadditions (thesessionstool + retirelbschema, read-only hint).🤖 Generated with Claude Code