mirror of
https://github.com/laramies/theHarvester.git
synced 2026-08-17 19:35:40 +02:00
docs: make README diagrams readable
This commit is contained in:
@@ -1,109 +1,158 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="harvestview-architecture-title harvestview-architecture-desc">
|
||||
<title id="harvestview-architecture-title">HarvestView run desk architecture</title>
|
||||
<desc id="harvestview-architecture-desc">HarvestView validates local browser requests through the authenticated API, records one durable run, executes it in an isolated worker, and returns normalized evidence to the route workbench.</desc>
|
||||
<defs>
|
||||
<style>@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap');</style>
|
||||
<style>
|
||||
.title { font: 400 28px "Instrument Serif", Georgia, serif; fill: #0e1d22; }
|
||||
.subtitle { font: 400 12px "Geist", system-ui, sans-serif; fill: #4f5e63; }
|
||||
.eyebrow { font: 600 8px "Geist Mono", ui-monospace, monospace; letter-spacing: .16em; fill: #4f5e63; }
|
||||
.node-title { font: 600 12px "Geist", system-ui, sans-serif; fill: #0e1d22; }
|
||||
.node-copy { font: 400 8px "Geist Mono", ui-monospace, monospace; fill: #4f5e63; }
|
||||
.node-copy-strong { font: 500 8px "Geist Mono", ui-monospace, monospace; fill: #34464c; }
|
||||
.boundary { fill: rgba(14,29,34,.018); stroke: #889ca3; stroke-width: 1; stroke-dasharray: 8 8; }
|
||||
.node { fill: #fdfaf4; stroke: #889ca3; stroke-width: 1; }
|
||||
.node-muted { fill: #ede7dd; stroke: #889ca3; stroke-width: 1; }
|
||||
.node-focal { fill: #bcede4; stroke: #009685; stroke-width: 1.2; }
|
||||
.tag { fill: #f5efe7; stroke: #889ca3; stroke-width: .8; }
|
||||
.tag-teal { fill: #bcede4; stroke: #009685; stroke-width: .8; }
|
||||
.tag-text { font: 600 8px "Geist Mono", ui-monospace, monospace; fill: #34464c; text-anchor: middle; }
|
||||
.tag-text-teal { fill: #00594c; }
|
||||
.connector { fill: none; stroke: #4f5e63; stroke-width: 1.2; }
|
||||
.connector-accent { fill: none; stroke: #009685; stroke-width: 1.2; }
|
||||
.legend { font: 400 8px "Geist Mono", ui-monospace, monospace; fill: #4f5e63; }
|
||||
</style>
|
||||
<marker id="harvestview-architecture-arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5e63"/></marker>
|
||||
<marker id="harvestview-architecture-arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#009685"/></marker>
|
||||
<marker id="harvestview-architecture-arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#00548c"/></marker>
|
||||
</defs>
|
||||
<svg viewBox="0 0 960 640" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="harvestview-architecture-title harvestview-architecture-desc">
|
||||
<title id="harvestview-architecture-title">HarvestView run desk architecture</title>
|
||||
<desc id="harvestview-architecture-desc">A loopback-only HarvestView workflow sends a reviewed plan through the authenticated REST API and durable run control to an isolated worker, preserves normalized evidence separately from lifecycle state, supports inspection and child actions, and imports or exports JSONL and SQLite evidence.</desc>
|
||||
<defs>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap');
|
||||
:root {
|
||||
--paper: #2d3142;
|
||||
--paper-2: #393e53;
|
||||
--ink: #f5f5f5;
|
||||
--muted: #bfc0c0;
|
||||
--soft: #8e98ac;
|
||||
--rule: rgba(245,245,245,.16);
|
||||
--rule-strong: rgba(245,245,245,.28);
|
||||
--boundary-fill: rgba(245,245,245,.025);
|
||||
--accent: #f08a59;
|
||||
--accent-tint: rgba(240,138,89,.10);
|
||||
--link: #6a95d8;
|
||||
--link-tint: rgba(106,149,216,.10);
|
||||
}
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--paper: #f5f5f5;
|
||||
--paper-2: #ececec;
|
||||
--ink: #2d3142;
|
||||
--muted: #4f5d75;
|
||||
--soft: #7a8399;
|
||||
--rule: rgba(45,49,66,.14);
|
||||
--rule-strong: rgba(45,49,66,.28);
|
||||
--boundary-fill: rgba(45,49,66,.02);
|
||||
--accent: #b84f24;
|
||||
--accent-tint: rgba(235,108,54,.10);
|
||||
--link: #2e5aa8;
|
||||
--link-tint: rgba(46,90,168,.08);
|
||||
}
|
||||
}
|
||||
.bg { fill: var(--paper); }
|
||||
.title { font: 400 28px 'Instrument Serif', Georgia, serif; fill: var(--ink); }
|
||||
.subtitle { font: 400 12px 'Geist', system-ui, sans-serif; fill: var(--muted); }
|
||||
.eyebrow { font: 600 8px 'Geist Mono', ui-monospace, monospace; letter-spacing: .16em; fill: var(--soft); }
|
||||
.boundary { fill: var(--boundary-fill); stroke: var(--rule-strong); stroke-width: 1; stroke-dasharray: 8 8; }
|
||||
.boundary-mask { fill: var(--paper); }
|
||||
.node { fill: var(--paper); stroke: var(--rule-strong); stroke-width: 1; }
|
||||
.node-muted { fill: var(--paper-2); stroke: var(--rule-strong); stroke-width: 1; }
|
||||
.node-link { fill: var(--link-tint); stroke: var(--link); stroke-width: 1; }
|
||||
.node-focal { fill: var(--accent-tint); stroke: var(--accent); stroke-width: 1.2; }
|
||||
.tag { fill: var(--paper-2); stroke: var(--rule-strong); stroke-width: .8; }
|
||||
.tag-link { fill: var(--link-tint); stroke: var(--link); stroke-width: .8; }
|
||||
.tag-accent { fill: var(--accent-tint); stroke: var(--accent); stroke-width: .8; }
|
||||
.tag-text { font: 600 8px 'Geist Mono', ui-monospace, monospace; letter-spacing: .08em; fill: var(--muted); text-anchor: middle; }
|
||||
.tag-text-link { fill: var(--link); }
|
||||
.tag-text-accent { fill: var(--accent); }
|
||||
.node-title { font: 600 16px 'Geist', system-ui, sans-serif; fill: var(--ink); }
|
||||
.node-copy { font: 400 12px 'Geist Mono', ui-monospace, monospace; fill: var(--muted); }
|
||||
.node-copy-strong { font: 500 12px 'Geist Mono', ui-monospace, monospace; fill: var(--ink); }
|
||||
.connector { fill: none; stroke: var(--muted); stroke-width: 1.2; }
|
||||
.connector-link { fill: none; stroke: var(--link); stroke-width: 1.2; }
|
||||
.connector-accent { fill: none; stroke: var(--accent); stroke-width: 1.2; }
|
||||
.dashed { stroke-dasharray: 4 4; }
|
||||
.marker-muted { fill: var(--muted); }
|
||||
.marker-link { fill: var(--link); }
|
||||
.marker-accent { fill: var(--accent); }
|
||||
.legend { font: 500 12px 'Geist Mono', ui-monospace, monospace; fill: var(--muted); }
|
||||
</style>
|
||||
<marker id="harvestview-arrow" markerWidth="8" markerHeight="8" refX="8" refY="4" orient="auto"><polygon points="0 0, 8 4, 0 8" class="marker-muted"/></marker>
|
||||
<marker id="harvestview-arrow-link" markerWidth="8" markerHeight="8" refX="8" refY="4" orient="auto"><polygon points="0 0, 8 4, 0 8" class="marker-link"/></marker>
|
||||
<marker id="harvestview-arrow-accent" markerWidth="8" markerHeight="8" refX="8" refY="4" orient="auto"><polygon points="0 0, 8 4, 0 8" class="marker-accent"/></marker>
|
||||
</defs>
|
||||
|
||||
<rect width="1280" height="720" fill="#f5efe7"/>
|
||||
<text x="40" y="52" class="eyebrow">HARVESTVIEW · LOCAL OPERATOR WORKFLOW</text>
|
||||
<text x="40" y="88" class="title">One run desk, one durable lifecycle</text>
|
||||
<text x="40" y="112" class="subtitle">The browser reviews scope; the API validates; an isolated worker executes; evidence remains available after terminal state.</text>
|
||||
<rect width="960" height="640" class="bg"/>
|
||||
<text x="40" y="32" class="eyebrow">HARVESTVIEW · LOCAL OPERATOR WORKFLOW</text>
|
||||
<text x="40" y="64" class="title">One run desk, one durable evidence path</text>
|
||||
<text x="40" y="88" class="subtitle">The browser reviews scope; the API validates; an isolated worker executes; completed evidence remains portable.</text>
|
||||
|
||||
<rect x="40" y="132" width="1200" height="436" rx="8" class="boundary"/>
|
||||
<rect x="56" y="136" width="184" height="16" fill="#f5efe7"/>
|
||||
<text x="60" y="148" class="eyebrow">LOCAL HOST · 127.0.0.1</text>
|
||||
<rect x="24" y="120" width="912" height="408" rx="8" class="boundary"/>
|
||||
<rect x="40" y="124" width="204" height="16" rx="4" class="boundary-mask"/>
|
||||
<text x="48" y="136" class="eyebrow">LOCALHOST · 127.0.0.1:5000</text>
|
||||
|
||||
<line x1="224" y1="292" x2="264" y2="292" class="connector" marker-end="url(#harvestview-architecture-arrow)"/>
|
||||
<line x1="464" y1="292" x2="504" y2="292" class="connector" marker-end="url(#harvestview-architecture-arrow)"/>
|
||||
<line x1="604" y1="364" x2="604" y2="412" class="connector" marker-end="url(#harvestview-architecture-arrow)"/>
|
||||
<line x1="704" y1="472" x2="744" y2="472" class="connector" marker-end="url(#harvestview-architecture-arrow)"/>
|
||||
<line x1="844" y1="412" x2="844" y2="364" class="connector-accent" marker-end="url(#harvestview-architecture-arrow-accent)"/>
|
||||
<line x1="944" y1="292" x2="984" y2="292" class="connector" marker-end="url(#harvestview-architecture-arrow)"/>
|
||||
<line x1="220" y1="224" x2="244" y2="224" class="connector" marker-end="url(#harvestview-arrow)"/>
|
||||
<line x1="444" y1="192" x2="468" y2="192" class="connector-link dashed" marker-end="url(#harvestview-arrow-link)"/>
|
||||
<line x1="344" y1="296" x2="344" y2="336" class="connector" marker-end="url(#harvestview-arrow)"/>
|
||||
<line x1="444" y1="408" x2="468" y2="408" class="connector" marker-end="url(#harvestview-arrow)"/>
|
||||
<line x1="568" y1="336" x2="568" y2="296" class="connector-accent" marker-end="url(#harvestview-arrow-accent)"/>
|
||||
<line x1="668" y1="224" x2="692" y2="224" class="connector" marker-end="url(#harvestview-arrow)"/>
|
||||
<line x1="806" y1="296" x2="806" y2="336" class="connector-link" marker-end="url(#harvestview-arrow-link)"/>
|
||||
|
||||
<rect x="64" y="220" width="160" height="144" rx="8" class="node"/>
|
||||
<rect x="76" y="232" width="72" height="20" rx="4" class="tag"/>
|
||||
<text x="112" y="246" class="tag-text">BROWSER</text>
|
||||
<text x="80" y="276" class="node-title">Create or import</text>
|
||||
<text x="80" y="300" class="node-copy-strong">new run · JSONL · SQLite</text>
|
||||
<text x="80" y="320" class="node-copy-strong">source and action review</text>
|
||||
<text x="80" y="344" class="node-copy">P0 · P1 · P2 authorization</text>
|
||||
<rect x="40" y="152" width="180" height="144" rx="8" class="node"/>
|
||||
<rect x="52" y="164" width="72" height="20" rx="4" class="tag"/>
|
||||
<text x="88" y="180" class="tag-text">BROWSER</text>
|
||||
<text x="56" y="216" class="node-title">Plan and authorize</text>
|
||||
<text x="56" y="240" class="node-copy-strong">target · sources</text>
|
||||
<text x="56" y="256" class="node-copy-strong">actions · P0/P1/P2</text>
|
||||
<text x="56" y="272" class="node-copy">review before submit</text>
|
||||
|
||||
<rect x="264" y="220" width="200" height="144" rx="8" class="node"/>
|
||||
<rect x="276" y="232" width="96" height="20" rx="4" class="tag"/>
|
||||
<text x="324" y="246" class="tag-text">API GATE</text>
|
||||
<text x="280" y="276" class="node-title">Authenticated REST API</text>
|
||||
<text x="280" y="300" class="node-copy-strong">derived HttpOnly browser session</text>
|
||||
<text x="280" y="320" class="node-copy-strong">X-API-Key for API clients</text>
|
||||
<text x="280" y="344" class="node-copy">target · scope · options · limits</text>
|
||||
<rect x="244" y="152" width="200" height="144" rx="8" class="node-link"/>
|
||||
<rect x="256" y="164" width="88" height="20" rx="4" class="tag-link"/>
|
||||
<text x="300" y="180" class="tag-text tag-text-link">API GATE</text>
|
||||
<text x="260" y="216" class="node-title">Authenticated REST API</text>
|
||||
<text x="260" y="240" class="node-copy-strong">HttpOnly · X-API-Key</text>
|
||||
<text x="260" y="256" class="node-copy-strong">target · scope · limits</text>
|
||||
<text x="260" y="272" class="node-copy">create · list</text>
|
||||
<text x="260" y="288" class="node-copy">detail · cancel</text>
|
||||
|
||||
<rect x="504" y="220" width="200" height="144" rx="8" class="node-muted"/>
|
||||
<rect x="516" y="232" width="96" height="20" rx="4" class="tag"/>
|
||||
<text x="564" y="246" class="tag-text">CONTROL</text>
|
||||
<text x="520" y="276" class="node-title">Durable run control</text>
|
||||
<text x="520" y="300" class="node-copy-strong">queued → running → terminal</text>
|
||||
<text x="520" y="320" class="node-copy-strong">cancel request · source status</text>
|
||||
<text x="520" y="344" class="node-copy">one record per finite run</text>
|
||||
<rect x="468" y="152" width="200" height="144" rx="8" class="node-focal"/>
|
||||
<rect x="480" y="164" width="88" height="20" rx="4" class="tag-accent"/>
|
||||
<text x="524" y="180" class="tag-text tag-text-accent">EVIDENCE</text>
|
||||
<text x="484" y="216" class="node-title">Canonical evidence</text>
|
||||
<text x="484" y="240" class="node-copy-strong">results · provenance</text>
|
||||
<text x="484" y="256" class="node-copy-strong">source/action outcomes</text>
|
||||
<text x="484" y="272" class="node-copy">artifacts · status</text>
|
||||
<text x="484" y="288" class="node-copy">complete · partial · failed</text>
|
||||
|
||||
<rect x="504" y="412" width="200" height="120" rx="8" class="node"/>
|
||||
<rect x="516" y="424" width="80" height="20" rx="4" class="tag"/>
|
||||
<text x="556" y="438" class="tag-text">WORKER</text>
|
||||
<text x="520" y="468" class="node-title">Isolated run worker</text>
|
||||
<text x="520" y="492" class="node-copy-strong">claim · checkpoint · cancel</text>
|
||||
<text x="520" y="512" class="node-copy">bounded output · child cleanup</text>
|
||||
<rect x="692" y="152" width="228" height="144" rx="8" class="node"/>
|
||||
<rect x="704" y="164" width="112" height="20" rx="4" class="tag"/>
|
||||
<text x="760" y="180" class="tag-text">WORKBENCH</text>
|
||||
<text x="708" y="216" class="node-title">Inspect and act</text>
|
||||
<text x="708" y="240" class="node-copy-strong">history · assessment</text>
|
||||
<text x="708" y="256" class="node-copy-strong">route tabs · search</text>
|
||||
<text x="708" y="272" class="node-copy">filters · copy · logs</text>
|
||||
<text x="708" y="288" class="node-copy">screenshots · child runs</text>
|
||||
|
||||
<rect x="744" y="412" width="200" height="120" rx="8" class="node"/>
|
||||
<rect x="756" y="424" width="80" height="20" rx="4" class="tag"/>
|
||||
<text x="796" y="438" class="tag-text">ENGINE</text>
|
||||
<text x="760" y="468" class="node-title">theHarvester engine</text>
|
||||
<text x="760" y="492" class="node-copy-strong">cataloged sources · explicit actions</text>
|
||||
<text x="760" y="512" class="node-copy">DNS · Shodan · RouteViews · vhost</text>
|
||||
<rect x="244" y="336" width="200" height="144" rx="8" class="node-muted"/>
|
||||
<rect x="256" y="348" width="88" height="20" rx="4" class="tag"/>
|
||||
<text x="300" y="364" class="tag-text">CONTROL</text>
|
||||
<text x="260" y="392" class="node-title">Durable run lifecycle</text>
|
||||
<text x="260" y="420" class="node-copy-strong">queued · running</text>
|
||||
<text x="260" y="436" class="node-copy-strong">cancelling · cancelled</text>
|
||||
<text x="260" y="452" class="node-copy">completed · failed</text>
|
||||
<text x="260" y="468" class="node-copy">leases · deadlines</text>
|
||||
|
||||
<rect x="744" y="220" width="200" height="144" rx="8" class="node-focal"/>
|
||||
<rect x="756" y="232" width="96" height="20" rx="4" class="tag-teal"/>
|
||||
<text x="804" y="246" class="tag-text tag-text-teal">EVIDENCE</text>
|
||||
<text x="760" y="276" class="node-title">Evidence & artifacts</text>
|
||||
<text x="760" y="300" class="node-copy-strong">CompletedResult · route records</text>
|
||||
<text x="760" y="320" class="node-copy-strong">SQLite · screenshots · logs</text>
|
||||
<text x="760" y="344" class="node-copy">partial evidence remains inspectable</text>
|
||||
<rect x="468" y="336" width="200" height="144" rx="8" class="node"/>
|
||||
<rect x="480" y="348" width="80" height="20" rx="4" class="tag"/>
|
||||
<text x="520" y="364" class="tag-text">WORKER</text>
|
||||
<text x="484" y="392" class="node-title">Isolated run worker</text>
|
||||
<text x="484" y="420" class="node-copy-strong">claim · execute</text>
|
||||
<text x="484" y="436" class="node-copy-strong">checkpoint · cancel</text>
|
||||
<text x="484" y="452" class="node-copy">58 sources</text>
|
||||
<text x="484" y="468" class="node-copy">10 explicit actions</text>
|
||||
|
||||
<rect x="984" y="220" width="232" height="144" rx="8" class="node"/>
|
||||
<rect x="996" y="232" width="112" height="20" rx="4" class="tag"/>
|
||||
<text x="1052" y="246" class="tag-text">WORKBENCH</text>
|
||||
<text x="1000" y="276" class="node-title">Inspect and export</text>
|
||||
<text x="1000" y="300" class="node-copy-strong">history · assessment · route tabs</text>
|
||||
<text x="1000" y="320" class="node-copy-strong">screenshots · source outcomes · logs</text>
|
||||
<text x="1000" y="340" class="node-copy">review actions · JSONL / SQLite export</text>
|
||||
<rect x="692" y="336" width="228" height="144" rx="8" class="node-link"/>
|
||||
<rect x="704" y="348" width="104" height="20" rx="4" class="tag-link"/>
|
||||
<text x="756" y="364" class="tag-text tag-text-link">INTERCHANGE</text>
|
||||
<text x="708" y="392" class="node-title">Import and export</text>
|
||||
<text x="708" y="420" class="node-copy-strong">JSONL · one run</text>
|
||||
<text x="708" y="436" class="node-copy-strong">SQLite · completed set</text>
|
||||
<text x="708" y="452" class="node-copy">screenshot files separate</text>
|
||||
|
||||
<line x1="40" y1="636" x2="1240" y2="636" stroke="rgba(14,29,34,.14)" stroke-width=".8"/>
|
||||
<line x1="48" y1="676" x2="88" y2="676" class="connector" marker-end="url(#harvestview-architecture-arrow)"/>
|
||||
<text x="104" y="680" class="legend">control and lifecycle handoff</text>
|
||||
<line x1="352" y1="676" x2="392" y2="676" class="connector-accent" marker-end="url(#harvestview-architecture-arrow-accent)"/>
|
||||
<text x="408" y="680" class="legend">normalized evidence handoff</text>
|
||||
<rect x="676" y="664" width="20" height="20" rx="4" class="tag-teal"/>
|
||||
<text x="708" y="680" class="legend">durable evidence boundary</text>
|
||||
<text x="1240" y="680" class="legend" text-anchor="end">provider credentials remain server-side</text>
|
||||
</svg>
|
||||
<text x="48" y="512" class="node-copy">Provider credentials stay server-side. Lifecycle state never replaces terminal evidence status.</text>
|
||||
|
||||
<line x1="40" y1="584" x2="920" y2="584" stroke="var(--rule)" stroke-width=".8"/>
|
||||
<line x1="48" y1="616" x2="80" y2="616" class="connector" marker-end="url(#harvestview-arrow)"/>
|
||||
<text x="92" y="620" class="legend">run control</text>
|
||||
<line x1="248" y1="616" x2="280" y2="616" class="connector-accent" marker-end="url(#harvestview-arrow-accent)"/>
|
||||
<text x="292" y="620" class="legend">evidence handoff</text>
|
||||
<line x1="500" y1="616" x2="532" y2="616" class="connector-link dashed" marker-end="url(#harvestview-arrow-link)"/>
|
||||
<text x="544" y="620" class="legend">import path</text>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 10 KiB |
Reference in New Issue
Block a user