Describes what this actually is (multi-user OSINT investigation
platform), the 9 collectors, and step-by-step setup (DB, Python venvs,
queue worker, optional OpenCorporates token).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes the last coverage gap for org (person remains intentionally
unaddressed — no good free/non-scraping option exists). Unlike the
other 8 sources, OpenCorporates now requires an API token even on its
free tier (confirmed: keyless request gets 401). RunnerRegistry::has()
checks services.opencorporates.token is configured before exposing the
source as runnable, so it degrades to "not yet integrated" in the UI
rather than a broken Run button, until OPENCORPORATES_API_TOKEN is set.
Also fixes a real bug hit while building this: a RunnerRegistry::REQUIRES
class constant mapping source key to a closure crashed on file load
(PHP class constants can't hold closures) — inlined the one check
instead of building an abstraction for a single case.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two pure-PHP collectors, no Python/venv/subprocess needed:
- GravatarRunner (email): checks gravatar.com/avatar/{md5}?d=404 for a
200 vs 404. Scoped to that binary signal since Gravatar's profile
JSON endpoint now requires API auth even for real, public profiles
(confirmed against Gravatar's own creator's email).
- DnsRunner (domain): dns_get_record() for A/AAAA/MX/NS/TXT/CNAME. Raw
payload is naturally keyed by record type, which the existing
generic list-renderer on the investigation page turns into one
collapsible section per type with no UI changes needed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes the email target-type gap (previously had zero collectors).
Checks whether an email is registered on 120+ sites via the
password-reset-oracle technique. Shares the Sherlock/whois venv.
HoleheRunner gates success on the CSV file existing rather than the
process exit code: holehe's CLI calls Python's exit("message") right
after writing results on its normal success path, which always yields
exit code 1 regardless of outcome — discovered while verifying this
end-to-end against the real dev server and queue worker.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Run-all buttons (per target and per investigation) queue every applicable,
not-already-in-flight source via a new FindingDispatcher, re-attempting
prior failures automatically. RunFinding now applies a per-source
RateLimited queue middleware so a bulk run can't hammer the free public
APIs (ip-api, crt.sh, whois, sherlock, theharvester) it depends on;
$tries raised to 30 to survive rate-limiter releases, with a failed()
handler so exhausted retries still resolve the Finding instead of leaving
it stuck pending.
Also fixes CrtShRunner treating crt.sh's intermittent 404/502 (a known
flaky free service) as fatal on the first try — added a bounded retry.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Runs php artisan queue:work as a systemd --user service (Restart=always,
hourly recycling) so OSINT lookups process automatically instead of
requiring a manually-run queue:work. All 8 planned phases now done.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Multi-user OSINT investigation tool with owner-controlled per-user and
per-group access grants. Includes Sherlock, theHarvester, crt.sh, WHOIS,
and ip-api.com collectors wired through a pluggable Runner/queue pipeline,
investigation search, and printable/CSV/JSON reporting.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>