refactor: rip out the legacy TrackedRepository / repositories path
CI / Check (pull_request) Successful in 5m29s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped

Onboarded targets are now the sole persisted entity. The legacy
`TrackedRepository` model, the `repositories` collection, the `/repositories`
API, the Repositories dashboard page, the one-shot migration, and the
`UNIFIED_PIPELINE` transition flag are all removed. Net −1.7k LOC.

Agent
- New internal `pipeline::repo_view::RepoView` (non-persisted) replaces the
  `TrackedRepository` model; it's projected from an `OnboardedTarget` + its code
  artifact by `RepoView::from_target` (the old `repo_view_from_target`), so the
  scan/PR-review pipeline is byte-for-byte the same behaviour it already ran on
  the unified path — only the type's origin changed.
- `run_scan` always runs the unified `run_target`; the legacy `orchestrator::run`
  and the `unified_pipeline` flag are gone. `run_pr_review` resolves the target
  from `onboarded_targets`.
- Webhooks (github/gitea/gitlab), the CVE monitor, graph build, chat embeddings,
  health stats, and the pentest repo lookup all read `onboarded_targets`.
- `delete_target` now cascades the full downstream set (findings, sbom, scans,
  cve, tracker issues, graph, embeddings, DAST targets + pentest sessions and
  their children) — matching the old repository delete.
- `get_ssh_public_key` moved to the health handler; `repositories()` accessor,
  `repos.rs`, and `migrate/` deleted.

Core
- `TrackedRepository` removed; `ScanTrigger` stays. `unified_pipeline` config
  field removed.

Dashboard
- Repositories page + route deleted; overview / graph / chat / pentest-wizard
  read onboarded targets; `infrastructure/repositories.rs` trimmed to just the
  SSH-key fetch.

Tests
- Legacy repositories-API and migration integration tests removed; tenant
  isolation, cascade-delete, and stats tests repointed to `/targets` /
  `onboarded_targets`. `git.rs` gains a `sanitize_repo_dir` unit test.

Local: fmt clean; agent/mcp clippy clean; dashboard server+web compile; core +
agent lib tests (32) pass; integration tests compile.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-07-13 21:17:41 +02:00
co-authored by Claude Opus 4.8
parent 87f240b26f
commit dadccb9264
46 changed files with 386 additions and 2123 deletions
@@ -113,15 +113,16 @@ async fn delete_repo_cascades_to_dast_and_pentest_data() {
// Create a repo
let resp = server
.post(
"/api/v1/repositories",
"/api/v1/targets",
&json!({
"name": "cascade-test",
"git_url": "https://github.com/example/cascade-test.git",
"target_type": "web_app",
"artifacts": [{ "kind": "git_repo", "source_ref": "https://github.com/example/cascade-test.git", "branch": "main" }],
}),
)
.await;
let body: serde_json::Value = resp.json().await.unwrap();
let repo_id = body["data"]["id"].as_str().unwrap().to_string();
let repo_id = body["data"]["_id"]["$oid"].as_str().unwrap().to_string();
// Insert DAST target linked to repo
let target_id = insert_dast_target(&server, &repo_id, "cascade-target").await;
@@ -140,9 +141,7 @@ async fn delete_repo_cascades_to_dast_and_pentest_data() {
assert_eq!(count_docs(&server, "dast_findings").await, 1);
// Delete the repo
let resp = server
.delete(&format!("/api/v1/repositories/{repo_id}"))
.await;
let resp = server.delete(&format!("/api/v1/targets/{repo_id}")).await;
assert_eq!(resp.status(), 200);
// All downstream data should be gone
@@ -161,15 +160,16 @@ async fn delete_repo_cascades_sast_findings_and_sbom() {
// Create a repo
let resp = server
.post(
"/api/v1/repositories",
"/api/v1/targets",
&json!({
"name": "sast-cascade",
"git_url": "https://github.com/example/sast-cascade.git",
"target_type": "web_app",
"artifacts": [{ "kind": "git_repo", "source_ref": "https://github.com/example/sast-cascade.git", "branch": "main" }],
}),
)
.await;
let body: serde_json::Value = resp.json().await.unwrap();
let repo_id = body["data"]["id"].as_str().unwrap().to_string();
let repo_id = body["data"]["_id"]["$oid"].as_str().unwrap().to_string();
// Insert SAST finding and SBOM entry
let mongodb_uri = std::env::var("TEST_MONGODB_URI")
@@ -209,9 +209,7 @@ async fn delete_repo_cascades_sast_findings_and_sbom() {
assert_eq!(count_docs(&server, "sbom_entries").await, 1);
// Delete repo
server
.delete(&format!("/api/v1/repositories/{repo_id}"))
.await;
server.delete(&format!("/api/v1/targets/{repo_id}")).await;
// Both should be gone
assert_eq!(count_docs(&server, "findings").await, 0);