From liongard
Guides on Liongard detections for automated change/anomaly detection, alerts, custom metrics, alert rules, metric evaluation, and timeline audit trails in compliance monitoring.
npx claudepluginhub wyre-technology/msp-claude-plugins --plugin liongardThis skill uses the workspace's default tool permissions.
Detections are Liongard's automated change and anomaly detection system. Every time an inspection runs, Liongard compares the new data with previous inspection results and identifies changes. These changes become detections that MSPs can monitor, investigate, and act upon.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Reviews prose for communication issues impeding comprehension, outputs minimal fixes in a three-column table per Microsoft Writing Style Guide. Useful for 'review prose' or 'improve prose' requests.
Detections are Liongard's automated change and anomaly detection system. Every time an inspection runs, Liongard compares the new data with previous inspection results and identifies changes. These changes become detections that MSPs can monitor, investigate, and act upon.
The detection ecosystem includes:
Detections represent specific changes identified between inspection runs. When Liongard inspects a system and finds that something has changed since the previous inspection, it creates a detection record. Examples include:
| Field | Type | Description |
|---|---|---|
ID | int | Unique detection identifier |
Type | string | Detection type (Added, Removed, Changed, Threshold) |
Severity | string | Critical, High, Medium, Low, Info |
SystemID | int | System where detection occurred |
SystemName | string | System display name |
EnvironmentID | int | Parent environment |
EnvironmentName | string | Environment display name |
InspectorName | string | Inspector that triggered detection |
Status | string | New, Acknowledged, Resolved, Dismissed |
Summary | string | Brief description of the change |
Details | object | Detailed before/after data |
DetectedOn | datetime | When the change was detected |
AcknowledgedOn | datetime | When acknowledged by user |
ResolvedOn | datetime | When marked resolved |
| Type | Description | Example |
|---|---|---|
Added | New item discovered | New user account created |
Removed | Item no longer present | Device removed from network |
Changed | Existing item modified | Firewall rule updated |
Threshold | Value crossed a defined threshold | Disk usage exceeded 90% |
| Severity | Description | Typical Use |
|---|---|---|
Critical | Immediate action required | Security policy disabled, admin account compromised |
High | Urgent attention needed | MFA disabled, backup failure |
Medium | Review within business hours | Configuration change, new admin user |
Low | Informational but notable | New standard user, minor setting change |
Info | Routine change logged | Regular updates, expected modifications |
POST /api/v1/detections
X-ROAR-API-KEY: {api_key}
Content-Type: application/json
{
"Pagination": {
"Page": 1,
"PageSize": 100
},
"conditions": [
{
"path": "EnvironmentID",
"op": "eq",
"value": 1234
},
{
"path": "Severity",
"op": "in",
"value": ["Critical", "High"]
},
{
"path": "Status",
"op": "eq",
"value": "New"
}
],
"orderBy": [
{
"path": "DetectedOn",
"direction": "desc"
}
]
}
Response:
{
"Data": [
{
"ID": 80001,
"Type": "Changed",
"Severity": "High",
"SystemID": 10001,
"SystemName": "DC01.acme.local",
"EnvironmentID": 1234,
"EnvironmentName": "Acme Corporation",
"InspectorName": "Active Directory",
"Status": "New",
"Summary": "Password policy minimum length changed from 12 to 8",
"Details": {
"Before": {
"PasswordPolicy.MinimumLength": 12
},
"After": {
"PasswordPolicy.MinimumLength": 8
}
},
"DetectedOn": "2024-02-15T02:15:00Z"
}
],
"TotalRows": 15,
"HasMoreRows": false,
"CurrentPage": 1,
"TotalPages": 1,
"PageSize": 100
}
The v2 endpoint provides enhanced filtering and field selection:
POST /api/v2/detections
X-ROAR-API-KEY: {api_key}
Content-Type: application/json
{
"Pagination": {
"Page": 1,
"PageSize": 100
},
"conditions": [
{
"path": "DetectedOn",
"op": "gte",
"value": "2024-02-01T00:00:00Z"
},
{
"path": "Severity",
"op": "eq",
"value": "Critical"
}
],
"fields": ["ID", "Type", "Severity", "SystemName", "EnvironmentName", "Summary", "DetectedOn"],
"orderBy": [
{
"path": "DetectedOn",
"direction": "desc"
}
]
}
New ───────────────────> Dismissed
| |
v v
Acknowledged ──────> Resolved
Status Descriptions:
Alerts are configurable rules that define what types of detections should trigger notifications. Alert rules specify:
GET /api/v1/alerts?page=1&pageSize=50
X-ROAR-API-KEY: {api_key}
Response:
{
"Data": [
{
"ID": 2001,
"Name": "Critical Security Changes",
"Description": "Alert on critical severity detections across all environments",
"Enabled": true,
"Conditions": {
"Severity": ["Critical"],
"Type": ["Changed", "Removed"]
},
"Notifications": {
"Email": ["security@msp.com"],
"Webhook": "https://hooks.slack.com/services/..."
},
"CreatedOn": "2023-01-01T00:00:00Z"
}
],
"TotalRows": 10,
"HasMoreRows": false,
"CurrentPage": 1,
"TotalPages": 1,
"PageSize": 50
}
GET /api/v1/alerts/{alertId}
X-ROAR-API-KEY: {api_key}
POST /api/v1/alerts
X-ROAR-API-KEY: {api_key}
Content-Type: application/json
{
"Name": "MFA Disabled Alert",
"Description": "Alert when MFA is disabled in any M365 tenant",
"Enabled": true,
"Conditions": {
"InspectorName": ["Microsoft 365"],
"Severity": ["Critical", "High"],
"Summary": "MFA"
},
"Notifications": {
"Email": ["alerts@msp.com"]
}
}
PUT /api/v1/alerts/{alertId}
X-ROAR-API-KEY: {api_key}
Content-Type: application/json
{
"Enabled": false
}
DELETE /api/v1/alerts/{alertId}
X-ROAR-API-KEY: {api_key}
GET /api/v1/alerts/triggered?page=1&pageSize=100
X-ROAR-API-KEY: {api_key}
Response:
{
"Data": [
{
"ID": 50001,
"AlertRuleID": 2001,
"AlertRuleName": "Critical Security Changes",
"DetectionID": 80001,
"EnvironmentName": "Acme Corporation",
"SystemName": "DC01.acme.local",
"Summary": "Password policy minimum length changed from 12 to 8",
"TriggeredOn": "2024-02-15T02:15:30Z",
"Status": "New"
}
],
"TotalRows": 5,
"HasMoreRows": false,
"CurrentPage": 1,
"TotalPages": 1,
"PageSize": 100
}
Metrics allow MSPs to define custom measurements that are tracked across systems and environments. Metrics can evaluate specific data points from system details and aggregate results for compliance reporting, health monitoring, and trend analysis.
GET /api/v1/metrics?page=1&pageSize=50
X-ROAR-API-KEY: {api_key}
Response:
{
"Data": [
{
"ID": 3001,
"Name": "Password Policy Compliance",
"Description": "Checks if password minimum length is >= 12",
"InspectorID": 100,
"Expression": "Data.PasswordPolicy.MinimumLength",
"Threshold": 12,
"Operator": "gte",
"CreatedOn": "2023-01-15T00:00:00Z"
}
]
}
POST /api/v1/metrics
X-ROAR-API-KEY: {api_key}
Content-Type: application/json
{
"Name": "MFA Enabled Check",
"Description": "Verifies MFA is enabled in M365 tenants",
"InspectorID": 101,
"Expression": "Data.SecurityDefaults.MFAEnabled",
"Threshold": true,
"Operator": "eq"
}
Evaluate a metric across all applicable systems:
POST /api/v2/metrics/evaluate
X-ROAR-API-KEY: {api_key}
Content-Type: application/json
{
"MetricID": 3001,
"Pagination": {
"Page": 1,
"PageSize": 100
}
}
Response:
{
"Data": [
{
"SystemID": 10001,
"SystemName": "DC01.acme.local",
"EnvironmentID": 1234,
"EnvironmentName": "Acme Corporation",
"Value": 12,
"Compliant": true,
"EvaluatedOn": "2024-02-15T02:15:00Z"
},
{
"SystemID": 10002,
"SystemName": "DC01.newco.local",
"EnvironmentID": 5678,
"EnvironmentName": "New Company Inc",
"Value": 8,
"Compliant": false,
"EvaluatedOn": "2024-02-15T03:00:00Z"
}
],
"TotalRows": 50,
"HasMoreRows": false,
"CurrentPage": 1,
"TotalPages": 1,
"PageSize": 100
}
Evaluate all metrics for specific systems:
POST /api/v2/metrics/evaluate-systems
X-ROAR-API-KEY: {api_key}
Content-Type: application/json
{
"SystemIDs": [10001, 10002],
"Pagination": {
"Page": 1,
"PageSize": 100
}
}
Response:
{
"Data": [
{
"SystemID": 10001,
"MetricID": 3001,
"MetricName": "Password Policy Compliance",
"Value": 12,
"Compliant": true
},
{
"SystemID": 10001,
"MetricID": 3002,
"MetricName": "MFA Enabled Check",
"Value": true,
"Compliant": true
}
]
}
PUT /api/v1/metrics/{metricId}
X-ROAR-API-KEY: {api_key}
Content-Type: application/json
{
"Threshold": 14,
"Description": "Updated: Checks if password minimum length is >= 14"
}
DELETE /api/v1/metrics/{metricId}
X-ROAR-API-KEY: {api_key}
The timeline provides a comprehensive audit trail of all events within Liongard. It captures inspection runs, detection triggers, user actions, configuration changes, and system events.
GET /api/v1/timeline?page=1&pageSize=100
X-ROAR-API-KEY: {api_key}
The v2 endpoint supports POST-based filtering:
POST /api/v2/timelines-query
X-ROAR-API-KEY: {api_key}
Content-Type: application/json
{
"Pagination": {
"Page": 1,
"PageSize": 100
},
"conditions": [
{
"path": "EnvironmentID",
"op": "eq",
"value": 1234
},
{
"path": "EventDate",
"op": "gte",
"value": "2024-02-01T00:00:00Z"
}
],
"orderBy": [
{
"path": "EventDate",
"direction": "desc"
}
]
}
Response:
{
"Data": [
{
"ID": 900001,
"EventType": "InspectionCompleted",
"EnvironmentID": 1234,
"EnvironmentName": "Acme Corporation",
"SystemID": 10001,
"SystemName": "DC01.acme.local",
"Description": "Active Directory inspection completed successfully",
"EventDate": "2024-02-15T02:15:00Z",
"UserID": null
},
{
"ID": 900002,
"EventType": "DetectionCreated",
"EnvironmentID": 1234,
"EnvironmentName": "Acme Corporation",
"SystemID": 10001,
"SystemName": "DC01.acme.local",
"Description": "Password policy minimum length changed",
"EventDate": "2024-02-15T02:15:30Z",
"UserID": null
},
{
"ID": 900003,
"EventType": "UserAction",
"EnvironmentID": null,
"Description": "User admin@msp.com acknowledged detection #80001",
"EventDate": "2024-02-15T09:00:00Z",
"UserID": 1
}
],
"TotalRows": 500,
"HasMoreRows": true,
"CurrentPage": 1,
"TotalPages": 5,
"PageSize": 100
}
| Event Type | Description |
|---|---|
InspectionQueued | Inspection was scheduled to run |
InspectionStarted | Inspection began executing |
InspectionCompleted | Inspection finished successfully |
InspectionFailed | Inspection encountered an error |
DetectionCreated | New detection was identified |
DetectionAcknowledged | Detection was acknowledged by user |
DetectionResolved | Detection was marked resolved |
AlertTriggered | Alert rule fired a notification |
UserAction | User performed an action in the platform |
EnvironmentCreated | New environment was added |
LaunchpointCreated | New launchpoint was configured |
AgentOnline | Agent came online |
AgentOffline | Agent went offline |
async function processNewDetections(environmentId) {
// Fetch new detections for the environment
const response = await fetch(
`https://${instance}.app.liongard.com/api/v1/detections`,
{
method: 'POST',
headers: {
'X-ROAR-API-KEY': process.env.LIONGARD_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
Pagination: { Page: 1, PageSize: 100 },
conditions: [
{ path: 'EnvironmentID', op: 'eq', value: environmentId },
{ path: 'Status', op: 'eq', value: 'New' }
],
orderBy: [{ path: 'Severity', direction: 'asc' }]
})
}
);
const data = await response.json();
// Categorize by severity
const critical = data.Data.filter(d => d.Severity === 'Critical');
const high = data.Data.filter(d => d.Severity === 'High');
const medium = data.Data.filter(d => d.Severity === 'Medium');
const low = data.Data.filter(d => d.Severity === 'Low');
return {
total: data.TotalRows,
critical: critical.length,
high: high.length,
medium: medium.length,
low: low.length,
detections: data.Data
};
}
| Code | Message | Resolution |
|---|---|---|
| 400 | Invalid filter conditions | Check condition syntax |
| 401 | Unauthorized | Verify API key |
| 404 | Detection not found | Confirm detection ID |
| 404 | Alert rule not found | Confirm alert ID |
| 422 | Invalid metric expression | Check JMESPath syntax |
| 429 | Rate limited | Wait and retry (300 req/min) |
| Error | Cause | Fix |
|---|---|---|
| Expression error | Invalid JMESPath in metric | Fix the metric expression |
| No data | System has no detail data | Run an inspection first |
| Type mismatch | Threshold type doesn't match value | Align threshold with data type |
Detection (DetectionID)
|
+-- System (SystemID)
+-- Environment (EnvironmentID)
+-- Inspector (InspectorName)
+-- Severity / Type / Status
+-- Before/After Details
Alert Rule (AlertID)
|
+-- Conditions (Severity, Type, Inspector)
+-- Notifications (Email, Webhook)
+-- Triggered Alerts
+-- Detection (DetectionID)
Metric (MetricID)
|
+-- Inspector (InspectorID)
+-- Expression (JMESPath)
+-- Threshold / Operator
+-- Evaluations
+-- System (SystemID)
+-- Value / Compliant
Timeline (EventID)
|
+-- EventType
+-- Environment (EnvironmentID)
+-- System (SystemID)
+-- User (UserID)
+-- EventDate