type !== 'org') { throw new RunnerException('OpenCorporates only supports "org" targets.'); } $token = config('services.opencorporates.token'); if (blank($token)) { throw new RunnerException('OpenCorporates API token not configured (OPENCORPORATES_API_TOKEN).'); } $response = Http::timeout((int) config('osint.run_timeout')) ->get('https://api.opencorporates.com/v0.4/companies/search', [ 'q' => $target->value, 'api_token' => $token, 'per_page' => 10, ]); if (! $response->successful()) { throw new RunnerException('OpenCorporates request failed with status '.$response->status().'.'); } $companies = $response->json('results.companies') ?? []; $matches = collect($companies)->map(function (array $entry) { $company = $entry['company']; $label = sprintf( '%s (%s%s)', $company['name'], $company['jurisdiction_code'] ?? 'unknown jurisdiction', $company['current_status'] ? ', '.$company['current_status'] : '' ); return ['name' => $label, 'url' => $company['opencorporates_url']]; })->all(); $summary = count($matches) > 0 ? sprintf('Found %d compan%s matching "%s".', count($matches), count($matches) === 1 ? 'y' : 'ies', $target->value) : sprintf('No companies found matching "%s".', $target->value); return new RunnerResult(raw: ['matches' => $matches], summary: $summary); } }