mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-20 15:21:30 +02:00
A pentester asked how to see vulnerabilities and the answer was "open a scan". Every result surface was scoped to one run, which is a scanner's model rather than an ASM platform's. The keystone is QueryScope: the set of scans a query reads — one on a scan page, the latest covering scan of every target on a project view (a producing stage succeeded, or rows exist; the rule target_summary already used, now shared as covering_stages()). scope.match() emits `== id` for a single scan so no scan-page plan changed, and the predicates accept a UUID, a QueryScope or a sequence so single-scan callers were untouched. Because the scope generalises rather than duplicates, the same table components render both views: the grammar, facets, leads, group-by, evidence and detail sheets all follow. No results table exists twice. Scan-level facts had to become per-row: _per_scan() ORs and_(col == sid, build(sid)) so *_has_baseline — and therefore is:new — stays exact across many scans, and baselined_targets() makes the row-level is_new flag ask per target, or a first-scanned target badges everything New. Addresses are the exception: the IPs view folds one row per address across every target that serves it, so newness is judged against target_ids with the row's own first_seen as cutoff. - target: is a field in all five grammars and a group dimension in all five - /surface/[dimension] renders from SURFACE_ORDER; routeLabels take their five labels from it so nav, breadcrumb and heading cannot drift - a scope strip states how many targets the reading covers, how old the oldest is, and which targets were never scanned for that dimension, with a launch action — absent is not empty - anything needing a parent run (rescan, recheck, the endpoints Gone lens) is off project-wide, and the coverage strips drop their "on this scan" copy - the scan page's tab strip links to the same dimension across all targets, carrying the typed query Verified: every group token and every counted lead in all five dimensions returns exactly its own count in both scopes, and project-scoped is:new equals the union of the per-scan answers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EQgatRaA9fNsv2jXh4rZ47
48 lines
1.1 KiB
Python
48 lines
1.1 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Sequence
|
|
from dataclasses import dataclass
|
|
from uuid import UUID
|
|
|
|
from sqlalchemy import false
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class QueryScope:
|
|
"""The scans a query reads: one on a scan page, one per target on a project view."""
|
|
|
|
ids: tuple[UUID, ...]
|
|
project_id: UUID | None = None
|
|
|
|
@classmethod
|
|
def of(cls, value: ScopeLike) -> QueryScope:
|
|
if isinstance(value, QueryScope):
|
|
return value
|
|
if isinstance(value, UUID):
|
|
return cls((value,))
|
|
return cls(tuple(value))
|
|
|
|
@property
|
|
def single(self) -> UUID | None:
|
|
return self.ids[0] if len(self.ids) == 1 else None
|
|
|
|
def match(self, column):
|
|
if not self.ids:
|
|
return false()
|
|
one = self.single
|
|
return column == one if one is not None else column.in_(self.ids)
|
|
|
|
def __bool__(self) -> bool:
|
|
return bool(self.ids)
|
|
|
|
|
|
ScopeLike = UUID | QueryScope | Sequence[UUID]
|
|
|
|
|
|
def scope_of(value: ScopeLike) -> QueryScope:
|
|
return QueryScope.of(value)
|
|
|
|
|
|
def scan_filter(column, value: ScopeLike):
|
|
return QueryScope.of(value).match(column)
|