mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-20 15:21:30 +02:00
How is the surface hosted? One three-column flow on both Overviews answers it: resolving web assets → fronting (CDN or WAF edge · cloud provider · direct to origin) → network (the top nine AS organisations and "Other networks"). It sits after Vulnerabilities on the scan page and after Needs attention on the target page, renders only when something resolves, and replaces Composition's "Hosting networks" ranked list, which said the same thing without the fronting relationship. GET /subdomains/hosting-flow aggregates Subdomain LEFT JOIN a distinct-on HttpAsset per host. Every node and link carries its query token — is:resolved, is:cdn, is:cloud (new on the host grammar: cdn_type == 'cloud'), asn:<n>, and "is:resolved and not (asn:… or …)" for the remainder — and the count is a promise: on gov.cy and hamropatro every figure equals the row count its query lands on. "Resolving" uses the grammar's own resolved predicate rather than is_active (they differed by two), and the one expression is shared between SELECT and GROUP BY because a second call binds a second parameter Postgres rejects. Unresolved hosts are not a node: they have no flow and they crushed the scale; the head line says "444 of 1,379 resolve · 26 networks" instead. The sankey is hand-rolled (no d3-sankey; node_modules is baked into the image): a minimum node height so a one-asset network stays legible, centred columns, labels clipped at 30 characters with the full name in the tooltip, and a halo so mid-column labels read over ribbons. The whole row is the hit target and every ribbon has a wide transparent twin; nodes are Tab stops with a focus ring and an anchored tooltip; the tooltip carries the share and the query with a Web Assets affordance; the traced path wears a moving dash that reduced motion turns off; the draw-in starts when the panel scrolls into view. Click pivots into Web Assets with the query. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012YK61xuAJGMhq1uniLhHX5
27 lines
511 B
Python
27 lines
511 B
Python
from pydantic import BaseModel, Field
|
|
|
|
|
|
class FlowNode(BaseModel):
|
|
id: str
|
|
label: str
|
|
count: int
|
|
column: int
|
|
tone: str
|
|
query: str | None = None
|
|
detail: str | None = None
|
|
|
|
|
|
class FlowLink(BaseModel):
|
|
source: str
|
|
target: str
|
|
count: int
|
|
query: str | None = None
|
|
|
|
|
|
class HostingFlow(BaseModel):
|
|
hosts: int = 0
|
|
resolving: int = 0
|
|
networks: int = 0
|
|
nodes: list[FlowNode] = Field(default_factory=list)
|
|
links: list[FlowLink] = Field(default_factory=list)
|