feat(appgate): add AppGate SDP integration health check and sync service
Registers AppGate as a checkConfigOnly integration-health row and public sync route, matching the existing factory + is<Name>Configured() pattern. Committed now so Phase 13's worktree-isolated executors fork from a HEAD that includes this integration-health.ts entry, since Plan 13-02 inserts the PAX8 row immediately after it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LHRgZqkzBHBbAbc3KHneuR
This commit is contained in:
parent
f70a4a36ed
commit
b168d44585
9 changed files with 998 additions and 0 deletions
130
lib/types/appgate.ts
Normal file
130
lib/types/appgate.ts
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* Type definitions for the AppGate SDP Controller REST API (v22.5) and the
|
||||
* shapes Pulse persists. Source spec lives at
|
||||
* `https://wawnvaagp01.wulfconsulting.com:8443/api_specs.html`.
|
||||
*
|
||||
* Only the slices Pulse consumes are typed — the API exposes ~150 endpoints,
|
||||
* most of which are administrative writes Pulse never makes.
|
||||
*/
|
||||
|
||||
// ─── API response shapes ──────────────────────────────────────────────────
|
||||
|
||||
export interface AppgateLoginResponse {
|
||||
user?: unknown;
|
||||
token: string;
|
||||
expires: string; // ISO timestamp
|
||||
messageOfTheDay?: string;
|
||||
ztpCollectiveType?: string;
|
||||
ztpAccountType?: string;
|
||||
crlEnabled?: boolean;
|
||||
}
|
||||
|
||||
export interface AppgateDeviceAndUser {
|
||||
distinguishedName: string;
|
||||
deviceId?: string;
|
||||
username?: string;
|
||||
providerName?: string;
|
||||
}
|
||||
|
||||
export interface AppgateActiveSession extends AppgateDeviceAndUser {
|
||||
geoIpLatitude?: number;
|
||||
geoIpLongitude?: number;
|
||||
hostname?: string;
|
||||
osFamily?: string;
|
||||
osName?: string;
|
||||
osParent?: string;
|
||||
clientVersion?: string;
|
||||
clientType?: string;
|
||||
clientSupport?: 'full' | 'partial' | 'none';
|
||||
gateways?: string[];
|
||||
}
|
||||
|
||||
export interface AppgateOnBoardedDevice extends AppgateDeviceAndUser {
|
||||
device_type?: string;
|
||||
hostname?: string;
|
||||
onBoardedAt?: string;
|
||||
lastSeenAt?: string;
|
||||
}
|
||||
|
||||
export interface AppgateAppliance {
|
||||
id: string;
|
||||
name: string;
|
||||
notes?: string;
|
||||
hostname?: string;
|
||||
version?: number;
|
||||
site?: string;
|
||||
siteName?: string;
|
||||
activated?: boolean;
|
||||
pendingCertificateRenewal?: boolean;
|
||||
tags?: string[];
|
||||
created?: string;
|
||||
updated?: string;
|
||||
controller?: { enabled?: boolean };
|
||||
gateway?: { enabled?: boolean };
|
||||
logServer?: { enabled?: boolean };
|
||||
logForwarder?: { enabled?: boolean };
|
||||
metricsAggregator?: { enabled?: boolean };
|
||||
connector?: { enabled?: boolean };
|
||||
portal?: { enabled?: boolean };
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface AppgateUserLicense {
|
||||
userDistinguishedName: string;
|
||||
username?: string;
|
||||
providerName?: string;
|
||||
type?: string; // user | portal | service
|
||||
profileName?: string;
|
||||
created?: string;
|
||||
lastSeenAt?: string;
|
||||
}
|
||||
|
||||
export interface AppgateLicense {
|
||||
id?: string;
|
||||
version?: number;
|
||||
type?: number; // 1 production, 2 install, 3 test, 4 built-in, 5 aws, 6 metered
|
||||
expiration?: string;
|
||||
error?: string;
|
||||
maxUsers?: number;
|
||||
maxPortalUsers?: number;
|
||||
maxServiceUsers?: number;
|
||||
maxSites?: number;
|
||||
maxAccessPolicies?: number;
|
||||
maxConnectorGroups?: number;
|
||||
riskEngine?: boolean;
|
||||
applicationDiscovery?: boolean;
|
||||
digitalExperienceMonitoring?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* `/stats/user-logins` returns a 24-hour rolling map keyed by hour-of-day,
|
||||
* each value either a number or `{ total: number }` per-controller breakdown.
|
||||
* Hour keys past "now" represent yesterday; everything else is today.
|
||||
*/
|
||||
export type AppgateHourlyLogins = Record<
|
||||
string,
|
||||
number | { total?: number | string; [controller: string]: number | string | undefined }
|
||||
>;
|
||||
|
||||
export interface AppgateResultList<T> {
|
||||
range?: string;
|
||||
totalCount?: number;
|
||||
data: T[];
|
||||
}
|
||||
|
||||
// ─── Sync orchestration ───────────────────────────────────────────────────
|
||||
|
||||
export interface AppgateSyncResult {
|
||||
syncId: string;
|
||||
syncType: 'sessions' | 'daily' | 'full';
|
||||
startedAt: Date;
|
||||
completedAt: Date;
|
||||
durationMs: number;
|
||||
status: 'completed' | 'failed';
|
||||
sessions: number;
|
||||
devices: { upserted: number; tombstoned: number };
|
||||
appliances: { upserted: number; tombstoned: number };
|
||||
licenseUsers: number;
|
||||
loginsCaptured: number;
|
||||
errors: string[];
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue