Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions sdk/typescript/_bundled_plugin/scripts/workbench_native_indexes.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,23 +202,29 @@ def list_repositories(
for row in connection.execute(
"SELECT id, target_id FROM scans ORDER BY started_at DESC, id DESC"
):
latest_scan_by_target.setdefault(row["target_id"], scans_by_id[row["id"]])
scan = scans_by_id.get(row["id"])
if scan is not None:
latest_scan_by_target.setdefault(row["target_id"], scan)

open_findings_by_target = Counter(
row["target_id"] for row in _indexed_findings(connection) if row["status"] == "open"
)
targets = {row["id"]: row for row in connection.execute("SELECT * FROM security_targets")}
target_ids = [
*latest_scan_by_target,
*(target_id for target_id in targets if target_id not in latest_scan_by_target),
]
repositories = [
{
"checkoutAvailable": Path(target["current_path"]).is_dir(),
"displayName": target["display_name"],
"latestScan": latest_scan,
"latestScan": latest_scan_by_target.get(target_id),
"openFindingsCount": open_findings_by_target.get(target_id, 0),
"scanCount": scan_count_by_target[target_id],
"scanCount": scan_count_by_target.get(target_id, 0),
"targetId": target_id,
"targetPath": target["current_path"],
}
for target_id, latest_scan in latest_scan_by_target.items()
for target_id in target_ids
if (target := targets.get(target_id)) is not None
]
if args is None:
Expand All @@ -229,7 +235,8 @@ def list_repositories(
repository
for repository in repositories
if (args.target_id is None or repository["targetId"] == args.target_id)
and args.status != "not_scanned"
and (args.status != "scanned" or repository["scanCount"] > 0)
and (args.status != "not_scanned" or repository["scanCount"] == 0)
and (args.status != "open_findings" or repository["openFindingsCount"] > 0)
and (
not query
Expand Down
108 changes: 108 additions & 0 deletions sdk/typescript/tests-ts/native-repository-index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { spawnSync } from "node:child_process";
import { join } from "node:path";
import { expect, test } from "bun:test";
import { PLUGIN_ROOT } from "./plugin-root.js";

test("repository index includes and filters persisted unscanned targets", () => {
const python = Bun.which("python3") ?? Bun.which("python") ?? Bun.which("py");
expect(python).not.toBeNull();
const scripts = join(PLUGIN_ROOT, "scripts");
const probe = `
import argparse
import json
import sqlite3
import sys
sys.path.insert(0, sys.argv[1])
import workbench_native_indexes as indexes

connection = sqlite3.connect(":memory:")
connection.row_factory = sqlite3.Row
connection.executescript("""
CREATE TABLE security_targets (
id TEXT PRIMARY KEY,
current_path TEXT NOT NULL,
display_name TEXT NOT NULL
);
CREATE TABLE scans (
id TEXT PRIMARY KEY,
target_id TEXT NOT NULL,
started_at TEXT NOT NULL
);
""")
connection.executemany(
"INSERT INTO security_targets VALUES (?, ?, ?)",
[
("target-scanned", "/repo/scanned", "Scanned"),
("target-unscanned", "/repo/unscanned", "Unscanned"),
],
)
connection.execute(
"INSERT INTO scans VALUES (?, ?, ?)",
("scan-1", "target-scanned", "2026-08-18T00:00:00Z"),
)
connection.commit()

indexes.scan_history.list_scans = lambda _connection: {
"scans": [{"scanId": "scan-1", "targetId": "target-scanned"}]
}
indexes._indexed_findings = lambda _connection: iter(())

def arguments(status):
return argparse.Namespace(
query=None,
target_id=None,
status=status,
offset=0,
limit=None,
)

def compact(result):
return [
{
"targetId": row["targetId"],
"scanCount": row["scanCount"],
"latestScan": row["latestScan"],
}
for row in result["repositories"]
]

print(json.dumps({
"all": compact(indexes.list_repositories(connection)),
"scanned": compact(indexes.list_repositories(connection, arguments("scanned"))),
"notScanned": compact(indexes.list_repositories(connection, arguments("not_scanned"))),
}))
`;

const result = spawnSync(python!, ["-I", "-B", "-c", probe, scripts], {
encoding: "utf8",
});
expect(result.status, result.stderr).toBe(0);
expect(JSON.parse(result.stdout)).toEqual({
all: [
{
targetId: "target-scanned",
scanCount: 1,
latestScan: { scanId: "scan-1", targetId: "target-scanned" },
},
{
targetId: "target-unscanned",
scanCount: 0,
latestScan: null,
},
],
scanned: [
{
targetId: "target-scanned",
scanCount: 1,
latestScan: { scanId: "scan-1", targetId: "target-scanned" },
},
],
notScanned: [
{
targetId: "target-unscanned",
scanCount: 0,
latestScan: null,
},
],
});
});
Loading