module EhcStore
EhcStore — per-host scan history for self-improving CTF recon prompts. Public: PLUGIN, MAX_SCANS, MAX_FINDINGS, load_scans, record_scan, insights_for Depends: RabbotDb Tests: test/lib/ehc_store_test.rb
Constants
- MAX_FINDINGS
- MAX_INSIGHTS
- MAX_SCANS
- MAX_SIGNALS
- PLUGIN
Public Instance Methods
Source
# File lib/ehc_store.rb, line 68 def dedupe_lines(lines) seen = {} lines.filter_map do |line| text = line.to_s.strip next if text.empty? key = text.downcase next if seen[key] seen[key] = true text end end
Source
# File lib/ehc_store.rb, line 64 def fetch_value(data, key) data[key] || data[key.to_sym] end
Source
# File lib/ehc_store.rb, line 21 def host_key(host) "host:#{host.to_s.strip.downcase}" end
Source
# File lib/ehc_store.rb, line 39 def insights_for(host:, store: RabbotDb) data = load_scans(host: host, store: store) findings = Array(data["scans"]).flat_map { |scan| Array(scan["findings"]) } signals = Array(data["scans"]).flat_map { |scan| Array(scan["signals"]) } lines = (findings + signals.map { |signal| "Prior signal: #{signal}" }) dedupe_lines(lines).first(MAX_INSIGHTS) end
Source
# File lib/ehc_store.rb, line 25 def load_scans(host:, store: RabbotDb) data = store.get_plugin_json(plugin: PLUGIN, key: host_key(host), default: nil) normalize_data(data) end
Source
# File lib/ehc_store.rb, line 48 def normalize_data(raw) data = raw.is_a?(Hash) ? raw : {} { "scans" => Array(data["scans"]).map { |entry| normalize_scan(entry) } } end
Source
# File lib/ehc_store.rb, line 53 def normalize_scan(raw, host: nil, now: Time.now.utc) data = raw.is_a?(Hash) ? raw : {} { "host" => (host || fetch_value(data, "host")).to_s.strip, "scanned_at" => fetch_value(data, "scanned_at").to_s.strip.empty? ? now.utc.iso8601 : fetch_value(data, "scanned_at").to_s, "status" => fetch_value(data, "status").to_i, "signals" => Array(fetch_value(data, "signals")).map(&:to_s).reject(&:empty?).first(MAX_SIGNALS), "findings" => Array(fetch_value(data, "findings")).map(&:to_s).reject(&:empty?).first(MAX_FINDINGS) } end
Source
# File lib/ehc_store.rb, line 30 def record_scan(host:, scan:, store: RabbotDb, now: Time.now.utc) data = load_scans(host: host, store: store) entry = normalize_scan(scan, host: host, now: now) scans = Array(data["scans"]) + [entry] scans = scans.last(MAX_SCANS) store.set_plugin_json(plugin: PLUGIN, key: host_key(host), value: { "scans" => scans }) entry end