Files
rengine/shared/models/surface.py
T
Yogesh OjhaandClaude Opus 5 8f341131fc refactor(ui): enterprise naming for the navigation, and Interest becomes Exposures
The menu read as hacker cosplay rather than security software: "Worth a look"
as a product feature, swords for the tool library, a sparkle for a risk
surface, a crosshair for the asset list.

"Worth a look" is now Exposures. Studying what the layer does settles the name:
it scores an asset for what it IS — admin interface, developer tooling, remote
access, non-production, legacy, no authentication, exposed content, takeover
risk — and for how far it stands out from the estate. That is an exposure, the
Gartner CTEM term, and it pairs with Vulnerabilities, which is what a scanner
found. Bands are Critical/High/Notable, not "Look first"/"Worth a look".

Only the user-visible layer is renamed. The interest/ package, the
interest_signals table and InterestKind keep their names because renaming them
is a migration with no user benefit. The host grammar's canonical tokens become
is:exposed, exposure:<kind> and exposure_band:<band>, with the old spellings
kept as aliases so no saved rule breaks — and the endpoint grammar's separate
interest: (open_redirect, traversal, admin) keeps its name, so the rename
removes a collision rather than creating one.

Exposures also stops being a settings page. The nav item opened Rules and
Dismissed while its name promised findings; it now opens the project-wide
ranked list over the same QueryScope as the five dimensions, with Rules and
Dismissed as tabs. Judging and rule suggestions are per-run and stay hidden
there, and a project view reports stale=false so it never queues a re-label.

Naming and icons elsewhere:
- IPs -> IP addresses; the other four dimensions keep their names
- Reconnaissance -> Discovery
- the Services "Exposure" panel -> "Open services", freeing the word
- swords -> library, sparkle -> scan-eye, crosshair -> target, plug-zap ->
  cable, network -> bot for MCP, layers -> sliders for scan contexts, and no
  two items in a group share a glyph

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EQgatRaA9fNsv2jXh4rZ47
2026-09-09 06:06:30 +05:30

43 lines
1.1 KiB
Python

import uuid
from datetime import datetime
from pydantic import BaseModel, Field
class SurfaceTargetRead(BaseModel):
target_id: uuid.UUID
target_value: str
target_type: str
scan_id: uuid.UUID | None = None
scan_status: str | None = None
observed_at: datetime | None = None
stale: bool = False
class SurfaceCoverage(BaseModel):
dimension: str
label: str
noun: str
noun_plural: str
total: int = 0
total_capped: bool = False
targets_total: int = 0
targets_covered: int = 0
observed_from: datetime | None = None
observed_to: datetime | None = None
covered: list[SurfaceTargetRead] = Field(default_factory=list)
uncovered: list[SurfaceTargetRead] = Field(default_factory=list)
@property
def stale_targets(self) -> int:
return sum(1 for row in self.covered if row.stale)
class SurfaceOverview(BaseModel):
project_id: uuid.UUID
targets_total: int = 0
live_scans: int = 0
exposures: int = 0
dimensions: list[SurfaceCoverage] = Field(default_factory=list)
generated_at: datetime