wulf-pulse/app/api/analyzer/itglue/sites/[companyId]/route.ts
lorentz 1112a06afe feat: RMM Overshell, IT Glue audit/write-back, LogLift, link-aware bundles, dashboard overhaul
- RMM Overshell (migration 077): admin page, dispatch UI, executor/worker, target
  resolver, script registry (AD/DHCP/DNS/event-log/services/software/network/loglift)
- LogLift evidence pipeline (migration 078): upload webhook, B2 storage client,
  receiver/matcher, EventLogCollector PowerShell script
- IT Glue audit + write-back (migrations 075, 076): asset-audit runner, ticket
  xrefs, applications/configurations browse pages + apply/revert/audit endpoints
- Link-aware analyzer bundles (migration 073) + provider toggle (migration 074):
  link-discovery service, OpenRouter LLM provider, related-tickets/itglue-suggestion
  panels, analyze-bundle endpoint
- Endpoint data model + device-link reconciliation (migrations 079, 080): conflicts
  admin page, reconciler service, resolve endpoints
- Dashboard overhaul: integration-health service + alerts, overview/health endpoints
- Permissions: add itglue + rmm scopes; middleware: public /api/rmm/loglift route

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 07:13:18 -04:00

67 lines
2.2 KiB
TypeScript

/**
* GET /api/analyzer/itglue/sites/:companyId
*
* Returns the site-discovery summary for a client: company identity,
* IT Glue org name, Datto site mapping, and the resolved Wulf Nurse
* Production endpoint (hostname + uid + online state).
*/
import { NextRequest, NextResponse } from 'next/server';
import { requireAuth } from '@/lib/auth-utils';
import postgresClient from '@/lib/services/postgres-client';
import {
listSiteAnchorTargets,
resolveSiteAnchorTarget,
} from '@/lib/services/rmm/target-resolver';
interface CompanyRow {
id: string;
company_name: string | null;
itglue_org_id: string | null;
itglue_org_name: string | null;
datto_site_id: number | null;
}
export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ companyId: string }> }
) {
const { error } = await requireAuth();
if (error) return error;
const { companyId } = await params;
const res = await postgresClient.query<CompanyRow>(
`SELECT c.id::text AS id,
c.company_name,
o.id::text AS itglue_org_id,
o.name AS itglue_org_name,
ds.id AS datto_site_id
FROM companies c
LEFT JOIN itg_organizations o ON LOWER(o.name) = LOWER(c.company_name)
LEFT JOIN datto_rmm_sites ds ON ds.autotask_company_id = c.id
WHERE c.id = $1
LIMIT 1`,
[companyId]
);
if (res.rowCount === 0) {
return NextResponse.json({ error: 'Company not found' }, { status: 404 });
}
const c = res.rows[0];
const target = await resolveSiteAnchorTarget(companyId);
const allTargets = await listSiteAnchorTargets(companyId);
return NextResponse.json({
site: {
companyId: c.id,
companyName: c.company_name,
itglueOrgId: c.itglue_org_id,
itglueOrgName: c.itglue_org_name,
dattoSiteId: c.datto_site_id,
// The chosen primary target — what the executor picks by default.
wnpHostname: target?.hostname ?? null,
wnpDeviceUid: target?.device_uid ?? null,
wnpOnline: target?.online ?? null,
// Every available WNP across all sites for the client.
sites: allTargets,
},
});
}