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
150 lines
6.4 KiB
SQL
150 lines
6.4 KiB
SQL
-- AppGate SDP integration — Postgres schema.
|
|
--
|
|
-- Mirrors the slices of Appgate SDP Controller REST API v22.5 that Pulse
|
|
-- surfaces for the manager-on-the-go view:
|
|
--
|
|
-- • Active sessions (current snapshot) -> appgate_active_sessions
|
|
-- • On-boarded devices (slowly changing list) -> appgate_devices
|
|
-- • Controllers / Gateways -> appgate_appliances
|
|
-- • Per-user license consumption -> appgate_license_users
|
|
-- • Daily license capacity rollup -> appgate_license_snapshots
|
|
-- • Daily login totals (history series) -> appgate_user_logins_daily
|
|
|
|
-- Current active sessions — replaced each sync (no history beyond appliances log).
|
|
CREATE TABLE IF NOT EXISTS appgate_active_sessions (
|
|
distinguished_name TEXT PRIMARY KEY,
|
|
device_id UUID,
|
|
username TEXT,
|
|
provider_name TEXT,
|
|
hostname TEXT,
|
|
os_family TEXT,
|
|
os_name TEXT,
|
|
os_parent TEXT,
|
|
client_version TEXT,
|
|
client_type TEXT,
|
|
client_support TEXT,
|
|
geo_ip_latitude DOUBLE PRECISION,
|
|
geo_ip_longitude DOUBLE PRECISION,
|
|
gateways JSONB,
|
|
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_appgate_sessions_username ON appgate_active_sessions(username);
|
|
CREATE INDEX IF NOT EXISTS idx_appgate_sessions_provider ON appgate_active_sessions(provider_name);
|
|
|
|
-- On-boarded devices — persistent inventory. Uses the same soft-delete
|
|
-- pattern as qbo_invoices: a full sync tombstones any row not returned.
|
|
CREATE TABLE IF NOT EXISTS appgate_devices (
|
|
distinguished_name TEXT PRIMARY KEY,
|
|
device_id UUID,
|
|
username TEXT,
|
|
provider_name TEXT,
|
|
device_type TEXT,
|
|
hostname TEXT,
|
|
on_boarded_at TIMESTAMPTZ,
|
|
last_seen_at TIMESTAMPTZ,
|
|
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_appgate_devices_username ON appgate_devices(username);
|
|
CREATE INDEX IF NOT EXISTS idx_appgate_devices_is_deleted ON appgate_devices(is_deleted);
|
|
CREATE INDEX IF NOT EXISTS idx_appgate_devices_last_seen ON appgate_devices(last_seen_at);
|
|
|
|
-- Appliances (controllers, gateways, log servers, etc.).
|
|
CREATE TABLE IF NOT EXISTS appgate_appliances (
|
|
id UUID PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
hostname TEXT,
|
|
notes TEXT,
|
|
version INTEGER,
|
|
site TEXT,
|
|
site_name TEXT,
|
|
activated BOOLEAN,
|
|
pending_certificate_renewal BOOLEAN,
|
|
tags JSONB,
|
|
roles JSONB, -- {controller, gateway, logServer, ...} subset flags
|
|
raw JSONB, -- full payload — versioned schema changes
|
|
created_at TIMESTAMPTZ,
|
|
updated_at TIMESTAMPTZ,
|
|
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_appgate_appliances_is_deleted ON appgate_appliances(is_deleted);
|
|
CREATE INDEX IF NOT EXISTS idx_appgate_appliances_site ON appgate_appliances(site);
|
|
|
|
-- Per-user license consumption — current snapshot, replaced each sync.
|
|
CREATE TABLE IF NOT EXISTS appgate_license_users (
|
|
user_distinguished_name TEXT PRIMARY KEY,
|
|
username TEXT,
|
|
provider_name TEXT,
|
|
license_type TEXT,
|
|
profile_name TEXT,
|
|
created_at TIMESTAMPTZ,
|
|
last_seen_at TIMESTAMPTZ,
|
|
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_appgate_license_users_username ON appgate_license_users(username);
|
|
|
|
-- Daily license capacity rollup — one row per day, history retained.
|
|
CREATE TABLE IF NOT EXISTS appgate_license_snapshots (
|
|
snapshot_date DATE PRIMARY KEY,
|
|
max_users INTEGER,
|
|
max_portal_users INTEGER,
|
|
max_service_users INTEGER,
|
|
used_users INTEGER,
|
|
expiration TIMESTAMPTZ,
|
|
license_type INTEGER,
|
|
license_version INTEGER,
|
|
risk_engine_enabled BOOLEAN,
|
|
app_discovery_enabled BOOLEAN,
|
|
captured_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- Daily login totals — derived from the rolling 24h /stats/user-logins endpoint.
|
|
-- Sync replaces yesterday/today rows; older days never change.
|
|
CREATE TABLE IF NOT EXISTS appgate_user_logins_daily (
|
|
login_date DATE PRIMARY KEY,
|
|
total_logins INTEGER NOT NULL DEFAULT 0,
|
|
captured_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- Sync history.
|
|
CREATE TABLE IF NOT EXISTS appgate_sync_history (
|
|
id SERIAL PRIMARY KEY,
|
|
sync_id TEXT NOT NULL,
|
|
sync_type TEXT NOT NULL,
|
|
triggered_by TEXT NOT NULL,
|
|
started_at TIMESTAMPTZ NOT NULL,
|
|
completed_at TIMESTAMPTZ,
|
|
status TEXT NOT NULL,
|
|
sessions_synced INTEGER NOT NULL DEFAULT 0,
|
|
devices_synced INTEGER NOT NULL DEFAULT 0,
|
|
devices_tombstoned INTEGER NOT NULL DEFAULT 0,
|
|
appliances_synced INTEGER NOT NULL DEFAULT 0,
|
|
appliances_tombstoned INTEGER NOT NULL DEFAULT 0,
|
|
license_users_synced INTEGER NOT NULL DEFAULT 0,
|
|
last_error TEXT
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_appgate_sync_history_started ON appgate_sync_history(started_at DESC);
|
|
|
|
-- Scheduler entries — disabled by default until credentials configured.
|
|
-- sync_schedules has no unique constraint on name, so guard with NOT EXISTS.
|
|
INSERT INTO sync_schedules (id, name, description, cron_expression, sync_type, is_enabled)
|
|
SELECT 'appgate-sessions',
|
|
'AppGate Sessions',
|
|
'Active session snapshot every 5 minutes during business hours.',
|
|
'*/5 11-23 * * 1-5', 'appgate-sessions', false
|
|
WHERE NOT EXISTS (SELECT 1 FROM sync_schedules WHERE name = 'AppGate Sessions');
|
|
|
|
INSERT INTO sync_schedules (id, name, description, cron_expression, sync_type, is_enabled)
|
|
SELECT 'appgate-daily',
|
|
'AppGate Daily',
|
|
'Full AppGate sync — devices, appliances, license, login totals.',
|
|
'15 6 * * *', 'appgate-daily', false
|
|
WHERE NOT EXISTS (SELECT 1 FROM sync_schedules WHERE name = 'AppGate Daily');
|